From bf6b09c232e2d0eecb12984d13e3283862be2fe8 Mon Sep 17 00:00:00 2001 From: jian he 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