From af9f50ed1522bda716d10edf932bc5aeb4b0cb37 Mon Sep 17 00:00:00 2001 From: Henson Choi Date: Tue, 5 May 2026 11:36:53 +0900 Subject: [PATCH 04/11] Reclassify DEFINE qualifier check and reword diagnostic to "expression" Split the pre-check into three branches: pattern variable -> FEATURE_NOT_SUPPORTED, range variable (via refnameNamespaceItem) -> SYNTAX_ERROR, anything else -> fall through to normal resolution. Reword "qualified column reference" to "qualified expression" since the quoted token may include an indirection target on composite types (e.g. (A.items).amount). --- src/backend/parser/parse_expr.c | 31 +++++++--- src/test/regress/expected/rpr_base.out | 80 +++++++++++++++++++++++--- src/test/regress/sql/rpr_base.sql | 61 ++++++++++++++++++-- 3 files changed, 153 insertions(+), 19 deletions(-) diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index f145342e1fb..69148328719 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -628,11 +628,24 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref) if (node != NULL) return node; - /* - * Qualified column references in DEFINE are not supported. This covers - * both FROM-clause range variables (prohibited by §6.5) and pattern - * variable qualified names (e.g. UP.price), which are valid per §4.16 - * but not yet implemented. + /*---------- + * Qualified references in DEFINE need a tri-classification: + * + * pattern variable qualifier (e.g. UP.price): valid per 19075-5 4.16 + * but not yet implemented -- raise FEATURE_NOT_SUPPORTED. + * + * FROM-clause range variable qualifier: prohibited by 19075-5 6.5 + * -- raise SYNTAX_ERROR. + * + * any other qualifier (typo, undefined name): fall through and let + * normal column resolution produce a sensible error. + * + * The quoted text reflects only the ColumnRef portion; a trailing field + * selection on a composite type (e.g. ".amount" in "(A.items).amount") + * lives in the surrounding A_Indirection node and is not included here. + * That can be revisited when MEASURES support adds indirection-aware + * traversal. + *---------- */ if (pstate->p_expr_kind == EXPR_KIND_RPR_DEFINE && list_length(cref->fields) != 1) @@ -653,15 +666,17 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref) if (is_pattern_var) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("pattern variable qualified column reference \"%s\" is not supported in DEFINE clause", + errmsg("pattern variable qualified expression \"%s\" is not supported in DEFINE clause", NameListToString(cref->fields)), parser_errposition(pstate, cref->location))); - else + else if (refnameNamespaceItem(pstate, NULL, qualifier, + cref->location, NULL) != NULL) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("range variable qualified column reference \"%s\" is not allowed in DEFINE clause", + errmsg("range variable qualified expression \"%s\" is not allowed in DEFINE clause", NameListToString(cref->fields)), parser_errposition(pstate, cref->location))); + /* else: unknown qualifier -- fall through to normal resolution */ } /*---------- diff --git a/src/test/regress/expected/rpr_base.out b/src/test/regress/expected/rpr_base.out index a63211ff364..86abb96c177 100644 --- a/src/test/regress/expected/rpr_base.out +++ b/src/test/regress/expected/rpr_base.out @@ -3074,10 +3074,10 @@ WINDOW w AS ( PATTERN (A+) DEFINE A AS A.val > 0 ); -ERROR: pattern variable qualified column reference "a.val" is not supported in DEFINE clause +ERROR: pattern variable qualified expression "a.val" is not supported in DEFINE clause LINE 7: DEFINE A AS A.val > 0 ^ --- Expected: ERROR: pattern variable qualified column reference "a.val" is not supported +-- Expected: ERROR: pattern variable qualified expression "a.val" is not supported -- PATTERN-only variable qualified name: not supported even without DEFINE entry SELECT COUNT(*) OVER w FROM rpr_err @@ -3087,10 +3087,10 @@ WINDOW w AS ( PATTERN (A+ B+) DEFINE A AS B.val > 0 ); -ERROR: pattern variable qualified column reference "b.val" is not supported in DEFINE clause +ERROR: pattern variable qualified expression "b.val" is not supported in DEFINE clause LINE 7: DEFINE A AS B.val > 0 ^ --- Expected: ERROR: pattern variable qualified column reference "b.val" is not supported +-- Expected: ERROR: pattern variable qualified expression "b.val" is not supported -- DEFINE-only variable qualified name: still a pattern variable, not a range variable SELECT COUNT(*) OVER w FROM rpr_err @@ -3103,7 +3103,7 @@ WINDOW w AS ( ERROR: DEFINE variable "b" is not used in PATTERN LINE 7: DEFINE A AS val > 0, B AS B.val > 0 ^ --- Expected: ERROR: pattern variable qualified column reference "b.val" is not supported +-- Expected: ERROR: pattern variable qualified expression "b.val" is not supported -- FROM-clause range variable qualified name: not allowed (prohibited by SQL standard 6.5) SELECT COUNT(*) OVER w FROM rpr_err @@ -3113,10 +3113,76 @@ WINDOW w AS ( PATTERN (A+) DEFINE A AS rpr_err.val > 0 ); -ERROR: range variable qualified column reference "rpr_err.val" is not allowed in DEFINE clause +ERROR: range variable qualified expression "rpr_err.val" is not allowed in DEFINE clause LINE 7: DEFINE A AS rpr_err.val > 0 ^ --- Expected: ERROR: range variable qualified column reference "rpr_err.val" is not allowed +-- Expected: ERROR: range variable qualified expression "rpr_err.val" is not allowed +-- Unknown qualifier (neither pattern var nor range var): the DEFINE pre-check +-- must fall through so that normal column resolution produces a sensible error. +SELECT COUNT(*) OVER w +FROM rpr_err +WINDOW w AS ( + ORDER BY id + ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING + PATTERN (A+) + DEFINE A AS nosuch.val > 0 +); +ERROR: missing FROM-clause entry for table "nosuch" +LINE 7: DEFINE A AS nosuch.val > 0 + ^ +-- Expected: ERROR: missing FROM-clause entry for table "nosuch" +-- Unqualified composite field access in DEFINE works: no qualifier means no +-- pattern/range-var navigation, so the pre-check skips and normal resolution +-- handles "(items).amount" via A_Indirection on the current row. +CREATE TYPE rpr_item AS (name TEXT, amount INT); +CREATE TEMP TABLE rpr_composite (id int, items rpr_item); +INSERT INTO rpr_composite VALUES (1, ROW('a',5)), (2, ROW('b',15)), (3, ROW('c',25)); +SELECT id, (items).amount, COUNT(*) OVER w AS cnt +FROM rpr_composite +WINDOW w AS ( + ORDER BY id + ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING + AFTER MATCH SKIP TO NEXT ROW + PATTERN (A+) + DEFINE A AS (items).amount > 10 +); + id | amount | cnt +----+--------+----- + 1 | 5 | 0 + 2 | 15 | 2 + 3 | 25 | 1 +(3 rows) + +-- Expected: rows where (items).amount > 10 form matches; counts reflect frame size +-- Composite type field selection (qualified forms): the ColumnRef portion ("A.items" or +-- "rpr_composite.items") is what gets quoted; the trailing ".amount" lives in +-- the surrounding A_Indirection node and is not visible to the pre-check. +SELECT COUNT(*) OVER w +FROM rpr_composite +WINDOW w AS ( + ORDER BY id + ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING + PATTERN (A+) + DEFINE A AS (A.items).amount > 10 +); +ERROR: pattern variable qualified expression "a.items" is not supported in DEFINE clause +LINE 7: DEFINE A AS (A.items).amount > 10 + ^ +-- Expected: ERROR: pattern variable qualified expression "a.items" is not supported +SELECT COUNT(*) OVER w +FROM rpr_composite +WINDOW w AS ( + ORDER BY id + ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING + PATTERN (A+) + DEFINE A AS (rpr_composite.items).amount > 10 +); +ERROR: range variable qualified expression "rpr_composite.items" is not allowed in DEFINE clause +LINE 7: DEFINE A AS (rpr_composite.items).amount > 10 + ^ +-- Expected: ERROR: range variable qualified expression "rpr_composite.items" is not allowed +DROP TABLE rpr_composite; +DROP TYPE rpr_item; -- Semantic errors -- Undefined column in DEFINE SELECT COUNT(*) OVER w diff --git a/src/test/regress/sql/rpr_base.sql b/src/test/regress/sql/rpr_base.sql index 86ed06fec68..e8c72706720 100644 --- a/src/test/regress/sql/rpr_base.sql +++ b/src/test/regress/sql/rpr_base.sql @@ -2092,7 +2092,7 @@ WINDOW w AS ( PATTERN (A+) DEFINE A AS A.val > 0 ); --- Expected: ERROR: pattern variable qualified column reference "a.val" is not supported +-- Expected: ERROR: pattern variable qualified expression "a.val" is not supported -- PATTERN-only variable qualified name: not supported even without DEFINE entry SELECT COUNT(*) OVER w @@ -2103,7 +2103,7 @@ WINDOW w AS ( PATTERN (A+ B+) DEFINE A AS B.val > 0 ); --- Expected: ERROR: pattern variable qualified column reference "b.val" is not supported +-- Expected: ERROR: pattern variable qualified expression "b.val" is not supported -- DEFINE-only variable qualified name: still a pattern variable, not a range variable SELECT COUNT(*) OVER w @@ -2114,7 +2114,7 @@ WINDOW w AS ( PATTERN (A+) DEFINE A AS val > 0, B AS B.val > 0 ); --- Expected: ERROR: pattern variable qualified column reference "b.val" is not supported +-- Expected: ERROR: pattern variable qualified expression "b.val" is not supported -- FROM-clause range variable qualified name: not allowed (prohibited by SQL standard 6.5) SELECT COUNT(*) OVER w @@ -2125,7 +2125,60 @@ WINDOW w AS ( PATTERN (A+) DEFINE A AS rpr_err.val > 0 ); --- Expected: ERROR: range variable qualified column reference "rpr_err.val" is not allowed +-- Expected: ERROR: range variable qualified expression "rpr_err.val" is not allowed + +-- Unknown qualifier (neither pattern var nor range var): the DEFINE pre-check +-- must fall through so that normal column resolution produces a sensible error. +SELECT COUNT(*) OVER w +FROM rpr_err +WINDOW w AS ( + ORDER BY id + ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING + PATTERN (A+) + DEFINE A AS nosuch.val > 0 +); +-- Expected: ERROR: missing FROM-clause entry for table "nosuch" + +-- Unqualified composite field access in DEFINE works: no qualifier means no +-- pattern/range-var navigation, so the pre-check skips and normal resolution +-- handles "(items).amount" via A_Indirection on the current row. +CREATE TYPE rpr_item AS (name TEXT, amount INT); +CREATE TEMP TABLE rpr_composite (id int, items rpr_item); +INSERT INTO rpr_composite VALUES (1, ROW('a',5)), (2, ROW('b',15)), (3, ROW('c',25)); +SELECT id, (items).amount, COUNT(*) OVER w AS cnt +FROM rpr_composite +WINDOW w AS ( + ORDER BY id + ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING + AFTER MATCH SKIP TO NEXT ROW + PATTERN (A+) + DEFINE A AS (items).amount > 10 +); +-- Expected: rows where (items).amount > 10 form matches; counts reflect frame size + +-- Composite type field selection (qualified forms): the ColumnRef portion ("A.items" or +-- "rpr_composite.items") is what gets quoted; the trailing ".amount" lives in +-- the surrounding A_Indirection node and is not visible to the pre-check. +SELECT COUNT(*) OVER w +FROM rpr_composite +WINDOW w AS ( + ORDER BY id + ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING + PATTERN (A+) + DEFINE A AS (A.items).amount > 10 +); +-- Expected: ERROR: pattern variable qualified expression "a.items" is not supported +SELECT COUNT(*) OVER w +FROM rpr_composite +WINDOW w AS ( + ORDER BY id + ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING + PATTERN (A+) + DEFINE A AS (rpr_composite.items).amount > 10 +); +-- Expected: ERROR: range variable qualified expression "rpr_composite.items" is not allowed +DROP TABLE rpr_composite; +DROP TYPE rpr_item; -- Semantic errors -- 2.50.1 (Apple Git-155)