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