Line data Source code
1 : %{
2 : /*-------------------------------------------------------------------------
3 : *
4 : * repl_gram.y - Parser for the replication commands
5 : *
6 : * Portions Copyright (c) 1996-2017, 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/replnodes.h"
21 : #include "replication/walsender.h"
22 : #include "replication/walsender_private.h"
23 :
24 :
25 : /* Result of the parsing is returned here */
26 : Node *replication_parse_result;
27 :
28 : static SQLCmd *make_sqlcmd(void);
29 :
30 :
31 : /*
32 : * Bison doesn't allocate anything that needs to live across parser calls,
33 : * so we can easily have it use palloc instead of malloc. This prevents
34 : * memory leaks if we error out during parsing. Note this only works with
35 : * bison >= 2.0. However, in bison 1.875 the default is to use alloca()
36 : * if possible, so there's not really much problem anyhow, at least if
37 : * you're building with gcc.
38 : */
39 : #define YYMALLOC palloc
40 : #define YYFREE pfree
41 :
42 : %}
43 :
44 : %expect 0
45 : %name-prefix="replication_yy"
46 :
47 : %union {
48 : char *str;
49 : bool boolval;
50 : uint32 uintval;
51 :
52 : XLogRecPtr recptr;
53 : Node *node;
54 : List *list;
55 : DefElem *defelt;
56 : }
57 :
58 : /* Non-keyword tokens */
59 : %token <str> SCONST IDENT
60 : %token <uintval> UCONST
61 : %token <recptr> RECPTR
62 : %token T_WORD
63 :
64 : /* Keyword tokens. */
65 : %token K_BASE_BACKUP
66 : %token K_IDENTIFY_SYSTEM
67 : %token K_SHOW
68 : %token K_START_REPLICATION
69 : %token K_CREATE_REPLICATION_SLOT
70 : %token K_DROP_REPLICATION_SLOT
71 : %token K_TIMELINE_HISTORY
72 : %token K_LABEL
73 : %token K_PROGRESS
74 : %token K_FAST
75 : %token K_WAIT
76 : %token K_NOWAIT
77 : %token K_MAX_RATE
78 : %token K_WAL
79 : %token K_TABLESPACE_MAP
80 : %token K_TIMELINE
81 : %token K_PHYSICAL
82 : %token K_LOGICAL
83 : %token K_SLOT
84 : %token K_RESERVE_WAL
85 : %token K_TEMPORARY
86 : %token K_EXPORT_SNAPSHOT
87 : %token K_NOEXPORT_SNAPSHOT
88 : %token K_USE_SNAPSHOT
89 :
90 : %type <node> command
91 : %type <node> base_backup start_replication start_logical_replication
92 : create_replication_slot drop_replication_slot identify_system
93 : timeline_history show sql_cmd
94 : %type <list> base_backup_opt_list
95 : %type <defelt> base_backup_opt
96 : %type <uintval> opt_timeline
97 : %type <list> plugin_options plugin_opt_list
98 : %type <defelt> plugin_opt_elem
99 : %type <node> plugin_opt_arg
100 : %type <str> opt_slot var_name
101 : %type <boolval> opt_temporary
102 : %type <list> create_slot_opt_list
103 : %type <defelt> create_slot_opt
104 :
105 : %%
106 :
107 : firstcmd: command opt_semicolon
108 : {
109 0 : replication_parse_result = $1;
110 : }
111 : ;
112 :
113 : opt_semicolon: ';'
114 : | /* EMPTY */
115 : ;
116 :
117 : command:
118 : identify_system
119 : | base_backup
120 : | start_replication
121 : | start_logical_replication
122 : | create_replication_slot
123 : | drop_replication_slot
124 : | timeline_history
125 : | show
126 : | sql_cmd
127 : ;
128 :
129 : /*
130 : * IDENTIFY_SYSTEM
131 : */
132 : identify_system:
133 : K_IDENTIFY_SYSTEM
134 : {
135 0 : $$ = (Node *) makeNode(IdentifySystemCmd);
136 : }
137 : ;
138 :
139 : /*
140 : * SHOW setting
141 : */
142 : show:
143 : K_SHOW var_name
144 : {
145 0 : VariableShowStmt *n = makeNode(VariableShowStmt);
146 0 : n->name = $2;
147 0 : $$ = (Node *) n;
148 : }
149 :
150 0 : var_name: IDENT { $$ = $1; }
151 : | var_name '.' IDENT
152 0 : { $$ = psprintf("%s.%s", $1, $3); }
153 : ;
154 :
155 : /*
156 : * BASE_BACKUP [LABEL '<label>'] [PROGRESS] [FAST] [WAL] [NOWAIT]
157 : * [MAX_RATE %d] [TABLESPACE_MAP]
158 : */
159 : base_backup:
160 : K_BASE_BACKUP base_backup_opt_list
161 : {
162 0 : BaseBackupCmd *cmd = makeNode(BaseBackupCmd);
163 0 : cmd->options = $2;
164 0 : $$ = (Node *) cmd;
165 : }
166 : ;
167 :
168 : base_backup_opt_list:
169 : base_backup_opt_list base_backup_opt
170 0 : { $$ = lappend($1, $2); }
171 : | /* EMPTY */
172 0 : { $$ = NIL; }
173 : ;
174 :
175 : base_backup_opt:
176 : K_LABEL SCONST
177 : {
178 0 : $$ = makeDefElem("label",
179 0 : (Node *)makeString($2), -1);
180 : }
181 : | K_PROGRESS
182 : {
183 0 : $$ = makeDefElem("progress",
184 0 : (Node *)makeInteger(TRUE), -1);
185 : }
186 : | K_FAST
187 : {
188 0 : $$ = makeDefElem("fast",
189 0 : (Node *)makeInteger(TRUE), -1);
190 : }
191 : | K_WAL
192 : {
193 0 : $$ = makeDefElem("wal",
194 0 : (Node *)makeInteger(TRUE), -1);
195 : }
196 : | K_NOWAIT
197 : {
198 0 : $$ = makeDefElem("nowait",
199 0 : (Node *)makeInteger(TRUE), -1);
200 : }
201 : | K_MAX_RATE UCONST
202 : {
203 0 : $$ = makeDefElem("max_rate",
204 0 : (Node *)makeInteger($2), -1);
205 : }
206 : | K_TABLESPACE_MAP
207 : {
208 0 : $$ = makeDefElem("tablespace_map",
209 0 : (Node *)makeInteger(TRUE), -1);
210 : }
211 : ;
212 :
213 : create_replication_slot:
214 : /* CREATE_REPLICATION_SLOT slot TEMPORARY PHYSICAL RESERVE_WAL */
215 : K_CREATE_REPLICATION_SLOT IDENT opt_temporary K_PHYSICAL create_slot_opt_list
216 : {
217 : CreateReplicationSlotCmd *cmd;
218 0 : cmd = makeNode(CreateReplicationSlotCmd);
219 0 : cmd->kind = REPLICATION_KIND_PHYSICAL;
220 0 : cmd->slotname = $2;
221 0 : cmd->temporary = $3;
222 0 : cmd->options = $5;
223 0 : $$ = (Node *) cmd;
224 : }
225 : /* CREATE_REPLICATION_SLOT slot TEMPORARY LOGICAL plugin */
226 : | K_CREATE_REPLICATION_SLOT IDENT opt_temporary K_LOGICAL IDENT create_slot_opt_list
227 : {
228 : CreateReplicationSlotCmd *cmd;
229 0 : cmd = makeNode(CreateReplicationSlotCmd);
230 0 : cmd->kind = REPLICATION_KIND_LOGICAL;
231 0 : cmd->slotname = $2;
232 0 : cmd->temporary = $3;
233 0 : cmd->plugin = $5;
234 0 : cmd->options = $6;
235 0 : $$ = (Node *) cmd;
236 : }
237 : ;
238 :
239 : create_slot_opt_list:
240 : create_slot_opt_list create_slot_opt
241 0 : { $$ = lappend($1, $2); }
242 : | /* EMPTY */
243 0 : { $$ = NIL; }
244 : ;
245 :
246 : create_slot_opt:
247 : K_EXPORT_SNAPSHOT
248 : {
249 0 : $$ = makeDefElem("export_snapshot",
250 0 : (Node *)makeInteger(TRUE), -1);
251 : }
252 : | K_NOEXPORT_SNAPSHOT
253 : {
254 0 : $$ = makeDefElem("export_snapshot",
255 0 : (Node *)makeInteger(FALSE), -1);
256 : }
257 : | K_USE_SNAPSHOT
258 : {
259 0 : $$ = makeDefElem("use_snapshot",
260 0 : (Node *)makeInteger(TRUE), -1);
261 : }
262 : | K_RESERVE_WAL
263 : {
264 0 : $$ = makeDefElem("reserve_wal",
265 0 : (Node *)makeInteger(TRUE), -1);
266 : }
267 : ;
268 :
269 : /* DROP_REPLICATION_SLOT slot */
270 : drop_replication_slot:
271 : K_DROP_REPLICATION_SLOT IDENT
272 : {
273 : DropReplicationSlotCmd *cmd;
274 0 : cmd = makeNode(DropReplicationSlotCmd);
275 0 : cmd->slotname = $2;
276 0 : cmd->wait = false;
277 0 : $$ = (Node *) cmd;
278 : }
279 : | K_DROP_REPLICATION_SLOT IDENT K_WAIT
280 : {
281 : DropReplicationSlotCmd *cmd;
282 0 : cmd = makeNode(DropReplicationSlotCmd);
283 0 : cmd->slotname = $2;
284 0 : cmd->wait = true;
285 0 : $$ = (Node *) cmd;
286 : }
287 : ;
288 :
289 : /*
290 : * START_REPLICATION [SLOT slot] [PHYSICAL] %X/%X [TIMELINE %d]
291 : */
292 : start_replication:
293 : K_START_REPLICATION opt_slot opt_physical RECPTR opt_timeline
294 : {
295 : StartReplicationCmd *cmd;
296 :
297 0 : cmd = makeNode(StartReplicationCmd);
298 0 : cmd->kind = REPLICATION_KIND_PHYSICAL;
299 0 : cmd->slotname = $2;
300 0 : cmd->startpoint = $4;
301 0 : cmd->timeline = $5;
302 0 : $$ = (Node *) cmd;
303 : }
304 : ;
305 :
306 : /* START_REPLICATION SLOT slot LOGICAL %X/%X options */
307 : start_logical_replication:
308 : K_START_REPLICATION K_SLOT IDENT K_LOGICAL RECPTR plugin_options
309 : {
310 : StartReplicationCmd *cmd;
311 0 : cmd = makeNode(StartReplicationCmd);
312 0 : cmd->kind = REPLICATION_KIND_LOGICAL;
313 0 : cmd->slotname = $3;
314 0 : cmd->startpoint = $5;
315 0 : cmd->options = $6;
316 0 : $$ = (Node *) cmd;
317 : }
318 : ;
319 : /*
320 : * TIMELINE_HISTORY %d
321 : */
322 : timeline_history:
323 : K_TIMELINE_HISTORY UCONST
324 : {
325 : TimeLineHistoryCmd *cmd;
326 :
327 0 : if ($2 <= 0)
328 0 : ereport(ERROR,
329 : (errcode(ERRCODE_SYNTAX_ERROR),
330 : (errmsg("invalid timeline %u", $2))));
331 :
332 0 : cmd = makeNode(TimeLineHistoryCmd);
333 0 : cmd->timeline = $2;
334 :
335 0 : $$ = (Node *) cmd;
336 : }
337 : ;
338 :
339 : opt_physical:
340 : K_PHYSICAL
341 : | /* EMPTY */
342 : ;
343 :
344 : opt_temporary:
345 0 : K_TEMPORARY { $$ = true; }
346 0 : | /* EMPTY */ { $$ = false; }
347 : ;
348 :
349 : opt_slot:
350 : K_SLOT IDENT
351 0 : { $$ = $2; }
352 : | /* EMPTY */
353 0 : { $$ = NULL; }
354 : ;
355 :
356 : opt_timeline:
357 : K_TIMELINE UCONST
358 : {
359 0 : if ($2 <= 0)
360 0 : ereport(ERROR,
361 : (errcode(ERRCODE_SYNTAX_ERROR),
362 : (errmsg("invalid timeline %u", $2))));
363 0 : $$ = $2;
364 : }
365 0 : | /* EMPTY */ { $$ = 0; }
366 : ;
367 :
368 :
369 : plugin_options:
370 0 : '(' plugin_opt_list ')' { $$ = $2; }
371 0 : | /* EMPTY */ { $$ = NIL; }
372 : ;
373 :
374 : plugin_opt_list:
375 : plugin_opt_elem
376 : {
377 0 : $$ = list_make1($1);
378 : }
379 : | plugin_opt_list ',' plugin_opt_elem
380 : {
381 0 : $$ = lappend($1, $3);
382 : }
383 : ;
384 :
385 : plugin_opt_elem:
386 : IDENT plugin_opt_arg
387 : {
388 0 : $$ = makeDefElem($1, $2, -1);
389 : }
390 : ;
391 :
392 : plugin_opt_arg:
393 0 : SCONST { $$ = (Node *) makeString($1); }
394 0 : | /* EMPTY */ { $$ = NULL; }
395 : ;
396 :
397 : sql_cmd:
398 0 : IDENT { $$ = (Node *) make_sqlcmd(); }
399 : ;
400 : %%
401 :
402 : static SQLCmd *
403 0 : make_sqlcmd(void)
404 : {
405 0 : SQLCmd *cmd = makeNode(SQLCmd);
406 : int tok;
407 :
408 : /* Just move lexer to the end of command. */
409 : for (;;)
410 : {
411 0 : tok = yylex();
412 0 : if (tok == ';' || tok == 0)
413 : break;
414 0 : }
415 0 : return cmd;
416 : }
417 :
418 : #include "repl_scanner.c"
|