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