PostgreSQL Source Code git master
repl_scanner.l
Go to the documentation of this file.
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 */
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
35static void
36fprintf_to_ereport(const char *fmt, const char *msg)
37{
38 ereport(ERROR, (errmsg_internal("%s", msg)));
39}
40
42{
43 /* Pushed-back token (we only handle one) */
45
46 /* Work area for collecting literals */
48};
49
50static void startlit(yyscan_t yyscanner);
51static char *litbufdup(yyscan_t yyscanner);
52static void addlit(char *ytext, int yleng, yyscan_t yyscanner);
53static void addlitchar(unsigned char ychar, yyscan_t yyscanner);
54
55/* LCOV_EXCL_START */
56
void * yyscan_t
Definition: cubedata.h:67
int errmsg_internal(const char *fmt,...)
Definition: elog.c:1157
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
static void const char * fmt
static void startlit(yyscan_t yyscanner)
Definition: repl_scanner.l:232
static void addlitchar(unsigned char ychar, yyscan_t yyscanner)
Definition: repl_scanner.l:250
static void addlit(char *ytext, int yleng, yyscan_t yyscanner)
Definition: repl_scanner.l:244
static void fprintf_to_ereport(const char *fmt, const char *msg)
Definition: repl_scanner.l:36
static char * litbufdup(yyscan_t yyscanner)
Definition: repl_scanner.l:238
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
82space [ \t\n\r\f\v]
83
84quote '
85quotestop {quote}
86
87/* Extended quote
88 * xqdouble implements embedded quote, ''''
89 */
90xqstart {quote}
91xqdouble {quote}{quote}
92xqinside [^']+
93
94/* Double quote
95 * Allows embedded spaces and other special characters into identifiers.
96 */
97dquote \"
98xdstart {dquote}
99xdstop {dquote}
100xddouble {dquote}{dquote}
101xdinside [^"]+
102
103digit [0-9]
104hexdigit [0-9A-Fa-f]
105
106ident_start [A-Za-z\200-\377_]
107ident_cont [A-Za-z\200-\377_0-9\$]
108
109identifier {ident_start}{ident_cont}*
110
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)
#define yyextra
Definition: scan.l:1118
118 {
119 int result = yyextra->repl_pushed_back_token;
120
121 yyextra->repl_pushed_back_token = 0;
122 return result;
123 }
124%}
125
126BASE_BACKUP { return K_BASE_BACKUP; }
127IDENTIFY_SYSTEM { return K_IDENTIFY_SYSTEM; }
128READ_REPLICATION_SLOT { return K_READ_REPLICATION_SLOT; }
129SHOW { return K_SHOW; }
130TIMELINE { return K_TIMELINE; }
131START_REPLICATION { return K_START_REPLICATION; }
132CREATE_REPLICATION_SLOT { return K_CREATE_REPLICATION_SLOT; }
133DROP_REPLICATION_SLOT { return K_DROP_REPLICATION_SLOT; }
134ALTER_REPLICATION_SLOT { return K_ALTER_REPLICATION_SLOT; }
135TIMELINE_HISTORY { return K_TIMELINE_HISTORY; }
136PHYSICAL { return K_PHYSICAL; }
137RESERVE_WAL { return K_RESERVE_WAL; }
138LOGICAL { return K_LOGICAL; }
139SLOT { return K_SLOT; }
140TEMPORARY { return K_TEMPORARY; }
141TWO_PHASE { return K_TWO_PHASE; }
142EXPORT_SNAPSHOT { return K_EXPORT_SNAPSHOT; }
143NOEXPORT_SNAPSHOT { return K_NOEXPORT_SNAPSHOT; }
144USE_SNAPSHOT { return K_USE_SNAPSHOT; }
145WAIT { return K_WAIT; }
146UPLOAD_MANIFEST { return K_UPLOAD_MANIFEST; }
147
148{space}+ { /* do nothing */ }
149
150{digit}+ {
151 yylval->uintval = strtoul(yytext, NULL, 10);
152 return UCONST;
153 }
154
155{hexdigit}+\/{hexdigit}+ {
156 uint32 hi,
157 lo;
158 if (sscanf(yytext, "%X/%X", &hi, &lo) != 2)
159 replication_yyerror(NULL, yyscanner, "invalid streaming start location");
160 yylval->recptr = ((uint64) hi) << 32 | lo;
161 return RECPTR;
162 }
uint64_t uint64
Definition: c.h:489
uint32_t uint32
Definition: c.h:488
void replication_yyerror(Node **replication_parse_result_p, yyscan_t yyscanner, const char *message)
Definition: repl_scanner.l:260
163
164{xqstart} {
165 BEGIN(xq);
166 startlit(yyscanner);
167 }
168
169<xq>{quotestop} {
170 yyless(1);
171 BEGIN(INITIAL);
172 yylval->str = litbufdup(yyscanner);
173 return SCONST;
174 }
175
176<xq>{xqdouble} {
177 addlitchar('\'', yyscanner);
178 }
179
180<xq>{xqinside} {
181 addlit(yytext, yyleng, yyscanner);
182 }
#define yyleng
Definition: scan.l:1124
183
184{xdstart} {
185 BEGIN(xd);
186 startlit(yyscanner);
187 }
188
189<xd>{xdstop} {
190 int len;
191
192 yyless(1);
193 BEGIN(INITIAL);
194 yylval->str = litbufdup(yyscanner);
195 len = strlen(yylval->str);
196 truncate_identifier(yylval->str, len, true);
197 return IDENT;
198 }
const void size_t len
void truncate_identifier(char *ident, int len, bool warn)
Definition: scansup.c:93
199
200<xd>{xdinside} {
201 addlit(yytext, yyleng, yyscanner);
202 }
203
204{identifier} {
205 int len = strlen(yytext);
206
207 yylval->str = downcase_truncate_identifier(yytext, len, true);
208 return IDENT;
209 }
char * downcase_truncate_identifier(const char *ident, int len, bool warn)
Definition: scansup.c:37
210
211. {
212 /* Any char not recognized above is returned as itself */
213 return yytext[0];
214 }
215
216<xq,xd><<EOF>> { replication_yyerror(NULL, yyscanner, "unterminated quoted string"); }
217
218
219<<EOF>> {
220 yyterminate();
221 }
222
223%%
224
225/* LCOV_EXCL_STOP */
226
227/* see scan.l */
228#undef yyextra
229#define yyextra (((struct yyguts_t *) yyscanner)->yyextra_r)
230
231static void
233{
234 initStringInfo(&yyextra->litbuf);
235}
236
237static char *
239{
240 return yyextra->litbuf.data;
241}
242
243static void
244addlit(char *ytext, int yleng, yyscan_t yyscanner)
245{
246 appendBinaryStringInfo(&yyextra->litbuf, ytext, yleng);
247}
248
249static void
250addlitchar(unsigned char ychar, yyscan_t yyscanner)
251{
252 appendStringInfoChar(&yyextra->litbuf, ychar);
253}
254
255/*
256 * (The first argument is enforced by Bison to match the first argument of
257 * yyparse(), but it is not used here.)
258 */
259void
260replication_yyerror(Node **replication_parse_result_p, yyscan_t yyscanner, const char *message)
261{
263 (errcode(ERRCODE_SYNTAX_ERROR),
264 errmsg_internal("%s", message)));
265}
266
267void
268replication_scanner_init(const char *str, yyscan_t *yyscannerp)
269{
270 yyscan_t yyscanner;
272
273 if (yylex_init(yyscannerp) != 0)
274 elog(ERROR, "yylex_init() failed: %m");
275
276 yyscanner = *yyscannerp;
277
278 yyset_extra(yyext, yyscanner);
279
280 yy_scan_string(str, yyscanner);
281}
282
283void
285{
286 pfree(yyextra);
287 yylex_destroy(yyscanner);
288}
289
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 */
298bool
300{
301 YYSTYPE dummy;
302 int first_token = replication_yylex(&dummy, yyscanner);
303
304 switch (first_token)
305 {
306 case K_IDENTIFY_SYSTEM:
307 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 return true;
319 default:
320 /* Nope; we don't bother to push back the token. */
321 return false;
322 }
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
330void *
331yyalloc(yy_size_t size, yyscan_t yyscanner)
332{
333 return palloc(size);
334}
335
336void *
337yyrealloc(void *ptr, yy_size_t size, yyscan_t yyscanner)
338{
339 if (ptr)
340 return repalloc(ptr, size);
341 else
342 return palloc(size);
343}
344
345void
346yyfree(void *ptr, yyscan_t yyscanner)
347{
348 if (ptr)
349 pfree(ptr);
350}
int errcode(int sqlerrcode)
Definition: elog.c:853
#define elog(elevel,...)
Definition: elog.h:225
#define palloc0_object(type)
Definition: fe_memutils.h:75
const char * str
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1541
void pfree(void *pointer)
Definition: mcxt.c:1521
void * palloc(Size size)
Definition: mcxt.c:1317
int YYSTYPE
Definition: psqlscanslash.l:39
void * yyrealloc(void *ptr, yy_size_t size, yyscan_t yyscanner)
Definition: repl_scanner.l:337
bool replication_scanner_is_replication_command(yyscan_t yyscanner)
Definition: repl_scanner.l:299
void yyfree(void *ptr, yyscan_t yyscanner)
Definition: repl_scanner.l:346
void * yyalloc(yy_size_t size, yyscan_t yyscanner)
Definition: repl_scanner.l:331
void replication_scanner_finish(yyscan_t yyscanner)
Definition: repl_scanner.l:284
void replication_scanner_init(const char *str, yyscan_t *yyscannerp)
Definition: repl_scanner.l:268
static pg_noinline void Size size
Definition: slab.c:607
void appendBinaryStringInfo(StringInfo str, const void *data, int datalen)
Definition: stringinfo.c:281
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:242
void initStringInfo(StringInfo str)
Definition: stringinfo.c:97
Definition: nodes.h:129
int replication_yylex(union YYSTYPE *yylval_param, yyscan_t yyscanner)