1 /*-------------------------------------------------------------------------
4 * routines to support running postgres in 'bootstrap' mode
5 * bootstrap mode is used to create the initial template database
7 * Portions Copyright (c) 1996-2015, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
11 * src/backend/bootstrap/bootstrap.c
13 *-------------------------------------------------------------------------
20 #include "access/htup_details.h"
21 #include "bootstrap/bootstrap.h"
22 #include "catalog/index.h"
23 #include "catalog/pg_collation.h"
24 #include "catalog/pg_type.h"
25 #include "libpq/pqsignal.h"
26 #include "miscadmin.h"
27 #include "nodes/makefuncs.h"
28 #include "pg_getopt.h"
29 #include "postmaster/bgwriter.h"
30 #include "postmaster/startup.h"
31 #include "postmaster/walwriter.h"
32 #include "replication/walreceiver.h"
33 #include "storage/bufmgr.h"
34 #include "storage/bufpage.h"
35 #include "storage/ipc.h"
36 #include "storage/proc.h"
37 #include "tcop/tcopprot.h"
38 #include "utils/builtins.h"
39 #include "utils/fmgroids.h"
40 #include "utils/memutils.h"
41 #include "utils/ps_status.h"
42 #include "utils/rel.h"
43 #include "utils/relmapper.h"
44 #include "utils/tqual.h"
46 uint32 bootstrap_data_checksum_version = 0; /* No checksum */
49 #define ALLOC(t, c) ((t *) calloc((unsigned)(c), sizeof(t)))
51 static void CheckerModeMain(void);
52 static void BootstrapModeMain(void);
53 static void bootstrap_signals(void);
54 static void ShutdownAuxiliaryProcess(int code, Datum arg);
55 static Form_pg_attribute AllocateAttribute(void);
56 static Oid gettype(char *type);
57 static void cleanup(void);
64 AuxProcType MyAuxProcType = NotAnAuxProcess; /* declared in miscadmin.h */
66 Relation boot_reldesc; /* current relation descriptor */
68 Form_pg_attribute attrtypes[MAXATTR]; /* points to attribute info */
69 int numattr; /* number of attributes for cur. rel */
73 * Basic information associated with each type. This is used before
74 * pg_type is filled, so it has to cover the datatypes used as column types
75 * in the core "bootstrapped" catalogs.
77 * XXX several of these input/output functions do catalog scans
78 * (e.g., F_REGPROCIN scans pg_proc). this obviously creates some
79 * order dependencies in the catalog creation process.
83 char name[NAMEDATALEN];
95 static const struct typinfo TypInfo[] = {
96 {"bool", BOOLOID, 0, 1, true, 'c', 'p', InvalidOid,
98 {"bytea", BYTEAOID, 0, -1, false, 'i', 'x', InvalidOid,
99 F_BYTEAIN, F_BYTEAOUT},
100 {"char", CHAROID, 0, 1, true, 'c', 'p', InvalidOid,
101 F_CHARIN, F_CHAROUT},
102 {"int2", INT2OID, 0, 2, true, 's', 'p', InvalidOid,
103 F_INT2IN, F_INT2OUT},
104 {"int4", INT4OID, 0, 4, true, 'i', 'p', InvalidOid,
105 F_INT4IN, F_INT4OUT},
106 {"float4", FLOAT4OID, 0, 4, FLOAT4PASSBYVAL, 'i', 'p', InvalidOid,
107 F_FLOAT4IN, F_FLOAT4OUT},
108 {"name", NAMEOID, CHAROID, NAMEDATALEN, false, 'c', 'p', InvalidOid,
109 F_NAMEIN, F_NAMEOUT},
110 {"regclass", REGCLASSOID, 0, 4, true, 'i', 'p', InvalidOid,
111 F_REGCLASSIN, F_REGCLASSOUT},
112 {"regproc", REGPROCOID, 0, 4, true, 'i', 'p', InvalidOid,
113 F_REGPROCIN, F_REGPROCOUT},
114 {"regtype", REGTYPEOID, 0, 4, true, 'i', 'p', InvalidOid,
115 F_REGTYPEIN, F_REGTYPEOUT},
116 {"text", TEXTOID, 0, -1, false, 'i', 'x', DEFAULT_COLLATION_OID,
117 F_TEXTIN, F_TEXTOUT},
118 {"oid", OIDOID, 0, 4, true, 'i', 'p', InvalidOid,
120 {"tid", TIDOID, 0, 6, false, 's', 'p', InvalidOid,
122 {"xid", XIDOID, 0, 4, true, 'i', 'p', InvalidOid,
124 {"cid", CIDOID, 0, 4, true, 'i', 'p', InvalidOid,
126 {"pg_node_tree", PGNODETREEOID, 0, -1, false, 'i', 'x', DEFAULT_COLLATION_OID,
127 F_PG_NODE_TREE_IN, F_PG_NODE_TREE_OUT},
128 {"int2vector", INT2VECTOROID, INT2OID, -1, false, 'i', 'p', InvalidOid,
129 F_INT2VECTORIN, F_INT2VECTOROUT},
130 {"oidvector", OIDVECTOROID, OIDOID, -1, false, 'i', 'p', InvalidOid,
131 F_OIDVECTORIN, F_OIDVECTOROUT},
132 {"_int4", INT4ARRAYOID, INT4OID, -1, false, 'i', 'x', InvalidOid,
133 F_ARRAY_IN, F_ARRAY_OUT},
134 {"_text", 1009, TEXTOID, -1, false, 'i', 'x', DEFAULT_COLLATION_OID,
135 F_ARRAY_IN, F_ARRAY_OUT},
136 {"_oid", 1028, OIDOID, -1, false, 'i', 'x', InvalidOid,
137 F_ARRAY_IN, F_ARRAY_OUT},
138 {"_char", 1002, CHAROID, -1, false, 'i', 'x', InvalidOid,
139 F_ARRAY_IN, F_ARRAY_OUT},
140 {"_aclitem", 1034, ACLITEMOID, -1, false, 'i', 'x', InvalidOid,
141 F_ARRAY_IN, F_ARRAY_OUT}
144 static const int n_types = sizeof(TypInfo) / sizeof(struct typinfo);
149 FormData_pg_type am_typ;
152 static struct typmap **Typ = NULL;
153 static struct typmap *Ap = NULL;
155 static Datum values[MAXATTR]; /* current row's attribute values */
156 static bool Nulls[MAXATTR];
158 static MemoryContext nogc = NULL; /* special no-gc mem context */
161 * At bootstrap time, we first declare all the indices to be built, and
162 * then build them. The IndexList structure stores enough information
163 * to allow us to build the indices after they've been declared.
166 typedef struct _IndexList
171 struct _IndexList *il_next;
174 static IndexList *ILHead = NULL;
178 * AuxiliaryProcessMain
180 * The main entry point for auxiliary processes, such as the bgwriter,
181 * walwriter, walreceiver, bootstrapper and the shared memory checker code.
183 * This code is here just because of historical reasons.
186 AuxiliaryProcessMain(int argc, char *argv[])
188 char *progname = argv[0];
190 char *userDoption = NULL;
193 * Initialize process environment (already done if under postmaster, but
194 * not if standalone).
196 if (!IsUnderPostmaster)
197 InitStandaloneProcess(argv[0]);
200 * process command arguments
203 /* Set defaults, to be overriden by explicit options below */
204 if (!IsUnderPostmaster)
205 InitializeGUCOptions();
207 /* Ignore the initial --boot argument, if present */
208 if (argc > 1 && strcmp(argv[1], "--boot") == 0)
214 /* If no -x argument, we are a CheckerProcess */
215 MyAuxProcType = CheckerProcess;
217 while ((flag = getopt(argc, argv, "B:c:d:D:Fkr:x:-:")) != -1)
222 SetConfigOption("shared_buffers", optarg, PGC_POSTMASTER, PGC_S_ARGV);
225 userDoption = strdup(optarg);
229 /* Turn on debugging for the bootstrap process. */
232 debugstr = psprintf("debug%s", optarg);
233 SetConfigOption("log_min_messages", debugstr,
234 PGC_POSTMASTER, PGC_S_ARGV);
235 SetConfigOption("client_min_messages", debugstr,
236 PGC_POSTMASTER, PGC_S_ARGV);
241 SetConfigOption("fsync", "false", PGC_POSTMASTER, PGC_S_ARGV);
244 bootstrap_data_checksum_version = PG_DATA_CHECKSUM_VERSION;
247 strlcpy(OutputFileName, optarg, MAXPGPATH);
250 MyAuxProcType = atoi(optarg);
258 ParseLongOption(optarg, &name, &value);
263 (errcode(ERRCODE_SYNTAX_ERROR),
264 errmsg("--%s requires a value",
268 (errcode(ERRCODE_SYNTAX_ERROR),
269 errmsg("-c %s requires a value",
273 SetConfigOption(name, value, PGC_POSTMASTER, PGC_S_ARGV);
280 write_stderr("Try \"%s --help\" for more information.\n",
289 write_stderr("%s: invalid command-line arguments\n", progname);
294 * Identify myself via ps
296 if (IsUnderPostmaster)
300 switch (MyAuxProcType)
303 statmsg = "startup process";
305 case BgWriterProcess:
306 statmsg = "writer process";
308 case CheckpointerProcess:
309 statmsg = "checkpointer process";
311 case WalWriterProcess:
312 statmsg = "wal writer process";
314 case WalReceiverProcess:
315 statmsg = "wal receiver process";
318 statmsg = "??? process";
321 init_ps_display(statmsg, "", "", "");
324 /* Acquire configuration parameters, unless inherited from postmaster */
325 if (!IsUnderPostmaster)
327 if (!SelectConfigFiles(userDoption, progname))
331 /* Validate we have been given a reasonable-looking DataDir */
333 ValidatePgVersion(DataDir);
335 /* Change into DataDir (if under postmaster, should be done already) */
336 if (!IsUnderPostmaster)
339 /* If standalone, create lockfile for data directory */
340 if (!IsUnderPostmaster)
341 CreateDataDirLockFile(false);
343 SetProcessingMode(BootstrapProcessing);
344 IgnoreSystemIndexes = true;
346 /* Initialize MaxBackends (if under postmaster, was done already) */
347 if (!IsUnderPostmaster)
348 InitializeMaxBackends();
353 * When we are an auxiliary process, we aren't going to do the full
354 * InitPostgres pushups, but there are a couple of things that need to get
355 * lit up even in an auxiliary process.
357 if (IsUnderPostmaster)
360 * Create a PGPROC so we can use LWLocks. In the EXEC_BACKEND case,
361 * this was already done by SubPostmasterMain().
364 InitAuxiliaryProcess();
368 * Assign the ProcSignalSlot for an auxiliary process. Since it
369 * doesn't have a BackendId, the slot is statically allocated based on
370 * the auxiliary process type (MyAuxProcType). Backends use slots
371 * indexed in the range from 1 to MaxBackends (inclusive), so we use
372 * MaxBackends + AuxProcType + 1 as the index of the slot for an
375 * This will need rethinking if we ever want more than one of a
376 * particular auxiliary process type.
378 ProcSignalInit(MaxBackends + MyAuxProcType + 1);
380 /* finish setting up bufmgr.c */
381 InitBufferPoolBackend();
383 /* register a before-shutdown callback for LWLock cleanup */
384 before_shmem_exit(ShutdownAuxiliaryProcess, 0);
390 SetProcessingMode(NormalProcessing);
392 switch (MyAuxProcType)
395 /* don't set signals, they're useless here */
397 proc_exit(1); /* should never return */
399 case BootstrapProcess:
403 proc_exit(1); /* should never return */
406 /* don't set signals, startup process has its own agenda */
407 StartupProcessMain();
408 proc_exit(1); /* should never return */
410 case BgWriterProcess:
411 /* don't set signals, bgwriter has its own agenda */
412 BackgroundWriterMain();
413 proc_exit(1); /* should never return */
415 case CheckpointerProcess:
416 /* don't set signals, checkpointer has its own agenda */
418 proc_exit(1); /* should never return */
420 case WalWriterProcess:
421 /* don't set signals, walwriter has its own agenda */
424 proc_exit(1); /* should never return */
426 case WalReceiverProcess:
427 /* don't set signals, walreceiver has its own agenda */
429 proc_exit(1); /* should never return */
432 elog(PANIC, "unrecognized process type: %d", (int) MyAuxProcType);
438 * In shared memory checker mode, all we really want to do is create shared
439 * memory and semaphores (just to prove we can do it with the current GUC
440 * settings). Since, in fact, that was already done by BaseInit(),
441 * we have nothing more to do here.
444 CheckerModeMain(void)
450 * The main entry point for running the backend in bootstrap mode
452 * The bootstrap mode is used to initialize the template database.
453 * The bootstrap backend doesn't speak SQL, but instead expects
454 * commands in a special bootstrap language.
457 BootstrapModeMain(void)
461 Assert(!IsUnderPostmaster);
463 SetProcessingMode(BootstrapProcessing);
466 * Do backend-like initialization for bootstrap mode
470 InitPostgres(NULL, InvalidOid, NULL, InvalidOid, NULL);
472 /* Initialize stuff for bootstrap-file processing */
473 for (i = 0; i < MAXATTR; i++)
480 * Process bootstrap input.
485 * We should now know about all mapped relations, so it's okay to write
486 * out the initial relation mapping files.
488 RelationMapFinishBootstrap();
490 /* Clean up and exit */
496 /* ----------------------------------------------------------------
498 * ----------------------------------------------------------------
502 * Set up signal handling for a bootstrap process
505 bootstrap_signals(void)
507 Assert(!IsUnderPostmaster);
509 /* Set up appropriately for interactive use */
510 pqsignal(SIGHUP, die);
511 pqsignal(SIGINT, die);
512 pqsignal(SIGTERM, die);
513 pqsignal(SIGQUIT, die);
517 * Begin shutdown of an auxiliary process. This is approximately the equivalent
518 * of ShutdownPostgres() in postinit.c. We can't run transactions in an
519 * auxiliary process, so most of the work of AbortTransaction() is not needed,
520 * but we do need to make sure we've released any LWLocks we are holding.
521 * (This is only critical during an error exit.)
524 ShutdownAuxiliaryProcess(int code, Datum arg)
529 /* ----------------------------------------------------------------
530 * MANUAL BACKEND INTERACTIVE INTERFACE COMMANDS
531 * ----------------------------------------------------------------
539 boot_openrel(char *relname)
547 if (strlen(relname) >= NAMEDATALEN)
548 relname[NAMEDATALEN - 1] = '\0';
552 /* We can now load the pg_type data */
553 rel = heap_open(TypeRelationId, NoLock);
554 scan = heap_beginscan_catalog(rel, 0, NULL);
556 while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL)
559 app = Typ = ALLOC(struct typmap *, i + 1);
561 *app++ = ALLOC(struct typmap, 1);
563 scan = heap_beginscan_catalog(rel, 0, NULL);
565 while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL)
567 (*app)->am_oid = HeapTupleGetOid(tup);
568 memcpy((char *) &(*app)->am_typ,
569 (char *) GETSTRUCT(tup),
570 sizeof((*app)->am_typ));
574 heap_close(rel, NoLock);
577 if (boot_reldesc != NULL)
580 elog(DEBUG4, "open relation %s, attrsize %d",
581 relname, (int) ATTRIBUTE_FIXED_PART_SIZE);
583 boot_reldesc = heap_openrv(makeRangeVar(NULL, relname, -1), NoLock);
584 numattr = boot_reldesc->rd_rel->relnatts;
585 for (i = 0; i < numattr; i++)
587 if (attrtypes[i] == NULL)
588 attrtypes[i] = AllocateAttribute();
589 memmove((char *) attrtypes[i],
590 (char *) boot_reldesc->rd_att->attrs[i],
591 ATTRIBUTE_FIXED_PART_SIZE);
594 Form_pg_attribute at = attrtypes[i];
596 elog(DEBUG4, "create attribute %d name %s len %d num %d type %u",
597 i, NameStr(at->attname), at->attlen, at->attnum,
614 if (strcmp(RelationGetRelationName(boot_reldesc), name) != 0)
615 elog(ERROR, "close of %s when %s was expected",
616 name, RelationGetRelationName(boot_reldesc));
619 elog(ERROR, "close of %s before any relation was opened",
623 if (boot_reldesc == NULL)
624 elog(ERROR, "no open relation to close");
627 elog(DEBUG4, "close relation %s",
628 RelationGetRelationName(boot_reldesc));
629 heap_close(boot_reldesc, NoLock);
639 * define a <field,type> pair
640 * if there are n fields in a relation to be created, this routine
641 * will be called n times
645 DefineAttr(char *name, char *type, int attnum, int nullness)
649 if (boot_reldesc != NULL)
651 elog(WARNING, "no open relations allowed with CREATE command");
655 if (attrtypes[attnum] == NULL)
656 attrtypes[attnum] = AllocateAttribute();
657 MemSet(attrtypes[attnum], 0, ATTRIBUTE_FIXED_PART_SIZE);
659 namestrcpy(&attrtypes[attnum]->attname, name);
660 elog(DEBUG4, "column %s %s", NameStr(attrtypes[attnum]->attname), type);
661 attrtypes[attnum]->attnum = attnum + 1; /* fillatt */
663 typeoid = gettype(type);
667 attrtypes[attnum]->atttypid = Ap->am_oid;
668 attrtypes[attnum]->attlen = Ap->am_typ.typlen;
669 attrtypes[attnum]->attbyval = Ap->am_typ.typbyval;
670 attrtypes[attnum]->attstorage = Ap->am_typ.typstorage;
671 attrtypes[attnum]->attalign = Ap->am_typ.typalign;
672 attrtypes[attnum]->attcollation = Ap->am_typ.typcollation;
673 /* if an array type, assume 1-dimensional attribute */
674 if (Ap->am_typ.typelem != InvalidOid && Ap->am_typ.typlen < 0)
675 attrtypes[attnum]->attndims = 1;
677 attrtypes[attnum]->attndims = 0;
681 attrtypes[attnum]->atttypid = TypInfo[typeoid].oid;
682 attrtypes[attnum]->attlen = TypInfo[typeoid].len;
683 attrtypes[attnum]->attbyval = TypInfo[typeoid].byval;
684 attrtypes[attnum]->attstorage = TypInfo[typeoid].storage;
685 attrtypes[attnum]->attalign = TypInfo[typeoid].align;
686 attrtypes[attnum]->attcollation = TypInfo[typeoid].collation;
687 /* if an array type, assume 1-dimensional attribute */
688 if (TypInfo[typeoid].elem != InvalidOid &&
689 attrtypes[attnum]->attlen < 0)
690 attrtypes[attnum]->attndims = 1;
692 attrtypes[attnum]->attndims = 0;
695 attrtypes[attnum]->attstattarget = -1;
696 attrtypes[attnum]->attcacheoff = -1;
697 attrtypes[attnum]->atttypmod = -1;
698 attrtypes[attnum]->attislocal = true;
700 if (nullness == BOOTCOL_NULL_FORCE_NOT_NULL)
702 attrtypes[attnum]->attnotnull = true;
704 else if (nullness == BOOTCOL_NULL_FORCE_NULL)
706 attrtypes[attnum]->attnotnull = false;
710 Assert(nullness == BOOTCOL_NULL_AUTO);
713 * Mark as "not null" if type is fixed-width and prior columns are
714 * too. This corresponds to case where column can be accessed
715 * directly via C struct declaration.
717 * oidvector and int2vector are also treated as not-nullable, even
718 * though they are no longer fixed-width.
720 #define MARKNOTNULL(att) \
721 ((att)->attlen > 0 || \
722 (att)->atttypid == OIDVECTOROID || \
723 (att)->atttypid == INT2VECTOROID)
725 if (MARKNOTNULL(attrtypes[attnum]))
729 /* check earlier attributes */
730 for (i = 0; i < attnum; i++)
732 if (!attrtypes[i]->attnotnull)
736 attrtypes[attnum]->attnotnull = true;
745 * If objectid is not zero, it is a specific OID to assign to the tuple.
746 * Otherwise, an OID will be assigned (if necessary) by heap_insert.
750 InsertOneTuple(Oid objectid)
756 elog(DEBUG4, "inserting row oid %u, %d columns", objectid, numattr);
758 tupDesc = CreateTupleDesc(numattr,
759 RelationGetForm(boot_reldesc)->relhasoids,
761 tuple = heap_form_tuple(tupDesc, values, Nulls);
762 if (objectid != (Oid) 0)
763 HeapTupleSetOid(tuple, objectid);
764 pfree(tupDesc); /* just free's tupDesc, not the attrtypes */
766 simple_heap_insert(boot_reldesc, tuple);
767 heap_freetuple(tuple);
768 elog(DEBUG4, "row inserted");
771 * Reset null markers for next tuple
773 for (i = 0; i < numattr; i++)
782 InsertOneValue(char *value, int i)
793 AssertArg(i >= 0 && i < MAXATTR);
795 elog(DEBUG4, "inserting column %d value \"%s\"", i, value);
797 typoid = boot_reldesc->rd_att->attrs[i]->atttypid;
799 boot_get_type_io_data(typoid,
800 &typlen, &typbyval, &typalign,
801 &typdelim, &typioparam,
802 &typinput, &typoutput);
804 values[i] = OidInputFunctionCall(typinput, value, typioparam, -1);
807 * We use ereport not elog here so that parameters aren't evaluated unless
808 * the message is going to be printed, which generally it isn't
811 (errmsg_internal("inserted -> %s",
812 OidOutputFunctionCall(typoutput, values[i]))));
822 elog(DEBUG4, "inserting column %d NULL", i);
823 Assert(i >= 0 && i < MAXATTR);
824 values[i] = PointerGetDatum(NULL);
835 if (boot_reldesc != NULL)
842 * NB: this is really ugly; it will return an integer index into TypInfo[],
843 * and not an OID at all, until the first reference to a type not known in
844 * TypInfo[]. At that point it will read and cache pg_type in the Typ array,
845 * and subsequently return a real OID (and set the global pointer Ap to
846 * point at the found row in Typ). So caller must check whether Typ is
847 * still NULL to determine what the return value is!
861 for (app = Typ; *app != NULL; app++)
863 if (strncmp(NameStr((*app)->am_typ.typname), type, NAMEDATALEN) == 0)
866 return (*app)->am_oid;
872 for (i = 0; i < n_types; i++)
874 if (strncmp(type, TypInfo[i].name, NAMEDATALEN) == 0)
877 elog(DEBUG4, "external type: %s", type);
878 rel = heap_open(TypeRelationId, NoLock);
879 scan = heap_beginscan_catalog(rel, 0, NULL);
881 while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL)
884 app = Typ = ALLOC(struct typmap *, i + 1);
886 *app++ = ALLOC(struct typmap, 1);
888 scan = heap_beginscan_catalog(rel, 0, NULL);
890 while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL)
892 (*app)->am_oid = HeapTupleGetOid(tup);
893 memmove((char *) &(*app++)->am_typ,
894 (char *) GETSTRUCT(tup),
895 sizeof((*app)->am_typ));
898 heap_close(rel, NoLock);
899 return gettype(type);
901 elog(ERROR, "unrecognized type \"%s\"", type);
902 /* not reached, here to make compiler happy */
907 * boot_get_type_io_data
909 * Obtain type I/O information at bootstrap time. This intentionally has
910 * almost the same API as lsyscache.c's get_type_io_data, except that
911 * we only support obtaining the typinput and typoutput routines, not
912 * the binary I/O routines. It is exported so that array_in and array_out
913 * can be made to work during early bootstrap.
917 boot_get_type_io_data(Oid typid,
928 /* We have the boot-time contents of pg_type, so use it */
933 while (*app && (*app)->am_oid != typid)
937 elog(ERROR, "type OID %u not found in Typ list", typid);
939 *typlen = ap->am_typ.typlen;
940 *typbyval = ap->am_typ.typbyval;
941 *typalign = ap->am_typ.typalign;
942 *typdelim = ap->am_typ.typdelim;
944 /* XXX this logic must match getTypeIOParam() */
945 if (OidIsValid(ap->am_typ.typelem))
946 *typioparam = ap->am_typ.typelem;
950 *typinput = ap->am_typ.typinput;
951 *typoutput = ap->am_typ.typoutput;
955 /* We don't have pg_type yet, so use the hard-wired TypInfo array */
958 for (typeindex = 0; typeindex < n_types; typeindex++)
960 if (TypInfo[typeindex].oid == typid)
963 if (typeindex >= n_types)
964 elog(ERROR, "type OID %u not found in TypInfo", typid);
966 *typlen = TypInfo[typeindex].len;
967 *typbyval = TypInfo[typeindex].byval;
968 *typalign = TypInfo[typeindex].align;
969 /* We assume typdelim is ',' for all boot-time types */
972 /* XXX this logic must match getTypeIOParam() */
973 if (OidIsValid(TypInfo[typeindex].elem))
974 *typioparam = TypInfo[typeindex].elem;
978 *typinput = TypInfo[typeindex].inproc;
979 *typoutput = TypInfo[typeindex].outproc;
986 * Note: bootstrap never sets any per-column ACLs, so we only need
987 * ATTRIBUTE_FIXED_PART_SIZE space per attribute.
990 static Form_pg_attribute
991 AllocateAttribute(void)
993 Form_pg_attribute attribute = (Form_pg_attribute) malloc(ATTRIBUTE_FIXED_PART_SIZE);
995 if (!PointerIsValid(attribute))
996 elog(FATAL, "out of memory");
997 MemSet(attribute, 0, ATTRIBUTE_FIXED_PART_SIZE);
1005 * Given a type name, produce the corresponding array type name by prepending
1006 * '_' and truncating as needed to fit in NAMEDATALEN-1 bytes. This is only
1007 * used in bootstrap mode, so we can get away with assuming that the input is
1008 * ASCII and we don't need multibyte-aware truncation.
1010 * The given string normally ends with '[]' or '[digits]'; we discard that.
1012 * The result is a palloc'd string.
1015 MapArrayTypeName(const char *s)
1019 char newStr[NAMEDATALEN];
1023 for (i = 0; i < NAMEDATALEN - 2 && s[i] != '['; i++, j++)
1028 return pstrdup(newStr);
1033 * index_register() -- record an index that has been set up for building
1036 * At bootstrap time, we define a bunch of indexes on system catalogs.
1037 * We postpone actually building the indexes until just before we're
1038 * finished with initialization, however. This is because the indexes
1039 * themselves have catalog entries, and those have to be included in the
1040 * indexes on those catalogs. Doing it in two phases is the simplest
1041 * way of making sure the indexes have the right contents at the end.
1044 index_register(Oid heap,
1046 IndexInfo *indexInfo)
1049 MemoryContext oldcxt;
1052 * XXX mao 10/31/92 -- don't gc index reldescs, associated info at
1053 * bootstrap time. we'll declare the indexes now, but want to create them
1058 nogc = AllocSetContextCreate(NULL,
1060 ALLOCSET_DEFAULT_MINSIZE,
1061 ALLOCSET_DEFAULT_INITSIZE,
1062 ALLOCSET_DEFAULT_MAXSIZE);
1064 oldcxt = MemoryContextSwitchTo(nogc);
1066 newind = (IndexList *) palloc(sizeof(IndexList));
1067 newind->il_heap = heap;
1068 newind->il_ind = ind;
1069 newind->il_info = (IndexInfo *) palloc(sizeof(IndexInfo));
1071 memcpy(newind->il_info, indexInfo, sizeof(IndexInfo));
1072 /* expressions will likely be null, but may as well copy it */
1073 newind->il_info->ii_Expressions = (List *)
1074 copyObject(indexInfo->ii_Expressions);
1075 newind->il_info->ii_ExpressionsState = NIL;
1076 /* predicate will likely be null, but may as well copy it */
1077 newind->il_info->ii_Predicate = (List *)
1078 copyObject(indexInfo->ii_Predicate);
1079 newind->il_info->ii_PredicateState = NIL;
1080 /* no exclusion constraints at bootstrap time, so no need to copy */
1081 Assert(indexInfo->ii_ExclusionOps == NULL);
1082 Assert(indexInfo->ii_ExclusionProcs == NULL);
1083 Assert(indexInfo->ii_ExclusionStrats == NULL);
1085 newind->il_next = ILHead;
1088 MemoryContextSwitchTo(oldcxt);
1093 * build_indices -- fill in all the indexes registered earlier
1098 for (; ILHead != NULL; ILHead = ILHead->il_next)
1103 /* need not bother with locks during bootstrap */
1104 heap = heap_open(ILHead->il_heap, NoLock);
1105 ind = index_open(ILHead->il_ind, NoLock);
1107 index_build(heap, ind, ILHead->il_info, false, false);
1109 index_close(ind, NoLock);
1110 heap_close(heap, NoLock);