TLA Line data Source code
1 : %{
2 : /*-------------------------------------------------------------------------
3 : *
4 : * repl_gram.y - Parser for the replication commands
5 : *
6 : * Portions Copyright (c) 1996-2023, 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_TIMELINE_HISTORY
68 : %token K_WAIT
69 : %token K_TIMELINE
70 : %token K_PHYSICAL
71 : %token K_LOGICAL
72 : %token K_SLOT
73 : %token K_RESERVE_WAL
74 : %token K_TEMPORARY
75 : %token K_TWO_PHASE
76 : %token K_EXPORT_SNAPSHOT
77 : %token K_NOEXPORT_SNAPSHOT
78 : %token K_USE_SNAPSHOT
79 :
80 : %type <node> command
81 : %type <node> base_backup start_replication start_logical_replication
82 : create_replication_slot drop_replication_slot identify_system
83 : read_replication_slot timeline_history show
84 : %type <list> generic_option_list
85 : %type <defelt> generic_option
86 : %type <uintval> opt_timeline
87 : %type <list> plugin_options plugin_opt_list
88 : %type <defelt> plugin_opt_elem
89 : %type <node> plugin_opt_arg
90 : %type <str> opt_slot var_name ident_or_keyword
91 : %type <boolval> opt_temporary
92 : %type <list> create_slot_options create_slot_legacy_opt_list
93 : %type <defelt> create_slot_legacy_opt
94 :
95 : %%
96 :
97 ECB : firstcmd: command opt_semicolon
98 : {
99 GIC 2162 : replication_parse_result = $1;
100 : }
101 : ;
102 :
103 : opt_semicolon: ';'
104 : | /* EMPTY */
105 : ;
106 :
107 : command:
108 : identify_system
109 : | base_backup
110 : | start_replication
111 : | start_logical_replication
112 : | create_replication_slot
113 : | drop_replication_slot
114 : | read_replication_slot
115 : | timeline_history
116 : | show
117 : ;
118 :
119 : /*
120 : * IDENTIFY_SYSTEM
121 : */
122 : identify_system:
123 ECB : K_IDENTIFY_SYSTEM
124 : {
125 GIC 522 : $$ = (Node *) makeNode(IdentifySystemCmd);
126 : }
127 : ;
128 :
129 : /*
130 : * READ_REPLICATION_SLOT %s
131 : */
132 : read_replication_slot:
133 ECB : K_READ_REPLICATION_SLOT var_name
134 : {
135 CBC 6 : ReadReplicationSlotCmd *n = makeNode(ReadReplicationSlotCmd);
136 GIC 6 : n->slotname = $2;
137 6 : $$ = (Node *) n;
138 : }
139 : ;
140 :
141 : /*
142 : * SHOW setting
143 : */
144 : show:
145 ECB : K_SHOW var_name
146 : {
147 CBC 449 : VariableShowStmt *n = makeNode(VariableShowStmt);
148 GIC 449 : n->name = $2;
149 449 : $$ = (Node *) n;
150 ECB : }
151 :
152 GBC 455 : var_name: IDENT { $$ = $1; }
153 : | var_name '.' IDENT
154 UIC 0 : { $$ = psprintf("%s.%s", $1, $3); }
155 : ;
156 :
157 : /*
158 : * BASE_BACKUP [ ( option [ 'value' ] [, ...] ) ]
159 : */
160 : base_backup:
161 ECB : K_BASE_BACKUP '(' generic_option_list ')'
162 : {
163 CBC 142 : BaseBackupCmd *cmd = makeNode(BaseBackupCmd);
164 GIC 142 : cmd->options = $3;
165 142 : $$ = (Node *) cmd;
166 : }
167 ECB : | K_BASE_BACKUP
168 : {
169 GIC 1 : BaseBackupCmd *cmd = makeNode(BaseBackupCmd);
170 1 : $$ = (Node *) cmd;
171 : }
172 : ;
173 :
174 : create_replication_slot:
175 : /* CREATE_REPLICATION_SLOT slot [TEMPORARY] PHYSICAL [options] */
176 : K_CREATE_REPLICATION_SLOT IDENT opt_temporary K_PHYSICAL create_slot_options
177 ECB : {
178 : CreateReplicationSlotCmd *cmd;
179 CBC 97 : cmd = makeNode(CreateReplicationSlotCmd);
180 97 : cmd->kind = REPLICATION_KIND_PHYSICAL;
181 97 : cmd->slotname = $2;
182 97 : cmd->temporary = $3;
183 GIC 97 : cmd->options = $5;
184 97 : $$ = (Node *) cmd;
185 : }
186 : /* CREATE_REPLICATION_SLOT slot [TEMPORARY] LOGICAL plugin [options] */
187 : | K_CREATE_REPLICATION_SLOT IDENT opt_temporary K_LOGICAL IDENT create_slot_options
188 ECB : {
189 : CreateReplicationSlotCmd *cmd;
190 CBC 247 : cmd = makeNode(CreateReplicationSlotCmd);
191 247 : cmd->kind = REPLICATION_KIND_LOGICAL;
192 247 : cmd->slotname = $2;
193 247 : cmd->temporary = $3;
194 247 : cmd->plugin = $5;
195 GIC 247 : cmd->options = $6;
196 247 : $$ = (Node *) cmd;
197 : }
198 : ;
199 ECB :
200 : create_slot_options:
201 GIC 342 : '(' generic_option_list ')' { $$ = $2; }
202 2 : | create_slot_legacy_opt_list { $$ = $1; }
203 : ;
204 :
205 ECB : create_slot_legacy_opt_list:
206 : create_slot_legacy_opt_list create_slot_legacy_opt
207 CBC 1 : { $$ = lappend($1, $2); }
208 : | /* EMPTY */
209 GIC 2 : { $$ = NIL; }
210 : ;
211 :
212 : create_slot_legacy_opt:
213 EUB : K_EXPORT_SNAPSHOT
214 : {
215 UIC 0 : $$ = makeDefElem("snapshot",
216 0 : (Node *) makeString("export"), -1);
217 : }
218 EUB : | K_NOEXPORT_SNAPSHOT
219 : {
220 UIC 0 : $$ = makeDefElem("snapshot",
221 0 : (Node *) makeString("nothing"), -1);
222 : }
223 EUB : | K_USE_SNAPSHOT
224 : {
225 UIC 0 : $$ = makeDefElem("snapshot",
226 0 : (Node *) makeString("use"), -1);
227 : }
228 ECB : | K_RESERVE_WAL
229 : {
230 GIC 1 : $$ = makeDefElem("reserve_wal",
231 1 : (Node *) makeBoolean(true), -1);
232 : }
233 EUB : | K_TWO_PHASE
234 : {
235 UIC 0 : $$ = makeDefElem("two_phase",
236 0 : (Node *) makeBoolean(true), -1);
237 : }
238 : ;
239 :
240 : /* DROP_REPLICATION_SLOT slot */
241 : drop_replication_slot:
242 : K_DROP_REPLICATION_SLOT IDENT
243 ECB : {
244 : DropReplicationSlotCmd *cmd;
245 CBC 3 : cmd = makeNode(DropReplicationSlotCmd);
246 3 : cmd->slotname = $2;
247 GIC 3 : cmd->wait = false;
248 3 : $$ = (Node *) cmd;
249 : }
250 : | K_DROP_REPLICATION_SLOT IDENT K_WAIT
251 ECB : {
252 : DropReplicationSlotCmd *cmd;
253 CBC 189 : cmd = makeNode(DropReplicationSlotCmd);
254 189 : cmd->slotname = $2;
255 GIC 189 : cmd->wait = true;
256 189 : $$ = (Node *) cmd;
257 : }
258 : ;
259 :
260 : /*
261 : * START_REPLICATION [SLOT slot] [PHYSICAL] %X/%X [TIMELINE %d]
262 : */
263 : start_replication:
264 : K_START_REPLICATION opt_slot opt_physical RECPTR opt_timeline
265 : {
266 ECB : StartReplicationCmd *cmd;
267 :
268 CBC 195 : cmd = makeNode(StartReplicationCmd);
269 195 : cmd->kind = REPLICATION_KIND_PHYSICAL;
270 195 : cmd->slotname = $2;
271 195 : cmd->startpoint = $4;
272 GIC 195 : cmd->timeline = $5;
273 195 : $$ = (Node *) cmd;
274 : }
275 : ;
276 :
277 : /* START_REPLICATION SLOT slot LOGICAL %X/%X options */
278 : start_logical_replication:
279 : K_START_REPLICATION K_SLOT IDENT K_LOGICAL RECPTR plugin_options
280 ECB : {
281 : StartReplicationCmd *cmd;
282 CBC 298 : cmd = makeNode(StartReplicationCmd);
283 298 : cmd->kind = REPLICATION_KIND_LOGICAL;
284 298 : cmd->slotname = $3;
285 298 : cmd->startpoint = $5;
286 GIC 298 : cmd->options = $6;
287 298 : $$ = (Node *) cmd;
288 : }
289 : ;
290 : /*
291 : * TIMELINE_HISTORY %d
292 : */
293 : timeline_history:
294 : K_TIMELINE_HISTORY UCONST
295 : {
296 ECB : TimeLineHistoryCmd *cmd;
297 EUB :
298 GIC 13 : if ($2 <= 0)
299 UIC 0 : ereport(ERROR,
300 : (errcode(ERRCODE_SYNTAX_ERROR),
301 ECB : errmsg("invalid timeline %u", $2)));
302 :
303 GIC 13 : cmd = makeNode(TimeLineHistoryCmd);
304 CBC 13 : cmd->timeline = $2;
305 :
306 GIC 13 : $$ = (Node *) cmd;
307 : }
308 : ;
309 :
310 : opt_physical:
311 : K_PHYSICAL
312 : | /* EMPTY */
313 : ;
314 ECB :
315 : opt_temporary:
316 GIC 92 : K_TEMPORARY { $$ = true; }
317 252 : | /* EMPTY */ { $$ = false; }
318 : ;
319 :
320 ECB : opt_slot:
321 : K_SLOT IDENT
322 CBC 122 : { $$ = $2; }
323 : | /* EMPTY */
324 GIC 73 : { $$ = NULL; }
325 : ;
326 :
327 : opt_timeline:
328 ECB : K_TIMELINE UCONST
329 EUB : {
330 GIC 194 : if ($2 <= 0)
331 UIC 0 : ereport(ERROR,
332 ECB : (errcode(ERRCODE_SYNTAX_ERROR),
333 : errmsg("invalid timeline %u", $2)));
334 CBC 194 : $$ = $2;
335 : }
336 GIC 1 : | /* EMPTY */ { $$ = 0; }
337 : ;
338 :
339 ECB :
340 : plugin_options:
341 GIC 293 : '(' plugin_opt_list ')' { $$ = $2; }
342 5 : | /* EMPTY */ { $$ = NIL; }
343 : ;
344 :
345 : plugin_opt_list:
346 ECB : plugin_opt_elem
347 : {
348 GIC 293 : $$ = list_make1($1);
349 : }
350 ECB : | plugin_opt_list ',' plugin_opt_elem
351 : {
352 GIC 618 : $$ = lappend($1, $3);
353 : }
354 : ;
355 :
356 : plugin_opt_elem:
357 ECB : IDENT plugin_opt_arg
358 : {
359 GIC 911 : $$ = makeDefElem($1, $2, -1);
360 : }
361 : ;
362 ECB :
363 EUB : plugin_opt_arg:
364 GIC 911 : SCONST { $$ = (Node *) makeString($1); }
365 UIC 0 : | /* EMPTY */ { $$ = NULL; }
366 : ;
367 :
368 ECB : generic_option_list:
369 : generic_option_list ',' generic_option
370 CBC 808 : { $$ = lappend($1, $3); }
371 : | generic_option
372 GIC 484 : { $$ = list_make1($1); }
373 : ;
374 :
375 : generic_option:
376 ECB : ident_or_keyword
377 : {
378 GIC 292 : $$ = makeDefElem($1, NULL, -1);
379 : }
380 EUB : | ident_or_keyword IDENT
381 : {
382 UIC 0 : $$ = makeDefElem($1, (Node *) makeString($2), -1);
383 : }
384 ECB : | ident_or_keyword SCONST
385 : {
386 GIC 863 : $$ = makeDefElem($1, (Node *) makeString($2), -1);
387 : }
388 ECB : | ident_or_keyword UCONST
389 : {
390 GIC 137 : $$ = makeDefElem($1, (Node *) makeInteger($2), -1);
391 : }
392 : ;
393 ECB :
394 EUB : ident_or_keyword:
395 GBC 1060 : IDENT { $$ = $1; }
396 UBC 0 : | K_BASE_BACKUP { $$ = "base_backup"; }
397 0 : | K_IDENTIFY_SYSTEM { $$ = "identify_system"; }
398 0 : | K_SHOW { $$ = "show"; }
399 0 : | K_START_REPLICATION { $$ = "start_replication"; }
400 0 : | K_CREATE_REPLICATION_SLOT { $$ = "create_replication_slot"; }
401 LBC 0 : | K_DROP_REPLICATION_SLOT { $$ = "drop_replication_slot"; }
402 UBC 0 : | K_TIMELINE_HISTORY { $$ = "timeline_history"; }
403 GBC 135 : | K_WAIT { $$ = "wait"; }
404 UBC 0 : | K_TIMELINE { $$ = "timeline"; }
405 0 : | K_PHYSICAL { $$ = "physical"; }
406 LBC 0 : | K_LOGICAL { $$ = "logical"; }
407 UBC 0 : | K_SLOT { $$ = "slot"; }
408 CBC 95 : | K_RESERVE_WAL { $$ = "reserve_wal"; }
409 UBC 0 : | K_TEMPORARY { $$ = "temporary"; }
410 GBC 2 : | K_TWO_PHASE { $$ = "two_phase"; }
411 UBC 0 : | K_EXPORT_SNAPSHOT { $$ = "export_snapshot"; }
412 UIC 0 : | K_NOEXPORT_SNAPSHOT { $$ = "noexport_snapshot"; }
413 0 : | K_USE_SNAPSHOT { $$ = "use_snapshot"; }
414 : ;
415 :
416 : %%
|