mirror of
https://github.com/postgres/postgres.git
synced 2025-07-02 09:02:37 +03:00
Selectively include window frames in expression walks/mutates.
query_tree_walker and query_tree_mutator were skipping the
windowClause of the query, without regard for the fact that the
startOffset and endOffset in a WindowClause node are expression trees
that need to be processed. This was an oversight in commit ec4be2ee6
from 2010 which added the expression fields; the main symptom is that
function parameters in window frame clauses don't work in inlined
functions.
Fix (as conservatively as possible since this needs to not break
existing out-of-tree callers) and add tests.
Backpatch all the way, since this has been broken since 9.0.
Per report from Alastair McKinley; fix by me with kibitzing and review
from Tom Lane.
Discussion: https://postgr.es/m/DB6PR0202MB2904E7FDDA9D81504D1E8C68E3800@DB6PR0202MB2904.eurprd02.prod.outlook.com
This commit is contained in:
@ -3821,3 +3821,45 @@ SELECT i, b, bool_and(b) OVER w, bool_or(b) OVER w
|
||||
5 | t | t | t
|
||||
(5 rows)
|
||||
|
||||
-- Tests for problems with failure to walk or mutate expressions
|
||||
-- within window frame clauses.
|
||||
-- test walker (fails with collation error if expressions are not walked)
|
||||
SELECT array_agg(i) OVER w
|
||||
FROM generate_series(1,5) i
|
||||
WINDOW w AS (ORDER BY i ROWS BETWEEN (('foo' < 'foobar')::integer) PRECEDING AND CURRENT ROW);
|
||||
array_agg
|
||||
-----------
|
||||
{1}
|
||||
{1,2}
|
||||
{2,3}
|
||||
{3,4}
|
||||
{4,5}
|
||||
(5 rows)
|
||||
|
||||
-- test mutator (fails when inlined if expressions are not mutated)
|
||||
CREATE FUNCTION pg_temp.f(group_size BIGINT) RETURNS SETOF integer[]
|
||||
AS $$
|
||||
SELECT array_agg(s) OVER w
|
||||
FROM generate_series(1,5) s
|
||||
WINDOW w AS (ORDER BY s ROWS BETWEEN CURRENT ROW AND GROUP_SIZE FOLLOWING)
|
||||
$$ LANGUAGE SQL STABLE;
|
||||
EXPLAIN (costs off) SELECT * FROM pg_temp.f(2);
|
||||
QUERY PLAN
|
||||
------------------------------------------------------
|
||||
Subquery Scan on f
|
||||
-> WindowAgg
|
||||
-> Sort
|
||||
Sort Key: s.s
|
||||
-> Function Scan on generate_series s
|
||||
(5 rows)
|
||||
|
||||
SELECT * FROM pg_temp.f(2);
|
||||
f
|
||||
---------
|
||||
{1,2,3}
|
||||
{2,3,4}
|
||||
{3,4,5}
|
||||
{4,5}
|
||||
{5}
|
||||
(5 rows)
|
||||
|
||||
|
@ -1257,3 +1257,22 @@ SELECT to_char(SUM(n::float8) OVER (ORDER BY i ROWS BETWEEN CURRENT ROW AND 1 FO
|
||||
SELECT i, b, bool_and(b) OVER w, bool_or(b) OVER w
|
||||
FROM (VALUES (1,true), (2,true), (3,false), (4,false), (5,true)) v(i,b)
|
||||
WINDOW w AS (ORDER BY i ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING);
|
||||
|
||||
-- Tests for problems with failure to walk or mutate expressions
|
||||
-- within window frame clauses.
|
||||
|
||||
-- test walker (fails with collation error if expressions are not walked)
|
||||
SELECT array_agg(i) OVER w
|
||||
FROM generate_series(1,5) i
|
||||
WINDOW w AS (ORDER BY i ROWS BETWEEN (('foo' < 'foobar')::integer) PRECEDING AND CURRENT ROW);
|
||||
|
||||
-- test mutator (fails when inlined if expressions are not mutated)
|
||||
CREATE FUNCTION pg_temp.f(group_size BIGINT) RETURNS SETOF integer[]
|
||||
AS $$
|
||||
SELECT array_agg(s) OVER w
|
||||
FROM generate_series(1,5) s
|
||||
WINDOW w AS (ORDER BY s ROWS BETWEEN CURRENT ROW AND GROUP_SIZE FOLLOWING)
|
||||
$$ LANGUAGE SQL STABLE;
|
||||
|
||||
EXPLAIN (costs off) SELECT * FROM pg_temp.f(2);
|
||||
SELECT * FROM pg_temp.f(2);
|
||||
|
Reference in New Issue
Block a user