v47-0004-refactor-validateRPRPatternVarCount.nocfbot
application/octet-stream
Filename: v47-0004-refactor-validateRPRPatternVarCount.nocfbot
Type: application/octet-stream
Part: 3
Message:
Re: Row pattern recognition
From bf6b09c232e2d0eecb12984d13e3283862be2fe8 Mon Sep 17 00:00:00 2001
From: jian he <jian.universality@gmail.com>
Date: Fri, 12 Jun 2026 18:30:58 +0800
Subject: [PATCH v47 4/6] refactor validateRPRPatternVarCount
validateRPRPatternVarCount() is recursive. Using the `rpDefs != NULL` sentinel
to gate the "DEFINE variable not used in PATTERN" check at the outermost call
level is awkward. That cross-check only needs to run once; it is better
expressed in the caller, `transformDefineClause()`.
---
src/backend/parser/parse_rpr.c | 82 +++++++++++++++-------------------
1 file changed, 36 insertions(+), 46 deletions(-)
diff --git a/src/backend/parser/parse_rpr.c b/src/backend/parser/parse_rpr.c
index 7c7458f933..8521c8ee9f 100644
--- a/src/backend/parser/parse_rpr.c
+++ b/src/backend/parser/parse_rpr.c
@@ -53,7 +53,7 @@ typedef struct
/* Forward declarations */
static void validateRPRPatternVarCount(ParseState *pstate, RPRPatternNode *node,
- List *rpDefs, List **varNames);
+ List **varNames);
static List *transformDefineClause(ParseState *pstate, WindowClause *wc,
WindowDef *windef, List **targetlist);
static bool define_walker(Node *node, void *context);
@@ -191,15 +191,13 @@ transformRPR(ParseState *pstate, WindowClause *wc, WindowDef *windef,
* Throws an error if the number of unique variables would require a varId
* greater than RPR_VARID_MAX.
*
- * If rpDefs is non-NULL, each DEFINE variable name is also validated against
- * varNames; any DEFINE name not present in PATTERN is rejected with an error.
- * varNames itself is not extended by this step -- it carries only PATTERN
- * variable names, which is what transformColumnRef checks via
- * p_rpr_pattern_vars to identify pattern variable qualifiers.
+ * varNames carries only PATTERN variable names, which is what
+ * transformColumnRef checks via p_rpr_pattern_vars to identify pattern variable
+ * qualifiers.
*/
static void
validateRPRPatternVarCount(ParseState *pstate, RPRPatternNode *node,
- List *rpDefs, List **varNames)
+ List **varNames)
{
/* Pattern node must exist - parser always provides non-NULL root */
Assert(node != NULL);
@@ -254,39 +252,10 @@ validateRPRPatternVarCount(ParseState *pstate, RPRPatternNode *node,
/* Recurse into children */
foreach_node(RPRPatternNode, child, node->children)
{
- validateRPRPatternVarCount(pstate, child, NULL, varNames);
+ validateRPRPatternVarCount(pstate, child, varNames);
}
break;
}
-
- /*
- * After the top-level call, validate that every DEFINE variable name is
- * present in the PATTERN variable list; reject names not used in PATTERN.
- * This is only done once at the outermost recursion level, detected by
- * rpDefs being non-NULL (recursive calls pass NULL).
- */
- if (rpDefs)
- {
- foreach_node(ResTarget, rt, rpDefs)
- {
- bool found = false;
-
- foreach_node(String, varname, *varNames)
- {
- if (strcmp(strVal(varname), rt->name) == 0)
- {
- found = true;
- break;
- }
- }
- if (!found)
- ereport(ERROR,
- errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("DEFINE variable \"%s\" is not used in PATTERN",
- rt->name),
- parser_errposition(pstate, rt->location));
- }
- }
}
/*
@@ -321,18 +290,39 @@ transformDefineClause(ParseState *pstate, WindowClause *wc, WindowDef *windef,
List *patternVarNames = NIL;
/*
- * If Row Definition Common Syntax exists, DEFINE clause must exist. (the
- * raw parser should have already checked it.)
- */
- Assert(windef->rpCommonSyntax->rpDefs != NULL);
-
- /*
- * Validate PATTERN variable count, reject DEFINE variables not used in
- * PATTERN, and collect PATTERN variable names for transformColumnRef.
+ * Check PATTERN variable count limits and collect PATTERN variable names
+ * for transformColumnRef.
*/
validateRPRPatternVarCount(pstate, windef->rpCommonSyntax->rpPattern,
- windef->rpCommonSyntax->rpDefs,
&patternVarNames);
+
+ /*
+ * If Row Definition Common Syntax exists, DEFINE clause must exist.
+ */
+ Assert(windef->rpCommonSyntax->rpDefs != NIL);
+
+ /* reject DEFINE variables not used in PATTERN */
+ foreach_node(ResTarget, rt, windef->rpCommonSyntax->rpDefs)
+ {
+ bool found = false;
+
+ foreach_node(String, varname, patternVarNames)
+ {
+ if (strcmp(strVal(varname), rt->name) == 0)
+ {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ ereport(ERROR,
+ errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("DEFINE variable \"%s\" is not used in PATTERN",
+ rt->name),
+ parser_errposition(pstate, rt->location));
+ }
+
pstate->p_rpr_pattern_vars = patternVarNames;
/*
--
2.34.1