Line data Source code
1 : %{
2 : /*-------------------------------------------------------------------------
3 : *
4 : * bootparse.y
5 : * yacc grammar for the "bootstrap" mode (BKI file format)
6 : *
7 : * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
8 : * Portions Copyright (c) 1994, Regents of the University of California
9 : *
10 : *
11 : * IDENTIFICATION
12 : * src/backend/bootstrap/bootparse.y
13 : *
14 : *-------------------------------------------------------------------------
15 : */
16 :
17 : #include "postgres.h"
18 :
19 : #include <unistd.h>
20 :
21 : #include "bootstrap/bootstrap.h"
22 : #include "catalog/heap.h"
23 : #include "catalog/namespace.h"
24 : #include "catalog/pg_am.h"
25 : #include "catalog/pg_authid.h"
26 : #include "catalog/pg_class.h"
27 : #include "catalog/pg_namespace.h"
28 : #include "catalog/pg_tablespace.h"
29 : #include "catalog/toasting.h"
30 : #include "commands/defrem.h"
31 : #include "miscadmin.h"
32 : #include "nodes/makefuncs.h"
33 : #include "utils/memutils.h"
34 :
35 :
36 : /*
37 : * Bison doesn't allocate anything that needs to live across parser calls,
38 : * so we can easily have it use palloc instead of malloc. This prevents
39 : * memory leaks if we error out during parsing.
40 : */
41 : #define YYMALLOC palloc
42 : #define YYFREE pfree
43 :
44 : static MemoryContext per_line_ctx = NULL;
45 :
46 : static void
47 881280 : do_start(void)
48 : {
49 : Assert(CurrentMemoryContext == CurTransactionContext);
50 : /* First time through, create the per-line working context */
51 881280 : if (per_line_ctx == NULL)
52 80 : per_line_ctx = AllocSetContextCreate(CurTransactionContext,
53 : "bootstrap per-line processing",
54 : ALLOCSET_DEFAULT_SIZES);
55 881280 : MemoryContextSwitchTo(per_line_ctx);
56 881280 : }
57 :
58 :
59 : static void
60 881280 : do_end(void)
61 : {
62 : /* Reclaim memory allocated while processing this line */
63 881280 : MemoryContextSwitchTo(CurTransactionContext);
64 881280 : MemoryContextReset(per_line_ctx);
65 881280 : CHECK_FOR_INTERRUPTS(); /* allow SIGINT to kill bootstrap run */
66 881280 : if (isatty(0))
67 : {
68 0 : printf("bootstrap> ");
69 0 : fflush(stdout);
70 : }
71 881280 : }
72 :
73 :
74 : static int num_columns_read = 0;
75 :
76 : %}
77 :
78 : %expect 0
79 : %name-prefix="boot_yy"
80 :
81 : %union
82 : {
83 : List *list;
84 : IndexElem *ielem;
85 : char *str;
86 : const char *kw;
87 : int ival;
88 : Oid oidval;
89 : }
90 :
91 : %type <list> boot_index_params
92 : %type <ielem> boot_index_param
93 : %type <str> boot_ident
94 : %type <ival> optbootstrap optsharedrelation boot_column_nullness
95 : %type <oidval> oidspec optrowtypeoid
96 :
97 : %token <str> ID
98 : %token COMMA EQUALS LPAREN RPAREN
99 : /* NULLVAL is a reserved keyword */
100 : %token NULLVAL
101 : /* All the rest are unreserved, and should be handled in boot_ident! */
102 : %token <kw> OPEN XCLOSE XCREATE INSERT_TUPLE
103 : %token <kw> XDECLARE INDEX ON USING XBUILD INDICES UNIQUE XTOAST
104 : %token <kw> OBJ_ID XBOOTSTRAP XSHARED_RELATION XROWTYPE_OID
105 : %token <kw> XFORCE XNOT XNULL
106 :
107 : %start TopLevel
108 :
109 : %%
110 :
111 : TopLevel:
112 : Boot_Queries
113 : |
114 : ;
115 :
116 : Boot_Queries:
117 : Boot_Query
118 : | Boot_Queries Boot_Query
119 : ;
120 :
121 : Boot_Query :
122 : Boot_OpenStmt
123 : | Boot_CloseStmt
124 : | Boot_CreateStmt
125 : | Boot_InsertStmt
126 : | Boot_DeclareIndexStmt
127 : | Boot_DeclareUniqueIndexStmt
128 : | Boot_DeclareToastStmt
129 : | Boot_BuildIndsStmt
130 : ;
131 :
132 : Boot_OpenStmt:
133 : OPEN boot_ident
134 : {
135 4800 : do_start();
136 4800 : boot_openrel($2);
137 4800 : do_end();
138 : }
139 : ;
140 :
141 : Boot_CloseStmt:
142 : XCLOSE boot_ident
143 : {
144 5120 : do_start();
145 5120 : closerel($2);
146 5120 : do_end();
147 : }
148 : ;
149 :
150 : Boot_CreateStmt:
151 : XCREATE boot_ident oidspec optbootstrap optsharedrelation optrowtypeoid LPAREN
152 : {
153 5120 : do_start();
154 5120 : numattr = 0;
155 5120 : elog(DEBUG4, "creating%s%s relation %s %u",
156 : $4 ? " bootstrap" : "",
157 : $5 ? " shared" : "",
158 : $2,
159 : $3);
160 : }
161 : boot_column_list
162 : {
163 5120 : do_end();
164 : }
165 : RPAREN
166 : {
167 : TupleDesc tupdesc;
168 : bool shared_relation;
169 : bool mapped_relation;
170 :
171 5120 : do_start();
172 :
173 5120 : tupdesc = CreateTupleDesc(numattr, attrtypes);
174 :
175 5120 : shared_relation = $5;
176 :
177 : /*
178 : * The catalogs that use the relation mapper are the
179 : * bootstrap catalogs plus the shared catalogs. If this
180 : * ever gets more complicated, we should invent a BKI
181 : * keyword to mark the mapped catalogs, but for now a
182 : * quick hack seems the most appropriate thing. Note in
183 : * particular that all "nailed" heap rels (see formrdesc
184 : * in relcache.c) must be mapped.
185 : */
186 5120 : mapped_relation = ($4 || shared_relation);
187 :
188 5120 : if ($4)
189 : {
190 : TransactionId relfrozenxid;
191 : MultiXactId relminmxid;
192 :
193 320 : if (boot_reldesc)
194 : {
195 0 : elog(DEBUG4, "create bootstrap: warning, open relation exists, closing first");
196 0 : closerel(NULL);
197 : }
198 :
199 320 : boot_reldesc = heap_create($2,
200 : PG_CATALOG_NAMESPACE,
201 : shared_relation ? GLOBALTABLESPACE_OID : 0,
202 320 : $3,
203 : InvalidOid,
204 : HEAP_TABLE_AM_OID,
205 : tupdesc,
206 : RELKIND_RELATION,
207 : RELPERSISTENCE_PERMANENT,
208 : shared_relation,
209 : mapped_relation,
210 : true,
211 : &relfrozenxid,
212 : &relminmxid,
213 : true);
214 320 : elog(DEBUG4, "bootstrap relation created");
215 : }
216 : else
217 : {
218 : Oid id;
219 :
220 4800 : id = heap_create_with_catalog($2,
221 : PG_CATALOG_NAMESPACE,
222 : shared_relation ? GLOBALTABLESPACE_OID : 0,
223 4800 : $3,
224 4800 : $6,
225 : InvalidOid,
226 : BOOTSTRAP_SUPERUSERID,
227 : HEAP_TABLE_AM_OID,
228 : tupdesc,
229 : NIL,
230 : RELKIND_RELATION,
231 : RELPERSISTENCE_PERMANENT,
232 : shared_relation,
233 : mapped_relation,
234 : ONCOMMIT_NOOP,
235 : (Datum) 0,
236 : false,
237 : true,
238 : false,
239 : InvalidOid,
240 : NULL);
241 4800 : elog(DEBUG4, "relation created with OID %u", id);
242 : }
243 5120 : do_end();
244 : }
245 : ;
246 :
247 : Boot_InsertStmt:
248 : INSERT_TUPLE
249 : {
250 848240 : do_start();
251 848240 : elog(DEBUG4, "inserting row");
252 848240 : num_columns_read = 0;
253 : }
254 : LPAREN boot_column_val_list RPAREN
255 : {
256 848240 : if (num_columns_read != numattr)
257 0 : elog(ERROR, "incorrect number of columns in row (expected %d, got %d)",
258 : numattr, num_columns_read);
259 848240 : if (boot_reldesc == NULL)
260 0 : elog(FATAL, "relation not open");
261 848240 : InsertOneTuple();
262 848240 : do_end();
263 : }
264 : ;
265 :
266 : Boot_DeclareIndexStmt:
267 : XDECLARE INDEX boot_ident oidspec ON boot_ident USING boot_ident LPAREN boot_index_params RPAREN
268 : {
269 1120 : IndexStmt *stmt = makeNode(IndexStmt);
270 : Oid relationId;
271 :
272 1120 : elog(DEBUG4, "creating index \"%s\"", $3);
273 :
274 1120 : do_start();
275 :
276 1120 : stmt->idxname = $3;
277 1120 : stmt->relation = makeRangeVar(NULL, $6, -1);
278 1120 : stmt->accessMethod = $8;
279 1120 : stmt->tableSpace = NULL;
280 1120 : stmt->indexParams = $10;
281 1120 : stmt->indexIncludingParams = NIL;
282 1120 : stmt->options = NIL;
283 1120 : stmt->whereClause = NULL;
284 1120 : stmt->excludeOpNames = NIL;
285 1120 : stmt->idxcomment = NULL;
286 1120 : stmt->indexOid = InvalidOid;
287 1120 : stmt->oldNumber = InvalidRelFileNumber;
288 1120 : stmt->oldCreateSubid = InvalidSubTransactionId;
289 1120 : stmt->oldFirstRelfilelocatorSubid = InvalidSubTransactionId;
290 1120 : stmt->unique = false;
291 1120 : stmt->primary = false;
292 1120 : stmt->isconstraint = false;
293 1120 : stmt->deferrable = false;
294 1120 : stmt->initdeferred = false;
295 1120 : stmt->transformed = false;
296 1120 : stmt->concurrent = false;
297 1120 : stmt->if_not_exists = false;
298 1120 : stmt->reset_default_tblspc = false;
299 :
300 : /* locks and races need not concern us in bootstrap mode */
301 1120 : relationId = RangeVarGetRelid(stmt->relation, NoLock,
302 : false);
303 :
304 1120 : DefineIndex(relationId,
305 : stmt,
306 1120 : $4,
307 : InvalidOid,
308 : InvalidOid,
309 : -1,
310 : false,
311 : false,
312 : false,
313 : true, /* skip_build */
314 : false);
315 1120 : do_end();
316 : }
317 : ;
318 :
319 : Boot_DeclareUniqueIndexStmt:
320 : XDECLARE UNIQUE INDEX boot_ident oidspec ON boot_ident USING boot_ident LPAREN boot_index_params RPAREN
321 : {
322 8800 : IndexStmt *stmt = makeNode(IndexStmt);
323 : Oid relationId;
324 :
325 8800 : elog(DEBUG4, "creating unique index \"%s\"", $4);
326 :
327 8800 : do_start();
328 :
329 8800 : stmt->idxname = $4;
330 8800 : stmt->relation = makeRangeVar(NULL, $7, -1);
331 8800 : stmt->accessMethod = $9;
332 8800 : stmt->tableSpace = NULL;
333 8800 : stmt->indexParams = $11;
334 8800 : stmt->indexIncludingParams = NIL;
335 8800 : stmt->options = NIL;
336 8800 : stmt->whereClause = NULL;
337 8800 : stmt->excludeOpNames = NIL;
338 8800 : stmt->idxcomment = NULL;
339 8800 : stmt->indexOid = InvalidOid;
340 8800 : stmt->oldNumber = InvalidRelFileNumber;
341 8800 : stmt->oldCreateSubid = InvalidSubTransactionId;
342 8800 : stmt->oldFirstRelfilelocatorSubid = InvalidSubTransactionId;
343 8800 : stmt->unique = true;
344 8800 : stmt->primary = false;
345 8800 : stmt->isconstraint = false;
346 8800 : stmt->deferrable = false;
347 8800 : stmt->initdeferred = false;
348 8800 : stmt->transformed = false;
349 8800 : stmt->concurrent = false;
350 8800 : stmt->if_not_exists = false;
351 8800 : stmt->reset_default_tblspc = false;
352 :
353 : /* locks and races need not concern us in bootstrap mode */
354 8800 : relationId = RangeVarGetRelid(stmt->relation, NoLock,
355 : false);
356 :
357 8800 : DefineIndex(relationId,
358 : stmt,
359 8800 : $5,
360 : InvalidOid,
361 : InvalidOid,
362 : -1,
363 : false,
364 : false,
365 : false,
366 : true, /* skip_build */
367 : false);
368 8800 : do_end();
369 : }
370 : ;
371 :
372 : Boot_DeclareToastStmt:
373 : XDECLARE XTOAST oidspec oidspec ON boot_ident
374 : {
375 2880 : elog(DEBUG4, "creating toast table for table \"%s\"", $6);
376 :
377 2880 : do_start();
378 :
379 2880 : BootstrapToastTable($6, $3, $4);
380 2880 : do_end();
381 : }
382 : ;
383 :
384 : Boot_BuildIndsStmt:
385 : XBUILD INDICES
386 : {
387 80 : do_start();
388 80 : build_indices();
389 80 : do_end();
390 : }
391 : ;
392 :
393 :
394 : boot_index_params:
395 6480 : boot_index_params COMMA boot_index_param { $$ = lappend($1, $3); }
396 9920 : | boot_index_param { $$ = list_make1($1); }
397 : ;
398 :
399 : boot_index_param:
400 : boot_ident boot_ident
401 : {
402 16400 : IndexElem *n = makeNode(IndexElem);
403 :
404 16400 : n->name = $1;
405 16400 : n->expr = NULL;
406 16400 : n->indexcolname = NULL;
407 16400 : n->collation = NIL;
408 16400 : n->opclass = list_make1(makeString($2));
409 16400 : n->ordering = SORTBY_DEFAULT;
410 16400 : n->nulls_ordering = SORTBY_NULLS_DEFAULT;
411 16400 : $$ = n;
412 : }
413 : ;
414 :
415 : optbootstrap:
416 320 : XBOOTSTRAP { $$ = 1; }
417 4800 : | { $$ = 0; }
418 : ;
419 :
420 : optsharedrelation:
421 880 : XSHARED_RELATION { $$ = 1; }
422 4240 : | { $$ = 0; }
423 : ;
424 :
425 : optrowtypeoid:
426 720 : XROWTYPE_OID oidspec { $$ = $2; }
427 4400 : | { $$ = InvalidOid; }
428 : ;
429 :
430 : boot_column_list:
431 : boot_column_def
432 : | boot_column_list COMMA boot_column_def
433 : ;
434 :
435 : boot_column_def:
436 : boot_ident EQUALS boot_ident boot_column_nullness
437 : {
438 47920 : if (++numattr > MAXATTR)
439 0 : elog(FATAL, "too many columns");
440 47920 : DefineAttr($1, $3, numattr-1, $4);
441 : }
442 : ;
443 :
444 : boot_column_nullness:
445 2720 : XFORCE XNOT XNULL { $$ = BOOTCOL_NULL_FORCE_NOT_NULL; }
446 320 : | XFORCE XNULL { $$ = BOOTCOL_NULL_FORCE_NULL; }
447 44880 : | { $$ = BOOTCOL_NULL_AUTO; }
448 : ;
449 :
450 : oidspec:
451 21520 : boot_ident { $$ = atooid($1); }
452 : ;
453 :
454 : boot_column_val_list:
455 : boot_column_val
456 : | boot_column_val_list boot_column_val
457 : | boot_column_val_list COMMA boot_column_val
458 : ;
459 :
460 : boot_column_val:
461 : boot_ident
462 10103298 : { InsertOneValue($1, num_columns_read++); }
463 : | NULLVAL
464 2480062 : { InsertOneNull(num_columns_read++); }
465 : ;
466 :
467 : boot_ident:
468 10301138 : ID { $$ = $1; }
469 0 : | OPEN { $$ = pstrdup($1); }
470 0 : | XCLOSE { $$ = pstrdup($1); }
471 0 : | XCREATE { $$ = pstrdup($1); }
472 0 : | INSERT_TUPLE { $$ = pstrdup($1); }
473 0 : | XDECLARE { $$ = pstrdup($1); }
474 0 : | INDEX { $$ = pstrdup($1); }
475 0 : | ON { $$ = pstrdup($1); }
476 0 : | USING { $$ = pstrdup($1); }
477 0 : | XBUILD { $$ = pstrdup($1); }
478 0 : | INDICES { $$ = pstrdup($1); }
479 0 : | UNIQUE { $$ = pstrdup($1); }
480 0 : | XTOAST { $$ = pstrdup($1); }
481 0 : | OBJ_ID { $$ = pstrdup($1); }
482 0 : | XBOOTSTRAP { $$ = pstrdup($1); }
483 0 : | XSHARED_RELATION { $$ = pstrdup($1); }
484 0 : | XROWTYPE_OID { $$ = pstrdup($1); }
485 0 : | XFORCE { $$ = pstrdup($1); }
486 0 : | XNOT { $$ = pstrdup($1); }
487 0 : | XNULL { $$ = pstrdup($1); }
488 : ;
489 : %%
|