aboutsummaryrefslogtreecommitdiff
path: root/src/backend/replication/repl_scanner.l
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/replication/repl_scanner.l')
-rw-r--r--src/backend/replication/repl_scanner.l87
1 files changed, 70 insertions, 17 deletions
diff --git a/src/backend/replication/repl_scanner.l b/src/backend/replication/repl_scanner.l
index 81ac41e9d45..d992bcc2e3c 100644
--- a/src/backend/replication/repl_scanner.l
+++ b/src/backend/replication/repl_scanner.l
@@ -31,6 +31,10 @@ fprintf_to_ereport(const char *fmt, const char *msg)
/* Handle to the buffer that the lexer uses internally */
static YY_BUFFER_STATE scanbufhandle;
+/* Pushed-back token (we only handle one) */
+static int repl_pushed_back_token;
+
+/* Work area for collecting literals */
static StringInfoData litbuf;
static void startlit(void);
@@ -51,7 +55,18 @@ static void addlitchar(unsigned char ychar);
%option warn
%option prefix="replication_yy"
-%x xq xd
+/*
+ * Exclusive states:
+ * <xd> delimited identifiers (double-quoted identifiers)
+ * <xq> standard single-quoted strings
+ */
+%x xd
+%x xq
+
+space [ \t\n\r\f]
+
+quote '
+quotestop {quote}
/* Extended quote
* xqdouble implements embedded quote, ''''
@@ -69,11 +84,8 @@ xdstop {dquote}
xddouble {dquote}{dquote}
xdinside [^"]+
-digit [0-9]+
-hexdigit [0-9A-Za-z]+
-
-quote '
-quotestop {quote}
+digit [0-9]
+hexdigit [0-9A-Fa-f]
ident_start [A-Za-z\200-\377_]
ident_cont [A-Za-z\200-\377_0-9\$]
@@ -82,6 +94,19 @@ identifier {ident_start}{ident_cont}*
%%
+%{
+ /* This code is inserted at the start of replication_yylex() */
+
+ /* If we have a pushed-back token, return that. */
+ if (repl_pushed_back_token)
+ {
+ int result = repl_pushed_back_token;
+
+ repl_pushed_back_token = 0;
+ return result;
+ }
+%}
+
BASE_BACKUP { return K_BASE_BACKUP; }
FAST { return K_FAST; }
IDENTIFY_SYSTEM { return K_IDENTIFY_SYSTEM; }
@@ -112,14 +137,7 @@ WAIT { return K_WAIT; }
MANIFEST { return K_MANIFEST; }
MANIFEST_CHECKSUMS { return K_MANIFEST_CHECKSUMS; }
-"," { return ','; }
-";" { return ';'; }
-"(" { return '('; }
-")" { return ')'; }
-
-[\n] ;
-[\t] ;
-" " ;
+{space}+ { /* do nothing */ }
{digit}+ {
yylval.uintval = strtoul(yytext, NULL, 10);
@@ -181,6 +199,11 @@ MANIFEST_CHECKSUMS { return K_MANIFEST_CHECKSUMS; }
return IDENT;
}
+. {
+ /* Any char not recognized above is returned as itself */
+ return yytext[0];
+ }
+
<xq,xd><<EOF>> { yyerror("unterminated quoted string"); }
@@ -188,9 +211,6 @@ MANIFEST_CHECKSUMS { return K_MANIFEST_CHECKSUMS; }
yyterminate();
}
-. {
- return T_WORD;
- }
%%
/* LCOV_EXCL_STOP */
@@ -250,6 +270,7 @@ replication_scanner_init(const char *str)
/* Make sure we start in proper state */
BEGIN(INITIAL);
+ repl_pushed_back_token = 0;
}
void
@@ -258,3 +279,35 @@ replication_scanner_finish(void)
yy_delete_buffer(scanbufhandle);
scanbufhandle = NULL;
}
+
+/*
+ * Check to see if the first token of a command is a WalSender keyword.
+ *
+ * To keep repl_scanner.l minimal, we don't ask it to know every construct
+ * that the core lexer knows. Therefore, we daren't lex more than the
+ * first token of a general SQL command. That will usually look like an
+ * IDENT token here, although some other cases are possible.
+ */
+bool
+replication_scanner_is_replication_command(void)
+{
+ int first_token = replication_yylex();
+
+ switch (first_token)
+ {
+ case K_IDENTIFY_SYSTEM:
+ case K_BASE_BACKUP:
+ case K_START_REPLICATION:
+ case K_CREATE_REPLICATION_SLOT:
+ case K_DROP_REPLICATION_SLOT:
+ case K_READ_REPLICATION_SLOT:
+ case K_TIMELINE_HISTORY:
+ case K_SHOW:
+ /* Yes; push back the first token so we can parse later. */
+ repl_pushed_back_token = first_token;
+ return true;
+ default:
+ /* Nope; we don't bother to push back the token. */
+ return false;
+ }
+}