LCOV - code coverage report
Current view: top level - src/backend/bootstrap - bootstrap.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 88.1 % 360 317
Test Date: 2026-01-26 10:56:24 Functions: 100.0 % 16 16
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 51.7 % 271 140

             Branch data     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-2026, 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/toast_compression.h"
      25                 :             : #include "access/xact.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 "miscadmin.h"
      32                 :             : #include "nodes/makefuncs.h"
      33                 :             : #include "pg_getopt.h"
      34                 :             : #include "postmaster/postmaster.h"
      35                 :             : #include "storage/bufpage.h"
      36                 :             : #include "storage/ipc.h"
      37                 :             : #include "storage/proc.h"
      38                 :             : #include "utils/builtins.h"
      39                 :             : #include "utils/fmgroids.h"
      40                 :             : #include "utils/guc.h"
      41                 :             : #include "utils/memutils.h"
      42                 :             : #include "utils/rel.h"
      43                 :             : #include "utils/relmapper.h"
      44                 :             : 
      45                 :             : 
      46                 :             : static void CheckerModeMain(void);
      47                 :             : static void bootstrap_signals(void);
      48                 :             : static Form_pg_attribute AllocateAttribute(void);
      49                 :             : static void populate_typ_list(void);
      50                 :             : static Oid      gettype(char *type);
      51                 :             : static void cleanup(void);
      52                 :             : 
      53                 :             : /* ----------------
      54                 :             :  *              global variables
      55                 :             :  * ----------------
      56                 :             :  */
      57                 :             : 
      58                 :             : Relation        boot_reldesc;           /* current relation descriptor */
      59                 :             : 
      60                 :             : Form_pg_attribute attrtypes[MAXATTR];   /* points to attribute info */
      61                 :             : int                     numattr;                        /* number of attributes for cur. rel */
      62                 :             : 
      63                 :             : 
      64                 :             : /*
      65                 :             :  * Basic information associated with each type.  This is used before
      66                 :             :  * pg_type is filled, so it has to cover the datatypes used as column types
      67                 :             :  * in the core "bootstrapped" catalogs.
      68                 :             :  *
      69                 :             :  *              XXX several of these input/output functions do catalog scans
      70                 :             :  *                      (e.g., F_REGPROCIN scans pg_proc).  this obviously creates some
      71                 :             :  *                      order dependencies in the catalog creation process.
      72                 :             :  */
      73                 :             : struct typinfo
      74                 :             : {
      75                 :             :         char            name[NAMEDATALEN];
      76                 :             :         Oid                     oid;
      77                 :             :         Oid                     elem;
      78                 :             :         int16           len;
      79                 :             :         bool            byval;
      80                 :             :         char            align;
      81                 :             :         char            storage;
      82                 :             :         Oid                     collation;
      83                 :             :         Oid                     inproc;
      84                 :             :         Oid                     outproc;
      85                 :             : };
      86                 :             : 
      87                 :             : static const struct typinfo TypInfo[] = {
      88                 :             :         {"bool", BOOLOID, 0, 1, true, TYPALIGN_CHAR, TYPSTORAGE_PLAIN, InvalidOid,
      89                 :             :         F_BOOLIN, F_BOOLOUT},
      90                 :             :         {"bytea", BYTEAOID, 0, -1, false, TYPALIGN_INT, TYPSTORAGE_EXTENDED, InvalidOid,
      91                 :             :         F_BYTEAIN, F_BYTEAOUT},
      92                 :             :         {"char", CHAROID, 0, 1, true, TYPALIGN_CHAR, TYPSTORAGE_PLAIN, InvalidOid,
      93                 :             :         F_CHARIN, F_CHAROUT},
      94                 :             :         {"int2", INT2OID, 0, 2, true, TYPALIGN_SHORT, TYPSTORAGE_PLAIN, InvalidOid,
      95                 :             :         F_INT2IN, F_INT2OUT},
      96                 :             :         {"int4", INT4OID, 0, 4, true, TYPALIGN_INT, TYPSTORAGE_PLAIN, InvalidOid,
      97                 :             :         F_INT4IN, F_INT4OUT},
      98                 :             :         {"float4", FLOAT4OID, 0, 4, true, TYPALIGN_INT, TYPSTORAGE_PLAIN, InvalidOid,
      99                 :             :         F_FLOAT4IN, F_FLOAT4OUT},
     100                 :             :         {"name", NAMEOID, CHAROID, NAMEDATALEN, false, TYPALIGN_CHAR, TYPSTORAGE_PLAIN, C_COLLATION_OID,
     101                 :             :         F_NAMEIN, F_NAMEOUT},
     102                 :             :         {"regclass", REGCLASSOID, 0, 4, true, TYPALIGN_INT, TYPSTORAGE_PLAIN, InvalidOid,
     103                 :             :         F_REGCLASSIN, F_REGCLASSOUT},
     104                 :             :         {"regproc", REGPROCOID, 0, 4, true, TYPALIGN_INT, TYPSTORAGE_PLAIN, InvalidOid,
     105                 :             :         F_REGPROCIN, F_REGPROCOUT},
     106                 :             :         {"regtype", REGTYPEOID, 0, 4, true, TYPALIGN_INT, TYPSTORAGE_PLAIN, InvalidOid,
     107                 :             :         F_REGTYPEIN, F_REGTYPEOUT},
     108                 :             :         {"regrole", REGROLEOID, 0, 4, true, TYPALIGN_INT, TYPSTORAGE_PLAIN, InvalidOid,
     109                 :             :         F_REGROLEIN, F_REGROLEOUT},
     110                 :             :         {"regnamespace", REGNAMESPACEOID, 0, 4, true, TYPALIGN_INT, TYPSTORAGE_PLAIN, InvalidOid,
     111                 :             :         F_REGNAMESPACEIN, F_REGNAMESPACEOUT},
     112                 :             :         {"regdatabase", REGDATABASEOID, 0, 4, true, TYPALIGN_INT, TYPSTORAGE_PLAIN, InvalidOid,
     113                 :             :         F_REGDATABASEIN, F_REGDATABASEOUT},
     114                 :             :         {"text", TEXTOID, 0, -1, false, TYPALIGN_INT, TYPSTORAGE_EXTENDED, DEFAULT_COLLATION_OID,
     115                 :             :         F_TEXTIN, F_TEXTOUT},
     116                 :             :         {"oid", OIDOID, 0, 4, true, TYPALIGN_INT, TYPSTORAGE_PLAIN, InvalidOid,
     117                 :             :         F_OIDIN, F_OIDOUT},
     118                 :             :         {"oid8", OID8OID, 0, 8, true, TYPALIGN_DOUBLE, TYPSTORAGE_PLAIN, InvalidOid,
     119                 :             :         F_OID8IN, F_OID8OUT},
     120                 :             :         {"tid", TIDOID, 0, 6, false, TYPALIGN_SHORT, TYPSTORAGE_PLAIN, InvalidOid,
     121                 :             :         F_TIDIN, F_TIDOUT},
     122                 :             :         {"xid", XIDOID, 0, 4, true, TYPALIGN_INT, TYPSTORAGE_PLAIN, InvalidOid,
     123                 :             :         F_XIDIN, F_XIDOUT},
     124                 :             :         {"cid", CIDOID, 0, 4, true, TYPALIGN_INT, TYPSTORAGE_PLAIN, InvalidOid,
     125                 :             :         F_CIDIN, F_CIDOUT},
     126                 :             :         {"pg_node_tree", PG_NODE_TREEOID, 0, -1, false, TYPALIGN_INT, TYPSTORAGE_EXTENDED, DEFAULT_COLLATION_OID,
     127                 :             :         F_PG_NODE_TREE_IN, F_PG_NODE_TREE_OUT},
     128                 :             :         {"int2vector", INT2VECTOROID, INT2OID, -1, false, TYPALIGN_INT, TYPSTORAGE_PLAIN, InvalidOid,
     129                 :             :         F_INT2VECTORIN, F_INT2VECTOROUT},
     130                 :             :         {"oidvector", OIDVECTOROID, OIDOID, -1, false, TYPALIGN_INT, TYPSTORAGE_PLAIN, InvalidOid,
     131                 :             :         F_OIDVECTORIN, F_OIDVECTOROUT},
     132                 :             :         {"_int4", INT4ARRAYOID, INT4OID, -1, false, TYPALIGN_INT, TYPSTORAGE_EXTENDED, InvalidOid,
     133                 :             :         F_ARRAY_IN, F_ARRAY_OUT},
     134                 :             :         {"_text", 1009, TEXTOID, -1, false, TYPALIGN_INT, TYPSTORAGE_EXTENDED, DEFAULT_COLLATION_OID,
     135                 :             :         F_ARRAY_IN, F_ARRAY_OUT},
     136                 :             :         {"_oid", 1028, OIDOID, -1, false, TYPALIGN_INT, TYPSTORAGE_EXTENDED, InvalidOid,
     137                 :             :         F_ARRAY_IN, F_ARRAY_OUT},
     138                 :             :         {"_char", 1002, CHAROID, -1, false, TYPALIGN_INT, TYPSTORAGE_EXTENDED, InvalidOid,
     139                 :             :         F_ARRAY_IN, F_ARRAY_OUT},
     140                 :             :         {"_aclitem", 1034, ACLITEMOID, -1, false, TYPALIGN_INT, TYPSTORAGE_EXTENDED, InvalidOid,
     141                 :             :         F_ARRAY_IN, F_ARRAY_OUT}
     142                 :             : };
     143                 :             : 
     144                 :             : static const int n_types = sizeof(TypInfo) / sizeof(struct typinfo);
     145                 :             : 
     146                 :             : struct typmap
     147                 :             : {                                                               /* a hack */
     148                 :             :         Oid                     am_oid;
     149                 :             :         FormData_pg_type am_typ;
     150                 :             : };
     151                 :             : 
     152                 :             : static List *Typ = NIL;                 /* List of struct typmap* */
     153                 :             : static struct typmap *Ap = NULL;
     154                 :             : 
     155                 :             : static Datum values[MAXATTR];   /* current row's attribute values */
     156                 :             : static bool Nulls[MAXATTR];
     157                 :             : 
     158                 :             : static MemoryContext nogc = NULL;       /* special no-gc mem context */
     159                 :             : 
     160                 :             : /*
     161                 :             :  *      At bootstrap time, we first declare all the indices to be built, and
     162                 :             :  *      then build them.  The IndexList structure stores enough information
     163                 :             :  *      to allow us to build the indices after they've been declared.
     164                 :             :  */
     165                 :             : 
     166                 :             : typedef struct _IndexList
     167                 :             : {
     168                 :             :         Oid                     il_heap;
     169                 :             :         Oid                     il_ind;
     170                 :             :         IndexInfo  *il_info;
     171                 :             :         struct _IndexList *il_next;
     172                 :             : } IndexList;
     173                 :             : 
     174                 :             : static IndexList *ILHead = NULL;
     175                 :             : 
     176                 :             : 
     177                 :             : /*
     178                 :             :  * In shared memory checker mode, all we really want to do is create shared
     179                 :             :  * memory and semaphores (just to prove we can do it with the current GUC
     180                 :             :  * settings).  Since, in fact, that was already done by
     181                 :             :  * CreateSharedMemoryAndSemaphores(), we have nothing more to do here.
     182                 :             :  */
     183                 :             : static void
     184                 :           2 : CheckerModeMain(void)
     185                 :             : {
     186                 :           2 :         proc_exit(0);
     187                 :             : }
     188                 :             : 
     189                 :             : /*
     190                 :             :  *       The main entry point for running the backend in bootstrap mode
     191                 :             :  *
     192                 :             :  *       The bootstrap mode is used to initialize the template database.
     193                 :             :  *       The bootstrap backend doesn't speak SQL, but instead expects
     194                 :             :  *       commands in a special bootstrap language.
     195                 :             :  *
     196                 :             :  *       When check_only is true, startup is done only far enough to verify that
     197                 :             :  *       the current configuration, particularly the passed in options pertaining
     198                 :             :  *       to shared memory sizing, options work (or at least do not cause an error
     199                 :             :  *       up to shared memory creation).
     200                 :             :  */
     201                 :             : void
     202                 :           3 : BootstrapModeMain(int argc, char *argv[], bool check_only)
     203                 :             : {
     204                 :           3 :         int                     i;
     205                 :           3 :         char       *progname = argv[0];
     206                 :           3 :         int                     flag;
     207                 :           3 :         char       *userDoption = NULL;
     208                 :           3 :         uint32          bootstrap_data_checksum_version = 0;    /* No checksum */
     209                 :           3 :         yyscan_t        scanner;
     210                 :             : 
     211         [ -  + ]:           3 :         Assert(!IsUnderPostmaster);
     212                 :             : 
     213                 :           3 :         InitStandaloneProcess(argv[0]);
     214                 :             : 
     215                 :             :         /* Set defaults, to be overridden by explicit options below */
     216                 :           3 :         InitializeGUCOptions();
     217                 :             : 
     218                 :             :         /* an initial --boot or --check should be present */
     219   [ +  -  +  +  :           3 :         Assert(argc > 1
                   +  - ]
     220                 :             :                    && (strcmp(argv[1], "--boot") == 0
     221                 :             :                            || strcmp(argv[1], "--check") == 0));
     222                 :           3 :         argv++;
     223                 :           3 :         argc--;
     224                 :             : 
     225         [ +  + ]:          19 :         while ((flag = getopt(argc, argv, "B:c:d:D:Fkr:X:-:")) != -1)
     226                 :             :         {
     227   [ -  -  -  +  :          16 :                 switch (flag)
          -  -  +  +  -  
                      + ]
     228                 :             :                 {
     229                 :             :                         case 'B':
     230                 :           0 :                                 SetConfigOption("shared_buffers", optarg, PGC_POSTMASTER, PGC_S_ARGV);
     231                 :           0 :                                 break;
     232                 :             :                         case '-':
     233                 :             : 
     234                 :             :                                 /*
     235                 :             :                                  * Error if the user misplaced a special must-be-first option
     236                 :             :                                  * for dispatching to a subprogram.  parse_dispatch_option()
     237                 :             :                                  * returns DISPATCH_POSTMASTER if it doesn't find a match, so
     238                 :             :                                  * error for anything else.
     239                 :             :                                  */
     240         [ #  # ]:           0 :                                 if (parse_dispatch_option(optarg) != DISPATCH_POSTMASTER)
     241   [ #  #  #  # ]:           0 :                                         ereport(ERROR,
     242                 :             :                                                         (errcode(ERRCODE_SYNTAX_ERROR),
     243                 :             :                                                          errmsg("--%s must be first argument", optarg)));
     244                 :             : 
     245                 :             :                                 /* FALLTHROUGH */
     246                 :             :                         case 'c':
     247                 :             :                                 {
     248                 :          11 :                                         char       *name,
     249                 :             :                                                            *value;
     250                 :             : 
     251                 :          11 :                                         ParseLongOption(optarg, &name, &value);
     252         [ +  - ]:          11 :                                         if (!value)
     253                 :             :                                         {
     254         [ #  # ]:           0 :                                                 if (flag == '-')
     255   [ #  #  #  # ]:           0 :                                                         ereport(ERROR,
     256                 :             :                                                                         (errcode(ERRCODE_SYNTAX_ERROR),
     257                 :             :                                                                          errmsg("--%s requires a value",
     258                 :             :                                                                                         optarg)));
     259                 :             :                                                 else
     260   [ #  #  #  # ]:           0 :                                                         ereport(ERROR,
     261                 :             :                                                                         (errcode(ERRCODE_SYNTAX_ERROR),
     262                 :             :                                                                          errmsg("-c %s requires a value",
     263                 :             :                                                                                         optarg)));
     264                 :           0 :                                         }
     265                 :             : 
     266                 :          11 :                                         SetConfigOption(name, value, PGC_POSTMASTER, PGC_S_ARGV);
     267                 :          11 :                                         pfree(name);
     268                 :          11 :                                         pfree(value);
     269                 :             :                                         break;
     270                 :          11 :                                 }
     271                 :             :                         case 'D':
     272                 :           0 :                                 userDoption = pstrdup(optarg);
     273                 :           0 :                                 break;
     274                 :             :                         case 'd':
     275                 :             :                                 {
     276                 :             :                                         /* Turn on debugging for the bootstrap process. */
     277                 :           0 :                                         char       *debugstr;
     278                 :             : 
     279                 :           0 :                                         debugstr = psprintf("debug%s", optarg);
     280                 :           0 :                                         SetConfigOption("log_min_messages", debugstr,
     281                 :             :                                                                         PGC_POSTMASTER, PGC_S_ARGV);
     282                 :           0 :                                         SetConfigOption("client_min_messages", debugstr,
     283                 :             :                                                                         PGC_POSTMASTER, PGC_S_ARGV);
     284                 :           0 :                                         pfree(debugstr);
     285                 :           0 :                                 }
     286                 :           0 :                                 break;
     287                 :             :                         case 'F':
     288                 :           3 :                                 SetConfigOption("fsync", "false", PGC_POSTMASTER, PGC_S_ARGV);
     289                 :           3 :                                 break;
     290                 :             :                         case 'k':
     291                 :           1 :                                 bootstrap_data_checksum_version = PG_DATA_CHECKSUM_VERSION;
     292                 :           1 :                                 break;
     293                 :             :                         case 'r':
     294                 :           0 :                                 strlcpy(OutputFileName, optarg, MAXPGPATH);
     295                 :           0 :                                 break;
     296                 :             :                         case 'X':
     297                 :           1 :                                 SetConfigOption("wal_segment_size", optarg, PGC_INTERNAL, PGC_S_DYNAMIC_DEFAULT);
     298                 :           1 :                                 break;
     299                 :             :                         default:
     300                 :           0 :                                 write_stderr("Try \"%s --help\" for more information.\n",
     301                 :           0 :                                                          progname);
     302                 :           0 :                                 proc_exit(1);
     303                 :             :                                 break;
     304                 :             :                 }
     305                 :             :         }
     306                 :             : 
     307         [ -  + ]:           3 :         if (argc != optind)
     308                 :             :         {
     309                 :           0 :                 write_stderr("%s: invalid command-line arguments\n", progname);
     310                 :           0 :                 proc_exit(1);
     311                 :             :         }
     312                 :             : 
     313                 :             :         /* Acquire configuration parameters */
     314         [ +  - ]:           3 :         if (!SelectConfigFiles(userDoption, progname))
     315                 :           0 :                 proc_exit(1);
     316                 :             : 
     317                 :             :         /*
     318                 :             :          * Validate we have been given a reasonable-looking DataDir and change
     319                 :             :          * into it
     320                 :             :          */
     321                 :           3 :         checkDataDir();
     322                 :           3 :         ChangeToDataDir();
     323                 :             : 
     324                 :           3 :         CreateDataDirLockFile(false);
     325                 :             : 
     326                 :           3 :         SetProcessingMode(BootstrapProcessing);
     327                 :           3 :         IgnoreSystemIndexes = true;
     328                 :             : 
     329                 :           3 :         InitializeMaxBackends();
     330                 :             : 
     331                 :             :         /*
     332                 :             :          * Even though bootstrapping runs in single-process mode, initialize
     333                 :             :          * postmaster child slots array so that --check can detect running out of
     334                 :             :          * shared memory or other resources if max_connections is set too high.
     335                 :             :          */
     336                 :           3 :         InitPostmasterChildSlots();
     337                 :             : 
     338                 :           3 :         InitializeFastPathLocks();
     339                 :             : 
     340                 :           3 :         CreateSharedMemoryAndSemaphores();
     341                 :             : 
     342                 :             :         /*
     343                 :             :          * Estimate number of openable files.  This is essential too in --check
     344                 :             :          * mode, because on some platforms semaphores count as open files.
     345                 :             :          */
     346                 :           3 :         set_max_safe_fds();
     347                 :             : 
     348                 :             :         /*
     349                 :             :          * XXX: It might make sense to move this into its own function at some
     350                 :             :          * point. Right now it seems like it'd cause more code duplication than
     351                 :             :          * it's worth.
     352                 :             :          */
     353         [ +  + ]:           3 :         if (check_only)
     354                 :             :         {
     355                 :           2 :                 SetProcessingMode(NormalProcessing);
     356                 :           2 :                 CheckerModeMain();
     357                 :           2 :                 abort();
     358                 :             :         }
     359                 :             : 
     360                 :             :         /*
     361                 :             :          * Do backend-like initialization for bootstrap mode
     362                 :             :          */
     363                 :           1 :         InitProcess();
     364                 :             : 
     365                 :           1 :         BaseInit();
     366                 :             : 
     367                 :           1 :         bootstrap_signals();
     368                 :           1 :         BootStrapXLOG(bootstrap_data_checksum_version);
     369                 :             : 
     370                 :             :         /*
     371                 :             :          * To ensure that src/common/link-canary.c is linked into the backend, we
     372                 :             :          * must call it from somewhere.  Here is as good as anywhere.
     373                 :             :          */
     374         [ +  - ]:           1 :         if (pg_link_canary_is_frontend())
     375   [ #  #  #  # ]:           0 :                 elog(ERROR, "backend is incorrectly linked to frontend functions");
     376                 :             : 
     377                 :           1 :         InitPostgres(NULL, InvalidOid, NULL, InvalidOid, 0, NULL);
     378                 :             : 
     379                 :             :         /* Initialize stuff for bootstrap-file processing */
     380         [ +  + ]:          41 :         for (i = 0; i < MAXATTR; i++)
     381                 :             :         {
     382                 :          40 :                 attrtypes[i] = NULL;
     383                 :          40 :                 Nulls[i] = false;
     384                 :          40 :         }
     385                 :             : 
     386         [ +  - ]:           1 :         if (boot_yylex_init(&scanner) != 0)
     387   [ #  #  #  # ]:           0 :                 elog(ERROR, "yylex_init() failed: %m");
     388                 :             : 
     389                 :             :         /*
     390                 :             :          * Process bootstrap input.
     391                 :             :          */
     392                 :           1 :         StartTransactionCommand();
     393                 :           1 :         boot_yyparse(scanner);
     394                 :           1 :         CommitTransactionCommand();
     395                 :             : 
     396                 :             :         /*
     397                 :             :          * We should now know about all mapped relations, so it's okay to write
     398                 :             :          * out the initial relation mapping files.
     399                 :             :          */
     400                 :           1 :         RelationMapFinishBootstrap();
     401                 :             : 
     402                 :             :         /* Clean up and exit */
     403                 :           1 :         cleanup();
     404                 :           1 :         proc_exit(0);
     405                 :             : }
     406                 :             : 
     407                 :             : 
     408                 :             : /* ----------------------------------------------------------------
     409                 :             :  *                                              misc functions
     410                 :             :  * ----------------------------------------------------------------
     411                 :             :  */
     412                 :             : 
     413                 :             : /*
     414                 :             :  * Set up signal handling for a bootstrap process
     415                 :             :  */
     416                 :             : static void
     417                 :           1 : bootstrap_signals(void)
     418                 :             : {
     419         [ +  - ]:           1 :         Assert(!IsUnderPostmaster);
     420                 :             : 
     421                 :             :         /*
     422                 :             :          * We don't actually need any non-default signal handling in bootstrap
     423                 :             :          * mode; "curl up and die" is a sufficient response for all these cases.
     424                 :             :          * Let's set that handling explicitly, as documentation if nothing else.
     425                 :             :          */
     426                 :           1 :         pqsignal(SIGHUP, SIG_DFL);
     427                 :           1 :         pqsignal(SIGINT, SIG_DFL);
     428                 :           1 :         pqsignal(SIGTERM, SIG_DFL);
     429                 :           1 :         pqsignal(SIGQUIT, SIG_DFL);
     430                 :           1 : }
     431                 :             : 
     432                 :             : /* ----------------------------------------------------------------
     433                 :             :  *                              MANUAL BACKEND INTERACTIVE INTERFACE COMMANDS
     434                 :             :  * ----------------------------------------------------------------
     435                 :             :  */
     436                 :             : 
     437                 :             : /* ----------------
     438                 :             :  *              boot_openrel
     439                 :             :  *
     440                 :             :  * Execute BKI OPEN command.
     441                 :             :  * ----------------
     442                 :             :  */
     443                 :             : void
     444                 :          60 : boot_openrel(char *relname)
     445                 :             : {
     446                 :          60 :         int                     i;
     447                 :             : 
     448         [ +  - ]:          60 :         if (strlen(relname) >= NAMEDATALEN)
     449                 :           0 :                 relname[NAMEDATALEN - 1] = '\0';
     450                 :             : 
     451                 :             :         /*
     452                 :             :          * pg_type must be filled before any OPEN command is executed, hence we
     453                 :             :          * can now populate Typ if we haven't yet.
     454                 :             :          */
     455         [ +  - ]:          60 :         if (Typ == NIL)
     456                 :           0 :                 populate_typ_list();
     457                 :             : 
     458         [ +  - ]:          60 :         if (boot_reldesc != NULL)
     459                 :           0 :                 closerel(NULL);
     460                 :             : 
     461   [ -  +  -  + ]:          60 :         elog(DEBUG4, "open relation %s, attrsize %d",
     462                 :             :                  relname, (int) ATTRIBUTE_FIXED_PART_SIZE);
     463                 :             : 
     464                 :          60 :         boot_reldesc = table_openrv(makeRangeVar(NULL, relname, -1), NoLock);
     465                 :          60 :         numattr = RelationGetNumberOfAttributes(boot_reldesc);
     466         [ +  + ]:         549 :         for (i = 0; i < numattr; i++)
     467                 :             :         {
     468         [ +  - ]:         489 :                 if (attrtypes[i] == NULL)
     469                 :           0 :                         attrtypes[i] = AllocateAttribute();
     470                 :         489 :                 memmove(attrtypes[i],
     471                 :             :                                 TupleDescAttr(boot_reldesc->rd_att, i),
     472                 :             :                                 ATTRIBUTE_FIXED_PART_SIZE);
     473                 :             : 
     474                 :             :                 {
     475                 :         489 :                         Form_pg_attribute at = attrtypes[i];
     476                 :             : 
     477   [ -  +  -  + ]:         489 :                         elog(DEBUG4, "create attribute %d name %s len %d num %d type %u",
     478                 :             :                                  i, NameStr(at->attname), at->attlen, at->attnum,
     479                 :             :                                  at->atttypid);
     480                 :         489 :                 }
     481                 :         489 :         }
     482                 :          60 : }
     483                 :             : 
     484                 :             : /* ----------------
     485                 :             :  *              closerel
     486                 :             :  * ----------------
     487                 :             :  */
     488                 :             : void
     489                 :          64 : closerel(char *relname)
     490                 :             : {
     491         [ -  + ]:          64 :         if (relname)
     492                 :             :         {
     493         [ +  - ]:          64 :                 if (boot_reldesc)
     494                 :             :                 {
     495         [ +  - ]:          64 :                         if (strcmp(RelationGetRelationName(boot_reldesc), relname) != 0)
     496   [ #  #  #  # ]:           0 :                                 elog(ERROR, "close of %s when %s was expected",
     497                 :             :                                          relname, RelationGetRelationName(boot_reldesc));
     498                 :          64 :                 }
     499                 :             :                 else
     500   [ #  #  #  # ]:           0 :                         elog(ERROR, "close of %s before any relation was opened",
     501                 :             :                                  relname);
     502                 :          64 :         }
     503                 :             : 
     504         [ +  - ]:          64 :         if (boot_reldesc == NULL)
     505   [ #  #  #  # ]:           0 :                 elog(ERROR, "no open relation to close");
     506                 :             :         else
     507                 :             :         {
     508   [ -  +  -  + ]:          64 :                 elog(DEBUG4, "close relation %s",
     509                 :             :                          RelationGetRelationName(boot_reldesc));
     510                 :          64 :                 table_close(boot_reldesc, NoLock);
     511                 :          64 :                 boot_reldesc = NULL;
     512                 :             :         }
     513                 :          64 : }
     514                 :             : 
     515                 :             : 
     516                 :             : 
     517                 :             : /* ----------------
     518                 :             :  * DEFINEATTR()
     519                 :             :  *
     520                 :             :  * define a <field,type> pair
     521                 :             :  * if there are n fields in a relation to be created, this routine
     522                 :             :  * will be called n times
     523                 :             :  * ----------------
     524                 :             :  */
     525                 :             : void
     526                 :         610 : DefineAttr(char *name, char *type, int attnum, int nullness)
     527                 :             : {
     528                 :         610 :         Oid                     typeoid;
     529                 :             : 
     530         [ +  - ]:         610 :         if (boot_reldesc != NULL)
     531                 :             :         {
     532   [ #  #  #  # ]:           0 :                 elog(WARNING, "no open relations allowed with CREATE command");
     533                 :           0 :                 closerel(NULL);
     534                 :           0 :         }
     535                 :             : 
     536         [ +  + ]:         610 :         if (attrtypes[attnum] == NULL)
     537                 :          34 :                 attrtypes[attnum] = AllocateAttribute();
     538   [ +  -  -  +  :         610 :         MemSet(attrtypes[attnum], 0, ATTRIBUTE_FIXED_PART_SIZE);
          #  #  #  #  #  
                      # ]
     539                 :             : 
     540                 :         610 :         namestrcpy(&attrtypes[attnum]->attname, name);
     541   [ -  +  -  + ]:         610 :         elog(DEBUG4, "column %s %s", NameStr(attrtypes[attnum]->attname), type);
     542                 :         610 :         attrtypes[attnum]->attnum = attnum + 1;
     543                 :             : 
     544                 :         610 :         typeoid = gettype(type);
     545                 :             : 
     546         [ +  + ]:         610 :         if (Typ != NIL)
     547                 :             :         {
     548                 :         524 :                 attrtypes[attnum]->atttypid = Ap->am_oid;
     549                 :         524 :                 attrtypes[attnum]->attlen = Ap->am_typ.typlen;
     550                 :         524 :                 attrtypes[attnum]->attbyval = Ap->am_typ.typbyval;
     551                 :         524 :                 attrtypes[attnum]->attalign = Ap->am_typ.typalign;
     552                 :         524 :                 attrtypes[attnum]->attstorage = Ap->am_typ.typstorage;
     553                 :         524 :                 attrtypes[attnum]->attcompression = InvalidCompressionMethod;
     554                 :         524 :                 attrtypes[attnum]->attcollation = Ap->am_typ.typcollation;
     555                 :             :                 /* if an array type, assume 1-dimensional attribute */
     556   [ +  +  +  + ]:         524 :                 if (Ap->am_typ.typelem != InvalidOid && Ap->am_typ.typlen < 0)
     557                 :          47 :                         attrtypes[attnum]->attndims = 1;
     558                 :             :                 else
     559                 :         477 :                         attrtypes[attnum]->attndims = 0;
     560                 :         524 :         }
     561                 :             :         else
     562                 :             :         {
     563                 :          86 :                 attrtypes[attnum]->atttypid = TypInfo[typeoid].oid;
     564                 :          86 :                 attrtypes[attnum]->attlen = TypInfo[typeoid].len;
     565                 :          86 :                 attrtypes[attnum]->attbyval = TypInfo[typeoid].byval;
     566                 :          86 :                 attrtypes[attnum]->attalign = TypInfo[typeoid].align;
     567                 :          86 :                 attrtypes[attnum]->attstorage = TypInfo[typeoid].storage;
     568                 :          86 :                 attrtypes[attnum]->attcompression = InvalidCompressionMethod;
     569                 :          86 :                 attrtypes[attnum]->attcollation = TypInfo[typeoid].collation;
     570                 :             :                 /* if an array type, assume 1-dimensional attribute */
     571   [ +  +  +  + ]:          86 :                 if (TypInfo[typeoid].elem != InvalidOid &&
     572                 :          14 :                         attrtypes[attnum]->attlen < 0)
     573                 :          11 :                         attrtypes[attnum]->attndims = 1;
     574                 :             :                 else
     575                 :          75 :                         attrtypes[attnum]->attndims = 0;
     576                 :             :         }
     577                 :             : 
     578                 :             :         /*
     579                 :             :          * If a system catalog column is collation-aware, force it to use C
     580                 :             :          * collation, so that its behavior is independent of the database's
     581                 :             :          * collation.  This is essential to allow template0 to be cloned with a
     582                 :             :          * different database collation.
     583                 :             :          */
     584         [ +  + ]:         610 :         if (OidIsValid(attrtypes[attnum]->attcollation))
     585                 :          99 :                 attrtypes[attnum]->attcollation = C_COLLATION_OID;
     586                 :             : 
     587                 :         610 :         attrtypes[attnum]->atttypmod = -1;
     588                 :         610 :         attrtypes[attnum]->attislocal = true;
     589                 :             : 
     590         [ +  + ]:         610 :         if (nullness == BOOTCOL_NULL_FORCE_NOT_NULL)
     591                 :             :         {
     592                 :          34 :                 attrtypes[attnum]->attnotnull = true;
     593                 :          34 :         }
     594         [ +  + ]:         576 :         else if (nullness == BOOTCOL_NULL_FORCE_NULL)
     595                 :             :         {
     596                 :           4 :                 attrtypes[attnum]->attnotnull = false;
     597                 :           4 :         }
     598                 :             :         else
     599                 :             :         {
     600         [ +  - ]:         572 :                 Assert(nullness == BOOTCOL_NULL_AUTO);
     601                 :             : 
     602                 :             :                 /*
     603                 :             :                  * Mark as "not null" if type is fixed-width and prior columns are
     604                 :             :                  * likewise fixed-width and not-null.  This corresponds to case where
     605                 :             :                  * column can be accessed directly via C struct declaration.
     606                 :             :                  */
     607         [ +  + ]:         572 :                 if (attrtypes[attnum]->attlen > 0)
     608                 :             :                 {
     609                 :         490 :                         int                     i;
     610                 :             : 
     611                 :             :                         /* check earlier attributes */
     612         [ +  + ]:        3503 :                         for (i = 0; i < attnum; i++)
     613                 :             :                         {
     614   [ +  +  -  + ]:        3016 :                                 if (attrtypes[i]->attlen <= 0 ||
     615                 :        3013 :                                         !attrtypes[i]->attnotnull)
     616                 :           3 :                                         break;
     617                 :        3013 :                         }
     618         [ +  + ]:         490 :                         if (i == attnum)
     619                 :         487 :                                 attrtypes[attnum]->attnotnull = true;
     620                 :         490 :                 }
     621                 :             :         }
     622                 :         610 : }
     623                 :             : 
     624                 :             : 
     625                 :             : /* ----------------
     626                 :             :  *              InsertOneTuple
     627                 :             :  *
     628                 :             :  * If objectid is not zero, it is a specific OID to assign to the tuple.
     629                 :             :  * Otherwise, an OID will be assigned (if necessary) by heap_insert.
     630                 :             :  * ----------------
     631                 :             :  */
     632                 :             : void
     633                 :       10912 : InsertOneTuple(void)
     634                 :             : {
     635                 :       10912 :         HeapTuple       tuple;
     636                 :       10912 :         TupleDesc       tupDesc;
     637                 :       10912 :         int                     i;
     638                 :             : 
     639   [ -  +  -  + ]:       10912 :         elog(DEBUG4, "inserting row with %d columns", numattr);
     640                 :             : 
     641                 :       10912 :         tupDesc = CreateTupleDesc(numattr, attrtypes);
     642                 :       10912 :         tuple = heap_form_tuple(tupDesc, values, Nulls);
     643                 :       10912 :         pfree(tupDesc);                         /* just free's tupDesc, not the attrtypes */
     644                 :             : 
     645                 :       10912 :         simple_heap_insert(boot_reldesc, tuple);
     646                 :       10912 :         heap_freetuple(tuple);
     647   [ -  +  -  + ]:       10912 :         elog(DEBUG4, "row inserted");
     648                 :             : 
     649                 :             :         /*
     650                 :             :          * Reset null markers for next tuple
     651                 :             :          */
     652         [ +  + ]:      172891 :         for (i = 0; i < numattr; i++)
     653                 :      161979 :                 Nulls[i] = false;
     654                 :       10912 : }
     655                 :             : 
     656                 :             : /* ----------------
     657                 :             :  *              InsertOneValue
     658                 :             :  * ----------------
     659                 :             :  */
     660                 :             : void
     661                 :      129938 : InsertOneValue(char *value, int i)
     662                 :             : {
     663                 :      129938 :         Oid                     typoid;
     664                 :      129938 :         int16           typlen;
     665                 :      129938 :         bool            typbyval;
     666                 :      129938 :         char            typalign;
     667                 :      129938 :         char            typdelim;
     668                 :      129938 :         Oid                     typioparam;
     669                 :      129938 :         Oid                     typinput;
     670                 :      129938 :         Oid                     typoutput;
     671                 :             : 
     672         [ +  - ]:      129938 :         Assert(i >= 0 && i < MAXATTR);
     673                 :             : 
     674   [ -  +  -  + ]:      129938 :         elog(DEBUG4, "inserting column %d value \"%s\"", i, value);
     675                 :             : 
     676                 :      129938 :         typoid = TupleDescAttr(boot_reldesc->rd_att, i)->atttypid;
     677                 :             : 
     678                 :      129938 :         boot_get_type_io_data(typoid,
     679                 :             :                                                   &typlen, &typbyval, &typalign,
     680                 :             :                                                   &typdelim, &typioparam,
     681                 :             :                                                   &typinput, &typoutput);
     682                 :             : 
     683                 :      129938 :         values[i] = OidInputFunctionCall(typinput, value, typioparam, -1);
     684                 :             : 
     685                 :             :         /*
     686                 :             :          * We use ereport not elog here so that parameters aren't evaluated unless
     687                 :             :          * the message is going to be printed, which generally it isn't
     688                 :             :          */
     689   [ -  +  -  + ]:      129938 :         ereport(DEBUG4,
     690                 :             :                         (errmsg_internal("inserted -> %s",
     691                 :             :                                                          OidOutputFunctionCall(typoutput, values[i]))));
     692                 :      129938 : }
     693                 :             : 
     694                 :             : /* ----------------
     695                 :             :  *              InsertOneNull
     696                 :             :  * ----------------
     697                 :             :  */
     698                 :             : void
     699                 :       32041 : InsertOneNull(int i)
     700                 :             : {
     701   [ -  +  -  + ]:       32041 :         elog(DEBUG4, "inserting column %d NULL", i);
     702         [ +  - ]:       32041 :         Assert(i >= 0 && i < MAXATTR);
     703         [ +  - ]:       32041 :         if (TupleDescAttr(boot_reldesc->rd_att, i)->attnotnull)
     704   [ #  #  #  # ]:           0 :                 elog(ERROR,
     705                 :             :                          "NULL value specified for not-null column \"%s\" of relation \"%s\"",
     706                 :             :                          NameStr(TupleDescAttr(boot_reldesc->rd_att, i)->attname),
     707                 :             :                          RelationGetRelationName(boot_reldesc));
     708                 :       32041 :         values[i] = PointerGetDatum(NULL);
     709                 :       32041 :         Nulls[i] = true;
     710                 :       32041 : }
     711                 :             : 
     712                 :             : /* ----------------
     713                 :             :  *              cleanup
     714                 :             :  * ----------------
     715                 :             :  */
     716                 :             : static void
     717                 :           1 : cleanup(void)
     718                 :             : {
     719         [ +  - ]:           1 :         if (boot_reldesc != NULL)
     720                 :           0 :                 closerel(NULL);
     721                 :           1 : }
     722                 :             : 
     723                 :             : /* ----------------
     724                 :             :  *              populate_typ_list
     725                 :             :  *
     726                 :             :  * Load the Typ list by reading pg_type.
     727                 :             :  * ----------------
     728                 :             :  */
     729                 :             : static void
     730                 :           2 : populate_typ_list(void)
     731                 :             : {
     732                 :           2 :         Relation        rel;
     733                 :           2 :         TableScanDesc scan;
     734                 :           2 :         HeapTuple       tup;
     735                 :           2 :         MemoryContext old;
     736                 :             : 
     737         [ +  - ]:           2 :         Assert(Typ == NIL);
     738                 :             : 
     739                 :           2 :         rel = table_open(TypeRelationId, NoLock);
     740                 :           2 :         scan = table_beginscan_catalog(rel, 0, NULL);
     741                 :           2 :         old = MemoryContextSwitchTo(TopMemoryContext);
     742         [ +  + ]:         428 :         while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL)
     743                 :             :         {
     744                 :         426 :                 Form_pg_type typForm = (Form_pg_type) GETSTRUCT(tup);
     745                 :         426 :                 struct typmap *newtyp;
     746                 :             : 
     747                 :         426 :                 newtyp = palloc_object(struct typmap);
     748                 :         426 :                 Typ = lappend(Typ, newtyp);
     749                 :             : 
     750                 :         426 :                 newtyp->am_oid = typForm->oid;
     751                 :         426 :                 memcpy(&newtyp->am_typ, typForm, sizeof(newtyp->am_typ));
     752                 :         426 :         }
     753                 :           2 :         MemoryContextSwitchTo(old);
     754                 :           2 :         table_endscan(scan);
     755                 :           2 :         table_close(rel, NoLock);
     756                 :           2 : }
     757                 :             : 
     758                 :             : /* ----------------
     759                 :             :  *              gettype
     760                 :             :  *
     761                 :             :  * NB: this is really ugly; it will return an integer index into TypInfo[],
     762                 :             :  * and not an OID at all, until the first reference to a type not known in
     763                 :             :  * TypInfo[].  At that point it will read and cache pg_type in Typ,
     764                 :             :  * and subsequently return a real OID (and set the global pointer Ap to
     765                 :             :  * point at the found row in Typ).  So caller must check whether Typ is
     766                 :             :  * still NIL to determine what the return value is!
     767                 :             :  * ----------------
     768                 :             :  */
     769                 :             : static Oid
     770                 :         611 : gettype(char *type)
     771                 :             : {
     772         [ +  + ]:         611 :         if (Typ != NIL)
     773                 :             :         {
     774                 :         524 :                 ListCell   *lc;
     775                 :             : 
     776   [ +  -  +  +  :       10315 :                 foreach(lc, Typ)
             +  +  +  + ]
     777                 :             :                 {
     778                 :        9791 :                         struct typmap *app = lfirst(lc);
     779                 :             : 
     780         [ +  + ]:        9791 :                         if (strncmp(NameStr(app->am_typ.typname), type, NAMEDATALEN) == 0)
     781                 :             :                         {
     782                 :         523 :                                 Ap = app;
     783                 :         523 :                                 return app->am_oid;
     784                 :             :                         }
     785         [ +  + ]:        9791 :                 }
     786                 :             : 
     787                 :             :                 /*
     788                 :             :                  * The type wasn't known; reload the pg_type contents and check again
     789                 :             :                  * to handle composite types, added since last populating the list.
     790                 :             :                  */
     791                 :             : 
     792                 :           1 :                 list_free_deep(Typ);
     793                 :           1 :                 Typ = NIL;
     794                 :           1 :                 populate_typ_list();
     795                 :             : 
     796                 :             :                 /*
     797                 :             :                  * Calling gettype would result in infinite recursion for types
     798                 :             :                  * missing in pg_type, so just repeat the lookup.
     799                 :             :                  */
     800   [ +  -  -  +  :         228 :                 foreach(lc, Typ)
             +  -  +  - ]
     801                 :             :                 {
     802                 :         227 :                         struct typmap *app = lfirst(lc);
     803                 :             : 
     804         [ +  + ]:         227 :                         if (strncmp(NameStr(app->am_typ.typname), type, NAMEDATALEN) == 0)
     805                 :             :                         {
     806                 :           1 :                                 Ap = app;
     807                 :           1 :                                 return app->am_oid;
     808                 :             :                         }
     809         [ +  + ]:         227 :                 }
     810      [ -  +  - ]:         524 :         }
     811                 :             :         else
     812                 :             :         {
     813                 :          87 :                 int                     i;
     814                 :             : 
     815         [ +  + ]:         874 :                 for (i = 0; i < n_types; i++)
     816                 :             :                 {
     817         [ +  + ]:         873 :                         if (strncmp(type, TypInfo[i].name, NAMEDATALEN) == 0)
     818                 :          86 :                                 return i;
     819                 :         787 :                 }
     820                 :             :                 /* Not in TypInfo, so we'd better be able to read pg_type now */
     821   [ -  +  -  + ]:           1 :                 elog(DEBUG4, "external type: %s", type);
     822                 :           1 :                 populate_typ_list();
     823                 :           1 :                 return gettype(type);
     824                 :          87 :         }
     825   [ #  #  #  # ]:           0 :         elog(ERROR, "unrecognized type \"%s\"", type);
     826                 :             :         /* not reached, here to make compiler happy */
     827                 :           0 :         return 0;
     828                 :         611 : }
     829                 :             : 
     830                 :             : /* ----------------
     831                 :             :  *              boot_get_type_io_data
     832                 :             :  *
     833                 :             :  * Obtain type I/O information at bootstrap time.  This intentionally has
     834                 :             :  * almost the same API as lsyscache.c's get_type_io_data, except that
     835                 :             :  * we only support obtaining the typinput and typoutput routines, not
     836                 :             :  * the binary I/O routines.  It is exported so that array_in and array_out
     837                 :             :  * can be made to work during early bootstrap.
     838                 :             :  * ----------------
     839                 :             :  */
     840                 :             : void
     841                 :      130428 : boot_get_type_io_data(Oid typid,
     842                 :             :                                           int16 *typlen,
     843                 :             :                                           bool *typbyval,
     844                 :             :                                           char *typalign,
     845                 :             :                                           char *typdelim,
     846                 :             :                                           Oid *typioparam,
     847                 :             :                                           Oid *typinput,
     848                 :             :                                           Oid *typoutput)
     849                 :             : {
     850         [ +  + ]:      130428 :         if (Typ != NIL)
     851                 :             :         {
     852                 :             :                 /* We have the boot-time contents of pg_type, so use it */
     853                 :       51495 :                 struct typmap *ap = NULL;
     854                 :       51495 :                 ListCell   *lc;
     855                 :             : 
     856   [ +  -  -  +  :      508075 :                 foreach(lc, Typ)
                   +  - ]
     857                 :             :                 {
     858                 :      456580 :                         ap = lfirst(lc);
     859         [ +  + ]:      456580 :                         if (ap->am_oid == typid)
     860                 :       51495 :                                 break;
     861                 :      405085 :                 }
     862                 :             : 
     863         [ +  - ]:       51495 :                 if (!ap || ap->am_oid != typid)
     864   [ #  #  #  # ]:           0 :                         elog(ERROR, "type OID %u not found in Typ list", typid);
     865                 :             : 
     866                 :       51495 :                 *typlen = ap->am_typ.typlen;
     867                 :       51495 :                 *typbyval = ap->am_typ.typbyval;
     868                 :       51495 :                 *typalign = ap->am_typ.typalign;
     869                 :       51495 :                 *typdelim = ap->am_typ.typdelim;
     870                 :             : 
     871                 :             :                 /* XXX this logic must match getTypeIOParam() */
     872         [ +  + ]:       51495 :                 if (OidIsValid(ap->am_typ.typelem))
     873                 :        1456 :                         *typioparam = ap->am_typ.typelem;
     874                 :             :                 else
     875                 :       50039 :                         *typioparam = typid;
     876                 :             : 
     877                 :       51495 :                 *typinput = ap->am_typ.typinput;
     878                 :       51495 :                 *typoutput = ap->am_typ.typoutput;
     879                 :       51495 :         }
     880                 :             :         else
     881                 :             :         {
     882                 :             :                 /* We don't have pg_type yet, so use the hard-wired TypInfo array */
     883                 :       78933 :                 int                     typeindex;
     884                 :             : 
     885         [ -  + ]:      665777 :                 for (typeindex = 0; typeindex < n_types; typeindex++)
     886                 :             :                 {
     887         [ +  + ]:      665777 :                         if (TypInfo[typeindex].oid == typid)
     888                 :       78933 :                                 break;
     889                 :      586844 :                 }
     890         [ +  - ]:       78933 :                 if (typeindex >= n_types)
     891   [ #  #  #  # ]:           0 :                         elog(ERROR, "type OID %u not found in TypInfo", typid);
     892                 :             : 
     893                 :       78933 :                 *typlen = TypInfo[typeindex].len;
     894                 :       78933 :                 *typbyval = TypInfo[typeindex].byval;
     895                 :       78933 :                 *typalign = TypInfo[typeindex].align;
     896                 :             :                 /* We assume typdelim is ',' for all boot-time types */
     897                 :       78933 :                 *typdelim = ',';
     898                 :             : 
     899                 :             :                 /* XXX this logic must match getTypeIOParam() */
     900         [ +  + ]:       78933 :                 if (OidIsValid(TypInfo[typeindex].elem))
     901                 :        7559 :                         *typioparam = TypInfo[typeindex].elem;
     902                 :             :                 else
     903                 :       71374 :                         *typioparam = typid;
     904                 :             : 
     905                 :       78933 :                 *typinput = TypInfo[typeindex].inproc;
     906                 :       78933 :                 *typoutput = TypInfo[typeindex].outproc;
     907                 :       78933 :         }
     908                 :      130428 : }
     909                 :             : 
     910                 :             : /* ----------------
     911                 :             :  *              AllocateAttribute
     912                 :             :  *
     913                 :             :  * Note: bootstrap never sets any per-column ACLs, so we only need
     914                 :             :  * ATTRIBUTE_FIXED_PART_SIZE space per attribute.
     915                 :             :  * ----------------
     916                 :             :  */
     917                 :             : static Form_pg_attribute
     918                 :          34 : AllocateAttribute(void)
     919                 :             : {
     920                 :          34 :         return (Form_pg_attribute)
     921                 :          34 :                 MemoryContextAllocZero(TopMemoryContext, ATTRIBUTE_FIXED_PART_SIZE);
     922                 :             : }
     923                 :             : 
     924                 :             : /*
     925                 :             :  *      index_register() -- record an index that has been set up for building
     926                 :             :  *                                              later.
     927                 :             :  *
     928                 :             :  *              At bootstrap time, we define a bunch of indexes on system catalogs.
     929                 :             :  *              We postpone actually building the indexes until just before we're
     930                 :             :  *              finished with initialization, however.  This is because the indexes
     931                 :             :  *              themselves have catalog entries, and those have to be included in the
     932                 :             :  *              indexes on those catalogs.  Doing it in two phases is the simplest
     933                 :             :  *              way of making sure the indexes have the right contents at the end.
     934                 :             :  */
     935                 :             : void
     936                 :         159 : index_register(Oid heap,
     937                 :             :                            Oid ind,
     938                 :             :                            const IndexInfo *indexInfo)
     939                 :             : {
     940                 :         159 :         IndexList  *newind;
     941                 :         159 :         MemoryContext oldcxt;
     942                 :             : 
     943                 :             :         /*
     944                 :             :          * XXX mao 10/31/92 -- don't gc index reldescs, associated info at
     945                 :             :          * bootstrap time.  we'll declare the indexes now, but want to create them
     946                 :             :          * later.
     947                 :             :          */
     948                 :             : 
     949         [ +  + ]:         159 :         if (nogc == NULL)
     950                 :           1 :                 nogc = AllocSetContextCreate(NULL,
     951                 :             :                                                                          "BootstrapNoGC",
     952                 :             :                                                                          ALLOCSET_DEFAULT_SIZES);
     953                 :             : 
     954                 :         159 :         oldcxt = MemoryContextSwitchTo(nogc);
     955                 :             : 
     956                 :         159 :         newind = palloc_object(IndexList);
     957                 :         159 :         newind->il_heap = heap;
     958                 :         159 :         newind->il_ind = ind;
     959                 :         159 :         newind->il_info = palloc_object(IndexInfo);
     960                 :             : 
     961                 :         159 :         memcpy(newind->il_info, indexInfo, sizeof(IndexInfo));
     962                 :             :         /* expressions will likely be null, but may as well copy it */
     963                 :         159 :         newind->il_info->ii_Expressions =
     964                 :         159 :                 copyObject(indexInfo->ii_Expressions);
     965                 :         159 :         newind->il_info->ii_ExpressionsState = NIL;
     966                 :             :         /* predicate will likely be null, but may as well copy it */
     967                 :         159 :         newind->il_info->ii_Predicate =
     968                 :         159 :                 copyObject(indexInfo->ii_Predicate);
     969                 :         159 :         newind->il_info->ii_PredicateState = NULL;
     970                 :             :         /* no exclusion constraints at bootstrap time, so no need to copy */
     971         [ +  - ]:         159 :         Assert(indexInfo->ii_ExclusionOps == NULL);
     972         [ +  - ]:         159 :         Assert(indexInfo->ii_ExclusionProcs == NULL);
     973         [ +  - ]:         159 :         Assert(indexInfo->ii_ExclusionStrats == NULL);
     974                 :             : 
     975                 :         159 :         newind->il_next = ILHead;
     976                 :         159 :         ILHead = newind;
     977                 :             : 
     978                 :         159 :         MemoryContextSwitchTo(oldcxt);
     979                 :         159 : }
     980                 :             : 
     981                 :             : 
     982                 :             : /*
     983                 :             :  * build_indices -- fill in all the indexes registered earlier
     984                 :             :  */
     985                 :             : void
     986                 :           1 : build_indices(void)
     987                 :             : {
     988         [ +  + ]:         160 :         for (; ILHead != NULL; ILHead = ILHead->il_next)
     989                 :             :         {
     990                 :         159 :                 Relation        heap;
     991                 :         159 :                 Relation        ind;
     992                 :             : 
     993                 :             :                 /* need not bother with locks during bootstrap */
     994                 :         159 :                 heap = table_open(ILHead->il_heap, NoLock);
     995                 :         159 :                 ind = index_open(ILHead->il_ind, NoLock);
     996                 :             : 
     997                 :         159 :                 index_build(heap, ind, ILHead->il_info, false, false);
     998                 :             : 
     999                 :         159 :                 index_close(ind, NoLock);
    1000                 :         159 :                 table_close(heap, NoLock);
    1001                 :         159 :         }
    1002                 :           1 : }
        

Generated by: LCOV version 2.3.2-1