v2-0004-replication-parser-Use-flex-yyextra.patch

text/plain

Filename: v2-0004-replication-parser-Use-flex-yyextra.patch
Type: text/plain
Part: 3
Message: Re: 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 v2-0004
Subject: replication parser: Use flex yyextra
File+
src/backend/replication/repl_scanner.l 39 30
src/backend/replication/walsender.c 1 0
From 6c50b086029a3bf955d72e454384bb90e61debb1 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
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 <andreas@proxel.se>
---
 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);
 				}
 
 <xq>{quotestop}	{
 					yyless(1);
 					BEGIN(INITIAL);
-					yylval->str = litbufdup();
+					yylval->str = litbufdup(yyscanner);
 					return SCONST;
 				}
 
 <xq>{xqdouble}	{
-					addlitchar('\'');
+					addlitchar('\'', yyscanner);
 				}
 
 <xq>{xqinside}  {
-					addlit(yytext, yyleng);
+					addlit(yytext, yyleng, yyscanner);
 				}
 
 {xdstart}		{
 					BEGIN(xd);
-					startlit();
+					startlit(yyscanner);
 				}
 
 <xd>{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;
 				}
 
 <xd>{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