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

Generated by: LCOV version 1.13