OSDN Git Service

Refactor broken CREATE TABLE IF NOT EXISTS support.
[pg-rex/syncrep.git] / src / backend / bootstrap / bootparse.y
1 %{
2 /*-------------------------------------------------------------------------
3  *
4  * bootparse.y
5  *        yacc grammar for the "bootstrap" mode (BKI file format)
6  *
7  * Portions Copyright (c) 1996-2011, 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 "access/attnum.h"
22 #include "access/htup.h"
23 #include "access/itup.h"
24 #include "access/skey.h"
25 #include "access/tupdesc.h"
26 #include "access/xact.h"
27 #include "bootstrap/bootstrap.h"
28 #include "catalog/catalog.h"
29 #include "catalog/heap.h"
30 #include "catalog/pg_am.h"
31 #include "catalog/pg_attribute.h"
32 #include "catalog/pg_authid.h"
33 #include "catalog/pg_class.h"
34 #include "catalog/pg_namespace.h"
35 #include "catalog/pg_tablespace.h"
36 #include "catalog/toasting.h"
37 #include "commands/defrem.h"
38 #include "miscadmin.h"
39 #include "nodes/makefuncs.h"
40 #include "nodes/nodes.h"
41 #include "nodes/parsenodes.h"
42 #include "nodes/pg_list.h"
43 #include "nodes/primnodes.h"
44 #include "rewrite/prs2lock.h"
45 #include "storage/block.h"
46 #include "storage/fd.h"
47 #include "storage/ipc.h"
48 #include "storage/itemptr.h"
49 #include "storage/off.h"
50 #include "storage/smgr.h"
51 #include "tcop/dest.h"
52 #include "utils/rel.h"
53
54 #define atooid(x)       ((Oid) strtoul((x), NULL, 10))
55
56
57 /*
58  * Bison doesn't allocate anything that needs to live across parser calls,
59  * so we can easily have it use palloc instead of malloc.  This prevents
60  * memory leaks if we error out during parsing.  Note this only works with
61  * bison >= 2.0.  However, in bison 1.875 the default is to use alloca()
62  * if possible, so there's not really much problem anyhow, at least if
63  * you're building with gcc.
64  */
65 #define YYMALLOC palloc
66 #define YYFREE   pfree
67
68 static void
69 do_start(void)
70 {
71         StartTransactionCommand();
72         elog(DEBUG4, "start transaction");
73 }
74
75
76 static void
77 do_end(void)
78 {
79         CommitTransactionCommand();
80         elog(DEBUG4, "commit transaction");
81         CHECK_FOR_INTERRUPTS();         /* allow SIGINT to kill bootstrap run */
82         if (isatty(0))
83         {
84                 printf("bootstrap> ");
85                 fflush(stdout);
86         }
87 }
88
89
90 static int num_columns_read = 0;
91
92 %}
93
94 %expect 0
95 %name-prefix="boot_yy"
96
97 %union
98 {
99         List            *list;
100         IndexElem       *ielem;
101         char            *str;
102         int                     ival;
103         Oid                     oidval;
104 }
105
106 %type <list>  boot_index_params
107 %type <ielem> boot_index_param
108 %type <str>   boot_const boot_ident
109 %type <ival>  optbootstrap optsharedrelation optwithoutoids
110 %type <oidval> oidspec optoideq optrowtypeoid
111
112 %token <str> CONST_P ID
113 %token OPEN XCLOSE XCREATE INSERT_TUPLE
114 %token XDECLARE INDEX ON USING XBUILD INDICES UNIQUE XTOAST
115 %token COMMA EQUALS LPAREN RPAREN
116 %token OBJ_ID XBOOTSTRAP XSHARED_RELATION XWITHOUT_OIDS XROWTYPE_OID NULLVAL
117
118 %start TopLevel
119
120 %nonassoc low
121 %nonassoc high
122
123 %%
124
125 TopLevel:
126                   Boot_Queries
127                 |
128                 ;
129
130 Boot_Queries:
131                   Boot_Query
132                 | Boot_Queries Boot_Query
133                 ;
134
135 Boot_Query :
136                   Boot_OpenStmt
137                 | Boot_CloseStmt
138                 | Boot_CreateStmt
139                 | Boot_InsertStmt
140                 | Boot_DeclareIndexStmt
141                 | Boot_DeclareUniqueIndexStmt
142                 | Boot_DeclareToastStmt
143                 | Boot_BuildIndsStmt
144                 ;
145
146 Boot_OpenStmt:
147                   OPEN boot_ident
148                                 {
149                                         do_start();
150                                         boot_openrel($2);
151                                         do_end();
152                                 }
153                 ;
154
155 Boot_CloseStmt:
156                   XCLOSE boot_ident %prec low
157                                 {
158                                         do_start();
159                                         closerel($2);
160                                         do_end();
161                                 }
162                 | XCLOSE %prec high
163                                 {
164                                         do_start();
165                                         closerel(NULL);
166                                         do_end();
167                                 }
168                 ;
169
170 Boot_CreateStmt:
171                   XCREATE boot_ident oidspec optbootstrap optsharedrelation optwithoutoids optrowtypeoid LPAREN
172                                 {
173                                         do_start();
174                                         numattr = 0;
175                                         elog(DEBUG4, "creating%s%s relation %s %u",
176                                                  $4 ? " bootstrap" : "",
177                                                  $5 ? " shared" : "",
178                                                  $2,
179                                                  $3);
180                                 }
181                   boot_column_list
182                                 {
183                                         do_end();
184                                 }
185                   RPAREN
186                                 {
187                                         TupleDesc tupdesc;
188                                         bool    shared_relation;
189                                         bool    mapped_relation;
190
191                                         do_start();
192
193                                         tupdesc = CreateTupleDesc(numattr, !($6), attrtypes);
194
195                                         shared_relation = $5;
196
197                                         /*
198                                          * The catalogs that use the relation mapper are the
199                                          * bootstrap catalogs plus the shared catalogs.  If this
200                                          * ever gets more complicated, we should invent a BKI
201                                          * keyword to mark the mapped catalogs, but for now a
202                                          * quick hack seems the most appropriate thing.  Note in
203                                          * particular that all "nailed" heap rels (see formrdesc
204                                          * in relcache.c) must be mapped.
205                                          */
206                                         mapped_relation = ($4 || shared_relation);
207
208                                         if ($4)
209                                         {
210                                                 if (boot_reldesc)
211                                                 {
212                                                         elog(DEBUG4, "create bootstrap: warning, open relation exists, closing first");
213                                                         closerel(NULL);
214                                                 }
215
216                                                 boot_reldesc = heap_create($2,
217                                                                                                    PG_CATALOG_NAMESPACE,
218                                                                                                    shared_relation ? GLOBALTABLESPACE_OID : 0,
219                                                                                                    $3,
220                                                                                                    tupdesc,
221                                                                                                    RELKIND_RELATION,
222                                                                                                    RELPERSISTENCE_PERMANENT,
223                                                                                                    shared_relation,
224                                                                                                    mapped_relation,
225                                                                                                    true);
226                                                 elog(DEBUG4, "bootstrap relation created");
227                                         }
228                                         else
229                                         {
230                                                 Oid id;
231
232                                                 id = heap_create_with_catalog($2,
233                                                                                                           PG_CATALOG_NAMESPACE,
234                                                                                                           shared_relation ? GLOBALTABLESPACE_OID : 0,
235                                                                                                           $3,
236                                                                                                           $7,
237                                                                                                           InvalidOid,
238                                                                                                           BOOTSTRAP_SUPERUSERID,
239                                                                                                           tupdesc,
240                                                                                                           NIL,
241                                                                                                           RELKIND_RELATION,
242                                                                                                           RELPERSISTENCE_PERMANENT,
243                                                                                                           shared_relation,
244                                                                                                           mapped_relation,
245                                                                                                           true,
246                                                                                                           0,
247                                                                                                           ONCOMMIT_NOOP,
248                                                                                                           (Datum) 0,
249                                                                                                           false,
250                                                                                                           true);
251                                                 elog(DEBUG4, "relation created with oid %u", id);
252                                         }
253                                         do_end();
254                                 }
255                 ;
256
257 Boot_InsertStmt:
258                   INSERT_TUPLE optoideq
259                                 {
260                                         do_start();
261                                         if ($2)
262                                                 elog(DEBUG4, "inserting row with oid %u", $2);
263                                         else
264                                                 elog(DEBUG4, "inserting row");
265                                         num_columns_read = 0;
266                                 }
267                   LPAREN boot_column_val_list RPAREN
268                                 {
269                                         if (num_columns_read != numattr)
270                                                 elog(ERROR, "incorrect number of columns in row (expected %d, got %d)",
271                                                          numattr, num_columns_read);
272                                         if (boot_reldesc == NULL)
273                                                 elog(FATAL, "relation not open");
274                                         InsertOneTuple($2);
275                                         do_end();
276                                 }
277                 ;
278
279 Boot_DeclareIndexStmt:
280                   XDECLARE INDEX boot_ident oidspec ON boot_ident USING boot_ident LPAREN boot_index_params RPAREN
281                                 {
282                                         do_start();
283
284                                         DefineIndex(makeRangeVar(NULL, $6, -1),
285                                                                 $3,
286                                                                 $4,
287                                                                 $8,
288                                                                 NULL,
289                                                                 $10,
290                                                                 NULL, NIL, NIL,
291                                                                 false, false, false, false, false,
292                                                                 false, false, true, false, false);
293                                         do_end();
294                                 }
295                 ;
296
297 Boot_DeclareUniqueIndexStmt:
298                   XDECLARE UNIQUE INDEX boot_ident oidspec ON boot_ident USING boot_ident LPAREN boot_index_params RPAREN
299                                 {
300                                         do_start();
301
302                                         DefineIndex(makeRangeVar(NULL, $7, -1),
303                                                                 $4,
304                                                                 $5,
305                                                                 $9,
306                                                                 NULL,
307                                                                 $11,
308                                                                 NULL, NIL, NIL,
309                                                                 true, false, false, false, false,
310                                                                 false, false, true, false, false);
311                                         do_end();
312                                 }
313                 ;
314
315 Boot_DeclareToastStmt:
316                   XDECLARE XTOAST oidspec oidspec ON boot_ident
317                                 {
318                                         do_start();
319
320                                         BootstrapToastTable($6, $3, $4);
321                                         do_end();
322                                 }
323                 ;
324
325 Boot_BuildIndsStmt:
326                   XBUILD INDICES
327                                 {
328                                         do_start();
329                                         build_indices();
330                                         do_end();
331                                 }
332                 ;
333
334
335 boot_index_params:
336                 boot_index_params COMMA boot_index_param        { $$ = lappend($1, $3); }
337                 | boot_index_param                                                      { $$ = list_make1($1); }
338                 ;
339
340 boot_index_param:
341                 boot_ident boot_ident
342                                 {
343                                         IndexElem *n = makeNode(IndexElem);
344                                         n->name = $1;
345                                         n->expr = NULL;
346                                         n->indexcolname = NULL;
347                                         n->collation = NIL;
348                                         n->opclass = list_make1(makeString($2));
349                                         n->ordering = SORTBY_DEFAULT;
350                                         n->nulls_ordering = SORTBY_NULLS_DEFAULT;
351                                         $$ = n;
352                                 }
353                 ;
354
355 optbootstrap:
356                         XBOOTSTRAP      { $$ = 1; }
357                 |                               { $$ = 0; }
358                 ;
359
360 optsharedrelation:
361                         XSHARED_RELATION        { $$ = 1; }
362                 |                                               { $$ = 0; }
363                 ;
364
365 optwithoutoids:
366                         XWITHOUT_OIDS   { $$ = 1; }
367                 |                                       { $$ = 0; }
368                 ;
369
370 optrowtypeoid:
371                         XROWTYPE_OID oidspec    { $$ = $2; }
372                 |                                                       { $$ = InvalidOid; }
373                 ;
374
375 boot_column_list:
376                   boot_column_def
377                 | boot_column_list COMMA boot_column_def
378                 ;
379
380 boot_column_def:
381                   boot_ident EQUALS boot_ident
382                                 {
383                                    if (++numattr > MAXATTR)
384                                                 elog(FATAL, "too many columns");
385                                    DefineAttr($1, $3, numattr-1);
386                                 }
387                 ;
388
389 oidspec:
390                         boot_ident                                                      { $$ = atooid($1); }
391                 ;
392
393 optoideq:
394                         OBJ_ID EQUALS oidspec                           { $$ = $3; }
395                 |                                                                               { $$ = InvalidOid; }
396                 ;
397
398 boot_column_val_list:
399                    boot_column_val
400                 |  boot_column_val_list boot_column_val
401                 |  boot_column_val_list COMMA boot_column_val
402                 ;
403
404 boot_column_val:
405                   boot_ident
406                         { InsertOneValue($1, num_columns_read++); }
407                 | boot_const
408                         { InsertOneValue($1, num_columns_read++); }
409                 | NULLVAL
410                         { InsertOneNull(num_columns_read++); }
411                 ;
412
413 boot_const :
414                   CONST_P { $$ = yylval.str; }
415                 ;
416
417 boot_ident :
418                   ID    { $$ = yylval.str; }
419                 ;
420 %%
421
422 #include "bootscanner.c"