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-2025, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
11 * src/backend/bootstrap/bootstrap.c
13 *-------------------------------------------------------------------------
39#include "utils/fmgroids.h"
61 int numattr;
/* number of attributes for cur. rel */
65 * Basic information associated with each type. This is used before
66 * pg_type is filled, so it has to cover the datatypes used as column types
67 * in the core "bootstrapped" catalogs.
69 * XXX several of these input/output functions do catalog scans
70 * (e.g., F_REGPROCIN scans pg_proc). this obviously creates some
71 * order dependencies in the catalog creation process.
88 {
"bool", BOOLOID, 0, 1,
true, TYPALIGN_CHAR, TYPSTORAGE_PLAIN,
InvalidOid,
90 {
"bytea", BYTEAOID, 0, -1,
false, TYPALIGN_INT, TYPSTORAGE_EXTENDED,
InvalidOid,
91 F_BYTEAIN, F_BYTEAOUT},
92 {
"char", CHAROID, 0, 1,
true, TYPALIGN_CHAR, TYPSTORAGE_PLAIN,
InvalidOid,
94 {
"int2", INT2OID, 0, 2,
true, TYPALIGN_SHORT, TYPSTORAGE_PLAIN,
InvalidOid,
96 {
"int4", INT4OID, 0, 4,
true, TYPALIGN_INT, TYPSTORAGE_PLAIN,
InvalidOid,
98 {
"float4", FLOAT4OID, 0, 4,
true, TYPALIGN_INT, TYPSTORAGE_PLAIN,
InvalidOid,
99 F_FLOAT4IN, F_FLOAT4OUT},
100 {
"name", NAMEOID, CHAROID,
NAMEDATALEN,
false, TYPALIGN_CHAR, TYPSTORAGE_PLAIN, C_COLLATION_OID,
101 F_NAMEIN, F_NAMEOUT},
102 {
"regclass", REGCLASSOID, 0, 4,
true, TYPALIGN_INT, TYPSTORAGE_PLAIN,
InvalidOid,
103 F_REGCLASSIN, F_REGCLASSOUT},
104 {
"regproc", REGPROCOID, 0, 4,
true, TYPALIGN_INT, TYPSTORAGE_PLAIN,
InvalidOid,
105 F_REGPROCIN, F_REGPROCOUT},
106 {
"regtype", REGTYPEOID, 0, 4,
true, TYPALIGN_INT, TYPSTORAGE_PLAIN,
InvalidOid,
107 F_REGTYPEIN, F_REGTYPEOUT},
108 {
"regrole", REGROLEOID, 0, 4,
true, TYPALIGN_INT, TYPSTORAGE_PLAIN,
InvalidOid,
109 F_REGROLEIN, F_REGROLEOUT},
110 {
"regnamespace", REGNAMESPACEOID, 0, 4,
true, TYPALIGN_INT, TYPSTORAGE_PLAIN,
InvalidOid,
111 F_REGNAMESPACEIN, F_REGNAMESPACEOUT},
112 {
"regdatabase", REGDATABASEOID, 0, 4,
true, TYPALIGN_INT, TYPSTORAGE_PLAIN,
InvalidOid,
113 F_REGDATABASEIN, F_REGDATABASEOUT},
114 {
"text", TEXTOID, 0, -1,
false, TYPALIGN_INT, TYPSTORAGE_EXTENDED, DEFAULT_COLLATION_OID,
115 F_TEXTIN, F_TEXTOUT},
116 {
"oid", OIDOID, 0, 4,
true, TYPALIGN_INT, TYPSTORAGE_PLAIN,
InvalidOid,
118 {
"tid", TIDOID, 0, 6,
false, TYPALIGN_SHORT, TYPSTORAGE_PLAIN,
InvalidOid,
120 {
"xid", XIDOID, 0, 4,
true, TYPALIGN_INT, TYPSTORAGE_PLAIN,
InvalidOid,
122 {
"cid", CIDOID, 0, 4,
true, TYPALIGN_INT, TYPSTORAGE_PLAIN,
InvalidOid,
124 {
"pg_node_tree", PG_NODE_TREEOID, 0, -1,
false, TYPALIGN_INT, TYPSTORAGE_EXTENDED, DEFAULT_COLLATION_OID,
125 F_PG_NODE_TREE_IN, F_PG_NODE_TREE_OUT},
126 {
"int2vector", INT2VECTOROID, INT2OID, -1,
false, TYPALIGN_INT, TYPSTORAGE_PLAIN,
InvalidOid,
127 F_INT2VECTORIN, F_INT2VECTOROUT},
128 {
"oidvector", OIDVECTOROID, OIDOID, -1,
false, TYPALIGN_INT, TYPSTORAGE_PLAIN,
InvalidOid,
129 F_OIDVECTORIN, F_OIDVECTOROUT},
130 {
"_int4", INT4ARRAYOID, INT4OID, -1,
false, TYPALIGN_INT, TYPSTORAGE_EXTENDED,
InvalidOid,
131 F_ARRAY_IN, F_ARRAY_OUT},
132 {
"_text", 1009, TEXTOID, -1,
false, TYPALIGN_INT, TYPSTORAGE_EXTENDED, DEFAULT_COLLATION_OID,
133 F_ARRAY_IN, F_ARRAY_OUT},
134 {
"_oid", 1028, OIDOID, -1,
false, TYPALIGN_INT, TYPSTORAGE_EXTENDED,
InvalidOid,
135 F_ARRAY_IN, F_ARRAY_OUT},
136 {
"_char", 1002, CHAROID, -1,
false, TYPALIGN_INT, TYPSTORAGE_EXTENDED,
InvalidOid,
137 F_ARRAY_IN, F_ARRAY_OUT},
138 {
"_aclitem", 1034, ACLITEMOID, -1,
false, TYPALIGN_INT, TYPSTORAGE_EXTENDED,
InvalidOid,
139 F_ARRAY_IN, F_ARRAY_OUT}
159 * At bootstrap time, we first declare all the indices to be built, and
160 * then build them. The IndexList structure stores enough information
161 * to allow us to build the indices after they've been declared.
176 * In shared memory checker mode, all we really want to do is create shared
177 * memory and semaphores (just to prove we can do it with the current GUC
178 * settings). Since, in fact, that was already done by
179 * CreateSharedMemoryAndSemaphores(), we have nothing more to do here.
188 * The main entry point for running the backend in bootstrap mode
190 * The bootstrap mode is used to initialize the template database.
191 * The bootstrap backend doesn't speak SQL, but instead expects
192 * commands in a special bootstrap language.
194 * When check_only is true, startup is done only far enough to verify that
195 * the current configuration, particularly the passed in options pertaining
196 * to shared memory sizing, options work (or at least do not cause an error
197 * up to shared memory creation).
206 uint32 bootstrap_data_checksum_version = 0;
/* No checksum */
213 /* Set defaults, to be overridden by explicit options below */
216 /* an initial --boot or --check should be present */
218 && (strcmp(argv[1],
"--boot") == 0
219 || strcmp(argv[1],
"--check") == 0));
223 while ((
flag =
getopt(argc, argv,
"B:c:d:D:Fkr:X:-:")) != -1)
233 * Error if the user misplaced a special must-be-first option
234 * for dispatching to a subprogram. parse_dispatch_option()
235 * returns DISPATCH_POSTMASTER if it doesn't find a match, so
236 * error for anything else.
240 (
errcode(ERRCODE_SYNTAX_ERROR),
254 (
errcode(ERRCODE_SYNTAX_ERROR),
255 errmsg(
"--%s requires a value",
259 (
errcode(ERRCODE_SYNTAX_ERROR),
260 errmsg(
"-c %s requires a value",
274 /* Turn on debugging for the bootstrap process. */
298 write_stderr(
"Try \"%s --help\" for more information.\n",
311 /* Acquire configuration parameters */
316 * Validate we have been given a reasonable-looking DataDir and change
330 * Even though bootstrapping runs in single-process mode, initialize
331 * postmaster child slots array so that --check can detect running out of
332 * shared memory or other resources if max_connections is set too high.
341 * Estimate number of openable files. This is essential too in --check
342 * mode, because on some platforms semaphores count as open files.
347 * XXX: It might make sense to move this into its own function at some
348 * point. Right now it seems like it'd cause more code duplication than
359 * Do backend-like initialization for bootstrap mode
369 * To ensure that src/common/link-canary.c is linked into the backend, we
370 * must call it from somewhere. Here is as good as anywhere.
373 elog(
ERROR,
"backend is incorrectly linked to frontend functions");
377 /* Initialize stuff for bootstrap-file processing */
388 * Process bootstrap input.
395 * We should now know about all mapped relations, so it's okay to write
396 * out the initial relation mapping files.
400 /* Clean up and exit */
406/* ----------------------------------------------------------------
408 * ----------------------------------------------------------------
412 * Set up signal handling for a bootstrap process
420 * We don't actually need any non-default signal handling in bootstrap
421 * mode; "curl up and die" is a sufficient response for all these cases.
422 * Let's set that handling explicitly, as documentation if nothing else.
430/* ----------------------------------------------------------------
431 * MANUAL BACKEND INTERACTIVE INTERFACE COMMANDS
432 * ----------------------------------------------------------------
438 * Execute BKI OPEN command.
450 * pg_type must be filled before any OPEN command is executed, hence we
451 * can now populate Typ if we haven't yet.
475 elog(
DEBUG4,
"create attribute %d name %s len %d num %d type %u",
476 i,
NameStr(at->attname), at->attlen, at->attnum,
494 elog(
ERROR,
"close of %s when %s was expected",
498 elog(
ERROR,
"close of %s before any relation was opened",
503 elog(
ERROR,
"no open relation to close");
518 * define a <field,type> pair
519 * if there are n fields in a relation to be created, this routine
520 * will be called n times
530 elog(
WARNING,
"no open relations allowed with CREATE command");
553 /* if an array type, assume 1-dimensional attribute */
568 /* if an array type, assume 1-dimensional attribute */
577 * If a system catalog column is collation-aware, force it to use C
578 * collation, so that its behavior is independent of the database's
579 * collation. This is essential to allow template0 to be cloned with a
580 * different database collation.
601 * Mark as "not null" if type is fixed-width and prior columns are
602 * likewise fixed-width and not-null. This corresponds to case where
603 * column can be accessed directly via C struct declaration.
609 /* check earlier attributes */
626 * If objectid is not zero, it is a specific OID to assign to the tuple.
627 * Otherwise, an OID will be assigned (if necessary) by heap_insert.
641 pfree(tupDesc);
/* just free's tupDesc, not the attrtypes */
648 * Reset null markers for next tuple
678 &typdelim, &typioparam,
679 &typinput, &typoutput);
684 * We use ereport not elog here so that parameters aren't evaluated unless
685 * the message is going to be printed, which generally it isn't
703 "NULL value specified for not-null column \"%s\" of relation \"%s\"",
724 * Load the Typ list by reading pg_type.
748 newtyp->
am_oid = typForm->oid;
749 memcpy(&newtyp->
am_typ, typForm,
sizeof(newtyp->
am_typ));
759 * NB: this is really ugly; it will return an integer index into TypInfo[],
760 * and not an OID at all, until the first reference to a type not known in
761 * TypInfo[]. At that point it will read and cache pg_type in Typ,
762 * and subsequently return a real OID (and set the global pointer Ap to
763 * point at the found row in Typ). So caller must check whether Typ is
764 * still NIL to determine what the return value is!
786 * The type wasn't known; reload the pg_type contents and check again
787 * to handle composite types, added since last populating the list.
795 * Calling gettype would result in infinite recursion for types
796 * missing in pg_type, so just repeat the lookup.
818 /* Not in TypInfo, so we'd better be able to read pg_type now */
824 /* not reached, here to make compiler happy */
829 * boot_get_type_io_data
831 * Obtain type I/O information at bootstrap time. This intentionally has
832 * almost the same API as lsyscache.c's get_type_io_data, except that
833 * we only support obtaining the typinput and typoutput routines, not
834 * the binary I/O routines. It is exported so that array_in and array_out
835 * can be made to work during early bootstrap.
850 /* We have the boot-time contents of pg_type, so use it */
861 if (!ap || ap->
am_oid != typid)
862 elog(
ERROR,
"type OID %u not found in Typ list", typid);
864 *typlen = ap->
am_typ.typlen;
865 *typbyval = ap->
am_typ.typbyval;
867 *typdelim = ap->
am_typ.typdelim;
869 /* XXX this logic must match getTypeIOParam() */
871 *typioparam = ap->
am_typ.typelem;
875 *typinput = ap->
am_typ.typinput;
876 *typoutput = ap->
am_typ.typoutput;
880 /* We don't have pg_type yet, so use the hard-wired TypInfo array */
883 for (typeindex = 0; typeindex <
n_types; typeindex++)
885 if (
TypInfo[typeindex].oid == typid)
889 elog(
ERROR,
"type OID %u not found in TypInfo", typid);
894 /* We assume typdelim is ',' for all boot-time types */
897 /* XXX this logic must match getTypeIOParam() */
911 * Note: bootstrap never sets any per-column ACLs, so we only need
912 * ATTRIBUTE_FIXED_PART_SIZE space per attribute.
923 * index_register() -- record an index that has been set up for building
926 * At bootstrap time, we define a bunch of indexes on system catalogs.
927 * We postpone actually building the indexes until just before we're
928 * finished with initialization, however. This is because the indexes
929 * themselves have catalog entries, and those have to be included in the
930 * indexes on those catalogs. Doing it in two phases is the simplest
931 * way of making sure the indexes have the right contents at the end.
942 * XXX mao 10/31/92 -- don't gc index reldescs, associated info at
943 * bootstrap time. we'll declare the indexes now, but want to create them
960 /* expressions will likely be null, but may as well copy it */
964 /* predicate will likely be null, but may as well copy it */
968 /* no exclusion constraints at bootstrap time, so no need to copy */
981 * build_indices -- fill in all the indexes registered earlier
991 /* need not bother with locks during bootstrap */
#define write_stderr(str)
static Oid gettype(char *type)
static Datum values[MAXATTR]
void closerel(char *relname)
static void populate_typ_list(void)
static void CheckerModeMain(void)
void InsertOneValue(char *value, int i)
static void cleanup(void)
void InsertOneNull(int i)
static const struct typinfo TypInfo[]
static struct typmap * Ap
void InsertOneTuple(void)
struct _IndexList IndexList
static void bootstrap_signals(void)
Form_pg_attribute attrtypes[MAXATTR]
void boot_get_type_io_data(Oid typid, int16 *typlen, bool *typbyval, char *typalign, char *typdelim, Oid *typioparam, Oid *typinput, Oid *typoutput)
static Form_pg_attribute AllocateAttribute(void)
static MemoryContext nogc
void BootstrapModeMain(int argc, char *argv[], bool check_only)
void DefineAttr(char *name, char *type, int attnum, int nullness)
static bool Nulls[MAXATTR]
void index_register(Oid heap, Oid ind, const IndexInfo *indexInfo)
void boot_openrel(char *relname)
static IndexList * ILHead
#define BOOTCOL_NULL_FORCE_NULL
int boot_yylex_init(yyscan_t *yyscannerp)
#define BOOTCOL_NULL_FORCE_NOT_NULL
#define BOOTCOL_NULL_AUTO
int boot_yyparse(yyscan_t yyscanner)
#define PG_DATA_CHECKSUM_VERSION
#define MemSet(start, val, len)
#define OidIsValid(objectId)
int errmsg_internal(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
void set_max_safe_fds(void)
Datum OidInputFunctionCall(Oid functionId, char *str, Oid typioparam, int32 typmod)
char * OidOutputFunctionCall(Oid functionId, Datum val)
char OutputFileName[MAXPGPATH]
void SetConfigOption(const char *name, const char *value, GucContext context, GucSource source)
bool SelectConfigFiles(const char *userDoption, const char *progname)
void ParseLongOption(const char *string, char **name, char **value)
void InitializeGUCOptions(void)
Assert(PointerIsAligned(start, uint64))
HeapTuple heap_getnext(TableScanDesc sscan, ScanDirection direction)
void simple_heap_insert(Relation relation, HeapTuple tup)
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
void heap_freetuple(HeapTuple htup)
static void * GETSTRUCT(const HeapTupleData *tuple)
void index_build(Relation heapRelation, Relation indexRelation, IndexInfo *indexInfo, bool isreindex, bool parallel)
void index_close(Relation relation, LOCKMODE lockmode)
Relation index_open(Oid relationId, LOCKMODE lockmode)
void CreateSharedMemoryAndSemaphores(void)
bool pg_link_canary_is_frontend(void)
List * lappend(List *list, void *datum)
void list_free_deep(List *list)
DispatchOption parse_dispatch_option(const char *name)
RangeVar * makeRangeVar(char *schemaname, char *relname, int location)
void * MemoryContextAllocZero(MemoryContext context, Size size)
char * pstrdup(const char *in)
void pfree(void *pointer)
MemoryContext TopMemoryContext
#define AllocSetContextCreate
#define ALLOCSET_DEFAULT_SIZES
#define SetProcessingMode(mode)
void ChangeToDataDir(void)
void InitStandaloneProcess(const char *argv0)
void CreateDataDirLockFile(bool amPostmaster)
void namestrcpy(Name name, const char *str)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
#define ATTRIBUTE_FIXED_PART_SIZE
FormData_pg_attribute * Form_pg_attribute
int getopt(int nargc, char *const *nargv, const char *ostr)
PGDLLIMPORT char * optarg
FormData_pg_type * Form_pg_type
void InitPostmasterChildSlots(void)
size_t strlcpy(char *dst, const char *src, size_t siz)
static const char * userDoption
static Datum PointerGetDatum(const void *X)
void InitializeMaxBackends(void)
void InitializeFastPathLocks(void)
void InitPostgres(const char *in_dbname, Oid dboid, const char *username, Oid useroid, bits32 flags, char *out_dbname)
char * psprintf(const char *fmt,...)
#define RelationGetNumberOfAttributes(relation)
#define RelationGetRelationName(relation)
void RelationMapFinishBootstrap(void)
uint16 * ii_ExclusionStrats
ExprState * ii_PredicateState
List * ii_ExpressionsState
struct _IndexList * il_next
void table_close(Relation relation, LOCKMODE lockmode)
Relation table_open(Oid relationId, LOCKMODE lockmode)
Relation table_openrv(const RangeVar *relation, LOCKMODE lockmode)
TableScanDesc table_beginscan_catalog(Relation relation, int nkeys, ScanKeyData *key)
static void table_endscan(TableScanDesc scan)
#define InvalidCompressionMethod
TupleDesc CreateTupleDesc(int natts, Form_pg_attribute *attrs)
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
void StartTransactionCommand(void)
void CommitTransactionCommand(void)
void BootStrapXLOG(uint32 data_checksum_version)