v2-0022-replication-parser-Use-flex-yyextra.patch
text/x-patch
Filename: v2-0022-replication-parser-Use-flex-yyextra.patch
Type: text/x-patch
Part: 2
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-0022
Subject: replication parser: Use flex yyextra
| File | + | − |
|---|---|---|
| src/backend/replication/repl_scanner.l | 45 | 30 |
From 676ed65db9cac70189c1f33269fbbac519f59ca9 Mon Sep 17 00:00:00 2001
From: Andreas Karlsson <andreas@proxel.se>
Date: Mon, 16 Dec 2024 23:13:36 +0100
Subject: [PATCH v2 22/22] 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.
---
src/backend/replication/repl_scanner.l | 75 +++++++++++++++-----------
1 file changed, 45 insertions(+), 30 deletions(-)
diff --git a/src/backend/replication/repl_scanner.l b/src/backend/replication/repl_scanner.l
index 6388024a598..1c4fc302df0 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 repl_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 repl_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,37 @@ UPLOAD_MANIFEST { return K_UPLOAD_MANIFEST; }
/* LCOV_EXCL_STOP */
+/*
+ * Arrange access to yyextra for subroutines of the main yylex() function.
+ * We expect each subroutine to have a yyscanner parameter. Rather than
+ * use the yyget_xxx functions, which might or might not get inlined by the
+ * compiler, we cheat just a bit and cast yyscanner to the right type.
+ */
+#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,16 +269,18 @@ void
replication_scanner_init(const char *str, yyscan_t *yyscannerp)
{
yyscan_t yyscanner;
+ struct repl_yy_extra_type *yyext = palloc(sizeof(struct repl_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);
+
+ yyext->repl_pushed_back_token = 0;
- /* Make sure we start in proper state */
- repl_pushed_back_token = 0;
+ yy_scan_string(str, yyscanner);
}
void
@@ -301,7 +316,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. */
--
2.45.2