Add a hack so that get_type_io_data() can work from bootstrap.c's
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 15 Aug 2006 22:36:17 +0000 (22:36 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 15 Aug 2006 22:36:17 +0000 (22:36 +0000)
internal TypInfo table in bootstrap mode.  This allows array_in and
array_out to be used during early bootstrap, which eliminates the
former obstacle to giving OUT parameters to built-in functions.

src/backend/bootstrap/bootstrap.c
src/backend/utils/cache/lsyscache.c
src/include/bootstrap/bootstrap.h

index 08189bf07b23622001130cbc620a3ba4ce3a0030..06d8a5ca4fc056de949b3e89adb53eb12149b726 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.223 2006/07/31 20:09:00 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.224 2006/08/15 22:36:17 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -590,6 +590,7 @@ boot_openrel(char *relname)
 
        if (Typ == NULL)
        {
+               /* We can now load the pg_type data */
                rel = heap_open(TypeRelationId, NoLock);
                scan = heap_beginscan(rel, SnapshotNow, 0, NULL);
                i = 0;
@@ -806,6 +807,10 @@ void
 InsertOneValue(char *value, int i)
 {
        Oid                     typoid;
+       int16           typlen;
+       bool            typbyval;
+       char            typalign;
+       char            typdelim;
        Oid                     typioparam;
        Oid                     typinput;
        Oid                     typoutput;
@@ -817,52 +822,19 @@ InsertOneValue(char *value, int i)
 
        if (Typ != NULL)
        {
-               struct typmap **app;
-               struct typmap *ap;
-
-               elog(DEBUG5, "Typ != NULL");
                typoid = boot_reldesc->rd_att->attrs[i]->atttypid;
-               app = Typ;
-               while (*app && (*app)->am_oid != typoid)
-                       ++app;
-               ap = *app;
-               if (ap == NULL)
-                       elog(ERROR, "could not find atttypid %u in Typ list", typoid);
-
-               /* XXX this logic should match getTypeIOParam() */
-               if (OidIsValid(ap->am_typ.typelem))
-                       typioparam = ap->am_typ.typelem;
-               else
-                       typioparam = typoid;
-
-               typinput = ap->am_typ.typinput;
-               typoutput = ap->am_typ.typoutput;
        }
        else
        {
-               int                     typeindex;
-
-               /* XXX why is typoid determined differently in this path? */
+               /* XXX why is typoid determined differently in this case? */
                typoid = attrtypes[i]->atttypid;
-               for (typeindex = 0; typeindex < n_types; typeindex++)
-               {
-                       if (TypInfo[typeindex].oid == typoid)
-                               break;
-               }
-               if (typeindex >= n_types)
-                       elog(ERROR, "type oid %u not found", typoid);
-               elog(DEBUG5, "Typ == NULL, typeindex = %u", typeindex);
-
-               /* XXX this logic should match getTypeIOParam() */
-               if (OidIsValid(TypInfo[typeindex].elem))
-                       typioparam = TypInfo[typeindex].elem;
-               else
-                       typioparam = typoid;
-
-               typinput = TypInfo[typeindex].inproc;
-               typoutput = TypInfo[typeindex].outproc;
        }
 
+       boot_get_type_io_data(typoid,
+                                                 &typlen, &typbyval, &typalign,
+                                                 &typdelim, &typioparam,
+                                                 &typinput, &typoutput);
+
        values[i] = OidInputFunctionCall(typinput, value, typioparam, -1);
        prt = OidOutputFunctionCall(typoutput, values[i]);
        elog(DEBUG4, "inserted -> %s", prt);
@@ -972,6 +944,83 @@ gettype(char *type)
        return 0;
 }
 
+/* ----------------
+ *             boot_get_type_io_data
+ *
+ * Obtain type I/O information at bootstrap time.  This intentionally has
+ * almost the same API as lsyscache.c's get_type_io_data, except that
+ * we only support obtaining the typinput and typoutput routines, not
+ * the binary I/O routines.  It is exported so that array_in and array_out
+ * can be made to work during early bootstrap.
+ * ----------------
+ */
+void
+boot_get_type_io_data(Oid typid,
+                                         int16 *typlen,
+                                         bool *typbyval,
+                                         char *typalign,
+                                         char *typdelim,
+                                         Oid *typioparam,
+                                         Oid *typinput,
+                                         Oid *typoutput)
+{
+       if (Typ != NULL)
+       {
+               /* We have the boot-time contents of pg_type, so use it */
+               struct typmap **app;
+               struct typmap *ap;
+
+               app = Typ;
+               while (*app && (*app)->am_oid != typid)
+                       ++app;
+               ap = *app;
+               if (ap == NULL)
+                       elog(ERROR, "type OID %u not found in Typ list", typid);
+
+               *typlen = ap->am_typ.typlen;
+               *typbyval = ap->am_typ.typbyval;
+               *typalign = ap->am_typ.typalign;
+               *typdelim = ap->am_typ.typdelim;
+
+               /* XXX this logic must match getTypeIOParam() */
+               if (OidIsValid(ap->am_typ.typelem))
+                       *typioparam = ap->am_typ.typelem;
+               else
+                       *typioparam = typid;
+
+               *typinput = ap->am_typ.typinput;
+               *typoutput = ap->am_typ.typoutput;
+       }
+       else
+       {
+               /* We don't have pg_type yet, so use the hard-wired TypInfo array */
+               int                     typeindex;
+
+               for (typeindex = 0; typeindex < n_types; typeindex++)
+               {
+                       if (TypInfo[typeindex].oid == typid)
+                               break;
+               }
+               if (typeindex >= n_types)
+                       elog(ERROR, "type OID %u not found in TypInfo", typid);
+
+               *typlen = TypInfo[typeindex].len;
+               *typbyval = TypInfo[typeindex].byval;
+               *typalign = TypInfo[typeindex].align;
+               /* We assume typdelim is ',' for all boot-time types */
+               *typdelim = ',';
+
+               /* XXX this logic must match getTypeIOParam() */
+               if (OidIsValid(TypInfo[typeindex].elem))
+                       *typioparam = TypInfo[typeindex].elem;
+               else
+                       *typioparam = typid;
+
+               *typinput = TypInfo[typeindex].inproc;
+               *typoutput = TypInfo[typeindex].outproc;
+       }
+}
+
 /* ----------------
  *             AllocateAttribute
  * ----------------
index 93fa1f029f668312fe797f61a8f2bc496db94a71..769206e02c825bc82acd219be708ae90734fc308 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.135 2006/07/14 14:52:25 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.136 2006/08/15 22:36:17 tgl Exp $
  *
  * NOTES
  *       Eventually, the index information should go through here, too.
@@ -16,6 +16,7 @@
 #include "postgres.h"
 
 #include "access/hash.h"
+#include "bootstrap/bootstrap.h"
 #include "catalog/pg_amop.h"
 #include "catalog/pg_amproc.h"
 #include "catalog/pg_namespace.h"
@@ -24,6 +25,7 @@
 #include "catalog/pg_proc.h"
 #include "catalog/pg_statistic.h"
 #include "catalog/pg_type.h"
+#include "miscadmin.h"
 #include "nodes/makefuncs.h"
 #include "utils/array.h"
 #include "utils/builtins.h"
@@ -1350,7 +1352,7 @@ get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval,
  * This knowledge is intended to be centralized here --- direct references
  * to typelem elsewhere in the code are wrong, if they are associated with
  * I/O calls and not with actual subscripting operations!  (But see
- * bootstrap.c, which can't conveniently use this routine.)
+ * bootstrap.c's boot_get_type_io_data() if you need to change this.)
  *
  * As of PostgreSQL 8.1, output functions receive only the value itself
  * and not any auxiliary parameters, so the name of this routine is now
@@ -1392,6 +1394,38 @@ get_type_io_data(Oid typid,
        HeapTuple       typeTuple;
        Form_pg_type typeStruct;
 
+       /*
+        * In bootstrap mode, pass it off to bootstrap.c.  This hack allows
+        * us to use array_in and array_out during bootstrap.
+        */
+       if (IsBootstrapProcessingMode())
+       {
+               Oid     typinput;
+               Oid     typoutput;
+
+               boot_get_type_io_data(typid,
+                                                         typlen,
+                                                         typbyval,
+                                                         typalign,
+                                                         typdelim,
+                                                         typioparam,
+                                                         &typinput,
+                                                         &typoutput);
+               switch (which_func)
+               {
+                       case IOFunc_input:
+                               *func = typinput;
+                               break;
+                       case IOFunc_output:
+                               *func = typoutput;
+                               break;
+                       default:
+                               elog(ERROR, "binary I/O not supported during bootstrap");
+                               break;
+               }
+               return;
+       }
+
        typeTuple = SearchSysCache(TYPEOID,
                                                           ObjectIdGetDatum(typid),
                                                           0, 0, 0);
index 807f27664643f3e5289b2ebd338a34d59d5a85ff..6713b6df6788c3265ba005469f5b1d1607293a90 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/bootstrap/bootstrap.h,v 1.42 2006/07/13 16:49:19 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/bootstrap/bootstrap.h,v 1.43 2006/08/15 22:36:17 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -50,6 +50,15 @@ extern char *CleanUpStr(char *s);
 extern int     EnterString(char *str);
 extern void build_indices(void);
 
+extern void boot_get_type_io_data(Oid typid,
+                                                                 int16 *typlen,
+                                                                 bool *typbyval,
+                                                                 char *typalign,
+                                                                 char *typdelim,
+                                                                 Oid *typioparam,
+                                                                 Oid *typinput,
+                                                                 Oid *typoutput);
+
 extern int     boot_yyparse(void);
 
 extern int     boot_yylex(void);