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