Line data Source code
1 : %{
2 : /*-------------------------------------------------------------------------
3 : *
4 : * repl_gram.y - Parser for the replication commands
5 : *
6 : * Portions Copyright (c) 1996-2024, 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/parsenodes.h"
21 : #include "nodes/replnodes.h"
22 : #include "replication/walsender.h"
23 : #include "replication/walsender_private.h"
24 :
25 :
26 : /* silence -Wmissing-variable-declarations */
27 : extern int replication_yychar;
28 : extern int replication_yynerrs;
29 :
30 :
31 : /* Result of the parsing is returned here */
32 : Node *replication_parse_result;
33 :
34 :
35 : /*
36 : * Bison doesn't allocate anything that needs to live across parser calls,
37 : * so we can easily have it use palloc instead of malloc. This prevents
38 : * memory leaks if we error out during parsing.
39 : */
40 : #define YYMALLOC palloc
41 : #define YYFREE pfree
42 :
43 : %}
44 :
45 : %expect 0
46 : %name-prefix="replication_yy"
47 :
48 : %union
49 : {
50 : char *str;
51 : bool boolval;
52 : uint32 uintval;
53 : XLogRecPtr recptr;
54 : Node *node;
55 : List *list;
56 : DefElem *defelt;
57 : }
58 :
59 : /* Non-keyword tokens */
60 : %token <str> SCONST IDENT
61 : %token <uintval> UCONST
62 : %token <recptr> RECPTR
63 :
64 : /* Keyword tokens. */
65 : %token K_BASE_BACKUP
66 : %token K_IDENTIFY_SYSTEM
67 : %token K_READ_REPLICATION_SLOT
68 : %token K_SHOW
69 : %token K_START_REPLICATION
70 : %token K_CREATE_REPLICATION_SLOT
71 : %token K_DROP_REPLICATION_SLOT
72 : %token K_ALTER_REPLICATION_SLOT
73 : %token K_TIMELINE_HISTORY
74 : %token K_WAIT
75 : %token K_TIMELINE
76 : %token K_PHYSICAL
77 : %token K_LOGICAL
78 : %token K_SLOT
79 : %token K_RESERVE_WAL
80 : %token K_TEMPORARY
81 : %token K_TWO_PHASE
82 : %token K_EXPORT_SNAPSHOT
83 : %token K_NOEXPORT_SNAPSHOT
84 : %token K_USE_SNAPSHOT
85 : %token K_UPLOAD_MANIFEST
86 :
87 : %type <node> command
88 : %type <node> base_backup start_replication start_logical_replication
89 : create_replication_slot drop_replication_slot
90 : alter_replication_slot identify_system read_replication_slot
91 : timeline_history show upload_manifest
92 : %type <list> generic_option_list
93 : %type <defelt> generic_option
94 : %type <uintval> opt_timeline
95 : %type <list> plugin_options plugin_opt_list
96 : %type <defelt> plugin_opt_elem
97 : %type <node> plugin_opt_arg
98 : %type <str> opt_slot var_name ident_or_keyword
99 : %type <boolval> opt_temporary
100 : %type <list> create_slot_options create_slot_legacy_opt_list
101 : %type <defelt> create_slot_legacy_opt
102 :
103 : %%
104 :
105 : firstcmd: command opt_semicolon
106 : {
107 5062 : replication_parse_result = $1;
108 : }
109 : ;
110 :
111 : opt_semicolon: ';'
112 : | /* EMPTY */
113 : ;
114 :
115 : command:
116 : identify_system
117 : | base_backup
118 : | start_replication
119 : | start_logical_replication
120 : | create_replication_slot
121 : | drop_replication_slot
122 : | alter_replication_slot
123 : | read_replication_slot
124 : | timeline_history
125 : | show
126 : | upload_manifest
127 : ;
128 :
129 : /*
130 : * IDENTIFY_SYSTEM
131 : */
132 : identify_system:
133 : K_IDENTIFY_SYSTEM
134 : {
135 1226 : $$ = (Node *) makeNode(IdentifySystemCmd);
136 : }
137 : ;
138 :
139 : /*
140 : * READ_REPLICATION_SLOT %s
141 : */
142 : read_replication_slot:
143 : K_READ_REPLICATION_SLOT var_name
144 : {
145 12 : ReadReplicationSlotCmd *n = makeNode(ReadReplicationSlotCmd);
146 12 : n->slotname = $2;
147 12 : $$ = (Node *) n;
148 : }
149 : ;
150 :
151 : /*
152 : * SHOW setting
153 : */
154 : show:
155 : K_SHOW var_name
156 : {
157 1022 : VariableShowStmt *n = makeNode(VariableShowStmt);
158 1022 : n->name = $2;
159 1022 : $$ = (Node *) n;
160 : }
161 :
162 1034 : var_name: IDENT { $$ = $1; }
163 : | var_name '.' IDENT
164 0 : { $$ = psprintf("%s.%s", $1, $3); }
165 : ;
166 :
167 : /*
168 : * BASE_BACKUP [ ( option [ 'value' ] [, ...] ) ]
169 : */
170 : base_backup:
171 : K_BASE_BACKUP '(' generic_option_list ')'
172 : {
173 318 : BaseBackupCmd *cmd = makeNode(BaseBackupCmd);
174 318 : cmd->options = $3;
175 318 : $$ = (Node *) cmd;
176 : }
177 : | K_BASE_BACKUP
178 : {
179 2 : BaseBackupCmd *cmd = makeNode(BaseBackupCmd);
180 2 : $$ = (Node *) cmd;
181 : }
182 : ;
183 :
184 : create_replication_slot:
185 : /* CREATE_REPLICATION_SLOT slot [TEMPORARY] PHYSICAL [options] */
186 : K_CREATE_REPLICATION_SLOT IDENT opt_temporary K_PHYSICAL create_slot_options
187 : {
188 : CreateReplicationSlotCmd *cmd;
189 246 : cmd = makeNode(CreateReplicationSlotCmd);
190 246 : cmd->kind = REPLICATION_KIND_PHYSICAL;
191 246 : cmd->slotname = $2;
192 246 : cmd->temporary = $3;
193 246 : cmd->options = $5;
194 246 : $$ = (Node *) cmd;
195 : }
196 : /* CREATE_REPLICATION_SLOT slot [TEMPORARY] LOGICAL plugin [options] */
197 : | K_CREATE_REPLICATION_SLOT IDENT opt_temporary K_LOGICAL IDENT create_slot_options
198 : {
199 : CreateReplicationSlotCmd *cmd;
200 576 : cmd = makeNode(CreateReplicationSlotCmd);
201 576 : cmd->kind = REPLICATION_KIND_LOGICAL;
202 576 : cmd->slotname = $2;
203 576 : cmd->temporary = $3;
204 576 : cmd->plugin = $5;
205 576 : cmd->options = $6;
206 576 : $$ = (Node *) cmd;
207 : }
208 : ;
209 :
210 : create_slot_options:
211 818 : '(' generic_option_list ')' { $$ = $2; }
212 4 : | create_slot_legacy_opt_list { $$ = $1; }
213 : ;
214 :
215 : create_slot_legacy_opt_list:
216 : create_slot_legacy_opt_list create_slot_legacy_opt
217 2 : { $$ = lappend($1, $2); }
218 : | /* EMPTY */
219 4 : { $$ = NIL; }
220 : ;
221 :
222 : create_slot_legacy_opt:
223 : K_EXPORT_SNAPSHOT
224 : {
225 0 : $$ = makeDefElem("snapshot",
226 0 : (Node *) makeString("export"), -1);
227 : }
228 : | K_NOEXPORT_SNAPSHOT
229 : {
230 0 : $$ = makeDefElem("snapshot",
231 0 : (Node *) makeString("nothing"), -1);
232 : }
233 : | K_USE_SNAPSHOT
234 : {
235 0 : $$ = makeDefElem("snapshot",
236 0 : (Node *) makeString("use"), -1);
237 : }
238 : | K_RESERVE_WAL
239 : {
240 2 : $$ = makeDefElem("reserve_wal",
241 2 : (Node *) makeBoolean(true), -1);
242 : }
243 : | K_TWO_PHASE
244 : {
245 0 : $$ = makeDefElem("two_phase",
246 0 : (Node *) makeBoolean(true), -1);
247 : }
248 : ;
249 :
250 : /* DROP_REPLICATION_SLOT slot */
251 : drop_replication_slot:
252 : K_DROP_REPLICATION_SLOT IDENT
253 : {
254 : DropReplicationSlotCmd *cmd;
255 6 : cmd = makeNode(DropReplicationSlotCmd);
256 6 : cmd->slotname = $2;
257 6 : cmd->wait = false;
258 6 : $$ = (Node *) cmd;
259 : }
260 : | K_DROP_REPLICATION_SLOT IDENT K_WAIT
261 : {
262 : DropReplicationSlotCmd *cmd;
263 444 : cmd = makeNode(DropReplicationSlotCmd);
264 444 : cmd->slotname = $2;
265 444 : cmd->wait = true;
266 444 : $$ = (Node *) cmd;
267 : }
268 : ;
269 :
270 : /* ALTER_REPLICATION_SLOT slot (options) */
271 : alter_replication_slot:
272 : K_ALTER_REPLICATION_SLOT IDENT '(' generic_option_list ')'
273 : {
274 : AlterReplicationSlotCmd *cmd;
275 10 : cmd = makeNode(AlterReplicationSlotCmd);
276 10 : cmd->slotname = $2;
277 10 : cmd->options = $4;
278 10 : $$ = (Node *) cmd;
279 : }
280 : ;
281 :
282 : /*
283 : * START_REPLICATION [SLOT slot] [PHYSICAL] %X/%X [TIMELINE %u]
284 : */
285 : start_replication:
286 : K_START_REPLICATION opt_slot opt_physical RECPTR opt_timeline
287 : {
288 : StartReplicationCmd *cmd;
289 :
290 484 : cmd = makeNode(StartReplicationCmd);
291 484 : cmd->kind = REPLICATION_KIND_PHYSICAL;
292 484 : cmd->slotname = $2;
293 484 : cmd->startpoint = $4;
294 484 : cmd->timeline = $5;
295 484 : $$ = (Node *) cmd;
296 : }
297 : ;
298 :
299 : /* START_REPLICATION SLOT slot LOGICAL %X/%X options */
300 : start_logical_replication:
301 : K_START_REPLICATION K_SLOT IDENT K_LOGICAL RECPTR plugin_options
302 : {
303 : StartReplicationCmd *cmd;
304 670 : cmd = makeNode(StartReplicationCmd);
305 670 : cmd->kind = REPLICATION_KIND_LOGICAL;
306 670 : cmd->slotname = $3;
307 670 : cmd->startpoint = $5;
308 670 : cmd->options = $6;
309 670 : $$ = (Node *) cmd;
310 : }
311 : ;
312 : /*
313 : * TIMELINE_HISTORY %u
314 : */
315 : timeline_history:
316 : K_TIMELINE_HISTORY UCONST
317 : {
318 : TimeLineHistoryCmd *cmd;
319 :
320 28 : if ($2 <= 0)
321 0 : ereport(ERROR,
322 : (errcode(ERRCODE_SYNTAX_ERROR),
323 : errmsg("invalid timeline %u", $2)));
324 :
325 28 : cmd = makeNode(TimeLineHistoryCmd);
326 28 : cmd->timeline = $2;
327 :
328 28 : $$ = (Node *) cmd;
329 : }
330 : ;
331 :
332 : /* UPLOAD_MANIFEST doesn't currently accept any arguments */
333 : upload_manifest:
334 : K_UPLOAD_MANIFEST
335 : {
336 18 : UploadManifestCmd *cmd = makeNode(UploadManifestCmd);
337 :
338 18 : $$ = (Node *) cmd;
339 : }
340 :
341 : opt_physical:
342 : K_PHYSICAL
343 : | /* EMPTY */
344 : ;
345 :
346 : opt_temporary:
347 236 : K_TEMPORARY { $$ = true; }
348 586 : | /* EMPTY */ { $$ = false; }
349 : ;
350 :
351 : opt_slot:
352 : K_SLOT IDENT
353 332 : { $$ = $2; }
354 : | /* EMPTY */
355 152 : { $$ = NULL; }
356 : ;
357 :
358 : opt_timeline:
359 : K_TIMELINE UCONST
360 : {
361 482 : if ($2 <= 0)
362 0 : ereport(ERROR,
363 : (errcode(ERRCODE_SYNTAX_ERROR),
364 : errmsg("invalid timeline %u", $2)));
365 482 : $$ = $2;
366 : }
367 2 : | /* EMPTY */ { $$ = 0; }
368 : ;
369 :
370 :
371 : plugin_options:
372 660 : '(' plugin_opt_list ')' { $$ = $2; }
373 10 : | /* EMPTY */ { $$ = NIL; }
374 : ;
375 :
376 : plugin_opt_list:
377 : plugin_opt_elem
378 : {
379 660 : $$ = list_make1($1);
380 : }
381 : | plugin_opt_list ',' plugin_opt_elem
382 : {
383 1392 : $$ = lappend($1, $3);
384 : }
385 : ;
386 :
387 : plugin_opt_elem:
388 : IDENT plugin_opt_arg
389 : {
390 2052 : $$ = makeDefElem($1, $2, -1);
391 : }
392 : ;
393 :
394 : plugin_opt_arg:
395 2052 : SCONST { $$ = (Node *) makeString($1); }
396 0 : | /* EMPTY */ { $$ = NULL; }
397 : ;
398 :
399 : generic_option_list:
400 : generic_option_list ',' generic_option
401 1760 : { $$ = lappend($1, $3); }
402 : | generic_option
403 1146 : { $$ = list_make1($1); }
404 : ;
405 :
406 : generic_option:
407 : ident_or_keyword
408 : {
409 668 : $$ = makeDefElem($1, NULL, -1);
410 : }
411 : | ident_or_keyword IDENT
412 : {
413 8 : $$ = makeDefElem($1, (Node *) makeString($2), -1);
414 : }
415 : | ident_or_keyword SCONST
416 : {
417 1922 : $$ = makeDefElem($1, (Node *) makeString($2), -1);
418 : }
419 : | ident_or_keyword UCONST
420 : {
421 308 : $$ = makeDefElem($1, (Node *) makeInteger($2), -1);
422 : }
423 : ;
424 :
425 : ident_or_keyword:
426 2354 : IDENT { $$ = $1; }
427 0 : | K_BASE_BACKUP { $$ = "base_backup"; }
428 0 : | K_IDENTIFY_SYSTEM { $$ = "identify_system"; }
429 0 : | K_SHOW { $$ = "show"; }
430 0 : | K_START_REPLICATION { $$ = "start_replication"; }
431 0 : | K_CREATE_REPLICATION_SLOT { $$ = "create_replication_slot"; }
432 0 : | K_DROP_REPLICATION_SLOT { $$ = "drop_replication_slot"; }
433 0 : | K_ALTER_REPLICATION_SLOT { $$ = "alter_replication_slot"; }
434 0 : | K_TIMELINE_HISTORY { $$ = "timeline_history"; }
435 304 : | K_WAIT { $$ = "wait"; }
436 0 : | K_TIMELINE { $$ = "timeline"; }
437 0 : | K_PHYSICAL { $$ = "physical"; }
438 0 : | K_LOGICAL { $$ = "logical"; }
439 0 : | K_SLOT { $$ = "slot"; }
440 242 : | K_RESERVE_WAL { $$ = "reserve_wal"; }
441 0 : | K_TEMPORARY { $$ = "temporary"; }
442 6 : | K_TWO_PHASE { $$ = "two_phase"; }
443 0 : | K_EXPORT_SNAPSHOT { $$ = "export_snapshot"; }
444 0 : | K_NOEXPORT_SNAPSHOT { $$ = "noexport_snapshot"; }
445 0 : | K_USE_SNAPSHOT { $$ = "use_snapshot"; }
446 0 : | K_UPLOAD_MANIFEST { $$ = "upload_manifest"; }
447 : ;
448 :
449 : %%
|