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