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

