From 9874c80b4f36a39cd27ed4d5cd7b606c13abffb6 Mon Sep 17 00:00:00 2001 From: jian he Date: Fri, 24 Jul 2026 05:35:09 +0900 Subject: [PATCH] Remove the always-true RPR initial flag and simplify window deparse The clause is effectively always INITIAL: the grammar accepts INITIAL or an empty clause and rejects SEEK, so the initial field of RPCommonSyntax and WindowClause was a constant true. Drop the field, its grammar action and %type, its copy in transformRPR, and the redundant term it contributed to the window-dedup equality in optimize_window_clauses. Fold the AFTER MATCH, INITIAL, PATTERN, and DEFINE deparse in get_rule_windowspec into the rpPattern branch, emitting INITIAL as a literal. The window spec's closing parenthesis stays outside that branch so a non-RPR window still round-trips. --- src/backend/optimizer/plan/planner.c | 1 - src/backend/parser/gram.y | 6 ++-- src/backend/parser/parse_rpr.c | 3 -- src/backend/utils/adt/ruleutils.c | 51 ++++++++++++---------------- src/include/nodes/parsenodes.h | 4 --- 5 files changed, 23 insertions(+), 42 deletions(-) diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index 2dcc27ba93e..b07128c2131 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -6205,7 +6205,6 @@ optimize_window_clauses(PlannerInfo *root, WindowFuncLists *wflists) equal(wc->startOffset, existing_wc->startOffset) && equal(wc->endOffset, existing_wc->endOffset) && wc->rpSkipTo == existing_wc->rpSkipTo && - wc->initial == existing_wc->initial && equal(wc->defineClause, existing_wc->defineClause) && equal(wc->rpPattern, existing_wc->rpPattern)) { diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 56a05c3eea6..8c89d170422 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -741,7 +741,6 @@ static const char *rpr_invalid_quantifier_token(const char *tok); row_pattern_quantifier_opt %type row_pattern_definition_list %type opt_row_pattern_skip_to -%type opt_row_pattern_initial_or_seek /* * Non-keyword token types. These are hard-wired into the "flex" lexer. @@ -17674,7 +17673,6 @@ opt_row_pattern_skip_to opt_row_pattern_initial_or_seek { RPCommonSyntax *n = makeNode(RPCommonSyntax); n->rpSkipTo = $1; - n->initial = $2; n->rpPattern = (RPRPatternNode *) $5; n->rpDefs = $8; n->location = @3; @@ -17699,7 +17697,7 @@ opt_row_pattern_skip_to: ; opt_row_pattern_initial_or_seek: - INITIAL_P { $$ = true; } + INITIAL_P | SEEK { ereport(ERROR, @@ -17708,7 +17706,7 @@ opt_row_pattern_initial_or_seek: errhint("Use INITIAL instead."), parser_errposition(@1)); } - | /*EMPTY*/ { $$ = true; } + | /*EMPTY*/ ; row_pattern: diff --git a/src/backend/parser/parse_rpr.c b/src/backend/parser/parse_rpr.c index 67465da9831..770ed790385 100644 --- a/src/backend/parser/parse_rpr.c +++ b/src/backend/parser/parse_rpr.c @@ -174,9 +174,6 @@ transformRPR(ParseState *pstate, WindowClause *wc, WindowDef *windef, /* Assign AFTER MATCH SKIP TO flag */ wc->rpSkipTo = windef->rpCommonSyntax->rpSkipTo; - /* Assign INITIAL flag */ - wc->initial = windef->rpCommonSyntax->initial; - /* Transform DEFINE clause into list of TargetEntry's */ wc->defineClause = transformDefineClause(pstate, windef, targetlist); diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 2d46c5c21d1..dad85239dea 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -7340,42 +7340,33 @@ get_rule_windowspec(WindowClause *wc, List *targetList, } /* RPR */ - if (wc->rpSkipTo == ST_NEXT_ROW) - { - if (needspace) - appendStringInfoChar(buf, ' '); - appendStringInfoString(buf, - "\n AFTER MATCH SKIP TO NEXT ROW "); - needspace = true; - } - else if (wc->rpSkipTo == ST_PAST_LAST_ROW) - { - if (needspace) - appendStringInfoChar(buf, ' '); - appendStringInfoString(buf, - "\n AFTER MATCH SKIP PAST LAST ROW "); - needspace = true; - } - if (wc->initial) - { - if (needspace) - appendStringInfoChar(buf, ' '); - appendStringInfoString(buf, "\n INITIAL"); - needspace = true; - } if (wc->rpPattern) { - if (needspace) - appendStringInfoChar(buf, ' '); - appendStringInfoString(buf, "\n PATTERN "); + if (wc->rpSkipTo == ST_NEXT_ROW) + { + if (needspace) + appendStringInfoChar(buf, ' '); + appendStringInfoString(buf, + "\n AFTER MATCH SKIP TO NEXT ROW"); + needspace = true; + } + else + { + Assert(wc->rpSkipTo == ST_PAST_LAST_ROW); + + if (needspace) + appendStringInfoChar(buf, ' '); + appendStringInfoString(buf, + "\n AFTER MATCH SKIP PAST LAST ROW"); + needspace = true; + } + + appendStringInfoString(buf, "\n INITIAL\n PATTERN "); get_rule_pattern(wc->rpPattern, context); - needspace = true; - } - if (wc->defineClause) - { if (needspace) appendStringInfoChar(buf, ' '); + appendStringInfoString(buf, "\n DEFINE\n"); get_rule_define(wc->defineClause, context); appendStringInfoChar(buf, ' '); diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index ed3328b576d..f786a64e7b2 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -656,8 +656,6 @@ typedef struct RPCommonSyntax { NodeTag type; RPSkipTo rpSkipTo; /* Row Pattern AFTER MATCH SKIP type */ - bool initial; /* true if is - * initial */ RPRPatternNode *rpPattern; /* PATTERN parse tree */ List *rpDefs; /* row pattern definitions clause (list of * ResTarget) */ @@ -1766,8 +1764,6 @@ typedef struct WindowClause bool copiedOrder pg_node_attr(query_jumble_ignore); /* Row Pattern AFTER MATCH SKIP clause */ RPSkipTo rpSkipTo; /* Row Pattern Skip To type */ - bool initial; /* true if is - * initial */ /* Row Pattern DEFINE clause (list of TargetEntry) */ List *defineClause; /* Row Pattern PATTERN parse tree */ -- 2.50.1 (Apple Git-155)