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