1 /*-------------------------------------------------------------------------
2  *
3  * bootstrap.c
4  *	  routines to support running postgres in 'bootstrap' mode
5  *	bootstrap mode is used to create the initial template database
6  *
7  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
8  * Portions Copyright (c) 1994, Regents of the University of California
9  *
10  * IDENTIFICATION
11  *	  src/backend/bootstrap/bootstrap.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16 
17 #include <unistd.h>
18 #include <signal.h>
19 
20 #include "access/htup_details.h"
21 #include "access/xact.h"
22 #include "bootstrap/bootstrap.h"
23 #include "catalog/index.h"
24 #include "catalog/pg_collation.h"
25 #include "catalog/pg_type.h"
26 #include "libpq/pqsignal.h"
27 #include "miscadmin.h"
28 #include "nodes/makefuncs.h"
29 #include "pg_getopt.h"
30 #include "pgstat.h"
31 #include "postmaster/bgwriter.h"
32 #include "postmaster/startup.h"
33 #include "postmaster/walwriter.h"
34 #include "replication/walreceiver.h"
35 #include "storage/bufmgr.h"
36 #include "storage/bufpage.h"
37 #include "storage/condition_variable.h"
38 #include "storage/ipc.h"
39 #include "storage/proc.h"
40 #include "tcop/tcopprot.h"
41 #include "utils/builtins.h"
42 #include "utils/fmgroids.h"
43 #include "utils/memutils.h"
44 #include "utils/ps_status.h"
45 #include "utils/rel.h"
46 #include "utils/relmapper.h"
47 #include "utils/tqual.h"
48 
49 uint32		bootstrap_data_checksum_version = 0;	/* No checksum */
50 
51 
52 #define ALLOC(t, c) \
53 	((t *) MemoryContextAllocZero(TopMemoryContext, (unsigned)(c) * sizeof(t)))
54 
55 static void CheckerModeMain(void);
56 static void BootstrapModeMain(void);
57 static void bootstrap_signals(void);
58 static void ShutdownAuxiliaryProcess(int code, Datum arg);
59 static Form_pg_attribute AllocateAttribute(void);
60 static Oid	gettype(char *type);
61 static void cleanup(void);
62 
63 /* ----------------
64  *		global variables
65  * ----------------
66  */
67 
68 AuxProcType MyAuxProcType = NotAnAuxProcess;	/* declared in miscadmin.h */
69 
70 Relation	boot_reldesc;		/* current relation descriptor */
71 
72 Form_pg_attribute attrtypes[MAXATTR];	/* points to attribute info */
73 int			numattr;			/* number of attributes for cur. rel */
74 
75 
76 /*
77  * Basic information associated with each type.  This is used before
78  * pg_type is filled, so it has to cover the datatypes used as column types
79  * in the core "bootstrapped" catalogs.
80  *
81  *		XXX several of these input/output functions do catalog scans
82  *			(e.g., F_REGPROCIN scans pg_proc).  this obviously creates some
83  *			order dependencies in the catalog creation process.
84  */
85 struct typinfo
86 {
87 	char		name[NAMEDATALEN];
88 	Oid			oid;
89 	Oid			elem;
90 	int16		len;
91 	bool		byval;
92 	char		align;
93 	char		storage;
94 	Oid			collation;
95 	Oid			inproc;
96 	Oid			outproc;
97 };
98 
99 static const struct typinfo TypInfo[] = {
100 	{"bool", BOOLOID, 0, 1, true, 'c', 'p', InvalidOid,
101 	F_BOOLIN, F_BOOLOUT},
102 	{"bytea", BYTEAOID, 0, -1, false, 'i', 'x', InvalidOid,
103 	F_BYTEAIN, F_BYTEAOUT},
104 	{"char", CHAROID, 0, 1, true, 'c', 'p', InvalidOid,
105 	F_CHARIN, F_CHAROUT},
106 	{"int2", INT2OID, 0, 2, true, 's', 'p', InvalidOid,
107 	F_INT2IN, F_INT2OUT},
108 	{"int4", INT4OID, 0, 4, true, 'i', 'p', InvalidOid,
109 	F_INT4IN, F_INT4OUT},
110 	{"float4", FLOAT4OID, 0, 4, FLOAT4PASSBYVAL, 'i', 'p', InvalidOid,
111 	F_FLOAT4IN, F_FLOAT4OUT},
112 	{"name", NAMEOID, CHAROID, NAMEDATALEN, false, 'c', 'p', InvalidOid,
113 	F_NAMEIN, F_NAMEOUT},
114 	{"regclass", REGCLASSOID, 0, 4, true, 'i', 'p', InvalidOid,
115 	F_REGCLASSIN, F_REGCLASSOUT},
116 	{"regproc", REGPROCOID, 0, 4, true, 'i', 'p', InvalidOid,
117 	F_REGPROCIN, F_REGPROCOUT},
118 	{"regtype", REGTYPEOID, 0, 4, true, 'i', 'p', InvalidOid,
119 	F_REGTYPEIN, F_REGTYPEOUT},
120 	{"regrole", REGROLEOID, 0, 4, true, 'i', 'p', InvalidOid,
121 	F_REGROLEIN, F_REGROLEOUT},
122 	{"regnamespace", REGNAMESPACEOID, 0, 4, true, 'i', 'p', InvalidOid,
123 	F_REGNAMESPACEIN, F_REGNAMESPACEOUT},
124 	{"text", TEXTOID, 0, -1, false, 'i', 'x', DEFAULT_COLLATION_OID,
125 	F_TEXTIN, F_TEXTOUT},
126 	{"oid", OIDOID, 0, 4, true, 'i', 'p', InvalidOid,
127 	F_OIDIN, F_OIDOUT},
128 	{"tid", TIDOID, 0, 6, false, 's', 'p', InvalidOid,
129 	F_TIDIN, F_TIDOUT},
130 	{"xid", XIDOID, 0, 4, true, 'i', 'p', InvalidOid,
131 	F_XIDIN, F_XIDOUT},
132 	{"cid", CIDOID, 0, 4, true, 'i', 'p', InvalidOid,
133 	F_CIDIN, F_CIDOUT},
134 	{"pg_node_tree", PGNODETREEOID, 0, -1, false, 'i', 'x', DEFAULT_COLLATION_OID,
135 	F_PG_NODE_TREE_IN, F_PG_NODE_TREE_OUT},
136 	{"int2vector", INT2VECTOROID, INT2OID, -1, false, 'i', 'p', InvalidOid,
137 	F_INT2VECTORIN, F_INT2VECTOROUT},
138 	{"oidvector", OIDVECTOROID, OIDOID, -1, false, 'i', 'p', InvalidOid,
139 	F_OIDVECTORIN, F_OIDVECTOROUT},
140 	{"_int4", INT4ARRAYOID, INT4OID, -1, false, 'i', 'x', InvalidOid,
141 	F_ARRAY_IN, F_ARRAY_OUT},
142 	{"_text", 1009, TEXTOID, -1, false, 'i', 'x', DEFAULT_COLLATION_OID,
143 	F_ARRAY_IN, F_ARRAY_OUT},
144 	{"_oid", 1028, OIDOID, -1, false, 'i', 'x', InvalidOid,
145 	F_ARRAY_IN, F_ARRAY_OUT},
146 	{"_char", 1002, CHAROID, -1, false, 'i', 'x', InvalidOid,
147 	F_ARRAY_IN, F_ARRAY_OUT},
148 	{"_aclitem", 1034, ACLITEMOID, -1, false, 'i', 'x', InvalidOid,
149 	F_ARRAY_IN, F_ARRAY_OUT}
150 };
151 
152 static const int n_types = sizeof(TypInfo) / sizeof(struct typinfo);
153 
154 struct typmap
155 {								/* a hack */
156 	Oid			am_oid;
157 	FormData_pg_type am_typ;
158 };
159 
160 static struct typmap **Typ = NULL;
161 static struct typmap *Ap = NULL;
162 
163 static Datum values[MAXATTR];	/* current row's attribute values */
164 static bool Nulls[MAXATTR];
165 
166 static MemoryContext nogc = NULL;	/* special no-gc mem context */
167 
168 /*
169  *	At bootstrap time, we first declare all the indices to be built, and
170  *	then build them.  The IndexList structure stores enough information
171  *	to allow us to build the indices after they've been declared.
172  */
173 
174 typedef struct _IndexList
175 {
176 	Oid			il_heap;
177 	Oid			il_ind;
178 	IndexInfo  *il_info;
179 	struct _IndexList *il_next;
180 } IndexList;
181 
182 static IndexList *ILHead = NULL;
183 
184 
185 /*
186  *	 AuxiliaryProcessMain
187  *
188  *	 The main entry point for auxiliary processes, such as the bgwriter,
189  *	 walwriter, walreceiver, bootstrapper and the shared memory checker code.
190  *
191  *	 This code is here just because of historical reasons.
192  */
193 void
AuxiliaryProcessMain(int argc,char * argv[])194 AuxiliaryProcessMain(int argc, char *argv[])
195 {
196 	char	   *progname = argv[0];
197 	int			flag;
198 	char	   *userDoption = NULL;
199 
200 	/*
201 	 * Initialize process environment (already done if under postmaster, but
202 	 * not if standalone).
203 	 */
204 	if (!IsUnderPostmaster)
205 		InitStandaloneProcess(argv[0]);
206 
207 	/*
208 	 * process command arguments
209 	 */
210 
211 	/* Set defaults, to be overridden by explicit options below */
212 	if (!IsUnderPostmaster)
213 		InitializeGUCOptions();
214 
215 	/* Ignore the initial --boot argument, if present */
216 	if (argc > 1 && strcmp(argv[1], "--boot") == 0)
217 	{
218 		argv++;
219 		argc--;
220 	}
221 
222 	/* If no -x argument, we are a CheckerProcess */
223 	MyAuxProcType = CheckerProcess;
224 
225 	while ((flag = getopt(argc, argv, "B:c:d:D:Fkr:x:-:")) != -1)
226 	{
227 		switch (flag)
228 		{
229 			case 'B':
230 				SetConfigOption("shared_buffers", optarg, PGC_POSTMASTER, PGC_S_ARGV);
231 				break;
232 			case 'D':
233 				userDoption = pstrdup(optarg);
234 				break;
235 			case 'd':
236 				{
237 					/* Turn on debugging for the bootstrap process. */
238 					char	   *debugstr;
239 
240 					debugstr = psprintf("debug%s", optarg);
241 					SetConfigOption("log_min_messages", debugstr,
242 									PGC_POSTMASTER, PGC_S_ARGV);
243 					SetConfigOption("client_min_messages", debugstr,
244 									PGC_POSTMASTER, PGC_S_ARGV);
245 					pfree(debugstr);
246 				}
247 				break;
248 			case 'F':
249 				SetConfigOption("fsync", "false", PGC_POSTMASTER, PGC_S_ARGV);
250 				break;
251 			case 'k':
252 				bootstrap_data_checksum_version = PG_DATA_CHECKSUM_VERSION;
253 				break;
254 			case 'r':
255 				strlcpy(OutputFileName, optarg, MAXPGPATH);
256 				break;
257 			case 'x':
258 				MyAuxProcType = atoi(optarg);
259 				break;
260 			case 'c':
261 			case '-':
262 				{
263 					char	   *name,
264 							   *value;
265 
266 					ParseLongOption(optarg, &name, &value);
267 					if (!value)
268 					{
269 						if (flag == '-')
270 							ereport(ERROR,
271 									(errcode(ERRCODE_SYNTAX_ERROR),
272 									 errmsg("--%s requires a value",
273 											optarg)));
274 						else
275 							ereport(ERROR,
276 									(errcode(ERRCODE_SYNTAX_ERROR),
277 									 errmsg("-c %s requires a value",
278 											optarg)));
279 					}
280 
281 					SetConfigOption(name, value, PGC_POSTMASTER, PGC_S_ARGV);
282 					free(name);
283 					if (value)
284 						free(value);
285 					break;
286 				}
287 			default:
288 				write_stderr("Try \"%s --help\" for more information.\n",
289 							 progname);
290 				proc_exit(1);
291 				break;
292 		}
293 	}
294 
295 	if (argc != optind)
296 	{
297 		write_stderr("%s: invalid command-line arguments\n", progname);
298 		proc_exit(1);
299 	}
300 
301 	/*
302 	 * Identify myself via ps
303 	 */
304 	if (IsUnderPostmaster)
305 	{
306 		const char *statmsg;
307 
308 		switch (MyAuxProcType)
309 		{
310 			case StartupProcess:
311 				statmsg = "startup process";
312 				break;
313 			case BgWriterProcess:
314 				statmsg = "writer process";
315 				break;
316 			case CheckpointerProcess:
317 				statmsg = "checkpointer process";
318 				break;
319 			case WalWriterProcess:
320 				statmsg = "wal writer process";
321 				break;
322 			case WalReceiverProcess:
323 				statmsg = "wal receiver process";
324 				break;
325 			default:
326 				statmsg = "??? process";
327 				break;
328 		}
329 		init_ps_display(statmsg, "", "", "");
330 	}
331 
332 	/* Acquire configuration parameters, unless inherited from postmaster */
333 	if (!IsUnderPostmaster)
334 	{
335 		if (!SelectConfigFiles(userDoption, progname))
336 			proc_exit(1);
337 	}
338 
339 	/* Validate we have been given a reasonable-looking DataDir */
340 	Assert(DataDir);
341 	ValidatePgVersion(DataDir);
342 
343 	/* Change into DataDir (if under postmaster, should be done already) */
344 	if (!IsUnderPostmaster)
345 		ChangeToDataDir();
346 
347 	/* If standalone, create lockfile for data directory */
348 	if (!IsUnderPostmaster)
349 		CreateDataDirLockFile(false);
350 
351 	SetProcessingMode(BootstrapProcessing);
352 	IgnoreSystemIndexes = true;
353 
354 	/* Initialize MaxBackends (if under postmaster, was done already) */
355 	if (!IsUnderPostmaster)
356 		InitializeMaxBackends();
357 
358 	BaseInit();
359 
360 	/*
361 	 * When we are an auxiliary process, we aren't going to do the full
362 	 * InitPostgres pushups, but there are a couple of things that need to get
363 	 * lit up even in an auxiliary process.
364 	 */
365 	if (IsUnderPostmaster)
366 	{
367 		/*
368 		 * Create a PGPROC so we can use LWLocks.  In the EXEC_BACKEND case,
369 		 * this was already done by SubPostmasterMain().
370 		 */
371 #ifndef EXEC_BACKEND
372 		InitAuxiliaryProcess();
373 #endif
374 
375 		/*
376 		 * Assign the ProcSignalSlot for an auxiliary process.  Since it
377 		 * doesn't have a BackendId, the slot is statically allocated based on
378 		 * the auxiliary process type (MyAuxProcType).  Backends use slots
379 		 * indexed in the range from 1 to MaxBackends (inclusive), so we use
380 		 * MaxBackends + AuxProcType + 1 as the index of the slot for an
381 		 * auxiliary process.
382 		 *
383 		 * This will need rethinking if we ever want more than one of a
384 		 * particular auxiliary process type.
385 		 */
386 		ProcSignalInit(MaxBackends + MyAuxProcType + 1);
387 
388 		/* finish setting up bufmgr.c */
389 		InitBufferPoolBackend();
390 
391 		/* Initialize backend status information */
392 		pgstat_initialize();
393 		pgstat_bestart();
394 
395 		/* register a before-shutdown callback for LWLock cleanup */
396 		before_shmem_exit(ShutdownAuxiliaryProcess, 0);
397 	}
398 
399 	/*
400 	 * XLOG operations
401 	 */
402 	SetProcessingMode(NormalProcessing);
403 
404 	switch (MyAuxProcType)
405 	{
406 		case CheckerProcess:
407 			/* don't set signals, they're useless here */
408 			CheckerModeMain();
409 			proc_exit(1);		/* should never return */
410 
411 		case BootstrapProcess:
412 
413 			/*
414 			 * There was a brief instant during which mode was Normal; this is
415 			 * okay.  We need to be in bootstrap mode during BootStrapXLOG for
416 			 * the sake of multixact initialization.
417 			 */
418 			SetProcessingMode(BootstrapProcessing);
419 			bootstrap_signals();
420 			BootStrapXLOG();
421 			BootstrapModeMain();
422 			proc_exit(1);		/* should never return */
423 
424 		case StartupProcess:
425 			/* don't set signals, startup process has its own agenda */
426 			StartupProcessMain();
427 			proc_exit(1);		/* should never return */
428 
429 		case BgWriterProcess:
430 			/* don't set signals, bgwriter has its own agenda */
431 			BackgroundWriterMain();
432 			proc_exit(1);		/* should never return */
433 
434 		case CheckpointerProcess:
435 			/* don't set signals, checkpointer has its own agenda */
436 			CheckpointerMain();
437 			proc_exit(1);		/* should never return */
438 
439 		case WalWriterProcess:
440 			/* don't set signals, walwriter has its own agenda */
441 			InitXLOGAccess();
442 			WalWriterMain();
443 			proc_exit(1);		/* should never return */
444 
445 		case WalReceiverProcess:
446 			/* don't set signals, walreceiver has its own agenda */
447 			WalReceiverMain();
448 			proc_exit(1);		/* should never return */
449 
450 		default:
451 			elog(PANIC, "unrecognized process type: %d", (int) MyAuxProcType);
452 			proc_exit(1);
453 	}
454 }
455 
456 /*
457  * In shared memory checker mode, all we really want to do is create shared
458  * memory and semaphores (just to prove we can do it with the current GUC
459  * settings).  Since, in fact, that was already done by BaseInit(),
460  * we have nothing more to do here.
461  */
462 static void
CheckerModeMain(void)463 CheckerModeMain(void)
464 {
465 	proc_exit(0);
466 }
467 
468 /*
469  *	 The main entry point for running the backend in bootstrap mode
470  *
471  *	 The bootstrap mode is used to initialize the template database.
472  *	 The bootstrap backend doesn't speak SQL, but instead expects
473  *	 commands in a special bootstrap language.
474  */
475 static void
BootstrapModeMain(void)476 BootstrapModeMain(void)
477 {
478 	int			i;
479 
480 	Assert(!IsUnderPostmaster);
481 	Assert(IsBootstrapProcessingMode());
482 
483 	/*
484 	 * Do backend-like initialization for bootstrap mode
485 	 */
486 	InitProcess();
487 
488 	InitPostgres(NULL, InvalidOid, NULL, InvalidOid, NULL);
489 
490 	/* Initialize stuff for bootstrap-file processing */
491 	for (i = 0; i < MAXATTR; i++)
492 	{
493 		attrtypes[i] = NULL;
494 		Nulls[i] = false;
495 	}
496 
497 	/*
498 	 * Process bootstrap input.
499 	 */
500 	StartTransactionCommand();
501 	boot_yyparse();
502 	CommitTransactionCommand();
503 
504 	/*
505 	 * We should now know about all mapped relations, so it's okay to write
506 	 * out the initial relation mapping files.
507 	 */
508 	RelationMapFinishBootstrap();
509 
510 	/* Clean up and exit */
511 	cleanup();
512 	proc_exit(0);
513 }
514 
515 
516 /* ----------------------------------------------------------------
517  *						misc functions
518  * ----------------------------------------------------------------
519  */
520 
521 /*
522  * Set up signal handling for a bootstrap process
523  */
524 static void
bootstrap_signals(void)525 bootstrap_signals(void)
526 {
527 	Assert(!IsUnderPostmaster);
528 
529 	/* Set up appropriately for interactive use */
530 	pqsignal(SIGHUP, die);
531 	pqsignal(SIGINT, die);
532 	pqsignal(SIGTERM, die);
533 	pqsignal(SIGQUIT, die);
534 }
535 
536 /*
537  * Begin shutdown of an auxiliary process.  This is approximately the equivalent
538  * of ShutdownPostgres() in postinit.c.  We can't run transactions in an
539  * auxiliary process, so most of the work of AbortTransaction() is not needed,
540  * but we do need to make sure we've released any LWLocks we are holding.
541  * (This is only critical during an error exit.)
542  */
543 static void
ShutdownAuxiliaryProcess(int code,Datum arg)544 ShutdownAuxiliaryProcess(int code, Datum arg)
545 {
546 	LWLockReleaseAll();
547 	ConditionVariableCancelSleep();
548 	pgstat_report_wait_end();
549 }
550 
551 /* ----------------------------------------------------------------
552  *				MANUAL BACKEND INTERACTIVE INTERFACE COMMANDS
553  * ----------------------------------------------------------------
554  */
555 
556 /* ----------------
557  *		boot_openrel
558  * ----------------
559  */
560 void
boot_openrel(char * relname)561 boot_openrel(char *relname)
562 {
563 	int			i;
564 	struct typmap **app;
565 	Relation	rel;
566 	HeapScanDesc scan;
567 	HeapTuple	tup;
568 
569 	if (strlen(relname) >= NAMEDATALEN)
570 		relname[NAMEDATALEN - 1] = '\0';
571 
572 	if (Typ == NULL)
573 	{
574 		/* We can now load the pg_type data */
575 		rel = heap_open(TypeRelationId, NoLock);
576 		scan = heap_beginscan_catalog(rel, 0, NULL);
577 		i = 0;
578 		while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL)
579 			++i;
580 		heap_endscan(scan);
581 		app = Typ = ALLOC(struct typmap *, i + 1);
582 		while (i-- > 0)
583 			*app++ = ALLOC(struct typmap, 1);
584 		*app = NULL;
585 		scan = heap_beginscan_catalog(rel, 0, NULL);
586 		app = Typ;
587 		while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL)
588 		{
589 			(*app)->am_oid = HeapTupleGetOid(tup);
590 			memcpy((char *) &(*app)->am_typ,
591 				   (char *) GETSTRUCT(tup),
592 				   sizeof((*app)->am_typ));
593 			app++;
594 		}
595 		heap_endscan(scan);
596 		heap_close(rel, NoLock);
597 	}
598 
599 	if (boot_reldesc != NULL)
600 		closerel(NULL);
601 
602 	elog(DEBUG4, "open relation %s, attrsize %d",
603 		 relname, (int) ATTRIBUTE_FIXED_PART_SIZE);
604 
605 	boot_reldesc = heap_openrv(makeRangeVar(NULL, relname, -1), NoLock);
606 	numattr = boot_reldesc->rd_rel->relnatts;
607 	for (i = 0; i < numattr; i++)
608 	{
609 		if (attrtypes[i] == NULL)
610 			attrtypes[i] = AllocateAttribute();
611 		memmove((char *) attrtypes[i],
612 				(char *) boot_reldesc->rd_att->attrs[i],
613 				ATTRIBUTE_FIXED_PART_SIZE);
614 
615 		{
616 			Form_pg_attribute at = attrtypes[i];
617 
618 			elog(DEBUG4, "create attribute %d name %s len %d num %d type %u",
619 				 i, NameStr(at->attname), at->attlen, at->attnum,
620 				 at->atttypid);
621 		}
622 	}
623 }
624 
625 /* ----------------
626  *		closerel
627  * ----------------
628  */
629 void
closerel(char * name)630 closerel(char *name)
631 {
632 	if (name)
633 	{
634 		if (boot_reldesc)
635 		{
636 			if (strcmp(RelationGetRelationName(boot_reldesc), name) != 0)
637 				elog(ERROR, "close of %s when %s was expected",
638 					 name, RelationGetRelationName(boot_reldesc));
639 		}
640 		else
641 			elog(ERROR, "close of %s before any relation was opened",
642 				 name);
643 	}
644 
645 	if (boot_reldesc == NULL)
646 		elog(ERROR, "no open relation to close");
647 	else
648 	{
649 		elog(DEBUG4, "close relation %s",
650 			 RelationGetRelationName(boot_reldesc));
651 		heap_close(boot_reldesc, NoLock);
652 		boot_reldesc = NULL;
653 	}
654 }
655 
656 
657 
658 /* ----------------
659  * DEFINEATTR()
660  *
661  * define a <field,type> pair
662  * if there are n fields in a relation to be created, this routine
663  * will be called n times
664  * ----------------
665  */
666 void
DefineAttr(char * name,char * type,int attnum,int nullness)667 DefineAttr(char *name, char *type, int attnum, int nullness)
668 {
669 	Oid			typeoid;
670 
671 	if (boot_reldesc != NULL)
672 	{
673 		elog(WARNING, "no open relations allowed with CREATE command");
674 		closerel(NULL);
675 	}
676 
677 	if (attrtypes[attnum] == NULL)
678 		attrtypes[attnum] = AllocateAttribute();
679 	MemSet(attrtypes[attnum], 0, ATTRIBUTE_FIXED_PART_SIZE);
680 
681 	namestrcpy(&attrtypes[attnum]->attname, name);
682 	elog(DEBUG4, "column %s %s", NameStr(attrtypes[attnum]->attname), type);
683 	attrtypes[attnum]->attnum = attnum + 1; /* fillatt */
684 
685 	typeoid = gettype(type);
686 
687 	if (Typ != NULL)
688 	{
689 		attrtypes[attnum]->atttypid = Ap->am_oid;
690 		attrtypes[attnum]->attlen = Ap->am_typ.typlen;
691 		attrtypes[attnum]->attbyval = Ap->am_typ.typbyval;
692 		attrtypes[attnum]->attstorage = Ap->am_typ.typstorage;
693 		attrtypes[attnum]->attalign = Ap->am_typ.typalign;
694 		attrtypes[attnum]->attcollation = Ap->am_typ.typcollation;
695 		/* if an array type, assume 1-dimensional attribute */
696 		if (Ap->am_typ.typelem != InvalidOid && Ap->am_typ.typlen < 0)
697 			attrtypes[attnum]->attndims = 1;
698 		else
699 			attrtypes[attnum]->attndims = 0;
700 	}
701 	else
702 	{
703 		attrtypes[attnum]->atttypid = TypInfo[typeoid].oid;
704 		attrtypes[attnum]->attlen = TypInfo[typeoid].len;
705 		attrtypes[attnum]->attbyval = TypInfo[typeoid].byval;
706 		attrtypes[attnum]->attstorage = TypInfo[typeoid].storage;
707 		attrtypes[attnum]->attalign = TypInfo[typeoid].align;
708 		attrtypes[attnum]->attcollation = TypInfo[typeoid].collation;
709 		/* if an array type, assume 1-dimensional attribute */
710 		if (TypInfo[typeoid].elem != InvalidOid &&
711 			attrtypes[attnum]->attlen < 0)
712 			attrtypes[attnum]->attndims = 1;
713 		else
714 			attrtypes[attnum]->attndims = 0;
715 	}
716 
717 	attrtypes[attnum]->attstattarget = -1;
718 	attrtypes[attnum]->attcacheoff = -1;
719 	attrtypes[attnum]->atttypmod = -1;
720 	attrtypes[attnum]->attislocal = true;
721 
722 	if (nullness == BOOTCOL_NULL_FORCE_NOT_NULL)
723 	{
724 		attrtypes[attnum]->attnotnull = true;
725 	}
726 	else if (nullness == BOOTCOL_NULL_FORCE_NULL)
727 	{
728 		attrtypes[attnum]->attnotnull = false;
729 	}
730 	else
731 	{
732 		Assert(nullness == BOOTCOL_NULL_AUTO);
733 
734 		/*
735 		 * Mark as "not null" if type is fixed-width and prior columns are
736 		 * too.  This corresponds to case where column can be accessed
737 		 * directly via C struct declaration.
738 		 *
739 		 * oidvector and int2vector are also treated as not-nullable, even
740 		 * though they are no longer fixed-width.
741 		 */
742 #define MARKNOTNULL(att) \
743 		((att)->attlen > 0 || \
744 		 (att)->atttypid == OIDVECTOROID || \
745 		 (att)->atttypid == INT2VECTOROID)
746 
747 		if (MARKNOTNULL(attrtypes[attnum]))
748 		{
749 			int			i;
750 
751 			/* check earlier attributes */
752 			for (i = 0; i < attnum; i++)
753 			{
754 				if (!attrtypes[i]->attnotnull)
755 					break;
756 			}
757 			if (i == attnum)
758 				attrtypes[attnum]->attnotnull = true;
759 		}
760 	}
761 }
762 
763 
764 /* ----------------
765  *		InsertOneTuple
766  *
767  * If objectid is not zero, it is a specific OID to assign to the tuple.
768  * Otherwise, an OID will be assigned (if necessary) by heap_insert.
769  * ----------------
770  */
771 void
InsertOneTuple(Oid objectid)772 InsertOneTuple(Oid objectid)
773 {
774 	HeapTuple	tuple;
775 	TupleDesc	tupDesc;
776 	int			i;
777 
778 	elog(DEBUG4, "inserting row oid %u, %d columns", objectid, numattr);
779 
780 	tupDesc = CreateTupleDesc(numattr,
781 							  RelationGetForm(boot_reldesc)->relhasoids,
782 							  attrtypes);
783 	tuple = heap_form_tuple(tupDesc, values, Nulls);
784 	if (objectid != (Oid) 0)
785 		HeapTupleSetOid(tuple, objectid);
786 	pfree(tupDesc);				/* just free's tupDesc, not the attrtypes */
787 
788 	simple_heap_insert(boot_reldesc, tuple);
789 	heap_freetuple(tuple);
790 	elog(DEBUG4, "row inserted");
791 
792 	/*
793 	 * Reset null markers for next tuple
794 	 */
795 	for (i = 0; i < numattr; i++)
796 		Nulls[i] = false;
797 }
798 
799 /* ----------------
800  *		InsertOneValue
801  * ----------------
802  */
803 void
InsertOneValue(char * value,int i)804 InsertOneValue(char *value, int i)
805 {
806 	Oid			typoid;
807 	int16		typlen;
808 	bool		typbyval;
809 	char		typalign;
810 	char		typdelim;
811 	Oid			typioparam;
812 	Oid			typinput;
813 	Oid			typoutput;
814 
815 	AssertArg(i >= 0 && i < MAXATTR);
816 
817 	elog(DEBUG4, "inserting column %d value \"%s\"", i, value);
818 
819 	typoid = boot_reldesc->rd_att->attrs[i]->atttypid;
820 
821 	boot_get_type_io_data(typoid,
822 						  &typlen, &typbyval, &typalign,
823 						  &typdelim, &typioparam,
824 						  &typinput, &typoutput);
825 
826 	values[i] = OidInputFunctionCall(typinput, value, typioparam, -1);
827 
828 	/*
829 	 * We use ereport not elog here so that parameters aren't evaluated unless
830 	 * the message is going to be printed, which generally it isn't
831 	 */
832 	ereport(DEBUG4,
833 			(errmsg_internal("inserted -> %s",
834 							 OidOutputFunctionCall(typoutput, values[i]))));
835 }
836 
837 /* ----------------
838  *		InsertOneNull
839  * ----------------
840  */
841 void
InsertOneNull(int i)842 InsertOneNull(int i)
843 {
844 	elog(DEBUG4, "inserting column %d NULL", i);
845 	Assert(i >= 0 && i < MAXATTR);
846 	if (boot_reldesc->rd_att->attrs[i]->attnotnull)
847 		elog(ERROR,
848 			 "NULL value specified for not-null column \"%s\" of relation \"%s\"",
849 			 NameStr(boot_reldesc->rd_att->attrs[i]->attname),
850 			 RelationGetRelationName(boot_reldesc));
851 	values[i] = PointerGetDatum(NULL);
852 	Nulls[i] = true;
853 }
854 
855 /* ----------------
856  *		cleanup
857  * ----------------
858  */
859 static void
cleanup(void)860 cleanup(void)
861 {
862 	if (boot_reldesc != NULL)
863 		closerel(NULL);
864 }
865 
866 /* ----------------
867  *		gettype
868  *
869  * NB: this is really ugly; it will return an integer index into TypInfo[],
870  * and not an OID at all, until the first reference to a type not known in
871  * TypInfo[].  At that point it will read and cache pg_type in the Typ array,
872  * and subsequently return a real OID (and set the global pointer Ap to
873  * point at the found row in Typ).  So caller must check whether Typ is
874  * still NULL to determine what the return value is!
875  * ----------------
876  */
877 static Oid
gettype(char * type)878 gettype(char *type)
879 {
880 	int			i;
881 	Relation	rel;
882 	HeapScanDesc scan;
883 	HeapTuple	tup;
884 	struct typmap **app;
885 
886 	if (Typ != NULL)
887 	{
888 		for (app = Typ; *app != NULL; app++)
889 		{
890 			if (strncmp(NameStr((*app)->am_typ.typname), type, NAMEDATALEN) == 0)
891 			{
892 				Ap = *app;
893 				return (*app)->am_oid;
894 			}
895 		}
896 	}
897 	else
898 	{
899 		for (i = 0; i < n_types; i++)
900 		{
901 			if (strncmp(type, TypInfo[i].name, NAMEDATALEN) == 0)
902 				return i;
903 		}
904 		elog(DEBUG4, "external type: %s", type);
905 		rel = heap_open(TypeRelationId, NoLock);
906 		scan = heap_beginscan_catalog(rel, 0, NULL);
907 		i = 0;
908 		while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL)
909 			++i;
910 		heap_endscan(scan);
911 		app = Typ = ALLOC(struct typmap *, i + 1);
912 		while (i-- > 0)
913 			*app++ = ALLOC(struct typmap, 1);
914 		*app = NULL;
915 		scan = heap_beginscan_catalog(rel, 0, NULL);
916 		app = Typ;
917 		while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL)
918 		{
919 			(*app)->am_oid = HeapTupleGetOid(tup);
920 			memmove((char *) &(*app++)->am_typ,
921 					(char *) GETSTRUCT(tup),
922 					sizeof((*app)->am_typ));
923 		}
924 		heap_endscan(scan);
925 		heap_close(rel, NoLock);
926 		return gettype(type);
927 	}
928 	elog(ERROR, "unrecognized type \"%s\"", type);
929 	/* not reached, here to make compiler happy */
930 	return 0;
931 }
932 
933 /* ----------------
934  *		boot_get_type_io_data
935  *
936  * Obtain type I/O information at bootstrap time.  This intentionally has
937  * almost the same API as lsyscache.c's get_type_io_data, except that
938  * we only support obtaining the typinput and typoutput routines, not
939  * the binary I/O routines.  It is exported so that array_in and array_out
940  * can be made to work during early bootstrap.
941  * ----------------
942  */
943 void
boot_get_type_io_data(Oid typid,int16 * typlen,bool * typbyval,char * typalign,char * typdelim,Oid * typioparam,Oid * typinput,Oid * typoutput)944 boot_get_type_io_data(Oid typid,
945 					  int16 *typlen,
946 					  bool *typbyval,
947 					  char *typalign,
948 					  char *typdelim,
949 					  Oid *typioparam,
950 					  Oid *typinput,
951 					  Oid *typoutput)
952 {
953 	if (Typ != NULL)
954 	{
955 		/* We have the boot-time contents of pg_type, so use it */
956 		struct typmap **app;
957 		struct typmap *ap;
958 
959 		app = Typ;
960 		while (*app && (*app)->am_oid != typid)
961 			++app;
962 		ap = *app;
963 		if (ap == NULL)
964 			elog(ERROR, "type OID %u not found in Typ list", typid);
965 
966 		*typlen = ap->am_typ.typlen;
967 		*typbyval = ap->am_typ.typbyval;
968 		*typalign = ap->am_typ.typalign;
969 		*typdelim = ap->am_typ.typdelim;
970 
971 		/* XXX this logic must match getTypeIOParam() */
972 		if (OidIsValid(ap->am_typ.typelem))
973 			*typioparam = ap->am_typ.typelem;
974 		else
975 			*typioparam = typid;
976 
977 		*typinput = ap->am_typ.typinput;
978 		*typoutput = ap->am_typ.typoutput;
979 	}
980 	else
981 	{
982 		/* We don't have pg_type yet, so use the hard-wired TypInfo array */
983 		int			typeindex;
984 
985 		for (typeindex = 0; typeindex < n_types; typeindex++)
986 		{
987 			if (TypInfo[typeindex].oid == typid)
988 				break;
989 		}
990 		if (typeindex >= n_types)
991 			elog(ERROR, "type OID %u not found in TypInfo", typid);
992 
993 		*typlen = TypInfo[typeindex].len;
994 		*typbyval = TypInfo[typeindex].byval;
995 		*typalign = TypInfo[typeindex].align;
996 		/* We assume typdelim is ',' for all boot-time types */
997 		*typdelim = ',';
998 
999 		/* XXX this logic must match getTypeIOParam() */
1000 		if (OidIsValid(TypInfo[typeindex].elem))
1001 			*typioparam = TypInfo[typeindex].elem;
1002 		else
1003 			*typioparam = typid;
1004 
1005 		*typinput = TypInfo[typeindex].inproc;
1006 		*typoutput = TypInfo[typeindex].outproc;
1007 	}
1008 }
1009 
1010 /* ----------------
1011  *		AllocateAttribute
1012  *
1013  * Note: bootstrap never sets any per-column ACLs, so we only need
1014  * ATTRIBUTE_FIXED_PART_SIZE space per attribute.
1015  * ----------------
1016  */
1017 static Form_pg_attribute
AllocateAttribute(void)1018 AllocateAttribute(void)
1019 {
1020 	return (Form_pg_attribute)
1021 		MemoryContextAllocZero(TopMemoryContext, ATTRIBUTE_FIXED_PART_SIZE);
1022 }
1023 
1024 /*
1025  *		MapArrayTypeName
1026  *
1027  * Given a type name, produce the corresponding array type name by prepending
1028  * '_' and truncating as needed to fit in NAMEDATALEN-1 bytes.  This is only
1029  * used in bootstrap mode, so we can get away with assuming that the input is
1030  * ASCII and we don't need multibyte-aware truncation.
1031  *
1032  * The given string normally ends with '[]' or '[digits]'; we discard that.
1033  *
1034  * The result is a palloc'd string.
1035  */
1036 char *
MapArrayTypeName(const char * s)1037 MapArrayTypeName(const char *s)
1038 {
1039 	int			i,
1040 				j;
1041 	char		newStr[NAMEDATALEN];
1042 
1043 	newStr[0] = '_';
1044 	j = 1;
1045 	for (i = 0; i < NAMEDATALEN - 2 && s[i] != '['; i++, j++)
1046 		newStr[j] = s[i];
1047 
1048 	newStr[j] = '\0';
1049 
1050 	return pstrdup(newStr);
1051 }
1052 
1053 
1054 /*
1055  *	index_register() -- record an index that has been set up for building
1056  *						later.
1057  *
1058  *		At bootstrap time, we define a bunch of indexes on system catalogs.
1059  *		We postpone actually building the indexes until just before we're
1060  *		finished with initialization, however.  This is because the indexes
1061  *		themselves have catalog entries, and those have to be included in the
1062  *		indexes on those catalogs.  Doing it in two phases is the simplest
1063  *		way of making sure the indexes have the right contents at the end.
1064  */
1065 void
index_register(Oid heap,Oid ind,IndexInfo * indexInfo)1066 index_register(Oid heap,
1067 			   Oid ind,
1068 			   IndexInfo *indexInfo)
1069 {
1070 	IndexList  *newind;
1071 	MemoryContext oldcxt;
1072 
1073 	/*
1074 	 * XXX mao 10/31/92 -- don't gc index reldescs, associated info at
1075 	 * bootstrap time.  we'll declare the indexes now, but want to create them
1076 	 * later.
1077 	 */
1078 
1079 	if (nogc == NULL)
1080 		nogc = AllocSetContextCreate(NULL,
1081 									 "BootstrapNoGC",
1082 									 ALLOCSET_DEFAULT_SIZES);
1083 
1084 	oldcxt = MemoryContextSwitchTo(nogc);
1085 
1086 	newind = (IndexList *) palloc(sizeof(IndexList));
1087 	newind->il_heap = heap;
1088 	newind->il_ind = ind;
1089 	newind->il_info = (IndexInfo *) palloc(sizeof(IndexInfo));
1090 
1091 	memcpy(newind->il_info, indexInfo, sizeof(IndexInfo));
1092 	/* expressions will likely be null, but may as well copy it */
1093 	newind->il_info->ii_Expressions =
1094 		copyObject(indexInfo->ii_Expressions);
1095 	newind->il_info->ii_ExpressionsState = NIL;
1096 	/* predicate will likely be null, but may as well copy it */
1097 	newind->il_info->ii_Predicate =
1098 		copyObject(indexInfo->ii_Predicate);
1099 	newind->il_info->ii_PredicateState = NULL;
1100 	/* no exclusion constraints at bootstrap time, so no need to copy */
1101 	Assert(indexInfo->ii_ExclusionOps == NULL);
1102 	Assert(indexInfo->ii_ExclusionProcs == NULL);
1103 	Assert(indexInfo->ii_ExclusionStrats == NULL);
1104 
1105 	newind->il_next = ILHead;
1106 	ILHead = newind;
1107 
1108 	MemoryContextSwitchTo(oldcxt);
1109 }
1110 
1111 
1112 /*
1113  * build_indices -- fill in all the indexes registered earlier
1114  */
1115 void
build_indices(void)1116 build_indices(void)
1117 {
1118 	for (; ILHead != NULL; ILHead = ILHead->il_next)
1119 	{
1120 		Relation	heap;
1121 		Relation	ind;
1122 
1123 		/* need not bother with locks during bootstrap */
1124 		heap = heap_open(ILHead->il_heap, NoLock);
1125 		ind = index_open(ILHead->il_ind, NoLock);
1126 
1127 		index_build(heap, ind, ILHead->il_info, false, false);
1128 
1129 		index_close(ind, NoLock);
1130 		heap_close(heap, NoLock);
1131 	}
1132 }
1133