2/*-------------------------------------------------------------------------
5 * a lexical scanner for the replication commands
7 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
12 * src/backend/replication/repl_scanner.l
14 *-------------------------------------------------------------------------
23 * NB: include repl_gram.h only AFTER including walsender_private.h, because
24 * walsender_private includes headers that define XLogRecPtr.
31/* Avoid exit() on fatal scanner errors (a bit ugly -- see yy_fatal_error) */
33 #define fprintf(file, fmt, msg) fprintf_to_ereport(fmt, msg)
43 /* Pushed-back token (we only handle one) */
46 /* Work area for collecting literals */
int errmsg_internal(const char *fmt,...)
#define ereport(elevel,...)
static void startlit(yyscan_t yyscanner)
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)
62%option never-interactive
71%option prefix="replication_yy"
72%option extra-type="struct replication_yy_extra_type *"
76 * <xd> delimited identifiers (double-quoted identifiers)
77 * <xq> standard single-quoted strings
88 * xqdouble implements embedded quote, ''''
91xqdouble {quote}{quote}
95 * Allows embedded spaces and other special characters into identifiers.
100xddouble {dquote}{dquote}
106ident_start [A-Za-z200円-377円_]
107ident_cont [A-Za-z200円-377円_0-9\$]
109identifier {ident_start}{ident_cont}*
114 /* This code is inserted at the start of replication_yylex() */
116 /* If we have a pushed-back token, return that. */
117 if (
yyextra->repl_pushed_back_token)
119 int result =
yyextra->repl_pushed_back_token;
121 yyextra->repl_pushed_back_token = 0;
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; }
148{space}+ {
/* do nothing */ }
151 yylval->uintval = strtoul(yytext, NULL, 10);
155{hexdigit}+\/{hexdigit}+ {
158 if (sscanf(yytext,
"%X/%08X", &hi, &lo) != 2)
160 yylval->recptr = ((
uint64) hi) << 32 | lo;
void replication_yyerror(Node **replication_parse_result_p, yyscan_t yyscanner, const char *message)
195 len = strlen(yylval->str);
void truncate_identifier(char *ident, int len, bool warn)
205 int len = strlen(yytext);
char * downcase_truncate_identifier(const char *ident, int len, bool warn)
212 /* Any char not recognized above is returned as itself */
229#define yyextra (((struct yyguts_t *) yyscanner)->yyextra_r)
256 * (The first argument is enforced by Bison to match the first argument of
257 * yyparse(), but it is not used here.)
263 (
errcode(ERRCODE_SYNTAX_ERROR),
273 if (yylex_init(yyscannerp) != 0)
276 yyscanner = *yyscannerp;
278 yyset_extra(yyext, yyscanner);
280 yy_scan_string(
str, yyscanner);
287 yylex_destroy(yyscanner);
291 * Check to see if the first token of a command is a WalSender keyword.
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.
306 case K_IDENTIFY_SYSTEM:
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:
316 /* Yes; push back the first token so we can parse later. */
317 yyextra->repl_pushed_back_token = first_token;
320 /* Nope; we don't bother to push back the token. */
326 * Interface functions to make flex use palloc() instead of malloc().
327 * It'd be better to make these static, but flex insists otherwise.
int errcode(int sqlerrcode)
#define palloc0_object(type)
void * repalloc(void *pointer, Size size)
void pfree(void *pointer)
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)
void appendStringInfoChar(StringInfo str, char ch)
void initStringInfo(StringInfo str)
int replication_yylex(union YYSTYPE *yylval_param, yyscan_t yyscanner)