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