LCOV - code coverage report
Current view: top level - src/backend/bootstrap - bootstrap.c (source / functions) Hit Total Coverage
Test: PostgreSQL 13devel Lines: 287 346 82.9 %
Date: 2019-11-21 14:06:36 Functions: 17 17 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13