v47-0001-v47-rpr-reformat-gram.y-again.nocfbot
application/octet-stream
Filename: v47-0001-v47-rpr-reformat-gram.y-again.nocfbot
Type: application/octet-stream
Part: 2
Message:
Re: Row pattern recognition
From 382f1a2ba65406dcfc5b52ca87f124efa453f0c9 Mon Sep 17 00:00:00 2001
From: jian he <jian.universality@gmail.com>
Date: Mon, 8 Jun 2026 19:00:24 +0800
Subject: [PATCH v47 1/4] v47 rpr reformat gram.y again
Row pattern recognition: include the offending token in quantifier error messages
When an unrecognized token follows a quantifier (*?, +?, ??, {n}?, {n,}?, {,m}?,
{n,m}?), the error message now quotes the actual token that was found, making it
easier to diagnose the problem.
SELECT FROM rpr_err WINDOW w AS ( ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING PATTERN (A {2}??) DEFINE A AS TRUE);
ERROR: invalid token "??" after range quantifier
LINE 1: ...BETWEEN CURRENT ROW AND 1 FOLLOWING PATTERN (A {2}??) DEFINE...
^
HINT: Only "?" is allowed after {n} to make it reluctant.
Here, the ? follows a range quantifier. Even though we only have two of them,
explicitly quoting the wrong token makes it much easier to read.
---
src/backend/parser/gram.y | 14 ++++++-------
src/test/regress/expected/rpr_base.out | 29 +++++++++++++++-----------
src/test/regress/sql/rpr_base.sql | 3 ++-
3 files changed, 26 insertions(+), 20 deletions(-)
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index ac2e5d7914..b3d2435cf2 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -17813,7 +17813,7 @@ row_pattern_quantifier_opt:
else
ereport(ERROR,
errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("invalid token after \"*\" quantifier"),
+ errmsg("invalid token \"%s\" after \"*\" quantifier", $2),
errhint("Did you mean \"*?\" for reluctant quantifier?"),
parser_errposition(@2));
}
@@ -17830,7 +17830,7 @@ row_pattern_quantifier_opt:
else
ereport(ERROR,
errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("invalid token after \"+\" quantifier"),
+ errmsg("invalid token \"%s\" after \"+\" quantifier", $2),
errhint("Did you mean \"+?\" for reluctant quantifier?"),
parser_errposition(@2));
}
@@ -17839,7 +17839,7 @@ row_pattern_quantifier_opt:
if (strcmp($1, "?") != 0)
ereport(ERROR,
errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("invalid quantifier combination"),
+ errmsg("invalid quantifier combination: \"%s%s\"", $1, $2),
errhint("Did you mean \"??\" for reluctant quantifier?"),
parser_errposition(@1));
if (strcmp($2, "?") == 0)
@@ -17905,7 +17905,7 @@ row_pattern_quantifier_opt:
if (strcmp($4, "?") != 0 && strcmp($4, "?|") != 0)
ereport(ERROR,
errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("invalid token after range quantifier"),
+ errmsg("invalid token \"%s\" after range quantifier", $4),
errhint("Only \"?\" is allowed after {n} to make it reluctant."),
parser_errposition(@4));
if ($2 <= 0 || $2 >= PG_INT32_MAX)
@@ -17922,7 +17922,7 @@ row_pattern_quantifier_opt:
if (strcmp($5, "?") != 0 && strcmp($5, "?|") != 0)
ereport(ERROR,
errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("invalid token after range quantifier"),
+ errmsg("invalid token \"%s\" after range quantifier", $5),
errhint("Only \"?\" is allowed after {n,} or {,m} to make it reluctant."),
parser_errposition(@5));
if ($2 < 0 || $2 >= PG_INT32_MAX)
@@ -17939,7 +17939,7 @@ row_pattern_quantifier_opt:
if (strcmp($5, "?") != 0 && strcmp($5, "?|") != 0)
ereport(ERROR,
errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("invalid token after range quantifier"),
+ errmsg("invalid token \"%s\" after range quantifier", $5),
errhint("Only \"?\" is allowed after {n,} or {,m} to make it reluctant."),
parser_errposition(@5));
if ($3 <= 0 || $3 >= PG_INT32_MAX)
@@ -17956,7 +17956,7 @@ row_pattern_quantifier_opt:
if (strcmp($6, "?") != 0 && strcmp($6, "?|") != 0)
ereport(ERROR,
errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("invalid token after range quantifier"),
+ errmsg("invalid token \"%s\" after range quantifier", $6),
errhint("Only \"?\" is allowed after {n,m} to make it reluctant."),
parser_errposition(@6));
if ($2 < 0 || $4 <= 0 || $2 >= PG_INT32_MAX || $4 >= PG_INT32_MAX)
diff --git a/src/test/regress/expected/rpr_base.out b/src/test/regress/expected/rpr_base.out
index 2407c45516..43683c79e3 100644
--- a/src/test/regress/expected/rpr_base.out
+++ b/src/test/regress/expected/rpr_base.out
@@ -3217,12 +3217,12 @@ ERROR: alternation operator "|" requires a pattern on both sides
LINE 1: ...EEN CURRENT ROW AND UNBOUNDED FOLLOWING PATTERN ((A*|)) DEFI...
^
SELECT count(*) OVER w FROM rpr_glue WINDOW w AS (ORDER BY id ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING PATTERN (A* *|B) DEFINE A AS val > 0, B AS val <= 0);
-ERROR: invalid token after "*" quantifier
+ERROR: invalid token "*|" after "*" quantifier
LINE 1: ...N CURRENT ROW AND UNBOUNDED FOLLOWING PATTERN (A* *|B) DEFIN...
^
HINT: Did you mean "*?" for reluctant quantifier?
SELECT count(*) OVER w FROM rpr_glue WINDOW w AS (ORDER BY id ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING PATTERN (A* *?|B) DEFINE A AS val > 0, B AS val <= 0);
-ERROR: invalid token after "*" quantifier
+ERROR: invalid token "*?|" after "*" quantifier
LINE 1: ...N CURRENT ROW AND UNBOUNDED FOLLOWING PATTERN (A* *?|B) DEFI...
^
HINT: Did you mean "*?" for reluctant quantifier?
@@ -3232,12 +3232,12 @@ LINE 1: ...EEN CURRENT ROW AND UNBOUNDED FOLLOWING PATTERN (A? *?|B) DE...
^
HINT: Did you mean "??" for reluctant quantifier?
SELECT count(*) OVER w FROM rpr_glue WINDOW w AS (ORDER BY id ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING PATTERN (A{2}*?|B) DEFINE A AS val > 0, B AS val <= 0);
-ERROR: invalid token after range quantifier
+ERROR: invalid token "*?|" after range quantifier
LINE 1: ... CURRENT ROW AND UNBOUNDED FOLLOWING PATTERN (A{2}*?|B) DEFI...
^
HINT: Only "?" is allowed after {n} to make it reluctant.
SELECT count(*) OVER w FROM rpr_glue WINDOW w AS (ORDER BY id ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING PATTERN (A{2} *?|B) DEFINE A AS val > 0, B AS val <= 0);
-ERROR: invalid token after range quantifier
+ERROR: invalid token "*?|" after range quantifier
LINE 1: ...CURRENT ROW AND UNBOUNDED FOLLOWING PATTERN (A{2} *?|B) DEFI...
^
HINT: Only "?" is allowed after {n} to make it reluctant.
@@ -3283,19 +3283,19 @@ ERROR: unsupported quantifier "+!"
LINE 6: PATTERN (A+!)
^
HINT: Valid quantifiers are: *, +, ?, *?, +?, ??, {n}, {n,}, {,m}, {n,m} and their reluctant versions.
--- none of the following 4 queries should be accepted
+-- none of the following queries should be accepted
SELECT FROM rpr_err WINDOW w AS ( ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING PATTERN (A+ !) DEFINE A AS TRUE);
-ERROR: invalid token after "+" quantifier
+ERROR: invalid token "!" after "+" quantifier
LINE 1: ...S BETWEEN CURRENT ROW AND 1 FOLLOWING PATTERN (A+ !) DEFINE ...
^
HINT: Did you mean "+?" for reluctant quantifier?
SELECT FROM rpr_err WINDOW w AS ( ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING PATTERN (A+ ?+) DEFINE A AS TRUE);
-ERROR: invalid token after "+" quantifier
+ERROR: invalid token "?+" after "+" quantifier
LINE 1: ...S BETWEEN CURRENT ROW AND 1 FOLLOWING PATTERN (A+ ?+) DEFINE...
^
HINT: Did you mean "+?" for reluctant quantifier?
SELECT FROM rpr_err WINDOW w AS ( ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING PATTERN (A* ?+) DEFINE A AS TRUE);
-ERROR: invalid token after "*" quantifier
+ERROR: invalid token "?+" after "*" quantifier
LINE 1: ...S BETWEEN CURRENT ROW AND 1 FOLLOWING PATTERN (A* ?+) DEFINE...
^
HINT: Did you mean "*?" for reluctant quantifier?
@@ -3304,24 +3304,29 @@ ERROR: invalid quantifier combination
LINE 1: ...OWS BETWEEN CURRENT ROW AND 1 FOLLOWING PATTERN (A? ??) DEFI...
^
HINT: Did you mean "??" for reluctant quantifier?
+SELECT FROM rpr_err WINDOW w AS ( ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING PATTERN (A {1,2}??) DEFINE A AS TRUE);
+ERROR: invalid token "??" after range quantifier
+LINE 1: ...TWEEN CURRENT ROW AND 1 FOLLOWING PATTERN (A {1,2}??) DEFINE...
+ ^
+HINT: Only "?" is allowed after {n,m} to make it reluctant.
-- none of the following 4 range-quantifier queries should be accepted
SELECT FROM rpr_err WINDOW w AS ( ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING PATTERN (A{2} !) DEFINE A AS TRUE);
-ERROR: invalid token after range quantifier
+ERROR: invalid token "!" after range quantifier
LINE 1: ...BETWEEN CURRENT ROW AND 1 FOLLOWING PATTERN (A{2} !) DEFINE ...
^
HINT: Only "?" is allowed after {n} to make it reluctant.
SELECT FROM rpr_err WINDOW w AS ( ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING PATTERN (A{2,} !) DEFINE A AS TRUE);
-ERROR: invalid token after range quantifier
+ERROR: invalid token "!" after range quantifier
LINE 1: ...ETWEEN CURRENT ROW AND 1 FOLLOWING PATTERN (A{2,} !) DEFINE ...
^
HINT: Only "?" is allowed after {n,} or {,m} to make it reluctant.
SELECT FROM rpr_err WINDOW w AS ( ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING PATTERN (A{,3} !) DEFINE A AS TRUE);
-ERROR: invalid token after range quantifier
+ERROR: invalid token "!" after range quantifier
LINE 1: ...ETWEEN CURRENT ROW AND 1 FOLLOWING PATTERN (A{,3} !) DEFINE ...
^
HINT: Only "?" is allowed after {n,} or {,m} to make it reluctant.
SELECT FROM rpr_err WINDOW w AS ( ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING PATTERN (A{2,3} !) DEFINE A AS TRUE);
-ERROR: invalid token after range quantifier
+ERROR: invalid token "!" after range quantifier
LINE 1: ...TWEEN CURRENT ROW AND 1 FOLLOWING PATTERN (A{2,3} !) DEFINE ...
^
HINT: Only "?" is allowed after {n,m} to make it reluctant.
diff --git a/src/test/regress/sql/rpr_base.sql b/src/test/regress/sql/rpr_base.sql
index cec7ea1e8d..5e95859f75 100644
--- a/src/test/regress/sql/rpr_base.sql
+++ b/src/test/regress/sql/rpr_base.sql
@@ -2146,11 +2146,12 @@ WINDOW w AS (
DEFINE A AS val > 0
);
--- none of the following 4 queries should be accepted
+-- none of the following queries should be accepted
SELECT FROM rpr_err WINDOW w AS ( ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING PATTERN (A+ !) DEFINE A AS TRUE);
SELECT FROM rpr_err WINDOW w AS ( ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING PATTERN (A+ ?+) DEFINE A AS TRUE);
SELECT FROM rpr_err WINDOW w AS ( ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING PATTERN (A* ?+) DEFINE A AS TRUE);
SELECT FROM rpr_err WINDOW w AS ( ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING PATTERN (A? ??) DEFINE A AS TRUE);
+SELECT FROM rpr_err WINDOW w AS ( ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING PATTERN (A {1,2}??) DEFINE A AS TRUE);
-- none of the following 4 range-quantifier queries should be accepted
SELECT FROM rpr_err WINDOW w AS ( ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING PATTERN (A{2} !) DEFINE A AS TRUE);
--
2.34.1