Hi hackers,
cfbot has been failing to build CF 4460 since it rebased v50 onto
current master. The failure is in readfuncs.c, and it is not
something the posted series did wrong.
9673a0aa92f threaded a ReadNodeContext through the node read path:
pg_strtok() takes it as its first argument now, and so does every
hand-written _readXxx(). _readRPRPattern() was written before that
and still uses the one-argument form, so the file no longer compiles.
The commits involved:
9673a0aa92f Make stringToNode() infrastructure thread-safe --
Michael Paquier, 2026-08-24, the mainline change
db2d99323f1 master of 2026-08-25, the first base under CF 4460 to
carry it
f17fac1c234 "[CF 4460] v50 - Implement row pattern recognition
feature" -- the cfbot branch's current commit, the
posted v50 series applied to db2d99323f1
v50 as posted is cut against master of 2026-08-01, where pg_strtok()
still takes one argument, so nothing is wrong with the series as it
was sent. Only a base carrying 9673a0aa92f needs this, and
f17fac1c234 is what I cut the patch against.
The patch does that one adaptation and nothing else. Only the read
path changed upstream, so nothing else about this node needed
touching.
The attachment carries the number 1003, in the naming the earlier
postings use.
This one goes on top of the increment series already posted, as an
addition the base made necessary rather than anything that series
lacked. More may follow the same way as the base picks up further
mainline changes.
Best regards,
Henson
From 1359290e19117fa93e2b84478b7951c084966511 Mon Sep 17 00:00:00 2001
From: Henson Choi <[email protected]>
Date: Wed, 26 Aug 2026 10:45:27 +0900
Subject: [PATCH] Adapt the RPR pattern reader to the thread-safe stringToNode
API
Commit 9673a0aa92f threaded a ReadNodeContext through the node read
path: pg_strtok() takes it as its first argument, and every hand-written
_readXxx() takes it as a parameter. _readRPRPattern() was written
before that and still uses the one-argument form, so readfuncs.c no
longer compiles.
Only the read path changed, so the other two hand-written functions for
this node, _copyRPRPattern() and _outRPRPattern(), are unaffected, and
the generated readers regenerate correctly -- readfuncs.switch.c already
passes ctx to _readRPRPattern.
v50 as posted is cut against master of 2026-08-01, where pg_strtok()
still takes one argument, so this belongs only on a base that carries
9673a0aa92f.
---
src/backend/nodes/readfuncs.c | 32 ++++++++++++++++----------------
1 file changed, 16 insertions(+), 16 deletions(-)
diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c
index bfc3d41d868..d390073e344 100644
--- a/src/backend/nodes/readfuncs.c
+++ b/src/backend/nodes/readfuncs.c
@@ -569,7 +569,7 @@ _readExtensibleNode(ReadNodeContext *ctx)
}
static RPRPattern *
-_readRPRPattern(void)
+_readRPRPattern(ReadNodeContext *ctx)
{
READ_LOCALS(RPRPattern);
@@ -578,17 +578,17 @@ _readRPRPattern(void)
READ_INT_FIELD(numElements);
/* Read varNames array */
- token = pg_strtok(&length); /* skip :varNames */
- token = pg_strtok(&length); /* get '(' or '<>' */
+ token = pg_strtok(ctx, &length); /* skip :varNames */
+ token = pg_strtok(ctx, &length); /* get '(' or '<>' */
if (local_node->numVars > 0 && token[0] == '(')
{
local_node->varNames = palloc_array(char *,
local_node->numVars);
for (int i = 0; i < local_node->numVars; i++)
{
- token = pg_strtok(&length);
+ token = pg_strtok(ctx, &length);
local_node->varNames[i] = debackslash(token, length);
}
- token = pg_strtok(&length); /* skip ')' */
+ token = pg_strtok(ctx, &length); /* skip ')' */
}
else
{
@@ -596,8 +596,8 @@ _readRPRPattern(void)
}
/* Read elements array */
- token = pg_strtok(&length); /* skip :elements */
- token = pg_strtok(&length); /* get '(' */
+ token = pg_strtok(ctx, &length); /* skip :elements */
+ token = pg_strtok(ctx, &length); /* get '(' */
/* out always emits the array (makeRPRPattern guarantees numElements >=
2) */
Assert(local_node->numElements > 0 && token[0] == '(');
local_node->elements = palloc0_array(RPRPatternElement,
local_node->numElements);
@@ -613,21 +613,21 @@ _readRPRPattern(void)
jump;
/* Parse "(varId depth flags min max next jump)" */
- token = pg_strtok(&length);
+ token = pg_strtok(ctx, &length);
varId = atoi(token);
- token = pg_strtok(&length);
+ token = pg_strtok(ctx, &length);
depth = atoi(token);
- token = pg_strtok(&length);
+ token = pg_strtok(ctx, &length);
flags = atoi(token);
- token = pg_strtok(&length);
+ token = pg_strtok(ctx, &length);
min = atoi(token);
- token = pg_strtok(&length);
+ token = pg_strtok(ctx, &length);
max = atoi(token);
- token = pg_strtok(&length);
+ token = pg_strtok(ctx, &length);
next = atoi(token);
- token = pg_strtok(&length);
+ token = pg_strtok(ctx, &length);
jump = atoi(token);
- token = pg_strtok(&length); /* skip ')' */
+ token = pg_strtok(ctx, &length); /* skip ')' */
elem->varId = (RPRVarId) varId;
elem->flags = (RPRElemFlags) flags;
@@ -639,7 +639,7 @@ _readRPRPattern(void)
/* Read next element's '(' or end */
if (i < local_node->numElements - 1)
- token = pg_strtok(&length); /* get '(' */
+ token = pg_strtok(ctx, &length); /* get '(' */
}
READ_BOOL_FIELD(isAbsorbable);
--
2.50.1 (Apple Git-155)