Line data Source code
1 : %{
2 : /*-------------------------------------------------------------------------
3 : *
4 : * repl_gram.y - Parser for the replication commands
5 : *
6 : * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
7 : * Portions Copyright (c) 1994, Regents of the University of California
8 : *
9 : *
10 : * IDENTIFICATION
11 : * src/backend/replication/repl_gram.y
12 : *
13 : *-------------------------------------------------------------------------
14 : */
15 :
16 : #include "postgres.h"
17 :
18 : #include "access/xlogdefs.h"
19 : #include "nodes/makefuncs.h"
20 : #include "nodes/replnodes.h"
21 : #include "replication/walsender.h"
22 : #include "replication/walsender_private.h"
23 :
24 :
25 : /* Result of the parsing is returned here */
26 : Node *replication_parse_result;
27 :
28 : static SQLCmd *make_sqlcmd(void);
29 :
30 :
31 : /*
32 : * Bison doesn't allocate anything that needs to live across parser calls,
33 : * so we can easily have it use palloc instead of malloc. This prevents
34 : * memory leaks if we error out during parsing. Note this only works with
35 : * bison >= 2.0. However, in bison 1.875 the default is to use alloca()
36 : * if possible, so there's not really much problem anyhow, at least if
37 : * you're building with gcc.
38 : */
39 : #define YYMALLOC palloc
40 : #define YYFREE pfree
41 :
42 : %}
43 :
44 : %expect 0
45 : %name-prefix="replication_yy"
46 :
47 : %union {
48 : char *str;
49 : bool boolval;
50 : uint32 uintval;
51 :
52 : XLogRecPtr recptr;
53 : Node *node;
54 : List *list;
55 : DefElem *defelt;
56 : }
57 :
58 : /* Non-keyword tokens */
59 : %token <str> SCONST IDENT
60 : %token <uintval> UCONST
61 : %token <recptr> RECPTR
62 : %token T_WORD
63 :
64 : /* Keyword tokens. */
65 : %token K_BASE_BACKUP
66 : %token K_IDENTIFY_SYSTEM
67 : %token K_SHOW
68 : %token K_START_REPLICATION
69 : %token K_CREATE_REPLICATION_SLOT
70 : %token K_DROP_REPLICATION_SLOT
71 : %token K_TIMELINE_HISTORY
72 : %token K_LABEL
73 : %token K_PROGRESS
74 : %token K_FAST
75 : %token K_WAIT
76 : %token K_NOWAIT
77 : %token K_MAX_RATE
78 : %token K_WAL
79 : %token K_TABLESPACE_MAP
80 : %token K_NOVERIFY_CHECKSUMS
81 : %token K_TIMELINE
82 : %token K_PHYSICAL
83 : %token K_LOGICAL
84 : %token K_SLOT
85 : %token K_RESERVE_WAL
86 : %token K_TEMPORARY
87 : %token K_EXPORT_SNAPSHOT
88 : %token K_NOEXPORT_SNAPSHOT
89 : %token K_USE_SNAPSHOT
90 : %token K_MANIFEST
91 : %token K_MANIFEST_CHECKSUMS
92 :
93 : %type <node> command
94 : %type <node> base_backup start_replication start_logical_replication
95 : create_replication_slot drop_replication_slot identify_system
96 : timeline_history show sql_cmd
97 : %type <list> base_backup_opt_list
98 : %type <defelt> base_backup_opt
99 : %type <uintval> opt_timeline
100 : %type <list> plugin_options plugin_opt_list
101 : %type <defelt> plugin_opt_elem
102 : %type <node> plugin_opt_arg
103 : %type <str> opt_slot var_name
104 : %type <boolval> opt_temporary
105 : %type <list> create_slot_opt_list
106 : %type <defelt> create_slot_opt
107 :
108 : %%
109 :
110 : firstcmd: command opt_semicolon
111 : {
112 1454 : replication_parse_result = $1;
113 : }
114 : ;
115 :
116 : opt_semicolon: ';'
117 : | /* EMPTY */
118 : ;
119 :
120 : command:
121 : identify_system
122 : | base_backup
123 : | start_replication
124 : | start_logical_replication
125 : | create_replication_slot
126 : | drop_replication_slot
127 : | timeline_history
128 : | show
129 : | sql_cmd
130 : ;
131 :
132 : /*
133 : * IDENTIFY_SYSTEM
134 : */
135 : identify_system:
136 : K_IDENTIFY_SYSTEM
137 : {
138 74 : $$ = (Node *) makeNode(IdentifySystemCmd);
139 : }
140 : ;
141 :
142 : /*
143 : * SHOW setting
144 : */
145 : show:
146 : K_SHOW var_name
147 : {
148 0 : VariableShowStmt *n = makeNode(VariableShowStmt);
149 0 : n->name = $2;
150 0 : $$ = (Node *) n;
151 : }
152 :
153 0 : var_name: IDENT { $$ = $1; }
154 : | var_name '.' IDENT
155 0 : { $$ = psprintf("%s.%s", $1, $3); }
156 : ;
157 :
158 : /*
159 : * BASE_BACKUP [LABEL '<label>'] [PROGRESS] [FAST] [WAL] [NOWAIT]
160 : * [MAX_RATE %d] [TABLESPACE_MAP] [NOVERIFY_CHECKSUMS]
161 : * [MANIFEST %s] [MANIFEST_CHECKSUMS %s]
162 : */
163 : base_backup:
164 : K_BASE_BACKUP base_backup_opt_list
165 : {
166 0 : BaseBackupCmd *cmd = makeNode(BaseBackupCmd);
167 0 : cmd->options = $2;
168 0 : $$ = (Node *) cmd;
169 : }
170 : ;
171 :
172 : base_backup_opt_list:
173 : base_backup_opt_list base_backup_opt
174 0 : { $$ = lappend($1, $2); }
175 : | /* EMPTY */
176 0 : { $$ = NIL; }
177 : ;
178 :
179 : base_backup_opt:
180 : K_LABEL SCONST
181 : {
182 0 : $$ = makeDefElem("label",
183 0 : (Node *)makeString($2), -1);
184 : }
185 : | K_PROGRESS
186 : {
187 0 : $$ = makeDefElem("progress",
188 0 : (Node *)makeInteger(true), -1);
189 : }
190 : | K_FAST
191 : {
192 0 : $$ = makeDefElem("fast",
193 0 : (Node *)makeInteger(true), -1);
194 : }
195 : | K_WAL
196 : {
197 0 : $$ = makeDefElem("wal",
198 0 : (Node *)makeInteger(true), -1);
199 : }
200 : | K_NOWAIT
201 : {
202 0 : $$ = makeDefElem("nowait",
203 0 : (Node *)makeInteger(true), -1);
204 : }
205 : | K_MAX_RATE UCONST
206 : {
207 0 : $$ = makeDefElem("max_rate",
208 0 : (Node *)makeInteger($2), -1);
209 : }
210 : | K_TABLESPACE_MAP
211 : {
212 0 : $$ = makeDefElem("tablespace_map",
213 0 : (Node *)makeInteger(true), -1);
214 : }
215 : | K_NOVERIFY_CHECKSUMS
216 : {
217 0 : $$ = makeDefElem("noverify_checksums",
218 0 : (Node *)makeInteger(true), -1);
219 : }
220 : | K_MANIFEST SCONST
221 : {
222 0 : $$ = makeDefElem("manifest",
223 0 : (Node *)makeString($2), -1);
224 : }
225 : | K_MANIFEST_CHECKSUMS SCONST
226 : {
227 0 : $$ = makeDefElem("manifest_checksums",
228 0 : (Node *)makeString($2), -1);
229 : }
230 : ;
231 :
232 : create_replication_slot:
233 : /* CREATE_REPLICATION_SLOT slot TEMPORARY PHYSICAL RESERVE_WAL */
234 : K_CREATE_REPLICATION_SLOT IDENT opt_temporary K_PHYSICAL create_slot_opt_list
235 : {
236 : CreateReplicationSlotCmd *cmd;
237 0 : cmd = makeNode(CreateReplicationSlotCmd);
238 0 : cmd->kind = REPLICATION_KIND_PHYSICAL;
239 0 : cmd->slotname = $2;
240 0 : cmd->temporary = $3;
241 0 : cmd->options = $5;
242 0 : $$ = (Node *) cmd;
243 : }
244 : /* CREATE_REPLICATION_SLOT slot TEMPORARY LOGICAL plugin */
245 : | K_CREATE_REPLICATION_SLOT IDENT opt_temporary K_LOGICAL IDENT create_slot_opt_list
246 : {
247 : CreateReplicationSlotCmd *cmd;
248 182 : cmd = makeNode(CreateReplicationSlotCmd);
249 182 : cmd->kind = REPLICATION_KIND_LOGICAL;
250 182 : cmd->slotname = $2;
251 182 : cmd->temporary = $3;
252 182 : cmd->plugin = $5;
253 182 : cmd->options = $6;
254 182 : $$ = (Node *) cmd;
255 : }
256 : ;
257 :
258 : create_slot_opt_list:
259 : create_slot_opt_list create_slot_opt
260 182 : { $$ = lappend($1, $2); }
261 : | /* EMPTY */
262 182 : { $$ = NIL; }
263 : ;
264 :
265 : create_slot_opt:
266 : K_EXPORT_SNAPSHOT
267 : {
268 0 : $$ = makeDefElem("export_snapshot",
269 0 : (Node *)makeInteger(true), -1);
270 : }
271 : | K_NOEXPORT_SNAPSHOT
272 : {
273 56 : $$ = makeDefElem("export_snapshot",
274 56 : (Node *)makeInteger(false), -1);
275 : }
276 : | K_USE_SNAPSHOT
277 : {
278 126 : $$ = makeDefElem("use_snapshot",
279 126 : (Node *)makeInteger(true), -1);
280 : }
281 : | K_RESERVE_WAL
282 : {
283 0 : $$ = makeDefElem("reserve_wal",
284 0 : (Node *)makeInteger(true), -1);
285 : }
286 : ;
287 :
288 : /* DROP_REPLICATION_SLOT slot */
289 : drop_replication_slot:
290 : K_DROP_REPLICATION_SLOT IDENT
291 : {
292 : DropReplicationSlotCmd *cmd;
293 0 : cmd = makeNode(DropReplicationSlotCmd);
294 0 : cmd->slotname = $2;
295 0 : cmd->wait = false;
296 0 : $$ = (Node *) cmd;
297 : }
298 : | K_DROP_REPLICATION_SLOT IDENT K_WAIT
299 : {
300 : DropReplicationSlotCmd *cmd;
301 18 : cmd = makeNode(DropReplicationSlotCmd);
302 18 : cmd->slotname = $2;
303 18 : cmd->wait = true;
304 18 : $$ = (Node *) cmd;
305 : }
306 : ;
307 :
308 : /*
309 : * START_REPLICATION [SLOT slot] [PHYSICAL] %X/%X [TIMELINE %d]
310 : */
311 : start_replication:
312 : K_START_REPLICATION opt_slot opt_physical RECPTR opt_timeline
313 : {
314 : StartReplicationCmd *cmd;
315 :
316 0 : cmd = makeNode(StartReplicationCmd);
317 0 : cmd->kind = REPLICATION_KIND_PHYSICAL;
318 0 : cmd->slotname = $2;
319 0 : cmd->startpoint = $4;
320 0 : cmd->timeline = $5;
321 0 : $$ = (Node *) cmd;
322 : }
323 : ;
324 :
325 : /* START_REPLICATION SLOT slot LOGICAL %X/%X options */
326 : start_logical_replication:
327 : K_START_REPLICATION K_SLOT IDENT K_LOGICAL RECPTR plugin_options
328 : {
329 : StartReplicationCmd *cmd;
330 196 : cmd = makeNode(StartReplicationCmd);
331 196 : cmd->kind = REPLICATION_KIND_LOGICAL;
332 196 : cmd->slotname = $3;
333 196 : cmd->startpoint = $5;
334 196 : cmd->options = $6;
335 196 : $$ = (Node *) cmd;
336 : }
337 : ;
338 : /*
339 : * TIMELINE_HISTORY %d
340 : */
341 : timeline_history:
342 : K_TIMELINE_HISTORY UCONST
343 : {
344 : TimeLineHistoryCmd *cmd;
345 :
346 0 : if ($2 <= 0)
347 0 : ereport(ERROR,
348 : (errcode(ERRCODE_SYNTAX_ERROR),
349 : errmsg("invalid timeline %u", $2)));
350 :
351 0 : cmd = makeNode(TimeLineHistoryCmd);
352 0 : cmd->timeline = $2;
353 :
354 0 : $$ = (Node *) cmd;
355 : }
356 : ;
357 :
358 : opt_physical:
359 : K_PHYSICAL
360 : | /* EMPTY */
361 : ;
362 :
363 : opt_temporary:
364 126 : K_TEMPORARY { $$ = true; }
365 56 : | /* EMPTY */ { $$ = false; }
366 : ;
367 :
368 : opt_slot:
369 : K_SLOT IDENT
370 0 : { $$ = $2; }
371 : | /* EMPTY */
372 0 : { $$ = NULL; }
373 : ;
374 :
375 : opt_timeline:
376 : K_TIMELINE UCONST
377 : {
378 0 : if ($2 <= 0)
379 0 : ereport(ERROR,
380 : (errcode(ERRCODE_SYNTAX_ERROR),
381 : errmsg("invalid timeline %u", $2)));
382 0 : $$ = $2;
383 : }
384 0 : | /* EMPTY */ { $$ = 0; }
385 : ;
386 :
387 :
388 : plugin_options:
389 196 : '(' plugin_opt_list ')' { $$ = $2; }
390 0 : | /* EMPTY */ { $$ = NIL; }
391 : ;
392 :
393 : plugin_opt_list:
394 : plugin_opt_elem
395 : {
396 196 : $$ = list_make1($1);
397 : }
398 : | plugin_opt_list ',' plugin_opt_elem
399 : {
400 238 : $$ = lappend($1, $3);
401 : }
402 : ;
403 :
404 : plugin_opt_elem:
405 : IDENT plugin_opt_arg
406 : {
407 434 : $$ = makeDefElem($1, $2, -1);
408 : }
409 : ;
410 :
411 : plugin_opt_arg:
412 434 : SCONST { $$ = (Node *) makeString($1); }
413 0 : | /* EMPTY */ { $$ = NULL; }
414 : ;
415 :
416 : sql_cmd:
417 984 : IDENT { $$ = (Node *) make_sqlcmd(); }
418 : ;
419 : %%
420 :
421 : static SQLCmd *
422 984 : make_sqlcmd(void)
423 : {
424 984 : SQLCmd *cmd = makeNode(SQLCmd);
425 : int tok;
426 :
427 : /* Just move lexer to the end of command. */
428 : for (;;)
429 : {
430 22026 : tok = yylex();
431 22026 : if (tok == ';' || tok == 0)
432 : break;
433 21042 : }
434 984 : return cmd;
435 : }
436 :
437 : #include "repl_scanner.c"
|