diff options
Diffstat (limited to 'src/backend/replication/repl_scanner.l')
-rw-r--r-- | src/backend/replication/repl_scanner.l | 87 |
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; + } +} |