Age Owner Branch data TLA Line data Source code
1 : : %top{
2 : : /*-------------------------------------------------------------------------
3 : : *
4 : : * repl_scanner.l
5 : : * a lexical scanner for the replication commands
6 : : *
7 : : * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
8 : : * Portions Copyright (c) 1994, Regents of the University of California
9 : : *
10 : : *
11 : : * IDENTIFICATION
12 : : * src/backend/replication/repl_scanner.l
13 : : *
14 : : *-------------------------------------------------------------------------
15 : : */
16 : : #include "postgres.h"
17 : :
18 : : #include "nodes/parsenodes.h"
19 : : #include "utils/builtins.h"
20 : : #include "parser/scansup.h"
21 : :
22 : : /*
23 : : * NB: include repl_gram.h only AFTER including walsender_private.h, because
24 : : * walsender_private includes headers that define XLogRecPtr.
25 : : */
26 : : #include "replication/walsender_private.h"
27 : : #include "repl_gram.h"
28 : : }
29 : :
30 : : %{
31 : : /* Avoid exit() on fatal scanner errors (a bit ugly -- see yy_fatal_error) */
32 : : #undef fprintf
33 : : #define fprintf(file, fmt, msg) fprintf_to_ereport(fmt, msg)
34 : :
35 : : static void
4619 tgl@sss.pgh.pa.us 36 :UBC 0 : fprintf_to_ereport(const char *fmt, const char *msg)
37 : : {
38 [ # # ]: 0 : ereport(ERROR, (errmsg_internal("%s", msg)));
39 : : }
40 : :
41 : : struct replication_yy_extra_type
42 : : {
43 : : /* Pushed-back token (we only handle one) */
44 : : int repl_pushed_back_token;
45 : :
46 : : /* Work area for collecting literals */
47 : : StringInfoData litbuf;
48 : : };
49 : :
50 : : static void startlit(yyscan_t yyscanner);
51 : : static char *litbufdup(yyscan_t yyscanner);
52 : : static void addlit(char *ytext, int yleng, yyscan_t yyscanner);
53 : : static void addlitchar(unsigned char ychar, yyscan_t yyscanner);
54 : :
55 : : /* LCOV_EXCL_START */
56 : :
57 : : %}
58 : :
59 : : %option reentrant
60 : : %option bison-bridge
61 : : %option 8bit
62 : : %option never-interactive
63 : : %option nodefault
64 : : %option noinput
65 : : %option nounput
66 : : %option noyywrap
67 : : %option noyyalloc
68 : : %option noyyrealloc
69 : : %option noyyfree
70 : : %option warn
71 : : %option prefix="replication_yy"
72 : : %option extra-type="struct replication_yy_extra_type *"
73 : :
74 : : /*
75 : : * Exclusive states:
76 : : * <xd> delimited identifiers (double-quoted identifiers)
77 : : * <xq> standard single-quoted strings
78 : : */
79 : : %x xd
80 : : %x xq
81 : :
82 : : space [ \t\n\r\f\v]
83 : :
84 : : quote '
85 : : quotestop {quote}
86 : :
87 : : /* Extended quote
88 : : * xqdouble implements embedded quote, ''''
89 : : */
90 : : xqstart {quote}
91 : : xqdouble {quote}{quote}
92 : : xqinside [^']+
93 : :
94 : : /* Double quote
95 : : * Allows embedded spaces and other special characters into identifiers.
96 : : */
97 : : dquote \"
98 : : xdstart {dquote}
99 : : xdstop {dquote}
100 : : xddouble {dquote}{dquote}
101 : : xdinside [^"]+
102 : :
103 : : digit [0-9]
104 : : hexdigit [0-9A-Fa-f]
105 : :
106 : : ident_start [A-Za-z\200-\377_]
107 : : ident_cont [A-Za-z\200-\377_0-9\$]
108 : :
109 : : identifier {ident_start}{ident_cont}*
110 : :
111 : : %%
112 : :
113 : : %{
114 : : /* This code is inserted at the start of replication_yylex() */
115 : :
116 : : /* If we have a pushed-back token, return that. */
117 : : if (yyextra->repl_pushed_back_token)
1321 tgl@sss.pgh.pa.us 118 [ + + ]:CBC 26298 : {
119 : : int result = yyextra->repl_pushed_back_token;
120 : 2804 :
121 : : yyextra->repl_pushed_back_token = 0;
122 : 2804 : return result;
123 : 2804 : }
124 : : %}
125 : :
126 : : BASE_BACKUP { return K_BASE_BACKUP; }
5349 magnus@hagander.net 127 : 187 : IDENTIFY_SYSTEM { return K_IDENTIFY_SYSTEM; }
1412 michael@paquier.xyz 128 : 673 : READ_REPLICATION_SLOT { return K_READ_REPLICATION_SLOT; }
3147 rhaas@postgresql.org 129 : 673 : SHOW { return K_SHOW; }
4650 heikki.linnakangas@i 130 : 6 : TIMELINE { return K_TIMELINE; }
5349 magnus@hagander.net 131 : 540 : START_REPLICATION { return K_START_REPLICATION; }
4236 rhaas@postgresql.org 132 : 253 : CREATE_REPLICATION_SLOT { return K_CREATE_REPLICATION_SLOT; }
133 : 653 : DROP_REPLICATION_SLOT { return K_DROP_REPLICATION_SLOT; }
586 akapila@postgresql.o 134 : 443 : ALTER_REPLICATION_SLOT { return K_ALTER_REPLICATION_SLOT; }
4650 heikki.linnakangas@i 135 : 271 : TIMELINE_HISTORY { return K_TIMELINE_HISTORY; }
4236 rhaas@postgresql.org 136 : 6 : PHYSICAL { return K_PHYSICAL; }
3653 andres@anarazel.de 137 : 13 : RESERVE_WAL { return K_RESERVE_WAL; }
4198 rhaas@postgresql.org 138 : 134 : LOGICAL { return K_LOGICAL; }
4236 139 : 133 : SLOT { return K_SLOT; }
3194 peter_e@gmx.net 140 : 708 : TEMPORARY { return K_TEMPORARY; }
1529 akapila@postgresql.o 141 : 571 : TWO_PHASE { return K_TWO_PHASE; }
3098 peter_e@gmx.net 142 : 129 : EXPORT_SNAPSHOT { return K_EXPORT_SNAPSHOT; }
143 : 3 : NOEXPORT_SNAPSHOT { return K_NOEXPORT_SNAPSHOT; }
3089 peter_e@gmx.net 144 :UBC 0 : USE_SNAPSHOT { return K_USE_SNAPSHOT; }
2927 alvherre@alvh.no-ip. 145 : 0 : WAIT { return K_WAIT; }
626 rhaas@postgresql.org 146 : 0 : UPLOAD_MANIFEST { return K_UPLOAD_MANIFEST; }
4236 rhaas@postgresql.org 147 :CBC 441 :
1321 tgl@sss.pgh.pa.us 148 : 12 : {space}+ { /* do nothing */ }
5349 magnus@hagander.net 149 : 11603 :
4650 heikki.linnakangas@i 150 : 11603 : {digit}+ {
278 peter@eisentraut.org 151 : 444 : yylval->uintval = strtoul(yytext, NULL, 10);
4406 peter_e@gmx.net 152 : 444 : return UCONST;
4650 heikki.linnakangas@i 153 : 444 : }
154 : :
155 : : {hexdigit}+\/{hexdigit}+ {
4822 156 : 653 : uint32 hi,
157 : : lo;
158 : : if (sscanf(yytext, "%X/%08X", &hi, &lo) != 2)
225 peter@eisentraut.org 159 [ - + ]: 653 : replication_yyerror(NULL, yyscanner, "invalid streaming start location");
278 peter@eisentraut.org 160 :UBC 0 : yylval->recptr = ((uint64) hi) << 32 | lo;
5349 magnus@hagander.net 161 :CBC 653 : return RECPTR;
162 : 653 : }
163 : :
164 : : {xqstart} {
165 : 2688 : BEGIN(xq);
278 peter@eisentraut.org 166 : 2688 : startlit(yyscanner);
5349 magnus@hagander.net 167 : 2688 : }
168 : :
169 : 2688 : <xq>{quotestop} {
170 : 2688 : yyless(1);
171 : 2688 : BEGIN(INITIAL);
278 peter@eisentraut.org 172 : 2688 : yylval->str = litbufdup(yyscanner);
5349 magnus@hagander.net 173 : 2688 : return SCONST;
174 : 2688 : }
175 : :
176 : : <xq>{xqdouble} {
278 peter@eisentraut.org 177 :UBC 0 : addlitchar('\'', yyscanner);
5349 magnus@hagander.net 178 : 0 : }
179 : :
180 : 0 : <xq>{xqinside} {
278 peter@eisentraut.org 181 :CBC 2687 : addlit(yytext, yyleng, yyscanner);
5349 magnus@hagander.net 182 : 2687 : }
183 : :
4236 rhaas@postgresql.org 184 : 2687 : {xdstart} {
185 : 1021 : BEGIN(xd);
278 peter@eisentraut.org 186 : 1021 : startlit(yyscanner);
4236 rhaas@postgresql.org 187 : 1021 : }
188 : :
189 : 1021 : <xd>{xdstop} {
1212 peter@eisentraut.org 190 : 1021 : int len;
191 : :
192 : : yyless(1);
4236 rhaas@postgresql.org 193 : 1021 : BEGIN(INITIAL);
278 peter@eisentraut.org 194 : 1021 : yylval->str = litbufdup(yyscanner);
195 : 1021 : len = strlen(yylval->str);
196 : 1021 : truncate_identifier(yylval->str, len, true);
4236 rhaas@postgresql.org 197 : 1021 : return IDENT;
198 : 1021 : }
199 : :
200 : : <xd>{xdinside} {
278 peter@eisentraut.org 201 : 1021 : addlit(yytext, yyleng, yyscanner);
4236 rhaas@postgresql.org 202 : 1021 : }
203 : :
204 : 1021 : {identifier} {
1212 peter@eisentraut.org 205 : 6386 : int len = strlen(yytext);
4236 rhaas@postgresql.org 206 : 6386 :
207 : : yylval->str = downcase_truncate_identifier(yytext, len, true);
208 : 6386 : return IDENT;
209 : 6386 : }
210 : :
211 : : . {
1321 tgl@sss.pgh.pa.us 212 : 4322 : /* Any char not recognized above is returned as itself */
213 : : return yytext[0];
214 : 4322 : }
215 : :
216 : : <xq,xd><<EOF>> { replication_yyerror(NULL, yyscanner, "unterminated quoted string"); }
5349 magnus@hagander.net 217 :UBC 0 :
218 : :
5349 magnus@hagander.net 219 :CBC 2804 : <<EOF>> {
220 : : yyterminate();
221 : 2804 : }
222 : :
223 : : %%
5349 magnus@hagander.net 224 :UBC 0 :
225 : : /* LCOV_EXCL_STOP */
226 : :
227 : : /* see scan.l */
228 : : #undef yyextra
229 : : #define yyextra (((struct yyguts_t *) yyscanner)->yyextra_r)
230 : :
231 : : static void
232 : : startlit(yyscan_t yyscanner)
5349 magnus@hagander.net 233 :CBC 3709 : {
234 : : initStringInfo(&yyextra->litbuf);
235 : 3709 : }
236 : 3709 :
237 : : static char *
238 : : litbufdup(yyscan_t yyscanner)
239 : 3709 : {
240 : : return yyextra->litbuf.data;
241 : 3709 : }
242 : :
243 : : static void
244 : : addlit(char *ytext, int yleng, yyscan_t yyscanner)
245 : 3708 : {
246 : : appendBinaryStringInfo(&yyextra->litbuf, ytext, yleng);
247 : 3708 : }
248 : 3708 :
249 : : static void
250 : : addlitchar(unsigned char ychar, yyscan_t yyscanner)
5349 magnus@hagander.net 251 :UBC 0 : {
252 : : appendStringInfoChar(&yyextra->litbuf, ychar);
253 : 0 : }
254 : 0 :
255 : : /*
256 : : * (The first argument is enforced by Bison to match the first argument of
257 : : * yyparse(), but it is not used here.)
258 : : */
259 : : void
260 : : replication_yyerror(Node **replication_parse_result_p, yyscan_t yyscanner, const char *message)
261 : 0 : {
262 : : ereport(ERROR,
263 [ # # ]: 0 : (errcode(ERRCODE_SYNTAX_ERROR),
264 : : errmsg_internal("%s", message)));
265 : : }
266 : :
267 : : void
268 : : replication_scanner_init(const char *str, yyscan_t *yyscannerp)
5349 magnus@hagander.net 269 :CBC 5094 : {
270 : : yyscan_t yyscanner;
271 : : struct replication_yy_extra_type *yyext = palloc0_object(struct replication_yy_extra_type);
278 peter@eisentraut.org 272 : 5094 :
273 : : if (yylex_init(yyscannerp) != 0)
274 [ - + ]: 5094 : elog(ERROR, "yylex_init() failed: %m");
278 peter@eisentraut.org 275 [ # # ]:UBC 0 :
276 : : yyscanner = *yyscannerp;
278 peter@eisentraut.org 277 :CBC 5094 :
278 : : yyset_extra(yyext, yyscanner);
279 : 5094 :
280 : : yy_scan_string(str, yyscanner);
5349 magnus@hagander.net 281 : 5094 : }
282 : 5094 :
283 : : void
284 : : replication_scanner_finish(yyscan_t yyscanner)
285 : 5094 : {
286 : : pfree(yyextra);
278 peter@eisentraut.org 287 : 5094 : yylex_destroy(yyscanner);
5349 magnus@hagander.net 288 : 5094 : }
1321 tgl@sss.pgh.pa.us 289 : 5094 :
290 : : /*
291 : : * Check to see if the first token of a command is a WalSender keyword.
292 : : *
293 : : * To keep repl_scanner.l minimal, we don't ask it to know every construct
294 : : * that the core lexer knows. Therefore, we daren't lex more than the
295 : : * first token of a general SQL command. That will usually look like an
296 : : * IDENT token here, although some other cases are possible.
297 : : */
298 : : bool
299 : : replication_scanner_is_replication_command(yyscan_t yyscanner)
300 : 5094 : {
301 : : YYSTYPE dummy;
302 : : int first_token = replication_yylex(&dummy, yyscanner);
303 : 5094 :
304 : : switch (first_token)
305 [ + + ]: 5094 : {
306 : : case K_IDENTIFY_SYSTEM:
307 : 2804 : case K_BASE_BACKUP:
308 : : case K_START_REPLICATION:
309 : : case K_CREATE_REPLICATION_SLOT:
310 : : case K_DROP_REPLICATION_SLOT:
311 : : case K_ALTER_REPLICATION_SLOT:
312 : : case K_READ_REPLICATION_SLOT:
313 : : case K_TIMELINE_HISTORY:
314 : : case K_UPLOAD_MANIFEST:
315 : : case K_SHOW:
316 : : /* Yes; push back the first token so we can parse later. */
317 : : yyextra->repl_pushed_back_token = first_token;
318 : 2804 : return true;
319 : 2804 : default:
320 : 2290 : /* Nope; we don't bother to push back the token. */
321 : : return false;
322 : 2290 : }
323 : : }
324 : :
325 : : /*
326 : : * Interface functions to make flex use palloc() instead of malloc().
327 : : * It'd be better to make these static, but flex insists otherwise.
328 : : */
329 : :
330 : : void *
331 : : yyalloc(yy_size_t size, yyscan_t yyscanner)
278 peter@eisentraut.org 332 : 20376 : {
333 : : return palloc(size);
334 : 20376 : }
335 : :
336 : : void *
337 : : yyrealloc(void *ptr, yy_size_t size, yyscan_t yyscanner)
278 peter@eisentraut.org 338 :UBC 0 : {
339 : : if (ptr)
340 [ # # ]: 0 : return repalloc(ptr, size);
341 : 0 : else
342 : : return palloc(size);
343 : 0 : }
344 : :
345 : : void
346 : : yyfree(void *ptr, yyscan_t yyscanner)
278 peter@eisentraut.org 347 :CBC 25470 : {
348 : : if (ptr)
255 349 [ + + ]: 25470 : pfree(ptr);
278 350 : 20376 : }
0 s.n.thetic 351 : 25470 : /* END: function "replication_yyfree" */
|