Age Owner Branch data TLA 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 : : {
4839 magnus@hagander.net 102 :CBC 2657 : 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 : 669 : $$ = (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 : : {
902 michael@paquier.xyz 140 : 6 : ReadReplicationSlotCmd *n = makeNode(ReadReplicationSlotCmd);
141 : 6 : n->slotname = $2;
142 : 6 : $$ = (Node *) n;
143 : : }
144 : : ;
145 : :
146 : : /*
147 : : * SHOW setting
148 : : */
149 : : show:
150 : : K_SHOW var_name
151 : : {
2637 rhaas@postgresql.org 152 : 528 : VariableShowStmt *n = makeNode(VariableShowStmt);
153 : 528 : n->name = $2;
154 : 528 : $$ = (Node *) n;
155 : : }
156 : :
157 : 534 : var_name: IDENT { $$ = $1; }
158 : : | var_name '.' IDENT
2637 rhaas@postgresql.org 159 :UBC 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 : : {
922 rhaas@postgresql.org 168 :CBC 168 : BaseBackupCmd *cmd = makeNode(BaseBackupCmd);
169 : 168 : cmd->options = $3;
170 : 168 : $$ = (Node *) cmd;
171 : : }
172 : : | K_BASE_BACKUP
173 : : {
2669 peter_e@gmx.net 174 : 1 : BaseBackupCmd *cmd = makeNode(BaseBackupCmd);
4839 magnus@hagander.net 175 : 1 : $$ = (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;
3726 rhaas@postgresql.org 184 : 121 : cmd = makeNode(CreateReplicationSlotCmd);
185 : 121 : cmd->kind = REPLICATION_KIND_PHYSICAL;
186 : 121 : cmd->slotname = $2;
2684 peter_e@gmx.net 187 : 121 : cmd->temporary = $3;
2588 188 : 121 : cmd->options = $5;
3726 rhaas@postgresql.org 189 : 121 : $$ = (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;
3688 195 : 285 : cmd = makeNode(CreateReplicationSlotCmd);
196 : 285 : cmd->kind = REPLICATION_KIND_LOGICAL;
197 : 285 : cmd->slotname = $2;
2684 peter_e@gmx.net 198 : 285 : cmd->temporary = $3;
199 : 285 : cmd->plugin = $5;
2588 200 : 285 : cmd->options = $6;
3688 rhaas@postgresql.org 201 : 285 : $$ = (Node *) cmd;
202 : : }
203 : : ;
204 : :
205 : : create_slot_options:
922 206 : 404 : '(' generic_option_list ')' { $$ = $2; }
207 : 2 : | create_slot_legacy_opt_list { $$ = $1; }
208 : : ;
209 : :
210 : : create_slot_legacy_opt_list:
211 : : create_slot_legacy_opt_list create_slot_legacy_opt
2588 peter_e@gmx.net 212 : 1 : { $$ = lappend($1, $2); }
213 : : | /* EMPTY */
214 : 2 : { $$ = NIL; }
215 : : ;
216 : :
217 : : create_slot_legacy_opt:
218 : : K_EXPORT_SNAPSHOT
219 : : {
922 rhaas@postgresql.org 220 :UBC 0 : $$ = makeDefElem("snapshot",
702 peter@eisentraut.org 221 : 0 : (Node *) makeString("export"), -1);
222 : : }
223 : : | K_NOEXPORT_SNAPSHOT
224 : : {
922 rhaas@postgresql.org 225 : 0 : $$ = makeDefElem("snapshot",
702 peter@eisentraut.org 226 : 0 : (Node *) makeString("nothing"), -1);
227 : : }
228 : : | K_USE_SNAPSHOT
229 : : {
922 rhaas@postgresql.org 230 : 0 : $$ = makeDefElem("snapshot",
702 peter@eisentraut.org 231 : 0 : (Node *) makeString("use"), -1);
232 : : }
233 : : | K_RESERVE_WAL
234 : : {
2588 peter_e@gmx.net 235 :CBC 1 : $$ = makeDefElem("reserve_wal",
702 peter@eisentraut.org 236 : 1 : (Node *) makeBoolean(true), -1);
237 : : }
238 : : | K_TWO_PHASE
239 : : {
1019 akapila@postgresql.o 240 :UBC 0 : $$ = makeDefElem("two_phase",
702 peter@eisentraut.org 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;
3726 rhaas@postgresql.org 250 :CBC 3 : cmd = makeNode(DropReplicationSlotCmd);
251 : 3 : cmd->slotname = $2;
2417 alvherre@alvh.no-ip. 252 : 3 : cmd->wait = false;
253 : 3 : $$ = (Node *) cmd;
254 : : }
255 : : | K_DROP_REPLICATION_SLOT IDENT K_WAIT
256 : : {
257 : : DropReplicationSlotCmd *cmd;
258 : 220 : cmd = makeNode(DropReplicationSlotCmd);
259 : 220 : cmd->slotname = $2;
260 : 220 : cmd->wait = true;
3726 rhaas@postgresql.org 261 : 220 : $$ = (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;
76 akapila@postgresql.o 270 :GNC 10 : cmd = makeNode(AlterReplicationSlotCmd);
271 : 10 : cmd->slotname = $2;
272 : 10 : cmd->options = $4;
273 : 10 : $$ = (Node *) cmd;
274 : : }
275 : : ;
276 : :
277 : : /*
278 : : * START_REPLICATION [SLOT slot] [PHYSICAL] %X/%X [TIMELINE %u]
279 : : */
280 : : start_replication:
281 : : K_START_REPLICATION opt_slot opt_physical RECPTR opt_timeline
282 : : {
283 : : StartReplicationCmd *cmd;
284 : :
4839 magnus@hagander.net 285 :CBC 267 : cmd = makeNode(StartReplicationCmd);
3726 rhaas@postgresql.org 286 : 267 : cmd->kind = REPLICATION_KIND_PHYSICAL;
287 : 267 : cmd->slotname = $2;
288 : 267 : cmd->startpoint = $4;
289 : 267 : cmd->timeline = $5;
4140 heikki.linnakangas@i 290 : 267 : $$ = (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;
3688 rhaas@postgresql.org 299 : 358 : cmd = makeNode(StartReplicationCmd);
3302 heikki.linnakangas@i 300 : 358 : cmd->kind = REPLICATION_KIND_LOGICAL;
3688 rhaas@postgresql.org 301 : 358 : cmd->slotname = $3;
302 : 358 : cmd->startpoint = $5;
303 : 358 : cmd->options = $6;
304 : 358 : $$ = (Node *) cmd;
305 : : }
306 : : ;
307 : : /*
308 : : * TIMELINE_HISTORY %u
309 : : */
310 : : timeline_history:
311 : : K_TIMELINE_HISTORY UCONST
312 : : {
313 : : TimeLineHistoryCmd *cmd;
314 : :
4140 heikki.linnakangas@i 315 [ - + ]: 13 : if ($2 <= 0)
4140 heikki.linnakangas@i 316 [ # # ]:UBC 0 : ereport(ERROR,
317 : : (errcode(ERRCODE_SYNTAX_ERROR),
318 : : errmsg("invalid timeline %u", $2)));
319 : :
4140 heikki.linnakangas@i 320 :CBC 13 : cmd = makeNode(TimeLineHistoryCmd);
321 : 13 : cmd->timeline = $2;
322 : :
4839 magnus@hagander.net 323 : 13 : $$ = (Node *) cmd;
324 : : }
325 : : ;
326 : :
327 : : /* UPLOAD_MANIFEST doesn't currently accept any arguments */
328 : : upload_manifest:
329 : : K_UPLOAD_MANIFEST
330 : : {
116 rhaas@postgresql.org 331 :GNC 8 : UploadManifestCmd *cmd = makeNode(UploadManifestCmd);
332 : :
333 : 8 : $$ = (Node *) cmd;
334 : : }
335 : :
336 : : opt_physical:
337 : : K_PHYSICAL
338 : : | /* EMPTY */
339 : : ;
340 : :
341 : : opt_temporary:
2684 peter_e@gmx.net 342 :CBC 116 : K_TEMPORARY { $$ = true; }
343 : 290 : | /* EMPTY */ { $$ = false; }
344 : : ;
345 : :
346 : : opt_slot:
347 : : K_SLOT IDENT
3724 tgl@sss.pgh.pa.us 348 : 167 : { $$ = $2; }
349 : : | /* EMPTY */
350 : 100 : { $$ = NULL; }
351 : : ;
352 : :
353 : : opt_timeline:
354 : : K_TIMELINE UCONST
355 : : {
3688 rhaas@postgresql.org 356 [ - + ]: 266 : if ($2 <= 0)
3688 rhaas@postgresql.org 357 [ # # ]:UBC 0 : ereport(ERROR,
358 : : (errcode(ERRCODE_SYNTAX_ERROR),
359 : : errmsg("invalid timeline %u", $2)));
3688 rhaas@postgresql.org 360 :CBC 266 : $$ = $2;
361 : : }
362 : 1 : | /* EMPTY */ { $$ = 0; }
363 : : ;
364 : :
365 : :
366 : : plugin_options:
367 : 353 : '(' plugin_opt_list ')' { $$ = $2; }
368 : 5 : | /* EMPTY */ { $$ = NIL; }
369 : : ;
370 : :
371 : : plugin_opt_list:
372 : : plugin_opt_elem
373 : : {
374 : 353 : $$ = list_make1($1);
375 : : }
376 : : | plugin_opt_list ',' plugin_opt_elem
377 : : {
378 : 738 : $$ = lappend($1, $3);
379 : : }
380 : : ;
381 : :
382 : : plugin_opt_elem:
383 : : IDENT plugin_opt_arg
384 : : {
2777 peter_e@gmx.net 385 : 1091 : $$ = makeDefElem($1, $2, -1);
386 : : }
387 : : ;
388 : :
389 : : plugin_opt_arg:
3688 rhaas@postgresql.org 390 : 1091 : SCONST { $$ = (Node *) makeString($1); }
3688 rhaas@postgresql.org 391 :UBC 0 : | /* EMPTY */ { $$ = NULL; }
392 : : ;
393 : :
394 : : generic_option_list:
395 : : generic_option_list ',' generic_option
922 rhaas@postgresql.org 396 :CBC 946 : { $$ = lappend($1, $3); }
397 : : | generic_option
398 : 582 : { $$ = list_make1($1); }
399 : : ;
400 : :
401 : : generic_option:
402 : : ident_or_keyword
403 : : {
404 : 355 : $$ = makeDefElem($1, NULL, -1);
405 : : }
406 : : | ident_or_keyword IDENT
407 : : {
922 rhaas@postgresql.org 408 :GBC 9 : $$ = makeDefElem($1, (Node *) makeString($2), -1);
409 : : }
410 : : | ident_or_keyword SCONST
411 : : {
922 rhaas@postgresql.org 412 :CBC 1002 : $$ = makeDefElem($1, (Node *) makeString($2), -1);
413 : : }
414 : : | ident_or_keyword UCONST
415 : : {
416 : 162 : $$ = makeDefElem($1, (Node *) makeInteger($2), -1);
417 : : }
418 : : ;
419 : :
420 : : ident_or_keyword:
421 : 1248 : IDENT { $$ = $1; }
922 rhaas@postgresql.org 422 :UBC 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"; }
76 akapila@postgresql.o 428 :UNC 0 : | K_ALTER_REPLICATION_SLOT { $$ = "alter_replication_slot"; }
922 rhaas@postgresql.org 429 :UBC 0 : | K_TIMELINE_HISTORY { $$ = "timeline_history"; }
922 rhaas@postgresql.org 430 :CBC 159 : | K_WAIT { $$ = "wait"; }
922 rhaas@postgresql.org 431 :UBC 0 : | K_TIMELINE { $$ = "timeline"; }
432 : 0 : | K_PHYSICAL { $$ = "physical"; }
433 : 0 : | K_LOGICAL { $$ = "logical"; }
434 : 0 : | K_SLOT { $$ = "slot"; }
922 rhaas@postgresql.org 435 :CBC 119 : | K_RESERVE_WAL { $$ = "reserve_wal"; }
922 rhaas@postgresql.org 436 :UBC 0 : | K_TEMPORARY { $$ = "temporary"; }
922 rhaas@postgresql.org 437 :CBC 2 : | K_TWO_PHASE { $$ = "two_phase"; }
922 rhaas@postgresql.org 438 :UBC 0 : | K_EXPORT_SNAPSHOT { $$ = "export_snapshot"; }
439 : 0 : | K_NOEXPORT_SNAPSHOT { $$ = "noexport_snapshot"; }
440 : 0 : | K_USE_SNAPSHOT { $$ = "use_snapshot"; }
116 rhaas@postgresql.org 441 :UNC 0 : | K_UPLOAD_MANIFEST { $$ = "upload_manifest"; }
442 : : ;
443 : :
444 : : %%
|