From e3d0ecd07299c07cca83e1d1a75e72af4f789c0f Mon Sep 17 00:00:00 2001 From: Henson Choi Date: Sun, 8 Mar 2026 18:30:29 +0900 Subject: [PATCH 10/12] Walk DEFINE clause in window tree traversal --- src/backend/nodes/nodeFuncs.c | 6 ++++++ src/test/regress/expected/rpr_base.out | 29 ++++++++++++++++++++++++++ src/test/regress/sql/rpr_base.sql | 24 +++++++++++++++++++++ 3 files changed, 59 insertions(+) diff --git a/src/backend/nodes/nodeFuncs.c b/src/backend/nodes/nodeFuncs.c index 199ed27995f..ddf6812d7b0 100644 --- a/src/backend/nodes/nodeFuncs.c +++ b/src/backend/nodes/nodeFuncs.c @@ -2411,6 +2411,8 @@ expression_tree_walker_impl(Node *node, return true; if (WALK(wc->endOffset)) return true; + if (WALK(wc->defineClause)) + return true; } break; case T_CTECycleClause: @@ -2763,6 +2765,8 @@ query_tree_walker_impl(Query *query, return true; if (WALK(wc->endOffset)) return true; + if (WALK(wc->defineClause)) + return true; } } @@ -3499,6 +3503,7 @@ expression_tree_mutator_impl(Node *node, MUTATE(newnode->orderClause, wc->orderClause, List *); MUTATE(newnode->startOffset, wc->startOffset, Node *); MUTATE(newnode->endOffset, wc->endOffset, Node *); + MUTATE(newnode->defineClause, wc->defineClause, List *); return (Node *) newnode; } break; @@ -3831,6 +3836,7 @@ query_tree_mutator_impl(Query *query, FLATCOPY(newnode, wc, WindowClause); MUTATE(newnode->startOffset, wc->startOffset, Node *); MUTATE(newnode->endOffset, wc->endOffset, Node *); + MUTATE(newnode->defineClause, wc->defineClause, List *); resultlist = lappend(resultlist, (Node *) newnode); } diff --git a/src/test/regress/expected/rpr_base.out b/src/test/regress/expected/rpr_base.out index 09d079b05c6..ffd0f8ed9f1 100644 --- a/src/test/regress/expected/rpr_base.out +++ b/src/test/regress/expected/rpr_base.out @@ -28,6 +28,7 @@ -- Complex Expression Tests -- Set Operations Tests -- Sorting and Grouping Tests +-- SQL Function Inlining Tests -- Stress Tests -- Error Limit Tests -- @@ -5453,6 +5454,34 @@ LIMIT 3 OFFSET 1; (3 rows) DROP TABLE rpr_sort; +-- SQL function inlining: $1 in DEFINE must be substituted by +-- substitute_actual_parameters_in_from via query_tree_mutator. +CREATE TABLE rpr_srf_t (v int); +INSERT INTO rpr_srf_t SELECT generate_series(1, 5); +CREATE FUNCTION rpr_srf_f(threshold int) +RETURNS TABLE (v int, cnt bigint) +LANGUAGE sql STABLE AS $$ + SELECT v::int, count(*) OVER w + FROM rpr_srf_t + WINDOW w AS ( + ORDER BY v + ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING + PATTERN (A+) + DEFINE A AS v > $1 + ) +$$; +SELECT v, cnt FROM rpr_srf_f(3) ORDER BY v; + v | cnt +---+----- + 1 | 0 + 2 | 0 + 3 | 0 + 4 | 2 + 5 | 0 +(5 rows) + +DROP TABLE rpr_srf_t; +DROP FUNCTION rpr_srf_f(int); DROP TABLE rpr_planner; -- ============================================================ -- Stress Tests diff --git a/src/test/regress/sql/rpr_base.sql b/src/test/regress/sql/rpr_base.sql index 95cfb4b86fe..3d6ca2bc2a2 100644 --- a/src/test/regress/sql/rpr_base.sql +++ b/src/test/regress/sql/rpr_base.sql @@ -28,6 +28,7 @@ -- Complex Expression Tests -- Set Operations Tests -- Sorting and Grouping Tests +-- SQL Function Inlining Tests -- Stress Tests -- Error Limit Tests -- @@ -3478,6 +3479,29 @@ LIMIT 3 OFFSET 1; DROP TABLE rpr_sort; +-- SQL function inlining: $1 in DEFINE must be substituted by +-- substitute_actual_parameters_in_from via query_tree_mutator. +CREATE TABLE rpr_srf_t (v int); +INSERT INTO rpr_srf_t SELECT generate_series(1, 5); + +CREATE FUNCTION rpr_srf_f(threshold int) +RETURNS TABLE (v int, cnt bigint) +LANGUAGE sql STABLE AS $$ + SELECT v::int, count(*) OVER w + FROM rpr_srf_t + WINDOW w AS ( + ORDER BY v + ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING + PATTERN (A+) + DEFINE A AS v > $1 + ) +$$; + +SELECT v, cnt FROM rpr_srf_f(3) ORDER BY v; + +DROP TABLE rpr_srf_t; +DROP FUNCTION rpr_srf_f(int); + DROP TABLE rpr_planner; -- ============================================================ -- 2.50.1 (Apple Git-155)