nocfbot-0002-fix-rpr-reluctant-quantifier-flag-lost-during-view-s.txt
text/plain
Filename: nocfbot-0002-fix-rpr-reluctant-quantifier-flag-lost-during-view-s.txt
Type: text/plain
Part: 1
Message:
Re: Row pattern recognition
From 2bc7f29dcfceefc83fd787eb138c96247f565360 Mon Sep 17 00:00:00 2001
From: Henson Choi <assam258@gmail.com>
Date: Tue, 3 Mar 2026 15:50:48 +0900
Subject: [PATCH 2/8] Fix RPR reluctant quantifier flag lost during VIEW
serialization
diff --git a/src/backend/optimizer/plan/rpr.c b/src/backend/optimizer/plan/rpr.c
index 8792d8174fa..009c0f5019d 100644
--- a/src/backend/optimizer/plan/rpr.c
+++ b/src/backend/optimizer/plan/rpr.c
@@ -198,7 +198,7 @@ flattenSeqChildren(List *children)
/* GROUP{1,1} should have been unwrapped by optimizeGroupPattern */
Assert(!(opt->nodeType == RPR_PATTERN_GROUP &&
- opt->min == 1 && opt->max == 1 && opt->reluctant < 0));
+ opt->min == 1 && opt->max == 1 && opt->reluctant == false));
if (opt->nodeType == RPR_PATTERN_SEQ)
{
@@ -234,7 +234,7 @@ mergeConsecutiveVars(List *children)
{
RPRPatternNode *child = (RPRPatternNode *) lfirst(lc);
- if (child->nodeType == RPR_PATTERN_VAR && child->reluctant < 0)
+ if (child->nodeType == RPR_PATTERN_VAR && child->reluctant == false)
{
/* ----------------------
* Can merge consecutive VAR nodes if:
@@ -253,7 +253,7 @@ mergeConsecutiveVars(List *children)
* Merge: accumulate min/max into prev. prev is guaranteed to
* be a non-reluctant VAR by the outer condition.
*/
- Assert(prev->nodeType == RPR_PATTERN_VAR && prev->reluctant < 0);
+ Assert(prev->nodeType == RPR_PATTERN_VAR && prev->reluctant == false);
prev->min += child->min;
@@ -308,7 +308,7 @@ mergeConsecutiveGroups(List *children)
{
RPRPatternNode *child = (RPRPatternNode *) lfirst(lc);
- if (child->nodeType == RPR_PATTERN_GROUP && child->reluctant < 0)
+ if (child->nodeType == RPR_PATTERN_GROUP && child->reluctant == false)
{
/* ----------------------
* Can merge consecutive GROUP nodes if:
@@ -327,7 +327,7 @@ mergeConsecutiveGroups(List *children)
* Merge: accumulate min/max into prev. prev is guaranteed to
* be a non-reluctant GROUP by the outer condition.
*/
- Assert(prev->nodeType == RPR_PATTERN_GROUP && prev->reluctant < 0);
+ Assert(prev->nodeType == RPR_PATTERN_GROUP && prev->reluctant == false);
prev->min += child->min;
@@ -385,7 +385,7 @@ mergeConsecutiveAlts(List *children)
{
RPRPatternNode *child = (RPRPatternNode *) lfirst(lc);
- if (child->nodeType == RPR_PATTERN_ALT && child->reluctant < 0)
+ if (child->nodeType == RPR_PATTERN_ALT && child->reluctant == false)
{
if (prev != NULL &&
rprPatternChildrenEqual(prev->children, child->children))
@@ -406,7 +406,8 @@ mergeConsecutiveAlts(List *children)
group->nodeType = RPR_PATTERN_GROUP;
group->min = count;
group->max = count;
- group->reluctant = -1;
+ group->reluctant = false;
+ group->reluctant_location = -1;
group->location = -1;
group->children = list_make1(prev);
mergedChildren = lappend(mergedChildren, group);
@@ -430,7 +431,8 @@ mergeConsecutiveAlts(List *children)
group->nodeType = RPR_PATTERN_GROUP;
group->min = count;
group->max = count;
- group->reluctant = -1;
+ group->reluctant = false;
+ group->reluctant_location = -1;
group->location = -1;
group->children = list_make1(prev);
mergedChildren = lappend(mergedChildren, group);
@@ -454,7 +456,8 @@ mergeConsecutiveAlts(List *children)
group->nodeType = RPR_PATTERN_GROUP;
group->min = count;
group->max = count;
- group->reluctant = -1;
+ group->reluctant = false;
+ group->reluctant_location = -1;
group->location = -1;
group->children = list_make1(prev);
mergedChildren = lappend(mergedChildren, group);
@@ -498,7 +501,7 @@ mergeGroupPrefixSuffix(List *children)
* children. GROUP's content may be wrapped in a SEQ - unwrap for
* comparison.
*/
- if (child->nodeType == RPR_PATTERN_GROUP && child->reluctant < 0)
+ if (child->nodeType == RPR_PATTERN_GROUP && child->reluctant == false)
{
List *groupContent = child->children;
int groupChildCount;
@@ -773,14 +776,14 @@ tryMultiplyQuantifiers(RPRPatternNode *pattern)
/* Parser always creates GROUP with exactly one child */
Assert(list_length(pattern->children) == 1);
- if (pattern->reluctant >= 0)
+ if (pattern->reluctant)
return pattern;
child = (RPRPatternNode *) linitial(pattern->children);
if ((child->nodeType != RPR_PATTERN_VAR &&
child->nodeType != RPR_PATTERN_GROUP) ||
- child->reluctant >= 0)
+ child->reluctant)
return pattern;
/* Case 1: Both unbounded - (A*)* -> A*, (A+)+ -> A+ */
@@ -862,11 +865,12 @@ tryUnwrapGroup(RPRPatternNode *pattern)
* the child and unwrap. E.g., (A)?? -> A??, (A)+? -> A+?
*/
if (child->nodeType == RPR_PATTERN_VAR &&
- child->min == 1 && child->max == 1 && child->reluctant < 0)
+ child->min == 1 && child->max == 1 && child->reluctant == false)
{
child->min = pattern->min;
child->max = pattern->max;
child->reluctant = pattern->reluctant;
+ child->reluctant_location = pattern->reluctant_location;
return child;
}
@@ -1150,7 +1154,7 @@ fillRPRPatternVar(RPRPatternNode *node, RPRPattern *pat, int *idx, RPRDepth dept
elem->max = (node->max == INT_MAX) ? RPR_QUANTITY_INF : node->max;
elem->next = RPR_ELEMIDX_INVALID;
elem->jump = RPR_ELEMIDX_INVALID;
- if (node->reluctant >= 0)
+ if (node->reluctant)
elem->flags |= RPR_ELEM_RELUCTANT;
(*idx)++;
@@ -1189,7 +1193,7 @@ fillRPRPatternGroup(RPRPatternNode *node, RPRPattern *pat, int *idx, RPRDepth de
elem->max = (node->max == INT_MAX) ? RPR_QUANTITY_INF : node->max;
elem->next = RPR_ELEMIDX_INVALID; /* set by finalize */
elem->jump = RPR_ELEMIDX_INVALID; /* set after END */
- if (node->reluctant >= 0)
+ if (node->reluctant)
elem->flags |= RPR_ELEM_RELUCTANT;
(*idx)++;
groupStartIdx = *idx; /* children start after BEGIN */
@@ -1214,7 +1218,7 @@ fillRPRPatternGroup(RPRPatternNode *node, RPRPattern *pat, int *idx, RPRDepth de
endElem->max = (node->max == INT_MAX) ? RPR_QUANTITY_INF : node->max;
endElem->next = RPR_ELEMIDX_INVALID;
endElem->jump = groupStartIdx; /* loop to first child */
- if (node->reluctant >= 0)
+ if (node->reluctant)
endElem->flags |= RPR_ELEM_RELUCTANT;
/*
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index b55a11cc837..f1a71cd036b 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -16967,7 +16967,8 @@ row_pattern_alt:
n->children = list_make2($1, $3);
n->min = 1;
n->max = 1;
- n->reluctant = -1;
+ n->reluctant = false;
+ n->reluctant_location = -1;
n->location = @1;
$$ = (Node *) n;
}
@@ -16994,7 +16995,8 @@ row_pattern_seq:
n->children = list_make2($1, $2);
n->min = 1;
n->max = 1;
- n->reluctant = -1;
+ n->reluctant = false;
+ n->reluctant_location = -1;
n->location = @1;
$$ = (Node *) n;
}
@@ -17010,6 +17012,7 @@ row_pattern_term:
n->min = q->min;
n->max = q->max;
n->reluctant = q->reluctant;
+ n->reluctant_location = q->reluctant_location;
$$ = (Node *) n;
}
;
@@ -17022,7 +17025,8 @@ row_pattern_primary:
n->varName = $1;
n->min = 1;
n->max = 1;
- n->reluctant = -1;
+ n->reluctant = false;
+ n->reluctant_location = -1;
n->children = NIL;
n->location = @1;
$$ = (Node *) n;
@@ -17035,7 +17039,8 @@ row_pattern_primary:
n->children = list_make1(inner);
n->min = 1;
n->max = 1;
- n->reluctant = -1;
+ n->reluctant = false;
+ n->reluctant_location = -1;
n->location = @1;
$$ = (Node *) n;
}
@@ -20400,14 +20405,15 @@ makeRecursiveViewSelect(char *relname, List *aliases, Node *query)
* Create an RPRPatternNode with specified quantifier bounds.
*/
static RPRPatternNode *
-makeRPRQuantifier(int min, int max, ParseLoc reluctant, int location,
+makeRPRQuantifier(int min, int max, ParseLoc reluctant_location, int location,
core_yyscan_t yyscanner)
{
RPRPatternNode *n = makeNode(RPRPatternNode);
n->min = min;
n->max = max;
- n->reluctant = reluctant;
+ n->reluctant = (reluctant_location >= 0);
+ n->reluctant_location = reluctant_location;
n->location = location;
return n;
}
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index f5bb81e8c05..928bed2e9fb 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -6778,7 +6778,7 @@ append_pattern_quantifier(StringInfo buf, RPRPatternNode *node)
else
appendStringInfo(buf, "{%d,%d}", node->min, node->max);
- if (node->reluctant >= 0)
+ if (node->reluctant)
{
if (!has_quantifier)
appendStringInfo(buf, "{1}"); /* make reluctant ? unambiguous */
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 8af527b57d3..22e856c671d 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -608,8 +608,8 @@ typedef struct RPRPatternNode
RPRPatternNodeType nodeType; /* VAR, SEQ, ALT, GROUP */
int min; /* minimum repetitions (0 for *, ?) */
int max; /* maximum repetitions (INT_MAX for *, +) */
- ParseLoc reluctant; /* location of '?' for reluctant, -1 for
- * greedy */
+ bool reluctant; /* true for reluctant (non-greedy) */
+ ParseLoc reluctant_location; /* location of '?' token, or -1 */
ParseLoc location; /* token location, or -1 */
char *varName; /* VAR: variable name */
List *children; /* SEQ, ALT, GROUP: child nodes */
--
2.50.1 (Apple Git-155)