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-2024, 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/genam.h"
21 #include "access/heapam.h"
22 #include "access/htup_details.h"
23 #include "access/tableam.h"
24 #include "access/toast_compression.h"
25 #include "access/xact.h"
26 #include "bootstrap/bootstrap.h"
27 #include "catalog/index.h"
28 #include "catalog/pg_collation.h"
29 #include "catalog/pg_type.h"
30 #include "common/link-canary.h"
31 #include "miscadmin.h"
32 #include "nodes/makefuncs.h"
33 #include "pg_getopt.h"
34 #include "storage/bufpage.h"
35 #include "storage/ipc.h"
36 #include "storage/proc.h"
37 #include "utils/builtins.h"
38 #include "utils/fmgroids.h"
39 #include "utils/guc.h"
40 #include "utils/memutils.h"
41 #include "utils/rel.h"
42 #include "utils/relmapper.h"
45 static void CheckerModeMain(void);
46 static void bootstrap_signals(void);
47 static Form_pg_attribute
AllocateAttribute(void);
48 static void populate_typ_list(void);
49 static Oid
gettype(char *type
);
50 static void cleanup(void);
57 Relation boot_reldesc
; /* current relation descriptor */
59 Form_pg_attribute attrtypes
[MAXATTR
]; /* points to attribute info */
60 int numattr
; /* number of attributes for cur. rel */
64 * Basic information associated with each type. This is used before
65 * pg_type is filled, so it has to cover the datatypes used as column types
66 * in the core "bootstrapped" catalogs.
68 * XXX several of these input/output functions do catalog scans
69 * (e.g., F_REGPROCIN scans pg_proc). this obviously creates some
70 * order dependencies in the catalog creation process.
74 char name
[NAMEDATALEN
];
86 static const struct typinfo TypInfo
[] = {
87 {"bool", BOOLOID
, 0, 1, true, TYPALIGN_CHAR
, TYPSTORAGE_PLAIN
, InvalidOid
,
89 {"bytea", BYTEAOID
, 0, -1, false, TYPALIGN_INT
, TYPSTORAGE_EXTENDED
, InvalidOid
,
90 F_BYTEAIN
, F_BYTEAOUT
},
91 {"char", CHAROID
, 0, 1, true, TYPALIGN_CHAR
, TYPSTORAGE_PLAIN
, InvalidOid
,
93 {"int2", INT2OID
, 0, 2, true, TYPALIGN_SHORT
, TYPSTORAGE_PLAIN
, InvalidOid
,
95 {"int4", INT4OID
, 0, 4, true, TYPALIGN_INT
, TYPSTORAGE_PLAIN
, InvalidOid
,
97 {"float4", FLOAT4OID
, 0, 4, true, TYPALIGN_INT
, TYPSTORAGE_PLAIN
, InvalidOid
,
98 F_FLOAT4IN
, F_FLOAT4OUT
},
99 {"name", NAMEOID
, CHAROID
, NAMEDATALEN
, false, TYPALIGN_CHAR
, TYPSTORAGE_PLAIN
, C_COLLATION_OID
,
100 F_NAMEIN
, F_NAMEOUT
},
101 {"regclass", REGCLASSOID
, 0, 4, true, TYPALIGN_INT
, TYPSTORAGE_PLAIN
, InvalidOid
,
102 F_REGCLASSIN
, F_REGCLASSOUT
},
103 {"regproc", REGPROCOID
, 0, 4, true, TYPALIGN_INT
, TYPSTORAGE_PLAIN
, InvalidOid
,
104 F_REGPROCIN
, F_REGPROCOUT
},
105 {"regtype", REGTYPEOID
, 0, 4, true, TYPALIGN_INT
, TYPSTORAGE_PLAIN
, InvalidOid
,
106 F_REGTYPEIN
, F_REGTYPEOUT
},
107 {"regrole", REGROLEOID
, 0, 4, true, TYPALIGN_INT
, TYPSTORAGE_PLAIN
, InvalidOid
,
108 F_REGROLEIN
, F_REGROLEOUT
},
109 {"regnamespace", REGNAMESPACEOID
, 0, 4, true, TYPALIGN_INT
, TYPSTORAGE_PLAIN
, InvalidOid
,
110 F_REGNAMESPACEIN
, F_REGNAMESPACEOUT
},
111 {"text", TEXTOID
, 0, -1, false, TYPALIGN_INT
, TYPSTORAGE_EXTENDED
, DEFAULT_COLLATION_OID
,
112 F_TEXTIN
, F_TEXTOUT
},
113 {"oid", OIDOID
, 0, 4, true, TYPALIGN_INT
, TYPSTORAGE_PLAIN
, InvalidOid
,
115 {"tid", TIDOID
, 0, 6, false, TYPALIGN_SHORT
, TYPSTORAGE_PLAIN
, InvalidOid
,
117 {"xid", XIDOID
, 0, 4, true, TYPALIGN_INT
, TYPSTORAGE_PLAIN
, InvalidOid
,
119 {"cid", CIDOID
, 0, 4, true, TYPALIGN_INT
, TYPSTORAGE_PLAIN
, InvalidOid
,
121 {"pg_node_tree", PG_NODE_TREEOID
, 0, -1, false, TYPALIGN_INT
, TYPSTORAGE_EXTENDED
, DEFAULT_COLLATION_OID
,
122 F_PG_NODE_TREE_IN
, F_PG_NODE_TREE_OUT
},
123 {"int2vector", INT2VECTOROID
, INT2OID
, -1, false, TYPALIGN_INT
, TYPSTORAGE_PLAIN
, InvalidOid
,
124 F_INT2VECTORIN
, F_INT2VECTOROUT
},
125 {"oidvector", OIDVECTOROID
, OIDOID
, -1, false, TYPALIGN_INT
, TYPSTORAGE_PLAIN
, InvalidOid
,
126 F_OIDVECTORIN
, F_OIDVECTOROUT
},
127 {"_int4", INT4ARRAYOID
, INT4OID
, -1, false, TYPALIGN_INT
, TYPSTORAGE_EXTENDED
, InvalidOid
,
128 F_ARRAY_IN
, F_ARRAY_OUT
},
129 {"_text", 1009, TEXTOID
, -1, false, TYPALIGN_INT
, TYPSTORAGE_EXTENDED
, DEFAULT_COLLATION_OID
,
130 F_ARRAY_IN
, F_ARRAY_OUT
},
131 {"_oid", 1028, OIDOID
, -1, false, TYPALIGN_INT
, TYPSTORAGE_EXTENDED
, InvalidOid
,
132 F_ARRAY_IN
, F_ARRAY_OUT
},
133 {"_char", 1002, CHAROID
, -1, false, TYPALIGN_INT
, TYPSTORAGE_EXTENDED
, InvalidOid
,
134 F_ARRAY_IN
, F_ARRAY_OUT
},
135 {"_aclitem", 1034, ACLITEMOID
, -1, false, TYPALIGN_INT
, TYPSTORAGE_EXTENDED
, InvalidOid
,
136 F_ARRAY_IN
, F_ARRAY_OUT
}
139 static const int n_types
= sizeof(TypInfo
) / sizeof(struct typinfo
);
144 FormData_pg_type am_typ
;
147 static List
*Typ
= NIL
; /* List of struct typmap* */
148 static struct typmap
*Ap
= NULL
;
150 static Datum values
[MAXATTR
]; /* current row's attribute values */
151 static bool Nulls
[MAXATTR
];
153 static MemoryContext nogc
= NULL
; /* special no-gc mem context */
156 * At bootstrap time, we first declare all the indices to be built, and
157 * then build them. The IndexList structure stores enough information
158 * to allow us to build the indices after they've been declared.
161 typedef struct _IndexList
166 struct _IndexList
*il_next
;
169 static IndexList
*ILHead
= NULL
;
173 * In shared memory checker mode, all we really want to do is create shared
174 * memory and semaphores (just to prove we can do it with the current GUC
175 * settings). Since, in fact, that was already done by
176 * CreateSharedMemoryAndSemaphores(), we have nothing more to do here.
179 CheckerModeMain(void)
185 * The main entry point for running the backend in bootstrap mode
187 * The bootstrap mode is used to initialize the template database.
188 * The bootstrap backend doesn't speak SQL, but instead expects
189 * commands in a special bootstrap language.
191 * When check_only is true, startup is done only far enough to verify that
192 * the current configuration, particularly the passed in options pertaining
193 * to shared memory sizing, options work (or at least do not cause an error
194 * up to shared memory creation).
197 BootstrapModeMain(int argc
, char *argv
[], bool check_only
)
200 char *progname
= argv
[0];
202 char *userDoption
= NULL
;
203 uint32 bootstrap_data_checksum_version
= 0; /* No checksum */
205 Assert(!IsUnderPostmaster
);
207 InitStandaloneProcess(argv
[0]);
209 /* Set defaults, to be overridden by explicit options below */
210 InitializeGUCOptions();
212 /* an initial --boot or --check should be present */
214 && (strcmp(argv
[1], "--boot") == 0
215 || strcmp(argv
[1], "--check") == 0));
219 while ((flag
= getopt(argc
, argv
, "B:c:d:D:Fkr:X:-:")) != -1)
224 SetConfigOption("shared_buffers", optarg
, PGC_POSTMASTER
, PGC_S_ARGV
);
232 ParseLongOption(optarg
, &name
, &value
);
237 (errcode(ERRCODE_SYNTAX_ERROR
),
238 errmsg("--%s requires a value",
242 (errcode(ERRCODE_SYNTAX_ERROR
),
243 errmsg("-c %s requires a value",
247 SetConfigOption(name
, value
, PGC_POSTMASTER
, PGC_S_ARGV
);
253 userDoption
= pstrdup(optarg
);
257 /* Turn on debugging for the bootstrap process. */
260 debugstr
= psprintf("debug%s", optarg
);
261 SetConfigOption("log_min_messages", debugstr
,
262 PGC_POSTMASTER
, PGC_S_ARGV
);
263 SetConfigOption("client_min_messages", debugstr
,
264 PGC_POSTMASTER
, PGC_S_ARGV
);
269 SetConfigOption("fsync", "false", PGC_POSTMASTER
, PGC_S_ARGV
);
272 bootstrap_data_checksum_version
= PG_DATA_CHECKSUM_VERSION
;
275 strlcpy(OutputFileName
, optarg
, MAXPGPATH
);
278 SetConfigOption("wal_segment_size", optarg
, PGC_INTERNAL
, PGC_S_DYNAMIC_DEFAULT
);
281 write_stderr("Try \"%s --help\" for more information.\n",
290 write_stderr("%s: invalid command-line arguments\n", progname
);
294 /* Acquire configuration parameters */
295 if (!SelectConfigFiles(userDoption
, progname
))
299 * Validate we have been given a reasonable-looking DataDir and change
305 CreateDataDirLockFile(false);
307 SetProcessingMode(BootstrapProcessing
);
308 IgnoreSystemIndexes
= true;
310 InitializeMaxBackends();
312 InitializeFastPathLocks();
314 CreateSharedMemoryAndSemaphores();
317 * XXX: It might make sense to move this into its own function at some
318 * point. Right now it seems like it'd cause more code duplication than
323 SetProcessingMode(NormalProcessing
);
329 * Do backend-like initialization for bootstrap mode
336 BootStrapXLOG(bootstrap_data_checksum_version
);
339 * To ensure that src/common/link-canary.c is linked into the backend, we
340 * must call it from somewhere. Here is as good as anywhere.
342 if (pg_link_canary_is_frontend())
343 elog(ERROR
, "backend is incorrectly linked to frontend functions");
345 InitPostgres(NULL
, InvalidOid
, NULL
, InvalidOid
, 0, NULL
);
347 /* Initialize stuff for bootstrap-file processing */
348 for (i
= 0; i
< MAXATTR
; i
++)
355 * Process bootstrap input.
357 StartTransactionCommand();
359 CommitTransactionCommand();
362 * We should now know about all mapped relations, so it's okay to write
363 * out the initial relation mapping files.
365 RelationMapFinishBootstrap();
367 /* Clean up and exit */
373 /* ----------------------------------------------------------------
375 * ----------------------------------------------------------------
379 * Set up signal handling for a bootstrap process
382 bootstrap_signals(void)
384 Assert(!IsUnderPostmaster
);
387 * We don't actually need any non-default signal handling in bootstrap
388 * mode; "curl up and die" is a sufficient response for all these cases.
389 * Let's set that handling explicitly, as documentation if nothing else.
391 pqsignal(SIGHUP
, SIG_DFL
);
392 pqsignal(SIGINT
, SIG_DFL
);
393 pqsignal(SIGTERM
, SIG_DFL
);
394 pqsignal(SIGQUIT
, SIG_DFL
);
397 /* ----------------------------------------------------------------
398 * MANUAL BACKEND INTERACTIVE INTERFACE COMMANDS
399 * ----------------------------------------------------------------
405 * Execute BKI OPEN command.
409 boot_openrel(char *relname
)
413 if (strlen(relname
) >= NAMEDATALEN
)
414 relname
[NAMEDATALEN
- 1] = '\0';
417 * pg_type must be filled before any OPEN command is executed, hence we
418 * can now populate Typ if we haven't yet.
423 if (boot_reldesc
!= NULL
)
426 elog(DEBUG4
, "open relation %s, attrsize %d",
427 relname
, (int) ATTRIBUTE_FIXED_PART_SIZE
);
429 boot_reldesc
= table_openrv(makeRangeVar(NULL
, relname
, -1), NoLock
);
430 numattr
= RelationGetNumberOfAttributes(boot_reldesc
);
431 for (i
= 0; i
< numattr
; i
++)
433 if (attrtypes
[i
] == NULL
)
434 attrtypes
[i
] = AllocateAttribute();
435 memmove((char *) attrtypes
[i
],
436 (char *) TupleDescAttr(boot_reldesc
->rd_att
, i
),
437 ATTRIBUTE_FIXED_PART_SIZE
);
440 Form_pg_attribute at
= attrtypes
[i
];
442 elog(DEBUG4
, "create attribute %d name %s len %d num %d type %u",
443 i
, NameStr(at
->attname
), at
->attlen
, at
->attnum
,
454 closerel(char *relname
)
460 if (strcmp(RelationGetRelationName(boot_reldesc
), relname
) != 0)
461 elog(ERROR
, "close of %s when %s was expected",
462 relname
, RelationGetRelationName(boot_reldesc
));
465 elog(ERROR
, "close of %s before any relation was opened",
469 if (boot_reldesc
== NULL
)
470 elog(ERROR
, "no open relation to close");
473 elog(DEBUG4
, "close relation %s",
474 RelationGetRelationName(boot_reldesc
));
475 table_close(boot_reldesc
, NoLock
);
485 * define a <field,type> pair
486 * if there are n fields in a relation to be created, this routine
487 * will be called n times
491 DefineAttr(char *name
, char *type
, int attnum
, int nullness
)
495 if (boot_reldesc
!= NULL
)
497 elog(WARNING
, "no open relations allowed with CREATE command");
501 if (attrtypes
[attnum
] == NULL
)
502 attrtypes
[attnum
] = AllocateAttribute();
503 MemSet(attrtypes
[attnum
], 0, ATTRIBUTE_FIXED_PART_SIZE
);
505 namestrcpy(&attrtypes
[attnum
]->attname
, name
);
506 elog(DEBUG4
, "column %s %s", NameStr(attrtypes
[attnum
]->attname
), type
);
507 attrtypes
[attnum
]->attnum
= attnum
+ 1;
509 typeoid
= gettype(type
);
513 attrtypes
[attnum
]->atttypid
= Ap
->am_oid
;
514 attrtypes
[attnum
]->attlen
= Ap
->am_typ
.typlen
;
515 attrtypes
[attnum
]->attbyval
= Ap
->am_typ
.typbyval
;
516 attrtypes
[attnum
]->attalign
= Ap
->am_typ
.typalign
;
517 attrtypes
[attnum
]->attstorage
= Ap
->am_typ
.typstorage
;
518 attrtypes
[attnum
]->attcompression
= InvalidCompressionMethod
;
519 attrtypes
[attnum
]->attcollation
= Ap
->am_typ
.typcollation
;
520 /* if an array type, assume 1-dimensional attribute */
521 if (Ap
->am_typ
.typelem
!= InvalidOid
&& Ap
->am_typ
.typlen
< 0)
522 attrtypes
[attnum
]->attndims
= 1;
524 attrtypes
[attnum
]->attndims
= 0;
528 attrtypes
[attnum
]->atttypid
= TypInfo
[typeoid
].oid
;
529 attrtypes
[attnum
]->attlen
= TypInfo
[typeoid
].len
;
530 attrtypes
[attnum
]->attbyval
= TypInfo
[typeoid
].byval
;
531 attrtypes
[attnum
]->attalign
= TypInfo
[typeoid
].align
;
532 attrtypes
[attnum
]->attstorage
= TypInfo
[typeoid
].storage
;
533 attrtypes
[attnum
]->attcompression
= InvalidCompressionMethod
;
534 attrtypes
[attnum
]->attcollation
= TypInfo
[typeoid
].collation
;
535 /* if an array type, assume 1-dimensional attribute */
536 if (TypInfo
[typeoid
].elem
!= InvalidOid
&&
537 attrtypes
[attnum
]->attlen
< 0)
538 attrtypes
[attnum
]->attndims
= 1;
540 attrtypes
[attnum
]->attndims
= 0;
544 * If a system catalog column is collation-aware, force it to use C
545 * collation, so that its behavior is independent of the database's
546 * collation. This is essential to allow template0 to be cloned with a
547 * different database collation.
549 if (OidIsValid(attrtypes
[attnum
]->attcollation
))
550 attrtypes
[attnum
]->attcollation
= C_COLLATION_OID
;
552 attrtypes
[attnum
]->attcacheoff
= -1;
553 attrtypes
[attnum
]->atttypmod
= -1;
554 attrtypes
[attnum
]->attislocal
= true;
556 if (nullness
== BOOTCOL_NULL_FORCE_NOT_NULL
)
558 attrtypes
[attnum
]->attnotnull
= true;
560 else if (nullness
== BOOTCOL_NULL_FORCE_NULL
)
562 attrtypes
[attnum
]->attnotnull
= false;
566 Assert(nullness
== BOOTCOL_NULL_AUTO
);
569 * Mark as "not null" if type is fixed-width and prior columns are
570 * likewise fixed-width and not-null. This corresponds to case where
571 * column can be accessed directly via C struct declaration.
573 if (attrtypes
[attnum
]->attlen
> 0)
577 /* check earlier attributes */
578 for (i
= 0; i
< attnum
; i
++)
580 if (attrtypes
[i
]->attlen
<= 0 ||
581 !attrtypes
[i
]->attnotnull
)
585 attrtypes
[attnum
]->attnotnull
= true;
594 * If objectid is not zero, it is a specific OID to assign to the tuple.
595 * Otherwise, an OID will be assigned (if necessary) by heap_insert.
605 elog(DEBUG4
, "inserting row with %d columns", numattr
);
607 tupDesc
= CreateTupleDesc(numattr
, attrtypes
);
608 tuple
= heap_form_tuple(tupDesc
, values
, Nulls
);
609 pfree(tupDesc
); /* just free's tupDesc, not the attrtypes */
611 simple_heap_insert(boot_reldesc
, tuple
);
612 heap_freetuple(tuple
);
613 elog(DEBUG4
, "row inserted");
616 * Reset null markers for next tuple
618 for (i
= 0; i
< numattr
; i
++)
627 InsertOneValue(char *value
, int i
)
638 Assert(i
>= 0 && i
< MAXATTR
);
640 elog(DEBUG4
, "inserting column %d value \"%s\"", i
, value
);
642 typoid
= TupleDescAttr(boot_reldesc
->rd_att
, i
)->atttypid
;
644 boot_get_type_io_data(typoid
,
645 &typlen
, &typbyval
, &typalign
,
646 &typdelim
, &typioparam
,
647 &typinput
, &typoutput
);
649 values
[i
] = OidInputFunctionCall(typinput
, value
, typioparam
, -1);
652 * We use ereport not elog here so that parameters aren't evaluated unless
653 * the message is going to be printed, which generally it isn't
656 (errmsg_internal("inserted -> %s",
657 OidOutputFunctionCall(typoutput
, values
[i
]))));
667 elog(DEBUG4
, "inserting column %d NULL", i
);
668 Assert(i
>= 0 && i
< MAXATTR
);
669 if (TupleDescAttr(boot_reldesc
->rd_att
, i
)->attnotnull
)
671 "NULL value specified for not-null column \"%s\" of relation \"%s\"",
672 NameStr(TupleDescAttr(boot_reldesc
->rd_att
, i
)->attname
),
673 RelationGetRelationName(boot_reldesc
));
674 values
[i
] = PointerGetDatum(NULL
);
685 if (boot_reldesc
!= NULL
)
692 * Load the Typ list by reading pg_type.
696 populate_typ_list(void)
705 rel
= table_open(TypeRelationId
, NoLock
);
706 scan
= table_beginscan_catalog(rel
, 0, NULL
);
707 old
= MemoryContextSwitchTo(TopMemoryContext
);
708 while ((tup
= heap_getnext(scan
, ForwardScanDirection
)) != NULL
)
710 Form_pg_type typForm
= (Form_pg_type
) GETSTRUCT(tup
);
711 struct typmap
*newtyp
;
713 newtyp
= (struct typmap
*) palloc(sizeof(struct typmap
));
714 Typ
= lappend(Typ
, newtyp
);
716 newtyp
->am_oid
= typForm
->oid
;
717 memcpy(&newtyp
->am_typ
, typForm
, sizeof(newtyp
->am_typ
));
719 MemoryContextSwitchTo(old
);
721 table_close(rel
, NoLock
);
727 * NB: this is really ugly; it will return an integer index into TypInfo[],
728 * and not an OID at all, until the first reference to a type not known in
729 * TypInfo[]. At that point it will read and cache pg_type in Typ,
730 * and subsequently return a real OID (and set the global pointer Ap to
731 * point at the found row in Typ). So caller must check whether Typ is
732 * still NIL to determine what the return value is!
744 struct typmap
*app
= lfirst(lc
);
746 if (strncmp(NameStr(app
->am_typ
.typname
), type
, NAMEDATALEN
) == 0)
754 * The type wasn't known; reload the pg_type contents and check again
755 * to handle composite types, added since last populating the list.
763 * Calling gettype would result in infinite recursion for types
764 * missing in pg_type, so just repeat the lookup.
768 struct typmap
*app
= lfirst(lc
);
770 if (strncmp(NameStr(app
->am_typ
.typname
), type
, NAMEDATALEN
) == 0)
781 for (i
= 0; i
< n_types
; i
++)
783 if (strncmp(type
, TypInfo
[i
].name
, NAMEDATALEN
) == 0)
786 /* Not in TypInfo, so we'd better be able to read pg_type now */
787 elog(DEBUG4
, "external type: %s", type
);
789 return gettype(type
);
791 elog(ERROR
, "unrecognized type \"%s\"", type
);
792 /* not reached, here to make compiler happy */
797 * boot_get_type_io_data
799 * Obtain type I/O information at bootstrap time. This intentionally has
800 * almost the same API as lsyscache.c's get_type_io_data, except that
801 * we only support obtaining the typinput and typoutput routines, not
802 * the binary I/O routines. It is exported so that array_in and array_out
803 * can be made to work during early bootstrap.
807 boot_get_type_io_data(Oid typid
,
818 /* We have the boot-time contents of pg_type, so use it */
819 struct typmap
*ap
= NULL
;
825 if (ap
->am_oid
== typid
)
829 if (!ap
|| ap
->am_oid
!= typid
)
830 elog(ERROR
, "type OID %u not found in Typ list", typid
);
832 *typlen
= ap
->am_typ
.typlen
;
833 *typbyval
= ap
->am_typ
.typbyval
;
834 *typalign
= ap
->am_typ
.typalign
;
835 *typdelim
= ap
->am_typ
.typdelim
;
837 /* XXX this logic must match getTypeIOParam() */
838 if (OidIsValid(ap
->am_typ
.typelem
))
839 *typioparam
= ap
->am_typ
.typelem
;
843 *typinput
= ap
->am_typ
.typinput
;
844 *typoutput
= ap
->am_typ
.typoutput
;
848 /* We don't have pg_type yet, so use the hard-wired TypInfo array */
851 for (typeindex
= 0; typeindex
< n_types
; typeindex
++)
853 if (TypInfo
[typeindex
].oid
== typid
)
856 if (typeindex
>= n_types
)
857 elog(ERROR
, "type OID %u not found in TypInfo", typid
);
859 *typlen
= TypInfo
[typeindex
].len
;
860 *typbyval
= TypInfo
[typeindex
].byval
;
861 *typalign
= TypInfo
[typeindex
].align
;
862 /* We assume typdelim is ',' for all boot-time types */
865 /* XXX this logic must match getTypeIOParam() */
866 if (OidIsValid(TypInfo
[typeindex
].elem
))
867 *typioparam
= TypInfo
[typeindex
].elem
;
871 *typinput
= TypInfo
[typeindex
].inproc
;
872 *typoutput
= TypInfo
[typeindex
].outproc
;
879 * Note: bootstrap never sets any per-column ACLs, so we only need
880 * ATTRIBUTE_FIXED_PART_SIZE space per attribute.
883 static Form_pg_attribute
884 AllocateAttribute(void)
886 return (Form_pg_attribute
)
887 MemoryContextAllocZero(TopMemoryContext
, ATTRIBUTE_FIXED_PART_SIZE
);
891 * index_register() -- record an index that has been set up for building
894 * At bootstrap time, we define a bunch of indexes on system catalogs.
895 * We postpone actually building the indexes until just before we're
896 * finished with initialization, however. This is because the indexes
897 * themselves have catalog entries, and those have to be included in the
898 * indexes on those catalogs. Doing it in two phases is the simplest
899 * way of making sure the indexes have the right contents at the end.
902 index_register(Oid heap
,
904 const IndexInfo
*indexInfo
)
907 MemoryContext oldcxt
;
910 * XXX mao 10/31/92 -- don't gc index reldescs, associated info at
911 * bootstrap time. we'll declare the indexes now, but want to create them
916 nogc
= AllocSetContextCreate(NULL
,
918 ALLOCSET_DEFAULT_SIZES
);
920 oldcxt
= MemoryContextSwitchTo(nogc
);
922 newind
= (IndexList
*) palloc(sizeof(IndexList
));
923 newind
->il_heap
= heap
;
924 newind
->il_ind
= ind
;
925 newind
->il_info
= (IndexInfo
*) palloc(sizeof(IndexInfo
));
927 memcpy(newind
->il_info
, indexInfo
, sizeof(IndexInfo
));
928 /* expressions will likely be null, but may as well copy it */
929 newind
->il_info
->ii_Expressions
=
930 copyObject(indexInfo
->ii_Expressions
);
931 newind
->il_info
->ii_ExpressionsState
= NIL
;
932 /* predicate will likely be null, but may as well copy it */
933 newind
->il_info
->ii_Predicate
=
934 copyObject(indexInfo
->ii_Predicate
);
935 newind
->il_info
->ii_PredicateState
= NULL
;
936 /* no exclusion constraints at bootstrap time, so no need to copy */
937 Assert(indexInfo
->ii_ExclusionOps
== NULL
);
938 Assert(indexInfo
->ii_ExclusionProcs
== NULL
);
939 Assert(indexInfo
->ii_ExclusionStrats
== NULL
);
941 newind
->il_next
= ILHead
;
944 MemoryContextSwitchTo(oldcxt
);
949 * build_indices -- fill in all the indexes registered earlier
954 for (; ILHead
!= NULL
; ILHead
= ILHead
->il_next
)
959 /* need not bother with locks during bootstrap */
960 heap
= table_open(ILHead
->il_heap
, NoLock
);
961 ind
= index_open(ILHead
->il_ind
, NoLock
);
963 index_build(heap
, ind
, ILHead
->il_info
, false, false);
965 index_close(ind
, NoLock
);
966 table_close(heap
, NoLock
);