PostgreSQL Source Code git master
Loading...
Searching...
No Matches
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-2026, 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:65
int int errmsg_internal(const char *fmt,...) pg_attribute_printf(1
#define ERROR
Definition elog.h:40
#define ereport(elevel,...)
Definition elog.h:152
static int fb(int x)
static void addlitchar(unsigned char ychar, yyscan_t yyscanner)
static void addlit(char *ytext, int yleng, yyscan_t yyscanner)
static void fprintf_to_ereport(const char *fmt, const char *msg)
static char * litbufdup(yyscan_t yyscanner)
#define startlit()
Definition scan.l:117
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
118 {
119 int result = yyextra->repl_pushed_back_token;
uint32 result
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/%08X", &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:681
uint32_t uint32
Definition c.h:680
void replication_yyerror(Node **replication_parse_result_p, yyscan_t yyscanner, const char *message)
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:1108
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:81
199
200<xd>{xddouble} {
201 addlitchar('"', yyscanner);
202 }
203
204<xd>{xdinside} {
205 addlit(yytext, yyleng, yyscanner);
206 }
207
208{identifier} {
209 int len = strlen(yytext);
210
212 return IDENT;
213 }
char * downcase_truncate_identifier(const char *ident, int len, bool warn)
Definition scansup.c:38
214
215. {
216 /* Any char not recognized above is returned as itself */
217 return yytext[0];
218 }
219
220<xq,xd><<EOF>> { replication_yyerror(NULL, yyscanner, "unterminated quoted string"); }
221
222
223<<EOF>> {
224 yyterminate();
225 }
226
227%%
228
229/* LCOV_EXCL_STOP */
230
231/* see scan.l */
232#undef yyextra
233#define yyextra (((struct yyguts_t *) yyscanner)->yyextra_r)
234
235static void
237{
238 initStringInfo(&yyextra->litbuf);
239}
240
241static char *
243{
244 return yyextra->litbuf.data;
245}
246
247static void
248addlit(char *ytext, int yleng, yyscan_t yyscanner)
249{
251}
252
253static void
254addlitchar(unsigned char ychar, yyscan_t yyscanner)
255{
257}
258
259/*
260 * (The first argument is enforced by Bison to match the first argument of
261 * yyparse(), but it is not used here.)
262 */
263void
265{
268 errmsg_internal("%s", message)));
269}
270
271void
273{
274 yyscan_t yyscanner;
276
277 if (yylex_init(yyscannerp) != 0)
278 elog(ERROR, "yylex_init() failed: %m");
279
280 yyscanner = *yyscannerp;
281
282 yyset_extra(yyext, yyscanner);
283
284 yy_scan_string(str, yyscanner);
285}
286
287void
289{
290 pfree(yyextra);
291 yylex_destroy(yyscanner);
292}
293
294/*
295 * Check to see if the first token of a command is a WalSender keyword.
296 *
297 * To keep repl_scanner.l minimal, we don't ask it to know every construct
298 * that the core lexer knows. Therefore, we daren't lex more than the
299 * first token of a general SQL command. That will usually look like an
300 * IDENT token here, although some other cases are possible.
301 */
302bool
304{
305 YYSTYPE dummy;
306 int first_token = replication_yylex(&dummy, yyscanner);
307
308 switch (first_token)
309 {
311 case K_BASE_BACKUP:
319 case K_SHOW:
320 /* Yes; push back the first token so we can parse later. */
321 yyextra->repl_pushed_back_token = first_token;
322 return true;
323 default:
324 /* Nope; we don't bother to push back the token. */
325 return false;
326 }
327}
328
329/*
330 * Interface functions to make flex use palloc() instead of malloc().
331 * It'd be better to make these static, but flex insists otherwise.
332 */
333
334void *
335yyalloc(yy_size_t size, yyscan_t yyscanner)
336{
337 return palloc(size);
338}
339
340void *
341yyrealloc(void *ptr, yy_size_t size, yyscan_t yyscanner)
342{
343 if (ptr)
344 return repalloc(ptr, size);
345 else
346 return palloc(size);
347}
348
349void
350yyfree(void *ptr, yyscan_t yyscanner)
351{
352 if (ptr)
353 pfree(ptr);
354}
int errcode(int sqlerrcode)
Definition elog.c:875
#define elog(elevel,...)
Definition elog.h:228
#define palloc0_object(type)
Definition fe_memutils.h:90
const char * str
void * repalloc(void *pointer, Size size)
Definition mcxt.c:1635
void pfree(void *pointer)
Definition mcxt.c:1619
void * palloc(Size size)
Definition mcxt.c:1390
int YYSTYPE
void * yyrealloc(void *ptr, yy_size_t size, yyscan_t yyscanner)
bool replication_scanner_is_replication_command(yyscan_t yyscanner)
void yyfree(void *ptr, yyscan_t yyscanner)
void * yyalloc(yy_size_t size, yyscan_t yyscanner)
void replication_scanner_finish(yyscan_t yyscanner)
void replication_scanner_init(const char *str, yyscan_t *yyscannerp)
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:133
int replication_yylex(union YYSTYPE *yylval_param, yyscan_t yyscanner)