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
4720 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)
1422 tgl@sss.pgh.pa.us 118 [ + + ]:CBC 26696 : {
119 : : int result = yyextra->repl_pushed_back_token;
120 : 2841 :
121 : : yyextra->repl_pushed_back_token = 0;
122 : 2841 : return result;
123 : 2841 : }
124 : : %}
125 : :
126 : : BASE_BACKUP { return K_BASE_BACKUP; }
5450 magnus@hagander.net 127 : 189 : IDENTIFY_SYSTEM { return K_IDENTIFY_SYSTEM; }
1513 michael@paquier.xyz 128 : 681 : READ_REPLICATION_SLOT { return K_READ_REPLICATION_SLOT; }
3248 rhaas@postgresql.org 129 : 681 : SHOW { return K_SHOW; }
4751 heikki.linnakangas@i 130 : 6 : TIMELINE { return K_TIMELINE; }
5450 magnus@hagander.net 131 : 546 : START_REPLICATION { return K_START_REPLICATION; }
4337 rhaas@postgresql.org 132 : 256 : CREATE_REPLICATION_SLOT { return K_CREATE_REPLICATION_SLOT; }
133 : 660 : DROP_REPLICATION_SLOT { return K_DROP_REPLICATION_SLOT; }
687 akapila@postgresql.o 134 : 452 : ALTER_REPLICATION_SLOT { return K_ALTER_REPLICATION_SLOT; }
4751 heikki.linnakangas@i 135 : 278 : TIMELINE_HISTORY { return K_TIMELINE_HISTORY; }
4337 rhaas@postgresql.org 136 : 6 : PHYSICAL { return K_PHYSICAL; }
3754 andres@anarazel.de 137 : 11 : RESERVE_WAL { return K_RESERVE_WAL; }
4299 rhaas@postgresql.org 138 : 136 : LOGICAL { return K_LOGICAL; }
4337 139 : 135 : SLOT { return K_SLOT; }
3295 peter_e@gmx.net 140 : 719 : TEMPORARY { return K_TEMPORARY; }
1630 akapila@postgresql.o 141 : 578 : TWO_PHASE { return K_TWO_PHASE; }
3199 peter_e@gmx.net 142 : 131 : EXPORT_SNAPSHOT { return K_EXPORT_SNAPSHOT; }
143 : 3 : NOEXPORT_SNAPSHOT { return K_NOEXPORT_SNAPSHOT; }
3190 peter_e@gmx.net 144 :UBC 0 : USE_SNAPSHOT { return K_USE_SNAPSHOT; }
3028 alvherre@alvh.no-ip. 145 : 0 : WAIT { return K_WAIT; }
727 rhaas@postgresql.org 146 : 0 : UPLOAD_MANIFEST { return K_UPLOAD_MANIFEST; }
4337 rhaas@postgresql.org 147 :CBC 450 :
1422 tgl@sss.pgh.pa.us 148 : 12 : {space}+ { /* do nothing */ }
5450 magnus@hagander.net 149 : 11755 :
4751 heikki.linnakangas@i 150 : 11755 : {digit}+ {
379 peter@eisentraut.org 151 : 447 : yylval->uintval = strtoul(yytext, NULL, 10);
4507 peter_e@gmx.net 152 : 447 : return UCONST;
4751 heikki.linnakangas@i 153 : 447 : }
154 : :
155 : : {hexdigit}+\/{hexdigit}+ {
4923 156 : 660 : uint32 hi,
157 : : lo;
158 : : if (sscanf(yytext, "%X/%08X", &hi, &lo) != 2)
326 peter@eisentraut.org 159 [ - + ]: 660 : replication_yyerror(NULL, yyscanner, "invalid streaming start location");
379 peter@eisentraut.org 160 :UBC 0 : yylval->recptr = ((uint64) hi) << 32 | lo;
5450 magnus@hagander.net 161 :CBC 660 : return RECPTR;
162 : 660 : }
163 : :
164 : : {xqstart} {
165 : 2719 : BEGIN(xq);
379 peter@eisentraut.org 166 : 2719 : startlit(yyscanner);
5450 magnus@hagander.net 167 : 2719 : }
168 : :
169 : 2719 : <xq>{quotestop} {
170 : 2719 : yyless(1);
171 : 2719 : BEGIN(INITIAL);
379 peter@eisentraut.org 172 : 2719 : yylval->str = litbufdup(yyscanner);
5450 magnus@hagander.net 173 : 2719 : return SCONST;
174 : 2719 : }
175 : :
176 : : <xq>{xqdouble} {
379 peter@eisentraut.org 177 :UBC 0 : addlitchar('\'', yyscanner);
5450 magnus@hagander.net 178 : 0 : }
179 : :
180 : 0 : <xq>{xqinside} {
379 peter@eisentraut.org 181 :CBC 2718 : addlit(yytext, yyleng, yyscanner);
5450 magnus@hagander.net 182 : 2718 : }
183 : :
4337 rhaas@postgresql.org 184 : 2718 : {xdstart} {
185 : 1037 : BEGIN(xd);
379 peter@eisentraut.org 186 : 1037 : startlit(yyscanner);
4337 rhaas@postgresql.org 187 : 1037 : }
188 : :
189 : 1037 : <xd>{xdstop} {
1313 peter@eisentraut.org 190 : 1037 : int len;
191 : :
192 : : yyless(1);
4337 rhaas@postgresql.org 193 : 1037 : BEGIN(INITIAL);
379 peter@eisentraut.org 194 : 1037 : yylval->str = litbufdup(yyscanner);
195 : 1037 : len = strlen(yylval->str);
196 : 1037 : truncate_identifier(yylval->str, len, true);
4337 rhaas@postgresql.org 197 : 1037 : return IDENT;
198 : 1037 : }
199 : :
200 : : <xd>{xdinside} {
379 peter@eisentraut.org 201 : 1037 : addlit(yytext, yyleng, yyscanner);
4337 rhaas@postgresql.org 202 : 1037 : }
203 : :
204 : 1037 : {identifier} {
1313 peter@eisentraut.org 205 : 6526 : int len = strlen(yytext);
4337 rhaas@postgresql.org 206 : 6526 :
207 : : yylval->str = downcase_truncate_identifier(yytext, len, true);
208 : 6526 : return IDENT;
209 : 6526 : }
210 : :
211 : : . {
1422 tgl@sss.pgh.pa.us 212 : 4376 : /* Any char not recognized above is returned as itself */
213 : : return yytext[0];
214 : 4376 : }
215 : :
216 : : <xq,xd><<EOF>> { replication_yyerror(NULL, yyscanner, "unterminated quoted string"); }
5450 magnus@hagander.net 217 :UBC 0 :
218 : :
5450 magnus@hagander.net 219 :CBC 2841 : <<EOF>> {
220 : : yyterminate();
221 : 2841 : }
222 : :
223 : : %%
5450 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)
5450 magnus@hagander.net 233 :CBC 3756 : {
234 : : initStringInfo(&yyextra->litbuf);
235 : 3756 : }
236 : 3756 :
237 : : static char *
238 : : litbufdup(yyscan_t yyscanner)
239 : 3756 : {
240 : : return yyextra->litbuf.data;
241 : 3756 : }
242 : :
243 : : static void
244 : : addlit(char *ytext, int yleng, yyscan_t yyscanner)
245 : 3755 : {
246 : : appendBinaryStringInfo(&yyextra->litbuf, ytext, yleng);
247 : 3755 : }
248 : 3755 :
249 : : static void
250 : : addlitchar(unsigned char ychar, yyscan_t yyscanner)
5450 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)
5450 magnus@hagander.net 269 :CBC 5216 : {
270 : : yyscan_t yyscanner;
271 : : struct replication_yy_extra_type *yyext = palloc0_object(struct replication_yy_extra_type);
379 peter@eisentraut.org 272 : 5216 :
273 : : if (yylex_init(yyscannerp) != 0)
274 [ - + ]: 5216 : elog(ERROR, "yylex_init() failed: %m");
379 peter@eisentraut.org 275 [ # # ]:UBC 0 :
276 : : yyscanner = *yyscannerp;
379 peter@eisentraut.org 277 :CBC 5216 :
278 : : yyset_extra(yyext, yyscanner);
279 : 5216 :
280 : : yy_scan_string(str, yyscanner);
5450 magnus@hagander.net 281 : 5216 : }
282 : 5216 :
283 : : void
284 : : replication_scanner_finish(yyscan_t yyscanner)
285 : 5216 : {
286 : : pfree(yyextra);
379 peter@eisentraut.org 287 : 5216 : yylex_destroy(yyscanner);
5450 magnus@hagander.net 288 : 5216 : }
1422 tgl@sss.pgh.pa.us 289 : 5216 :
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 : 5216 : {
301 : : YYSTYPE dummy;
302 : : int first_token = replication_yylex(&dummy, yyscanner);
303 : 5216 :
304 : : switch (first_token)
305 [ + + ]: 5216 : {
306 : : case K_IDENTIFY_SYSTEM:
307 : 2841 : 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 : 2841 : return true;
319 : 2841 : default:
320 : 2375 : /* Nope; we don't bother to push back the token. */
321 : : return false;
322 : 2375 : }
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)
379 peter@eisentraut.org 332 : 20864 : {
333 : : return palloc(size);
334 : 20864 : }
335 : :
336 : : void *
337 : : yyrealloc(void *ptr, yy_size_t size, yyscan_t yyscanner)
379 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)
379 peter@eisentraut.org 347 :CBC 26080 : {
348 : : if (ptr)
356 349 [ + + ]: 26080 : pfree(ptr);
379 350 : 20864 : }
0 s.n.thetic 351 : 26080 : /* END: function "replication_yyfree" */
|