From 6c50b086029a3bf955d72e454384bb90e61debb1 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Thu, 19 Dec 2024 21:20:10 +0100 Subject: [PATCH v2 04/11] replication parser: Use flex yyextra Use flex yyextra to handle context information, instead of global variables. This complements the earlier patch to make the scanner reentrant. Co-authored-by: Andreas Karlsson --- src/backend/replication/repl_scanner.l | 69 +++++++++++++++----------- src/backend/replication/walsender.c | 1 + 2 files changed, 40 insertions(+), 30 deletions(-) diff --git a/src/backend/replication/repl_scanner.l b/src/backend/replication/repl_scanner.l index 6388024a598..899114d901a 100644 --- a/src/backend/replication/repl_scanner.l +++ b/src/backend/replication/repl_scanner.l @@ -38,16 +38,20 @@ fprintf_to_ereport(const char *fmt, const char *msg) ereport(ERROR, (errmsg_internal("%s", msg))); } -/* Pushed-back token (we only handle one) */ -static int repl_pushed_back_token; /* FIXME */ +struct replication_yy_extra_type +{ + /* Pushed-back token (we only handle one) */ + int repl_pushed_back_token; -/* Work area for collecting literals */ -static StringInfoData litbuf; /* FIXME */ + /* Work area for collecting literals */ + StringInfoData litbuf; +}; +#define YY_EXTRA_TYPE struct replication_yy_extra_type * -static void startlit(void); -static char *litbufdup(void); -static void addlit(char *ytext, int yleng); -static void addlitchar(unsigned char ychar); +static void startlit(yyscan_t yyscanner); +static char *litbufdup(yyscan_t yyscanner); +static void addlit(char *ytext, int yleng, yyscan_t yyscanner); +static void addlitchar(unsigned char ychar, yyscan_t yyscanner); /* LCOV_EXCL_START */ @@ -110,11 +114,11 @@ 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) + if (yyextra->repl_pushed_back_token) { - int result = repl_pushed_back_token; + int result = yyextra->repl_pushed_back_token; - repl_pushed_back_token = 0; + yyextra->repl_pushed_back_token = 0; return result; } %} @@ -159,27 +163,27 @@ UPLOAD_MANIFEST { return K_UPLOAD_MANIFEST; } {xqstart} { BEGIN(xq); - startlit(); + startlit(yyscanner); } {quotestop} { yyless(1); BEGIN(INITIAL); - yylval->str = litbufdup(); + yylval->str = litbufdup(yyscanner); return SCONST; } {xqdouble} { - addlitchar('\''); + addlitchar('\'', yyscanner); } {xqinside} { - addlit(yytext, yyleng); + addlit(yytext, yyleng, yyscanner); } {xdstart} { BEGIN(xd); - startlit(); + startlit(yyscanner); } {xdstop} { @@ -187,14 +191,14 @@ UPLOAD_MANIFEST { return K_UPLOAD_MANIFEST; } yyless(1); BEGIN(INITIAL); - yylval->str = litbufdup(); + yylval->str = litbufdup(yyscanner); len = strlen(yylval->str); truncate_identifier(yylval->str, len, true); return IDENT; } {xdinside} { - addlit(yytext, yyleng); + addlit(yytext, yyleng, yyscanner); } {identifier} { @@ -220,28 +224,32 @@ UPLOAD_MANIFEST { return K_UPLOAD_MANIFEST; } /* LCOV_EXCL_STOP */ +/* see scan.l */ +#undef yyextra +#define yyextra (((struct yyguts_t *) yyscanner)->yyextra_r) + static void -startlit(void) +startlit(yyscan_t yyscanner) { - initStringInfo(&litbuf); + initStringInfo(&yyextra->litbuf); } static char * -litbufdup(void) +litbufdup(yyscan_t yyscanner) { - return litbuf.data; + return yyextra->litbuf.data; } static void -addlit(char *ytext, int yleng) +addlit(char *ytext, int yleng, yyscan_t yyscanner) { - appendBinaryStringInfo(&litbuf, ytext, yleng); + appendBinaryStringInfo(&yyextra->litbuf, ytext, yleng); } static void -addlitchar(unsigned char ychar) +addlitchar(unsigned char ychar, yyscan_t yyscanner) { - appendStringInfoChar(&litbuf, ychar); + appendStringInfoChar(&yyextra->litbuf, ychar); } void @@ -256,21 +264,22 @@ void replication_scanner_init(const char *str, yyscan_t *yyscannerp) { yyscan_t yyscanner; + struct replication_yy_extra_type *yyext = palloc0_object(struct replication_yy_extra_type); if (yylex_init(yyscannerp) != 0) elog(ERROR, "yylex_init() failed: %m"); yyscanner = *yyscannerp; - yy_scan_string(str, yyscanner); + yyset_extra(yyext, yyscanner); - /* Make sure we start in proper state */ - repl_pushed_back_token = 0; + yy_scan_string(str, yyscanner); } void replication_scanner_finish(yyscan_t yyscanner) { + pfree(yyextra); yylex_destroy(yyscanner); } @@ -301,7 +310,7 @@ replication_scanner_is_replication_command(yyscan_t yyscanner) case K_UPLOAD_MANIFEST: case K_SHOW: /* Yes; push back the first token so we can parse later. */ - repl_pushed_back_token = first_token; + yyextra->repl_pushed_back_token = first_token; return true; default: /* Nope; we don't bother to push back the token. */ diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c index dc25dd6af91..559dba48962 100644 --- a/src/backend/replication/walsender.c +++ b/src/backend/replication/walsender.c @@ -1998,6 +1998,7 @@ exec_replication_command(const char *cmd_string) */ if (!replication_scanner_is_replication_command(scanner)) { + elog(WARNING, "CHECK1: not-repl: %s", cmd_string); /* Nope; clean up and get out. */ replication_scanner_finish(scanner); -- 2.47.1