From 2db769b38bb4b339f57a9d2cff6bdd8f1305c551 Mon Sep 17 00:00:00 2001 From: Henson Choi Date: Mon, 23 Feb 2026 14:56:42 +0900 Subject: [PATCH 6/6] Allow A{0} quantifier --- src/backend/executor/nodeWindowAgg.c | 7 +++++++ src/backend/parser/gram.y | 8 +++---- src/test/regress/expected/rpr_base.out | 29 ++++++++++++++++++-------- src/test/regress/sql/rpr_base.sql | 8 +++---- 4 files changed, 35 insertions(+), 17 deletions(-) diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c index 98546fb17f7..72ded5efc1f 100644 --- a/src/backend/executor/nodeWindowAgg.c +++ b/src/backend/executor/nodeWindowAgg.c @@ -6070,6 +6070,13 @@ nfa_route_to_elem(WindowAggState *winstate, RPRNFAContext *ctx, { if (RPRElemIsVar(nextElem)) { + if (nextElem->max == 0) + { + /* max=0: variable never matches, treat as epsilon transition */ + state->elemIdx = nextElem->next; + nfa_advance_state(winstate, ctx, state, currentPos, initialAdvance); + return; + } nfa_add_state_unique(winstate, ctx, state); if (RPRElemCanSkip(nextElem)) { diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 5a3d141e992..17503b38e3a 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -17070,10 +17070,10 @@ row_pattern_quantifier_opt: /* {n}, {n,}, {,m}, {n,m} quantifiers */ | '{' Iconst '}' { - if ($2 <= 0 || $2 >= INT_MAX) + if ($2 < 0 || $2 >= INT_MAX) ereport(ERROR, errcode(ERRCODE_SYNTAX_ERROR), - errmsg("quantifier bound must be between 1 and %d", INT_MAX - 1), + errmsg("quantifier bound must be between 0 and %d", INT_MAX - 1), parser_errposition(@2)); $$ = (Node *) makeRPRQuantifier($2, $2, -1, @1, yyscanner); } @@ -17118,10 +17118,10 @@ row_pattern_quantifier_opt: errmsg("invalid token after range quantifier"), errhint("Only \"?\" is allowed after {n} to make it reluctant."), parser_errposition(@4))); - if ($2 <= 0 || $2 >= INT_MAX) + if ($2 < 0 || $2 >= INT_MAX) ereport(ERROR, errcode(ERRCODE_SYNTAX_ERROR), - errmsg("quantifier bound must be between 1 and %d", INT_MAX - 1), + errmsg("quantifier bound must be between 0 and %d", INT_MAX - 1), parser_errposition(@2)); $$ = (Node *) makeRPRQuantifier($2, $2, @4, @1, yyscanner); } diff --git a/src/test/regress/expected/rpr_base.out b/src/test/regress/expected/rpr_base.out index 43eea32130f..7df71aaa904 100644 --- a/src/test/regress/expected/rpr_base.out +++ b/src/test/regress/expected/rpr_base.out @@ -923,7 +923,7 @@ ORDER BY id; (10 rows) -- Edge case quantifiers --- {0} is not allowed (min must be >= 1) +-- {0} always skips the variable (zero iterations) SELECT id, val, COUNT(*) OVER w as cnt FROM rpr_quant WINDOW w AS ( @@ -933,10 +933,21 @@ WINDOW w AS ( DEFINE A AS val > 1000, B AS val > 0 ) ORDER BY id; -ERROR: quantifier bound must be between 1 and 2147483646 -LINE 6: PATTERN (A{0} B) - ^ --- Expected: ERROR: quantifier bound must be between 1 and 2147483646 + id | val | cnt +----+-----+----- + 1 | 10 | 1 + 2 | 20 | 1 + 3 | 30 | 1 + 4 | 40 | 1 + 5 | 50 | 1 + 6 | 60 | 1 + 7 | 70 | 1 + 8 | 80 | 1 + 9 | 90 | 1 + 10 | 100 | 1 +(10 rows) + +-- Expected: A{0} skips A, only B matches each row -- {0,0} is not allowed (max must be >= 1) SELECT id, val, COUNT(*) OVER w as cnt FROM rpr_quant @@ -1274,10 +1285,10 @@ WINDOW w AS ( PATTERN (A{2147483647}?) DEFINE A AS val > 0 ); -ERROR: quantifier bound must be between 1 and 2147483646 +ERROR: quantifier bound must be between 0 and 2147483646 LINE 6: PATTERN (A{2147483647}?) ^ --- Expected: ERROR: quantifier bound must be between 1 and 2147483646 +-- Expected: ERROR: quantifier bound must be between 0 and 2147483646 -- {-1,}? (negative lower bound) SELECT COUNT(*) OVER w FROM rpr_reluctant @@ -1537,10 +1548,10 @@ WINDOW w AS ( PATTERN (A{2147483647}) DEFINE A AS id > 0 ); -ERROR: quantifier bound must be between 1 and 2147483646 +ERROR: quantifier bound must be between 0 and 2147483646 LINE 6: PATTERN (A{2147483647}) ^ --- Expected: ERROR: quantifier bound must be between 1 and 2147483646 +-- Expected: ERROR: quantifier bound must be between 0 and 2147483646 -- {n,} boundary errors -- Negative lower bound in {n,} SELECT COUNT(*) OVER w diff --git a/src/test/regress/sql/rpr_base.sql b/src/test/regress/sql/rpr_base.sql index 992c081205a..d25ca07adaf 100644 --- a/src/test/regress/sql/rpr_base.sql +++ b/src/test/regress/sql/rpr_base.sql @@ -673,7 +673,7 @@ ORDER BY id; -- Edge case quantifiers --- {0} is not allowed (min must be >= 1) +-- {0} always skips the variable (zero iterations) SELECT id, val, COUNT(*) OVER w as cnt FROM rpr_quant WINDOW w AS ( @@ -683,7 +683,7 @@ WINDOW w AS ( DEFINE A AS val > 1000, B AS val > 0 ) ORDER BY id; --- Expected: ERROR: quantifier bound must be between 1 and 2147483646 +-- Expected: A{0} skips A, only B matches each row -- {0,0} is not allowed (max must be >= 1) SELECT id, val, COUNT(*) OVER w as cnt @@ -911,7 +911,7 @@ WINDOW w AS ( PATTERN (A{2147483647}?) DEFINE A AS val > 0 ); --- Expected: ERROR: quantifier bound must be between 1 and 2147483646 +-- Expected: ERROR: quantifier bound must be between 0 and 2147483646 -- {-1,}? (negative lower bound) SELECT COUNT(*) OVER w @@ -1118,7 +1118,7 @@ WINDOW w AS ( PATTERN (A{2147483647}) DEFINE A AS id > 0 ); --- Expected: ERROR: quantifier bound must be between 1 and 2147483646 +-- Expected: ERROR: quantifier bound must be between 0 and 2147483646 -- {n,} boundary errors -- 2.50.1 (Apple Git-155)