v0-0007-replication-parser-pure-parser-and-reentrant-scan.patch
text/plain
Filename: v0-0007-replication-parser-pure-parser-and-reentrant-scan.patch
Type: text/plain
Part: 6
Message:
pure parsers and reentrant scanners
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v0-0007
Subject: replication parser: pure parser and reentrant scanner
| File | + | − |
|---|---|---|
| src/backend/replication/repl_gram.y | 5 | 4 |
| src/backend/replication/repl_scanner.l | 26 | 28 |
| src/backend/replication/walsender.c | 6 | 5 |
| src/include/replication/walsender_private.h | 10 | 8 |
From 7e1af47bdec122c1ec939912943c968ec3862d73 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Mon, 2 Dec 2024 10:35:37 +0100
Subject: [PATCH v0 07/15] replication parser: pure parser and reentrant
scanner
---
src/backend/replication/repl_gram.y | 9 ++--
src/backend/replication/repl_scanner.l | 54 ++++++++++-----------
src/backend/replication/walsender.c | 11 +++--
src/include/replication/walsender_private.h | 18 ++++---
4 files changed, 47 insertions(+), 45 deletions(-)
diff --git a/src/backend/replication/repl_gram.y b/src/backend/replication/repl_gram.y
index 06daa954813..4fa71377e20 100644
--- a/src/backend/replication/repl_gram.y
+++ b/src/backend/replication/repl_gram.y
@@ -24,10 +24,6 @@
#include "repl_gram.h"
-/* silence -Wmissing-variable-declarations */
-extern int replication_yychar;
-extern int replication_yynerrs;
-
/* Result of the parsing is returned here */
Node *replication_parse_result;
@@ -43,6 +39,9 @@ Node *replication_parse_result;
%}
+%parse-param {yyscan_t yyscanner}
+%lex-param {yyscan_t yyscanner}
+%pure-parser
%expect 0
%name-prefix="replication_yy"
@@ -106,6 +105,8 @@ Node *replication_parse_result;
firstcmd: command opt_semicolon
{
replication_parse_result = $1;
+
+ (void) yynerrs; /* suppress compiler warning */
}
;
diff --git a/src/backend/replication/repl_scanner.l b/src/backend/replication/repl_scanner.l
index e7def800655..99f2efbb8f9 100644
--- a/src/backend/replication/repl_scanner.l
+++ b/src/backend/replication/repl_scanner.l
@@ -38,14 +38,11 @@ fprintf_to_ereport(const char *fmt, const char *msg)
ereport(ERROR, (errmsg_internal("%s", 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;
+static int repl_pushed_back_token; /* FIXME */
/* Work area for collecting literals */
-static StringInfoData litbuf;
+static StringInfoData litbuf; /* FIXME */
static void startlit(void);
static char *litbufdup(void);
@@ -56,6 +53,8 @@ static void addlitchar(unsigned char ychar);
%}
+%option reentrant
+%option bison-bridge
%option 8bit
%option never-interactive
%option nodefault
@@ -142,7 +141,7 @@ UPLOAD_MANIFEST { return K_UPLOAD_MANIFEST; }
{space}+ { /* do nothing */ }
{digit}+ {
- replication_yylval.uintval = strtoul(yytext, NULL, 10);
+ yylval->uintval = strtoul(yytext, NULL, 10);
return UCONST;
}
@@ -150,8 +149,8 @@ UPLOAD_MANIFEST { return K_UPLOAD_MANIFEST; }
uint32 hi,
lo;
if (sscanf(yytext, "%X/%X", &hi, &lo) != 2)
- replication_yyerror("invalid streaming start location");
- replication_yylval.recptr = ((uint64) hi) << 32 | lo;
+ replication_yyerror("invalid streaming start location", yyscanner);
+ yylval->recptr = ((uint64) hi) << 32 | lo;
return RECPTR;
}
@@ -163,7 +162,7 @@ UPLOAD_MANIFEST { return K_UPLOAD_MANIFEST; }
<xq>{quotestop} {
yyless(1);
BEGIN(INITIAL);
- replication_yylval.str = litbufdup();
+ yylval->str = litbufdup();
return SCONST;
}
@@ -185,9 +184,9 @@ UPLOAD_MANIFEST { return K_UPLOAD_MANIFEST; }
yyless(1);
BEGIN(INITIAL);
- replication_yylval.str = litbufdup();
- len = strlen(replication_yylval.str);
- truncate_identifier(replication_yylval.str, len, true);
+ yylval->str = litbufdup();
+ len = strlen(yylval->str);
+ truncate_identifier(yylval->str, len, true);
return IDENT;
}
@@ -198,7 +197,7 @@ UPLOAD_MANIFEST { return K_UPLOAD_MANIFEST; }
{identifier} {
int len = strlen(yytext);
- replication_yylval.str = downcase_truncate_identifier(yytext, len, true);
+ yylval->str = downcase_truncate_identifier(yytext, len, true);
return IDENT;
}
@@ -207,7 +206,7 @@ UPLOAD_MANIFEST { return K_UPLOAD_MANIFEST; }
return yytext[0];
}
-<xq,xd><<EOF>> { replication_yyerror("unterminated quoted string"); }
+<xq,xd><<EOF>> { replication_yyerror("unterminated quoted string", yyscanner); }
<<EOF>> {
@@ -243,7 +242,7 @@ addlitchar(unsigned char ychar)
}
void
-replication_yyerror(const char *message)
+replication_yyerror(yyscan_t yyscanner, const char *message)
{
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
@@ -252,16 +251,16 @@ replication_yyerror(const char *message)
void
-replication_scanner_init(const char *str)
+replication_scanner_init(const char *str, yyscan_t *yyscannerp)
{
Size slen = strlen(str);
char *scanbuf;
+ yyscan_t yyscanner;
- /*
- * Might be left over after ereport()
- */
- if (YY_CURRENT_BUFFER)
- yy_delete_buffer(YY_CURRENT_BUFFER);
+ if (yylex_init(yyscannerp) != 0)
+ elog(ERROR, "yylex_init() failed: %m");
+
+ yyscanner = *yyscannerp;
/*
* Make a scan buffer with special termination needed by flex.
@@ -269,18 +268,16 @@ replication_scanner_init(const char *str)
scanbuf = (char *) palloc(slen + 2);
memcpy(scanbuf, str, slen);
scanbuf[slen] = scanbuf[slen + 1] = YY_END_OF_BUFFER_CHAR;
- scanbufhandle = yy_scan_buffer(scanbuf, slen + 2);
+ yy_scan_buffer(scanbuf, slen + 2, yyscanner);
/* Make sure we start in proper state */
- BEGIN(INITIAL);
repl_pushed_back_token = 0;
}
void
-replication_scanner_finish(void)
+replication_scanner_finish(yyscan_t yyscanner)
{
- yy_delete_buffer(scanbufhandle);
- scanbufhandle = NULL;
+ yylex_destroy(yyscanner);
}
/*
@@ -292,9 +289,10 @@ replication_scanner_finish(void)
* IDENT token here, although some other cases are possible.
*/
bool
-replication_scanner_is_replication_command(void)
+replication_scanner_is_replication_command(yyscan_t yyscanner)
{
- int first_token = replication_yylex();
+ YYSTYPE dummy;
+ int first_token = replication_yylex(&dummy, yyscanner);
switch (first_token)
{
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index 371eef3dddc..4971bcfb765 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -1951,6 +1951,7 @@ WalSndWaitForWal(XLogRecPtr loc)
bool
exec_replication_command(const char *cmd_string)
{
+ yyscan_t scanner;
int parse_rc;
Node *cmd_node;
const char *cmdtag;
@@ -1990,15 +1991,15 @@ exec_replication_command(const char *cmd_string)
ALLOCSET_DEFAULT_SIZES);
old_context = MemoryContextSwitchTo(cmd_context);
- replication_scanner_init(cmd_string);
+ replication_scanner_init(cmd_string, &scanner);
/*
* Is it a WalSender command?
*/
- if (!replication_scanner_is_replication_command())
+ if (!replication_scanner_is_replication_command(scanner))
{
/* Nope; clean up and get out. */
- replication_scanner_finish();
+ replication_scanner_finish(scanner);
MemoryContextSwitchTo(old_context);
MemoryContextDelete(cmd_context);
@@ -2016,13 +2017,13 @@ exec_replication_command(const char *cmd_string)
/*
* Looks like a WalSender command, so parse it.
*/
- parse_rc = replication_yyparse();
+ parse_rc = replication_yyparse(scanner);
if (parse_rc != 0)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg_internal("replication command parser returned %d",
parse_rc)));
- replication_scanner_finish();
+ replication_scanner_finish(scanner);
cmd_node = replication_parse_result;
diff --git a/src/include/replication/walsender_private.h b/src/include/replication/walsender_private.h
index 41ac736b953..a82ce33c083 100644
--- a/src/include/replication/walsender_private.h
+++ b/src/include/replication/walsender_private.h
@@ -125,13 +125,15 @@ extern void WalSndSetState(WalSndState state);
* Internal functions for parsing the replication grammar, in repl_gram.y and
* repl_scanner.l
*/
-extern int replication_yyparse(void);
-extern int replication_yylex(void);
-extern void replication_yyerror(const char *message) pg_attribute_noreturn();
-extern void replication_scanner_init(const char *str);
-extern void replication_scanner_finish(void);
-extern bool replication_scanner_is_replication_command(void);
-
-extern PGDLLIMPORT Node *replication_parse_result;
+union YYSTYPE;
+typedef void *yyscan_t;
+extern int replication_yyparse(yyscan_t yyscanner);
+extern int replication_yylex(union YYSTYPE *yylval_param, yyscan_t yyscanner);
+extern void replication_yyerror(yyscan_t yyscanner, const char *message) pg_attribute_noreturn();
+extern void replication_scanner_init(const char *str, yyscan_t *yyscannerp);
+extern void replication_scanner_finish(yyscan_t yyscanner);
+extern bool replication_scanner_is_replication_command(yyscan_t yyscanner);
+
+extern PGDLLIMPORT Node *replication_parse_result; /* FIXME */
#endif /* _WALSENDER_PRIVATE_H */
--
2.47.1