@ -652,10 +652,11 @@ select first_value(max(x)) over (), y
QUERY PLAN
QUERY PLAN
---------------------------------------------
---------------------------------------------
WindowAgg
WindowAgg
Window: w1 AS ()
-> HashAggregate
-> HashAggregate
Group Key: (tenk1.ten + tenk1.four)
Group Key: (tenk1.ten + tenk1.four)
-> Seq Scan on tenk1
-> Seq Scan on tenk1
(4 rows)
(5 rows)
-- window functions returning pass-by-ref values from different rows
-- window functions returning pass-by-ref values from different rows
select x, lag(x, 1) over (order by x), lead(x, 3) over (order by x)
select x, lag(x, 1) over (order by x), lead(x, 3) over (order by x)
@ -3538,13 +3539,14 @@ select f1, sum(f1) over (partition by f1 order by f2
range between 1 preceding and 1 following)
range between 1 preceding and 1 following)
from t1 where f1 = f2;
from t1 where f1 = f2;
QUERY PLAN
QUERY PLAN
---------------------------------
-------------------------------------------------------------------------------------------------------------
WindowAgg
WindowAgg
Window: w1 AS (PARTITION BY f1 ORDER BY f2 RANGE BETWEEN '1'::bigint PRECEDING AND '1'::bigint FOLLOWING)
-> Sort
-> Sort
Sort Key: f1
Sort Key: f1
-> Seq Scan on t1
-> Seq Scan on t1
Filter: (f1 = f2)
Filter: (f1 = f2)
(5 rows)
(6 rows)
select f1, sum(f1) over (partition by f1 order by f2
select f1, sum(f1) over (partition by f1 order by f2
range between 1 preceding and 1 following)
range between 1 preceding and 1 following)
@ -3584,13 +3586,14 @@ select f1, sum(f1) over (partition by f1 order by f2
groups between 1 preceding and 1 following)
groups between 1 preceding and 1 following)
from t1 where f1 = f2;
from t1 where f1 = f2;
QUERY PLAN
QUERY PLAN
---------------------------------
--------------------------------------------------------------------------------------------------------------
WindowAgg
WindowAgg
Window: w1 AS (PARTITION BY f1 ORDER BY f2 GROUPS BETWEEN '1'::bigint PRECEDING AND '1'::bigint FOLLOWING)
-> Sort
-> Sort
Sort Key: f1
Sort Key: f1
-> Seq Scan on t1
-> Seq Scan on t1
Filter: (f1 = f2)
Filter: (f1 = f2)
(5 rows)
(6 rows)
select f1, sum(f1) over (partition by f1 order by f2
select f1, sum(f1) over (partition by f1 order by f2
groups between 1 preceding and 1 following)
groups between 1 preceding and 1 following)
@ -3712,12 +3715,13 @@ SELECT
CURRENT ROW AND UNBOUNDED FOLLOWING) cd
CURRENT ROW AND UNBOUNDED FOLLOWING) cd
FROM empsalary;
FROM empsalary;
QUERY PLAN
QUERY PLAN
----------------------------------------
--------------------------------------------------------------------------------------
WindowAgg
WindowAgg
Window: w1 AS (PARTITION BY depname ORDER BY enroll_date ROWS UNBOUNDED PRECEDING)
-> Sort
-> Sort
Sort Key: depname, enroll_date
Sort Key: depname, enroll_date
-> Seq Scan on empsalary
-> Seq Scan on empsalary
(4 rows)
(5 rows)
-- Ensure WindowFuncs which cannot support their WindowClause's frameOptions
-- Ensure WindowFuncs which cannot support their WindowClause's frameOptions
-- being changed are untouched
-- being changed are untouched
@ -3732,17 +3736,19 @@ SELECT
CURRENT ROW AND CURRENT ROW) cnt
CURRENT ROW AND CURRENT ROW) cnt
FROM empsalary;
FROM empsalary;
QUERY PLAN
QUERY PLAN
------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------
WindowAgg
WindowAgg
Output: empno, depname, (row_number() OVER (?)), (rank() OVER (?)), count(*) OVER (?), enroll_date
Output: empno, depname, (row_number() OVER w1), (rank() OVER w1), count(*) OVER w2, enroll_date
Window: w2 AS (PARTITION BY empsalary.depname ORDER BY empsalary.enroll_date RANGE BETWEEN CURRENT ROW AND CURRENT ROW)
-> WindowAgg
-> WindowAgg
Output: depname, enroll_date, empno, row_number() OVER (?), rank() OVER (?)
Output: depname, enroll_date, empno, row_number() OVER w1, rank() OVER w1
Window: w1 AS (PARTITION BY empsalary.depname ORDER BY empsalary.enroll_date ROWS UNBOUNDED PRECEDING)
-> Sort
-> Sort
Output: depname, enroll_date, empno
Output: depname, enroll_date, empno
Sort Key: empsalary.depname, empsalary.enroll_date
Sort Key: empsalary.depname, empsalary.enroll_date
-> Seq Scan on pg_temp.empsalary
-> Seq Scan on pg_temp.empsalary
Output: depname, enroll_date, empno
Output: depname, enroll_date, empno
(9 rows)
(11 rows)
-- Ensure the above query gives us the expected results
-- Ensure the above query gives us the expected results
SELECT
SELECT
@ -3778,15 +3784,17 @@ SELECT * FROM
FROM empsalary) emp
FROM empsalary) emp
WHERE depname = 'sales';
WHERE depname = 'sales';
QUERY PLAN
QUERY PLAN
--------------------------------------------------------------------------
---------------------------------------------------------------------------------------
Subquery Scan on emp
Subquery Scan on emp
-> WindowAgg
-> WindowAgg
Window: w2 AS ()
-> WindowAgg
-> WindowAgg
Window: w1 AS (PARTITION BY (((empsalary.depname)::text || 'A'::text)))
-> Sort
-> Sort
Sort Key: (((empsalary.depname)::text || 'A'::text))
Sort Key: (((empsalary.depname)::text || 'A'::text))
-> Seq Scan on empsalary
-> Seq Scan on empsalary
Filter: ((depname)::text = 'sales'::text)
Filter: ((depname)::text = 'sales'::text)
(7 rows)
(9 rows)
-- pushdown is unsafe because there's a PARTITION BY clause without depname:
-- pushdown is unsafe because there's a PARTITION BY clause without depname:
EXPLAIN (COSTS OFF)
EXPLAIN (COSTS OFF)
@ -3797,17 +3805,19 @@ SELECT * FROM
FROM empsalary) emp
FROM empsalary) emp
WHERE depname = 'sales';
WHERE depname = 'sales';
QUERY PLAN
QUERY PLAN
-------------------------------------------------------
--------------------------------------------------------------------
Subquery Scan on emp
Subquery Scan on emp
Filter: ((emp.depname)::text = 'sales'::text)
Filter: ((emp.depname)::text = 'sales'::text)
-> WindowAgg
-> WindowAgg
Window: w2 AS (PARTITION BY empsalary.enroll_date)
-> Sort
-> Sort
Sort Key: empsalary.enroll_date
Sort Key: empsalary.enroll_date
-> WindowAgg
-> WindowAgg
Window: w1 AS (PARTITION BY empsalary.depname)
-> Sort
-> Sort
Sort Key: empsalary.depname
Sort Key: empsalary.depname
-> Seq Scan on empsalary
-> Seq Scan on empsalary
(9 rows)
(11 rows)
-- Test window function run conditions are properly pushed down into the
-- Test window function run conditions are properly pushed down into the
-- WindowAgg
-- WindowAgg
@ -3818,13 +3828,14 @@ SELECT * FROM
FROM empsalary) emp
FROM empsalary) emp
WHERE rn < 3;
WHERE rn < 3;
QUERY PLAN
QUERY PLAN
----------------------------------------------
---------------------------------------------------------------------
WindowAgg
WindowAgg
Run Condition: (row_number() OVER (?) < 3)
Window: w1 AS (ORDER BY empsalary.empno ROWS UNBOUNDED PRECEDING)
Run Condition: (row_number() OVER w1 < 3)
-> Sort
-> Sort
Sort Key: empsalary.empno
Sort Key: empsalary.empno
-> Seq Scan on empsalary
-> Seq Scan on empsalary
(5 rows)
(6 rows)
-- The following 3 statements should result the same result.
-- The following 3 statements should result the same result.
SELECT * FROM
SELECT * FROM
@ -3869,13 +3880,14 @@ SELECT * FROM
FROM empsalary) emp
FROM empsalary) emp
WHERE r <= 3;
WHERE r <= 3;
QUERY PLAN
QUERY PLAN
-----------------------------------------
----------------------------------------------------------------------
WindowAgg
WindowAgg
Run Condition: (rank() OVER (?) <= 3)
Window: w1 AS (ORDER BY empsalary.salary ROWS UNBOUNDED PRECEDING)
Run Condition: (rank() OVER w1 <= 3)
-> Sort
-> Sort
Sort Key: empsalary.salary DESC
Sort Key: empsalary.salary DESC
-> Seq Scan on empsalary
-> Seq Scan on empsalary
(5 rows)
(6 rows)
SELECT * FROM
SELECT * FROM
(SELECT empno,
(SELECT empno,
@ -3899,15 +3911,16 @@ SELECT * FROM
FROM empsalary) emp
FROM empsalary) emp
WHERE dr = 1;
WHERE dr = 1;
QUERY PLAN
QUERY PLAN
-----------------------------------------------------
----------------------------------------------------------------------------
Subquery Scan on emp
Subquery Scan on emp
Filter: (emp.dr = 1)
Filter: (emp.dr = 1)
-> WindowAgg
-> WindowAgg
Run Condition: (dense_rank() OVER (?) <= 1)
Window: w1 AS (ORDER BY empsalary.salary ROWS UNBOUNDED PRECEDING)
Run Condition: (dense_rank() OVER w1 <= 1)
-> Sort
-> Sort
Sort Key: empsalary.salary DESC
Sort Key: empsalary.salary DESC
-> Seq Scan on empsalary
-> Seq Scan on empsalary
(7 rows)
(8 rows)
SELECT * FROM
SELECT * FROM
(SELECT empno,
(SELECT empno,
@ -3929,13 +3942,14 @@ SELECT * FROM
FROM empsalary) emp
FROM empsalary) emp
WHERE c <= 3;
WHERE c <= 3;
QUERY PLAN
QUERY PLAN
-------------------------------------------
---------------------------------------------
WindowAgg
WindowAgg
Run Condition: (count(*) OVER (?) <= 3)
Window: w1 AS (ORDER BY empsalary.salary)
Run Condition: (count(*) OVER w1 <= 3)
-> Sort
-> Sort
Sort Key: empsalary.salary DESC
Sort Key: empsalary.salary DESC
-> Seq Scan on empsalary
-> Seq Scan on empsalary
(5 rows)
(6 rows)
SELECT * FROM
SELECT * FROM
(SELECT empno,
(SELECT empno,
@ -3958,13 +3972,14 @@ SELECT * FROM
FROM empsalary) emp
FROM empsalary) emp
WHERE c <= 3;
WHERE c <= 3;
QUERY PLAN
QUERY PLAN
---------------------------------------------------------
--------------------------------------------------------
WindowAgg
WindowAgg
Run Condition: (count(empsalary.empno) OVER (?) <= 3)
Window: w1 AS (ORDER BY empsalary.salary)
Run Condition: (count(empsalary.empno) OVER w1 <= 3)
-> Sort
-> Sort
Sort Key: empsalary.salary DESC
Sort Key: empsalary.salary DESC
-> Seq Scan on empsalary
-> Seq Scan on empsalary
(5 rows)
(6 rows)
SELECT * FROM
SELECT * FROM
(SELECT empno,
(SELECT empno,
@ -3987,13 +4002,14 @@ SELECT * FROM
FROM empsalary) emp
FROM empsalary) emp
WHERE c >= 3;
WHERE c >= 3;
QUERY PLAN
QUERY PLAN
-------------------------------------------
----------------------------------------------------------------------------------------------
WindowAgg
WindowAgg
Run Condition: (count(*) OVER (?) >= 3)
Window: w1 AS (ORDER BY empsalary.salary ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
Run Condition: (count(*) OVER w1 >= 3)
-> Sort
-> Sort
Sort Key: empsalary.salary DESC
Sort Key: empsalary.salary DESC
-> Seq Scan on empsalary
-> Seq Scan on empsalary
(5 rows)
(6 rows)
EXPLAIN (COSTS OFF)
EXPLAIN (COSTS OFF)
SELECT * FROM
SELECT * FROM
@ -4003,11 +4019,12 @@ SELECT * FROM
FROM empsalary) emp
FROM empsalary) emp
WHERE 11 <= c;
WHERE 11 <= c;
QUERY PLAN
QUERY PLAN
--------------------------------------------
-------------------------------------------
WindowAgg
WindowAgg
Run Condition: (11 <= count(*) OVER (?))
Window: w1 AS ()
Run Condition: (11 <= count(*) OVER w1)
-> Seq Scan on empsalary
-> Seq Scan on empsalary
(3 rows)
(4 rows)
EXPLAIN (COSTS OFF)
EXPLAIN (COSTS OFF)
SELECT * FROM
SELECT * FROM
@ -4018,15 +4035,16 @@ SELECT * FROM
FROM empsalary) emp
FROM empsalary) emp
WHERE dr = 1;
WHERE dr = 1;
QUERY PLAN
QUERY PLAN
-----------------------------------------------------
----------------------------------------------------
Subquery Scan on emp
Subquery Scan on emp
Filter: (emp.dr = 1)
Filter: (emp.dr = 1)
-> WindowAgg
-> WindowAgg
Run Condition: (dense_rank() OVER (?) <= 1)
Window: w1 AS (ORDER BY empsalary.salary)
Run Condition: (dense_rank() OVER w1 <= 1)
-> Sort
-> Sort
Sort Key: empsalary.salary DESC
Sort Key: empsalary.salary DESC
-> Seq Scan on empsalary
-> Seq Scan on empsalary
(7 rows)
(8 rows)
-- Ensure we get a run condition when there's a PARTITION BY clause
-- Ensure we get a run condition when there's a PARTITION BY clause
EXPLAIN (COSTS OFF)
EXPLAIN (COSTS OFF)
@ -4037,13 +4055,14 @@ SELECT * FROM
FROM empsalary) emp
FROM empsalary) emp
WHERE rn < 3;
WHERE rn < 3;
QUERY PLAN
QUERY PLAN
------------------------------------------------------
----------------------------------------------------------------------------------------------------
WindowAgg
WindowAgg
Run Condition: (row_number() OVER (?) < 3)
Window: w1 AS (PARTITION BY empsalary.depname ORDER BY empsalary.empno ROWS UNBOUNDED PRECEDING)
Run Condition: (row_number() OVER w1 < 3)
-> Sort
-> Sort
Sort Key: empsalary.depname, empsalary.empno
Sort Key: empsalary.depname, empsalary.empno
-> Seq Scan on empsalary
-> Seq Scan on empsalary
(5 rows)
(6 rows)
-- and ensure we get the correct results from the above plan
-- and ensure we get the correct results from the above plan
SELECT * FROM
SELECT * FROM
@ -4072,14 +4091,15 @@ SELECT empno, depname FROM
FROM empsalary) emp
FROM empsalary) emp
WHERE rn < 3;
WHERE rn < 3;
QUERY PLAN
QUERY PLAN
------------------------------------------------------------
----------------------------------------------------------------------------------------------------------
Subquery Scan on emp
Subquery Scan on emp
-> WindowAgg
-> WindowAgg
Run Condition: (row_number() OVER (?) < 3)
Window: w1 AS (PARTITION BY empsalary.depname ORDER BY empsalary.empno ROWS UNBOUNDED PRECEDING)
Run Condition: (row_number() OVER w1 < 3)
-> Sort
-> Sort
Sort Key: empsalary.depname, empsalary.empno
Sort Key: empsalary.depname, empsalary.empno
-> Seq Scan on empsalary
-> Seq Scan on empsalary
(6 rows)
(7 rows)
-- likewise with count(empno) instead of row_number()
-- likewise with count(empno) instead of row_number()
EXPLAIN (COSTS OFF)
EXPLAIN (COSTS OFF)
@ -4091,13 +4111,14 @@ SELECT * FROM
FROM empsalary) emp
FROM empsalary) emp
WHERE c <= 3;
WHERE c <= 3;
QUERY PLAN
QUERY PLAN
------------------------------------------------------------
----------------------------------------------------------------------------
WindowAgg
WindowAgg
Run Condition: (count(empsalary.empno) OVER (?) <= 3)
Window: w1 AS (PARTITION BY empsalary.depname ORDER BY empsalary.salary)
Run Condition: (count(empsalary.empno) OVER w1 <= 3)
-> Sort
-> Sort
Sort Key: empsalary.depname, empsalary.salary DESC
Sort Key: empsalary.depname, empsalary.salary DESC
-> Seq Scan on empsalary
-> Seq Scan on empsalary
(5 rows)
(6 rows)
-- and again, check the results are what we expect.
-- and again, check the results are what we expect.
SELECT * FROM
SELECT * FROM
@ -4130,11 +4151,12 @@ SELECT * FROM
FROM empsalary) emp
FROM empsalary) emp
WHERE c = 1;
WHERE c = 1;
QUERY PLAN
QUERY PLAN
--------------------------------------------------------
-------------------------------------------------------
WindowAgg
WindowAgg
Run Condition: (count(empsalary.empno) OVER (?) = 1)
Window: w1 AS ()
Run Condition: (count(empsalary.empno) OVER w1 = 1)
-> Seq Scan on empsalary
-> Seq Scan on empsalary
(3 rows)
(4 rows)
-- Try another case with a WindowFunc with a byref return type
-- Try another case with a WindowFunc with a byref return type
SELECT * FROM
SELECT * FROM
@ -4158,22 +4180,25 @@ SELECT * FROM
FROM empsalary
FROM empsalary
) e WHERE rn <= 1 AND c1 <= 3 AND nt < 2;
) e WHERE rn <= 1 AND c1 <= 3 AND nt < 2;
QUERY PLAN
QUERY PLAN
-----------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------
Subquery Scan on e
Subquery Scan on e
-> WindowAgg
-> WindowAgg
Filter: (((row_number() OVER (?)) <= 1) AND ((ntile(2) OVER (?)) < 2))
Window: w3 AS (PARTITION BY (((empsalary.depname)::text || ''::text)))
Run Condition: (count(empsalary.salary) OVER (?) <= 3)
Run Condition: (count(empsalary.salary) OVER w3 <= 3)
Filter: (((row_number() OVER w2) <= 1) AND ((ntile(2) OVER w2) < 2))
-> Sort
-> Sort
Sort Key: (((empsalary.depname)::text || ''::text))
Sort Key: (((empsalary.depname)::text || ''::text))
-> WindowAgg
-> WindowAgg
Run Condition: ((row_number() OVER (?) <= 1) AND (ntile(2) OVER (?) < 2))
Window: w2 AS (PARTITION BY empsalary.depname)
Run Condition: ((row_number() OVER w2 <= 1) AND (ntile(2) OVER w2 < 2))
-> Sort
-> Sort
Sort Key: empsalary.depname
Sort Key: empsalary.depname
-> WindowAgg
-> WindowAgg
Window: w1 AS (PARTITION BY ((''::text || (empsalary.depname)::text)))
-> Sort
-> Sort
Sort Key: ((''::text || (empsalary.depname)::text))
Sort Key: ((''::text || (empsalary.depname)::text))
-> Seq Scan on empsalary
-> Seq Scan on empsalary
(14 rows)
(17 rows)
-- Ensure we correctly filter out all of the run conditions from each window
-- Ensure we correctly filter out all of the run conditions from each window
SELECT * FROM
SELECT * FROM
@ -4200,11 +4225,12 @@ SELECT 1 FROM
WHERE e1.empno = e2.empno) s
WHERE e1.empno = e2.empno) s
WHERE s.c = 1;
WHERE s.c = 1;
QUERY PLAN
QUERY PLAN
---------------------------------------------------------
--------------------------------------------------------------------------
Subquery Scan on s
Subquery Scan on s
Filter: (s.c = 1)
Filter: (s.c = 1)
-> WindowAgg
-> WindowAgg
Run Condition: (ntile(e2.salary) OVER (?) <= 1)
Window: w1 AS (PARTITION BY e1.depname ROWS UNBOUNDED PRECEDING)
Run Condition: (ntile(e2.salary) OVER w1 <= 1)
-> Sort
-> Sort
Sort Key: e1.depname
Sort Key: e1.depname
-> Merge Join
-> Merge Join
@ -4215,7 +4241,7 @@ WHERE s.c = 1;
-> Sort
-> Sort
Sort Key: e2.empno
Sort Key: e2.empno
-> Seq Scan on empsalary e2
-> Seq Scan on empsalary e2
(14 rows)
(15 rows)
-- Ensure the run condition optimization is used in cases where the WindowFunc
-- Ensure the run condition optimization is used in cases where the WindowFunc
-- has a Var from another query level
-- has a Var from another query level
@ -4225,15 +4251,16 @@ SELECT 1 FROM
FROM (SELECT (SELECT 1) AS x) AS s1) s
FROM (SELECT (SELECT 1) AS x) AS s1) s
WHERE s.c = 1;
WHERE s.c = 1;
QUERY PLAN
QUERY PLAN
-----------------------------------------------------------------
----------------------------------------------------------------
Subquery Scan on s
Subquery Scan on s
Filter: (s.c = 1)
Filter: (s.c = 1)
-> WindowAgg
-> WindowAgg
Run Condition: (ntile((InitPlan 1).col1) OVER (?) <= 1)
Window: w1 AS (ROWS UNBOUNDED PRECEDING)
Run Condition: (ntile((InitPlan 1).col1) OVER w1 <= 1)
InitPlan 1
InitPlan 1
-> Result
-> Result
-> Result
-> Result
(7 rows)
(8 rows)
-- Tests to ensure we don't push down the run condition when it's not valid to
-- Tests to ensure we don't push down the run condition when it's not valid to
-- do so.
-- do so.
@ -4247,14 +4274,15 @@ SELECT * FROM
FROM empsalary) emp
FROM empsalary) emp
WHERE c <= 3;
WHERE c <= 3;
QUERY PLAN
QUERY PLAN
-----------------------------------------------
----------------------------------------------------------------------------------------------------
Subquery Scan on emp
Subquery Scan on emp
Filter: (emp.c <= 3)
Filter: (emp.c <= 3)
-> WindowAgg
-> WindowAgg
Window: w1 AS (ORDER BY empsalary.salary ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
-> Sort
-> Sort
Sort Key: empsalary.salary DESC
Sort Key: empsalary.salary DESC
-> Seq Scan on empsalary
-> Seq Scan on empsalary
(6 rows)
(7 rows)
-- Ensure we don't push down when the window function's monotonic properties
-- Ensure we don't push down when the window function's monotonic properties
-- don't match that of the clauses.
-- don't match that of the clauses.
@ -4266,14 +4294,15 @@ SELECT * FROM
FROM empsalary) emp
FROM empsalary) emp
WHERE 3 <= c;
WHERE 3 <= c;
QUERY PLAN
QUERY PLAN
------------------------------------------
---------------------------------------------------
Subquery Scan on emp
Subquery Scan on emp
Filter: (3 <= emp.c)
Filter: (3 <= emp.c)
-> WindowAgg
-> WindowAgg
Window: w1 AS (ORDER BY empsalary.salary)
-> Sort
-> Sort
Sort Key: empsalary.salary
Sort Key: empsalary.salary
-> Seq Scan on empsalary
-> Seq Scan on empsalary
(6 rows)
(7 rows)
-- Ensure we don't use a run condition when there's a volatile function in the
-- Ensure we don't use a run condition when there's a volatile function in the
-- WindowFunc
-- WindowFunc
@ -4285,14 +4314,15 @@ SELECT * FROM
FROM empsalary) emp
FROM empsalary) emp
WHERE c = 1;
WHERE c = 1;
QUERY PLAN
QUERY PLAN
----------------------------------------------
--------------------------------------------------
Subquery Scan on emp
Subquery Scan on emp
Filter: (emp.c = 1)
Filter: (emp.c = 1)
-> WindowAgg
-> WindowAgg
Window: w1 AS (ORDER BY empsalary.empno)
-> Sort
-> Sort
Sort Key: empsalary.empno DESC
Sort Key: empsalary.empno DESC
-> Seq Scan on empsalary
-> Seq Scan on empsalary
(6 rows)
(7 rows)
-- Ensure we don't use a run condition when the WindowFunc contains subplans
-- Ensure we don't use a run condition when the WindowFunc contains subplans
EXPLAIN (COSTS OFF)
EXPLAIN (COSTS OFF)
@ -4303,16 +4333,17 @@ SELECT * FROM
FROM empsalary) emp
FROM empsalary) emp
WHERE c = 1;
WHERE c = 1;
QUERY PLAN
QUERY PLAN
----------------------------------------------
--------------------------------------------------
Subquery Scan on emp
Subquery Scan on emp
Filter: (emp.c = 1)
Filter: (emp.c = 1)
-> WindowAgg
-> WindowAgg
Window: w1 AS (ORDER BY empsalary.empno)
InitPlan 1
InitPlan 1
-> Result
-> Result
-> Sort
-> Sort
Sort Key: empsalary.empno DESC
Sort Key: empsalary.empno DESC
-> Seq Scan on empsalary
-> Seq Scan on empsalary
(8 rows)
(9 rows)
-- Test Sort node collapsing
-- Test Sort node collapsing
EXPLAIN (COSTS OFF)
EXPLAIN (COSTS OFF)
@ -4323,15 +4354,17 @@ SELECT * FROM
FROM empsalary) emp
FROM empsalary) emp
WHERE depname = 'sales';
WHERE depname = 'sales';
QUERY PLAN
QUERY PLAN
----------------------------------------------------------------------
-------------------------------------------------------------------------------------------
Subquery Scan on emp
Subquery Scan on emp
-> WindowAgg
-> WindowAgg
Window: w2 AS (ORDER BY empsalary.empno)
-> WindowAgg
-> WindowAgg
Window: w1 AS (PARTITION BY empsalary.empno ORDER BY empsalary.enroll_date)
-> Sort
-> Sort
Sort Key: empsalary.empno, empsalary.enroll_date
Sort Key: empsalary.empno, empsalary.enroll_date
-> Seq Scan on empsalary
-> Seq Scan on empsalary
Filter: ((depname)::text = 'sales'::text)
Filter: ((depname)::text = 'sales'::text)
(7 rows)
(9 rows)
-- Ensure that the evaluation order of the WindowAggs results in the WindowAgg
-- Ensure that the evaluation order of the WindowAggs results in the WindowAgg
-- with the same sort order that's required by the ORDER BY is evaluated last.
-- with the same sort order that's required by the ORDER BY is evaluated last.
@ -4344,16 +4377,18 @@ SELECT empno,
FROM empsalary
FROM empsalary
ORDER BY depname, empno;
ORDER BY depname, empno;
QUERY PLAN
QUERY PLAN
----------------------------------------------------
-------------------------------------------------------------------------
WindowAgg
WindowAgg
Window: w2 AS (PARTITION BY depname ORDER BY empno)
-> Incremental Sort
-> Incremental Sort
Sort Key: depname, empno
Sort Key: depname, empno
Presorted Key: depname
Presorted Key: depname
-> WindowAgg
-> WindowAgg
Window: w1 AS (PARTITION BY depname ORDER BY enroll_date)
-> Sort
-> Sort
Sort Key: depname, enroll_date
Sort Key: depname, enroll_date
-> Seq Scan on empsalary
-> Seq Scan on empsalary
(8 rows)
(10 rows)
-- As above, but with an adjusted ORDER BY to ensure the above plan didn't
-- As above, but with an adjusted ORDER BY to ensure the above plan didn't
-- perform only 2 sorts by accident.
-- perform only 2 sorts by accident.
@ -4366,16 +4401,18 @@ SELECT empno,
FROM empsalary
FROM empsalary
ORDER BY depname, enroll_date;
ORDER BY depname, enroll_date;
QUERY PLAN
QUERY PLAN
-----------------------------------------------
-------------------------------------------------------------------
WindowAgg
WindowAgg
Window: w2 AS (PARTITION BY depname ORDER BY enroll_date)
-> Incremental Sort
-> Incremental Sort
Sort Key: depname, enroll_date
Sort Key: depname, enroll_date
Presorted Key: depname
Presorted Key: depname
-> WindowAgg
-> WindowAgg
Window: w1 AS (PARTITION BY depname ORDER BY empno)
-> Sort
-> Sort
Sort Key: depname, empno
Sort Key: depname, empno
-> Seq Scan on empsalary
-> Seq Scan on empsalary
(8 rows)
(10 rows)
SET enable_hashagg TO off;
SET enable_hashagg TO off;
-- Ensure we don't get a sort for both DISTINCT and ORDER BY. We expect the
-- Ensure we don't get a sort for both DISTINCT and ORDER BY. We expect the
@ -4390,20 +4427,22 @@ SELECT DISTINCT
FROM empsalary
FROM empsalary
ORDER BY depname, enroll_date;
ORDER BY depname, enroll_date;
QUERY PLAN
QUERY PLAN
-----------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------
Unique
Unique
-> Incremental Sort
-> Incremental Sort
Sort Key: depname, enroll_date, empno, (sum(salary) OVER (?)), (min(salary) OVER (?) )
Sort Key: depname, enroll_date, empno, (sum(salary) OVER w1), (min(salary) OVER w2 )
Presorted Key: depname, enroll_date
Presorted Key: depname, enroll_date
-> WindowAgg
-> WindowAgg
Window: w2 AS (PARTITION BY depname ORDER BY enroll_date)
-> Incremental Sort
-> Incremental Sort
Sort Key: depname, enroll_date
Sort Key: depname, enroll_date
Presorted Key: depname
Presorted Key: depname
-> WindowAgg
-> WindowAgg
Window: w1 AS (PARTITION BY depname ORDER BY empno)
-> Sort
-> Sort
Sort Key: depname, empno
Sort Key: depname, empno
-> Seq Scan on empsalary
-> Seq Scan on empsalary
(12 rows)
(14 rows)
-- As above but adjust the ORDER BY clause to help ensure the plan with the
-- As above but adjust the ORDER BY clause to help ensure the plan with the
-- minimum amount of sorting wasn't a fluke.
-- minimum amount of sorting wasn't a fluke.
@ -4417,20 +4456,22 @@ SELECT DISTINCT
FROM empsalary
FROM empsalary
ORDER BY depname, empno;
ORDER BY depname, empno;
QUERY PLAN
QUERY PLAN
-----------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------
Unique
Unique
-> Incremental Sort
-> Incremental Sort
Sort Key: depname, empno, enroll_date, (sum(salary) OVER (?)), (min(salary) OVER (?) )
Sort Key: depname, empno, enroll_date, (sum(salary) OVER w2), (min(salary) OVER w1 )
Presorted Key: depname, empno
Presorted Key: depname, empno
-> WindowAgg
-> WindowAgg
Window: w2 AS (PARTITION BY depname ORDER BY empno)
-> Incremental Sort
-> Incremental Sort
Sort Key: depname, empno
Sort Key: depname, empno
Presorted Key: depname
Presorted Key: depname
-> WindowAgg
-> WindowAgg
Window: w1 AS (PARTITION BY depname ORDER BY enroll_date)
-> Sort
-> Sort
Sort Key: depname, enroll_date
Sort Key: depname, enroll_date
-> Seq Scan on empsalary
-> Seq Scan on empsalary
(12 rows)
(14 rows)
RESET enable_hashagg;
RESET enable_hashagg;
-- Test Sort node reordering
-- Test Sort node reordering
@ -4440,13 +4481,15 @@ SELECT
lag(1) OVER (PARTITION BY depname ORDER BY salary,enroll_date,empno)
lag(1) OVER (PARTITION BY depname ORDER BY salary,enroll_date,empno)
FROM empsalary;
FROM empsalary;
QUERY PLAN
QUERY PLAN
-------------------------------------------------------------
----------------------------------------------------------------------------------
WindowAgg
WindowAgg
Window: w2 AS (PARTITION BY depname ORDER BY salary, enroll_date)
-> WindowAgg
-> WindowAgg
Window: w1 AS (PARTITION BY depname ORDER BY salary, enroll_date, empno)
-> Sort
-> Sort
Sort Key: depname, salary, enroll_date, empno
Sort Key: depname, salary, enroll_date, empno
-> Seq Scan on empsalary
-> Seq Scan on empsalary
(5 rows)
(7 rows)
-- Test incremental sorting
-- Test incremental sorting
EXPLAIN (COSTS OFF)
EXPLAIN (COSTS OFF)
@ -4460,18 +4503,20 @@ SELECT * FROM
FROM empsalary) emp
FROM empsalary) emp
WHERE first_emp = 1 OR last_emp = 1;
WHERE first_emp = 1 OR last_emp = 1;
QUERY PLAN
QUERY PLAN
-----------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------
Subquery Scan on emp
Subquery Scan on emp
Filter: ((emp.first_emp = 1) OR (emp.last_emp = 1))
Filter: ((emp.first_emp = 1) OR (emp.last_emp = 1))
-> WindowAgg
-> WindowAgg
Window: w2 AS (PARTITION BY empsalary.depname ORDER BY empsalary.enroll_date ROWS UNBOUNDED PRECEDING)
-> Incremental Sort
-> Incremental Sort
Sort Key: empsalary.depname, empsalary.enroll_date
Sort Key: empsalary.depname, empsalary.enroll_date
Presorted Key: empsalary.depname
Presorted Key: empsalary.depname
-> WindowAgg
-> WindowAgg
Window: w1 AS (PARTITION BY empsalary.depname ORDER BY empsalary.enroll_date ROWS UNBOUNDED PRECEDING)
-> Sort
-> Sort
Sort Key: empsalary.depname, empsalary.enroll_date DESC
Sort Key: empsalary.depname, empsalary.enroll_date DESC
-> Seq Scan on empsalary
-> Seq Scan on empsalary
(10 rows)
(12 rows)
SELECT * FROM
SELECT * FROM
(SELECT depname,
(SELECT depname,
@ -5299,11 +5344,12 @@ LIMIT 1;
--------------------------------------------------------------------------
--------------------------------------------------------------------------
Limit
Limit
-> WindowAgg
-> WindowAgg
Window: w1 AS (ORDER BY t1.unique1)
-> Nested Loop
-> Nested Loop
-> Index Only Scan using tenk1_unique1 on tenk1 t1
-> Index Only Scan using tenk1_unique1 on tenk1 t1
-> Index Only Scan using tenk1_thous_tenthous on tenk1 t2
-> Index Only Scan using tenk1_thous_tenthous on tenk1 t2
Index Cond: (tenthous = t1.unique1)
Index Cond: (tenthous = t1.unique1)
(6 rows)
(7 rows)
-- Ensure we get a cheap total plan. Lack of ORDER BY in the WindowClause
-- Ensure we get a cheap total plan. Lack of ORDER BY in the WindowClause
-- means that all rows must be read from the join, so a cheap startup plan
-- means that all rows must be read from the join, so a cheap startup plan
@ -5317,13 +5363,14 @@ LIMIT 1;
-------------------------------------------------------------------
-------------------------------------------------------------------
Limit
Limit
-> WindowAgg
-> WindowAgg
Window: w1 AS ()
-> Hash Join
-> Hash Join
Hash Cond: (t1.unique1 = t2.tenthous)
Hash Cond: (t1.unique1 = t2.tenthous)
-> Index Only Scan using tenk1_unique1 on tenk1 t1
-> Index Only Scan using tenk1_unique1 on tenk1 t1
-> Hash
-> Hash
-> Seq Scan on tenk1 t2
-> Seq Scan on tenk1 t2
Filter: (two = 1)
Filter: (two = 1)
(8 rows)
(9 rows)
-- Ensure we get a cheap total plan. This time use UNBOUNDED FOLLOWING, which
-- Ensure we get a cheap total plan. This time use UNBOUNDED FOLLOWING, which
-- needs to read all join rows to output the first WindowAgg row.
-- needs to read all join rows to output the first WindowAgg row.
@ -5332,16 +5379,17 @@ SELECT COUNT(*) OVER (ORDER BY t1.unique1 ROWS BETWEEN UNBOUNDED PRECEDING AND U
FROM tenk1 t1 INNER JOIN tenk1 t2 ON t1.unique1 = t2.tenthous
FROM tenk1 t1 INNER JOIN tenk1 t2 ON t1.unique1 = t2.tenthous
LIMIT 1;
LIMIT 1;
QUERY PLAN
QUERY PLAN
--------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------
Limit
Limit
-> WindowAgg
-> WindowAgg
Window: w1 AS (ORDER BY t1.unique1 ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
-> Merge Join
-> Merge Join
Merge Cond: (t1.unique1 = t2.tenthous)
Merge Cond: (t1.unique1 = t2.tenthous)
-> Index Only Scan using tenk1_unique1 on tenk1 t1
-> Index Only Scan using tenk1_unique1 on tenk1 t1
-> Sort
-> Sort
Sort Key: t2.tenthous
Sort Key: t2.tenthous
-> Index Only Scan using tenk1_thous_tenthous on tenk1 t2
-> Index Only Scan using tenk1_thous_tenthous on tenk1 t2
(8 rows)
(9 rows)
-- Ensure we get a cheap total plan. This time use 10000 FOLLOWING so we need
-- Ensure we get a cheap total plan. This time use 10000 FOLLOWING so we need
-- to read all join rows.
-- to read all join rows.
@ -5350,16 +5398,17 @@ SELECT COUNT(*) OVER (ORDER BY t1.unique1 ROWS BETWEEN UNBOUNDED PRECEDING AND 1
FROM tenk1 t1 INNER JOIN tenk1 t2 ON t1.unique1 = t2.tenthous
FROM tenk1 t1 INNER JOIN tenk1 t2 ON t1.unique1 = t2.tenthous
LIMIT 1;
LIMIT 1;
QUERY PLAN
QUERY PLAN
--------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------
Limit
Limit
-> WindowAgg
-> WindowAgg
Window: w1 AS (ORDER BY t1.unique1 ROWS BETWEEN UNBOUNDED PRECEDING AND '10000'::bigint FOLLOWING)
-> Merge Join
-> Merge Join
Merge Cond: (t1.unique1 = t2.tenthous)
Merge Cond: (t1.unique1 = t2.tenthous)
-> Index Only Scan using tenk1_unique1 on tenk1 t1
-> Index Only Scan using tenk1_unique1 on tenk1 t1
-> Sort
-> Sort
Sort Key: t2.tenthous
Sort Key: t2.tenthous
-> Index Only Scan using tenk1_thous_tenthous on tenk1 t2
-> Index Only Scan using tenk1_thous_tenthous on tenk1 t2
(8 rows)
(9 rows)
-- Tests for problems with failure to walk or mutate expressions
-- Tests for problems with failure to walk or mutate expressions
-- within window frame clauses.
-- within window frame clauses.
@ -5385,13 +5434,14 @@ AS $$
$$ LANGUAGE SQL STABLE;
$$ LANGUAGE SQL STABLE;
EXPLAIN (costs off) SELECT * FROM pg_temp.f(2);
EXPLAIN (costs off) SELECT * FROM pg_temp.f(2);
QUERY PLAN
QUERY PLAN
------------------------------------------------------
----------------------------------------------------------------------------------------
Subquery Scan on f
Subquery Scan on f
-> WindowAgg
-> WindowAgg
Window: w AS (ORDER BY s.s ROWS BETWEEN CURRENT ROW AND '2'::bigint FOLLOWING)
-> Sort
-> Sort
Sort Key: s.s
Sort Key: s.s
-> Function Scan on generate_series s
-> Function Scan on generate_series s
(5 rows)
(6 rows)
SELECT * FROM pg_temp.f(2);
SELECT * FROM pg_temp.f(2);
f
f