提交 a802eb2f 编写于 作者: B Bhuvnesh Chaudhary

Fix pushing of quals containing window functions

Fix qual_is_pushdown_safe_set_operation to correctly resolve the
qual vars and identify if there are any window references in the top
level of the set operation's left or right subqueries. Before commit
b8002a9, instead of starting with rte of the level where the qual is
attached we started scanning the rte of the subqueries of the left and
right args of setop to identify the qual. However, because of this the
varno didn't match to the corresponding RTE due to which the quals
couldn't be resolved to winref and were incorrectly pushed down. This
caused the planner to return an error during execution.
上级 01adf026
......@@ -80,7 +80,7 @@ static bool recurse_pushdown_safe(Node *setOp, Query *topquery,
bool *differentTypes);
static void compare_tlist_datatypes(List *tlist, List *colTypes,
bool *differentTypes);
static bool qual_is_pushdown_safe(Query *subquery, Index rti, Node *qual,
static bool qual_is_pushdown_safe(Query *subquery, RangeTblEntry *rte, Index rti, Node *qual,
bool *differentTypes);
static void subquery_push_qual(Query *subquery,
RangeTblEntry *rte, Index rti, Node *qual);
......@@ -1429,7 +1429,7 @@ push_down_restrict(PlannerInfo *root, RelOptInfo *rel,
Node *clause = (Node *) rinfo->clause;
if (!rinfo->pseudoconstant &&
qual_is_pushdown_safe(subquery, rti, clause, differentTypes))
qual_is_pushdown_safe(subquery, rte, rti, clause, differentTypes))
{
/* Push it down */
subquery_push_qual(subquery, rte, rti, clause);
......@@ -1487,10 +1487,6 @@ subquery_is_pushdown_safe(Query *subquery, Query *topquery,
if (subquery->limitOffset != NULL || subquery->limitCount != NULL)
return false;
/* Check point 2 */
if (subquery->hasWindowFuncs)
return false;
/* Targetlist must not contain SRF */
if (expression_returns_set((Node *) subquery->targetList))
return false;
......@@ -1593,6 +1589,80 @@ compare_tlist_datatypes(List *tlist, List *colTypes,
elog(ERROR, "wrong number of tlist entries");
}
/*
* does qual include a reference to window function node?
*/
static bool
qual_contains_window_function(Query *subquery, RangeTblEntry *rte, Index rti, Node *qual)
{
bool result = false;
if (NULL != subquery && NIL != subquery->windowClause)
{
/*
* qual needs to be resolved first to map qual columns
* to the underlying set of produced columns,
* e.g., if we work on a setop child
*/
Node *qualNew = ResolveNew(qual, rti, 0, rte,
subquery->targetList,
CMD_SELECT, 0, NULL);
result = contain_window_function(qualNew);
pfree(qualNew);
}
return result;
}
/*
* is a particular qual safe to push down under set operation?
* if the qual contains references to windowref node, its not
* safe to push it down.
*/
static bool
qual_is_pushdown_safe_set_operation(Query *query, RangeTblEntry *rte, Index rti, Node *qual)
{
Query *subquery = NULL;
/*
* In case of CTE, cte->query is passed in as query, so the vars
* should be resolved via the input query
*/
if (rte->rtekind == RTE_CTE)
subquery = query;
else
subquery = rte->subquery;
Assert(subquery);
SetOperationStmt *setop = (SetOperationStmt *)subquery->setOperations;
Assert(setop);
/*
* for queries of the form:
* SELECT * from (SELECT max(i) over () as w from X Union Select 1 as w) as foo where w > 0
* the qual (w > 0) is not push_down_safe since it uses a window ref
*
* we check if this is the case for either left or right set operation inputs.
* The check for window function is only at the top level of the set
* operation inputs. It does not recurse deep inside the set operation
* child for resolving the qual reference for queries of the form:
* SELECT w FROM ( (SELECT w FROM Y, Z, (SELECT max(i) over () as w from X) AS bar) UNION SELECT 1 AS w) AS foo WHERE w > 0;
*
*/
RangeTblEntry *rteLeft = rt_fetch(((RangeTblRef *)setop->larg)->rtindex, subquery->rtable);
RangeTblEntry *rteRight = rt_fetch(((RangeTblRef *)setop->rarg)->rtindex, subquery->rtable);
if (qual_contains_window_function(rteLeft->subquery, rte, rti, qual) ||
qual_contains_window_function(rteRight->subquery, rte, rti, qual))
{
return false;
}
return true;
}
/*
* qual_is_pushdown_safe - is a particular qual safe to push down?
*
......@@ -1630,7 +1700,7 @@ compare_tlist_datatypes(List *tlist, List *colTypes,
* to multiple evaluation of a volatile function.
*/
static bool
qual_is_pushdown_safe(Query *subquery, Index rti, Node *qual,
qual_is_pushdown_safe(Query *subquery, RangeTblEntry *rte, Index rti, Node *qual,
bool *differentTypes)
{
bool safe = true;
......@@ -1647,7 +1717,11 @@ qual_is_pushdown_safe(Query *subquery, Index rti, Node *qual,
* the moment we could never see any in a qual anyhow. (The same applies
* to aggregates, which we check for in pull_var_clause below.)
*/
Assert(!contain_window_function(qual));
if (NULL != subquery->setOperations &&
!qual_is_pushdown_safe_set_operation(subquery, rte, rti, qual))
{
return false;
}
/*
* Examine all Vars used in clause; since it's a restriction clause, all
......
......@@ -8207,3 +8207,205 @@ FROM foo;
(30 rows)
drop table foo;
-- test predicate push down in subqueries for quals containing windowref nodes
-- start_ignore
drop table if exists window_preds;
NOTICE: table "window_preds" does not exist, skipping
create table window_preds(i int, j int, k int);
NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'i' as the Greenplum Database data distribution key for this table.
HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew.
insert into window_preds values(1,2,3);
insert into window_preds values(2,3,4);
insert into window_preds values(3,4,5);
insert into window_preds values(4,5,6);
insert into window_preds values(5,6,7);
insert into window_preds values(6,7,8);
-- end_ignore
-- for planner qual k = 1 should not be pushed down in the subquery as it has window refs at top level of subquery. orca is able to push down the predicate to appropriate node
explain select k from ( select row_number() over()+2 as k from window_preds union all select row_number() over()+2 as k from window_preds) as t where k = 3;
QUERY PLAN
----------------------------------------------------------------------------------------------
Subquery Scan on t (cost=0.00..2.09 rows=1 width=8)
Filter: t.k = 3
-> Append (cost=0.00..2.07 rows=2 width=0)
-> WindowAgg (cost=0.00..1.02 rows=1 width=0)
-> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..1.01 rows=1 width=0)
-> Seq Scan on window_preds (cost=0.00..1.01 rows=1 width=0)
-> WindowAgg (cost=0.00..1.02 rows=1 width=0)
-> Gather Motion 3:1 (slice2; segments: 3) (cost=0.00..1.01 rows=1 width=0)
-> Seq Scan on window_preds (cost=0.00..1.01 rows=1 width=0)
Optimizer: legacy query optimizer
(10 rows)
select k from ( select row_number() over()+2 as k from window_preds union all select row_number() over()+2 as k from window_preds) as t where k = 3;
k
---
3
3
(2 rows)
explain insert into window_preds select k from ( select row_number() over()+2 as k from window_preds union all select row_number() over()+2 as k from window_preds) as t where k = 3;
QUERY PLAN
----------------------------------------------------------------------------------------------------------
Insert (cost=0.00..2.10 rows=1 width=8)
-> Redistribute Motion 1:3 (slice3; segments: 1) (cost=0.00..2.10 rows=1 width=8)
Hash Key: (t.k::integer)
-> Subquery Scan on t (cost=0.00..2.10 rows=1 width=8)
Filter: t.k = 3
-> Append (cost=0.00..2.07 rows=2 width=0)
-> WindowAgg (cost=0.00..1.02 rows=1 width=0)
-> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..1.01 rows=1 width=0)
-> Seq Scan on window_preds (cost=0.00..1.01 rows=1 width=0)
-> WindowAgg (cost=0.00..1.02 rows=1 width=0)
-> Gather Motion 3:1 (slice2; segments: 3) (cost=0.00..1.01 rows=1 width=0)
-> Seq Scan on window_preds (cost=0.00..1.01 rows=1 width=0)
Optimizer: legacy query optimizer
(13 rows)
insert into window_preds select k from ( select row_number() over()+2 as k from window_preds union all select row_number() over()+2 as k from window_preds) as t where k = 3;
explain SELECT t.k FROM window_preds p1, window_preds p2, (SELECT ROW_NUMBER() OVER() AS k FROM window_preds union all SELECT ROW_NUMBER() OVER() AS k FROM window_preds) AS t WHERE t.k = 1 limit 1;
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------
Limit (cost=0.00..1.27 rows=1 width=8)
-> Nested Loop (cost=0.00..4.21 rows=4 width=8)
-> Nested Loop (cost=0.00..3.13 rows=4 width=8)
-> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..1.03 rows=1 width=0)
-> Seq Scan on window_preds p1 (cost=0.00..1.01 rows=1 width=0)
-> Materialize (cost=0.00..2.09 rows=1 width=8)
-> Subquery Scan on t (cost=0.00..2.09 rows=1 width=8)
Filter: t.k = 1
-> Append (cost=0.00..2.06 rows=2 width=0)
-> WindowAgg (cost=0.00..1.02 rows=1 width=0)
-> Gather Motion 3:1 (slice2; segments: 3) (cost=0.00..1.01 rows=1 width=0)
-> Seq Scan on window_preds (cost=0.00..1.01 rows=1 width=0)
-> WindowAgg (cost=0.00..1.02 rows=1 width=0)
-> Gather Motion 3:1 (slice3; segments: 3) (cost=0.00..1.01 rows=1 width=0)
-> Seq Scan on window_preds (cost=0.00..1.01 rows=1 width=0)
-> Materialize (cost=0.00..1.03 rows=1 width=0)
-> Gather Motion 3:1 (slice4; segments: 3) (cost=0.00..1.03 rows=1 width=0)
-> Seq Scan on window_preds p2 (cost=0.00..1.01 rows=1 width=0)
Optimizer: legacy query optimizer
(19 rows)
SELECT t.k FROM window_preds p1, window_preds p2, (SELECT ROW_NUMBER() OVER() AS k FROM window_preds union all SELECT ROW_NUMBER() OVER() AS k FROM window_preds) AS t WHERE t.k = 1 limit 1;
k
---
1
(1 row)
explain with CTE as (select i, row_number() over (partition by j) j from window_preds union all select i, row_number() over (partition by j) from window_preds) select * from cte where j = 1;
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------
Gather Motion 3:1 (slice3; segments: 3) (cost=0.00..0.04 rows=1 width=12)
-> Subquery Scan on cte (cost=0.00..0.04 rows=1 width=12)
Filter: cte.j = 1
-> Append (cost=1.04..2.14 rows=1 width=8)
-> Subquery Scan on "*SELECT* 1" (cost=1.04..1.07 rows=1 width=8)
-> WindowAgg (cost=1.04..1.06 rows=1 width=8)
Partition By: row_number() OVER (?)
-> Sort (cost=1.04..1.04 rows=1 width=8)
Sort Key: olap_window_seq.window_preds.j
-> Redistribute Motion 3:3 (slice1; segments: 3) (cost=0.00..1.03 rows=1 width=8)
Hash Key: olap_window_seq.window_preds.j
-> Seq Scan on window_preds (cost=0.00..1.01 rows=1 width=8)
-> Subquery Scan on "*SELECT* 2" (cost=1.04..1.07 rows=1 width=8)
-> WindowAgg (cost=1.04..1.06 rows=1 width=8)
Partition By: row_number() OVER (?)
-> Sort (cost=1.04..1.04 rows=1 width=8)
Sort Key: olap_window_seq.window_preds.j
-> Redistribute Motion 3:3 (slice2; segments: 3) (cost=0.00..1.03 rows=1 width=8)
Hash Key: olap_window_seq.window_preds.j
-> Seq Scan on window_preds (cost=0.00..1.01 rows=1 width=8)
Optimizer: legacy query optimizer
(21 rows)
insert into window_preds with CTE as (select i, row_number() over (partition by j) j from window_preds union all select i, row_number() over (partition by j) from window_preds) select * from cte where j = 1;
-- qual k = 1 should be pushed down
explain select k from ( select k from (select row_number() over() as k from window_preds) f union all select 1::bigint as k from window_preds) as t where k = 1;
QUERY PLAN
----------------------------------------------------------------------------------------------------------
Gather Motion 3:1 (slice3; segments: 3) (cost=0.00..2.06 rows=2 width=4)
-> Append (cost=0.00..2.06 rows=1 width=4)
-> Redistribute Motion 1:3 (slice2; segments: 1) (cost=0.00..1.04 rows=1 width=8)
Hash Key: f.k
-> Subquery Scan on f (cost=0.00..1.03 rows=1 width=8)
Filter: f.k = 1
-> WindowAgg (cost=0.00..1.02 rows=1 width=0)
-> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..1.01 rows=1 width=0)
-> Seq Scan on window_preds (cost=0.00..1.01 rows=1 width=0)
-> Seq Scan on window_preds (cost=0.00..1.01 rows=1 width=0)
Optimizer: legacy query optimizer
(11 rows)
select k from ( select k from (select row_number() over() as k from window_preds) f union all select 1::bigint as k from window_preds) as t where k = 1;
k
---
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
(23 rows)
explain insert into window_preds select k from ( select k from (select row_number() over() as k from window_preds) f union all select 1::bigint as k from window_preds) as t where k = 1;
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------
Insert (cost=0.00..2.09 rows=1 width=8)
-> Redistribute Motion 3:3 (slice3; segments: 3) (cost=0.00..2.09 rows=1 width=8)
Hash Key: (t.k::integer)
-> Subquery Scan on t (cost=0.00..2.09 rows=1 width=8)
-> Append (cost=0.00..2.06 rows=1 width=4)
-> Redistribute Motion 1:3 (slice2; segments: 1) (cost=0.00..1.04 rows=1 width=8)
Hash Key: f.k
-> Subquery Scan on f (cost=0.00..1.03 rows=1 width=8)
Filter: f.k = 1
-> WindowAgg (cost=0.00..1.02 rows=1 width=0)
-> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..1.01 rows=1 width=0)
-> Seq Scan on window_preds (cost=0.00..1.01 rows=1 width=0)
-> Seq Scan on window_preds (cost=0.00..1.01 rows=1 width=0)
Optimizer: legacy query optimizer
(14 rows)
insert into window_preds select k from ( select k from (select row_number() over() as k from window_preds) f union all select 1::bigint as k from window_preds) as t where k = 1;
explain with CTE as (select i, row_number() over (partition by j) j from window_preds union all select i, row_number() over (partition by j) from window_preds) select * from cte where i = 1;
QUERY PLAN
------------------------------------------------------------------------------------------
Gather Motion 1:1 (slice1; segments: 1) (cost=1.02..2.10 rows=2 width=8)
-> Append (cost=1.02..2.10 rows=1 width=8)
-> Subquery Scan on "*SELECT* 1" (cost=1.02..1.05 rows=1 width=8)
-> WindowAgg (cost=1.02..1.04 rows=1 width=8)
Partition By: row_number() OVER (?)
-> Sort (cost=1.02..1.03 rows=1 width=8)
Sort Key: olap_window_seq.window_preds.j
-> Seq Scan on window_preds (cost=0.00..1.01 rows=1 width=8)
Filter: i = 1
-> Subquery Scan on "*SELECT* 2" (cost=1.02..1.05 rows=1 width=8)
-> WindowAgg (cost=1.02..1.04 rows=1 width=8)
Partition By: row_number() OVER (?)
-> Sort (cost=1.02..1.03 rows=1 width=8)
Sort Key: olap_window_seq.window_preds.j
-> Seq Scan on window_preds (cost=0.00..1.01 rows=1 width=8)
Filter: i = 1
Optimizer: legacy query optimizer
(17 rows)
insert into window_preds with CTE as (select i, row_number() over (partition by j) j from window_preds union all select i, row_number() over (partition by j) from window_preds) select * from cte where i = 1;
-- End of Test
......@@ -8222,3 +8222,224 @@ FROM foo;
(31 rows)
drop table foo;
-- test predicate push down in subqueries for quals containing windowref nodes
-- start_ignore
drop table if exists window_preds;
NOTICE: table "window_preds" does not exist, skipping
create table window_preds(i int, j int, k int);
NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'i' as the Greenplum Database data distribution key for this table.
HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew.
insert into window_preds values(1,2,3);
insert into window_preds values(2,3,4);
insert into window_preds values(3,4,5);
insert into window_preds values(4,5,6);
insert into window_preds values(5,6,7);
insert into window_preds values(6,7,8);
-- end_ignore
-- for planner qual k = 1 should not be pushed down in the subquery as it has window refs at top level of subquery. orca is able to push down the predicate to appropriate node
explain select k from ( select row_number() over()+2 as k from window_preds union all select row_number() over()+2 as k from window_preds) as t where k = 3;
QUERY PLAN
------------------------------------------------------------------------------------------------------
Append (cost=0.00..862.00 rows=1 width=8)
-> Result (cost=0.00..431.00 rows=1 width=8)
Filter: ((row_number() OVER (?)) + 2) = 3
-> Result (cost=0.00..431.00 rows=1 width=8)
-> WindowAgg (cost=0.00..431.00 rows=1 width=8)
-> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=1)
-> Table Scan on window_preds (cost=0.00..431.00 rows=1 width=1)
-> Result (cost=0.00..431.00 rows=1 width=8)
Filter: ((row_number() OVER (?)) + 2) = 3
-> Result (cost=0.00..431.00 rows=1 width=8)
-> WindowAgg (cost=0.00..431.00 rows=1 width=8)
-> Gather Motion 3:1 (slice2; segments: 3) (cost=0.00..431.00 rows=1 width=1)
-> Table Scan on window_preds (cost=0.00..431.00 rows=1 width=1)
Optimizer: PQO version 2.55.20
(14 rows)
select k from ( select row_number() over()+2 as k from window_preds union all select row_number() over()+2 as k from window_preds) as t where k = 3;
k
---
3
3
(2 rows)
explain insert into window_preds select k from ( select row_number() over()+2 as k from window_preds union all select row_number() over()+2 as k from window_preds) as t where k = 3;
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------
Insert (cost=0.00..862.04 rows=1 width=4)
-> Redistribute Motion 1:3 (slice3) (cost=0.00..862.00 rows=2 width=16)
Hash Key: (int4(((row_number() OVER (?)) + 2)))
-> Result (cost=0.00..862.00 rows=1 width=16)
-> Append (cost=0.00..862.00 rows=1 width=8)
-> Result (cost=0.00..431.00 rows=1 width=8)
Filter: ((row_number() OVER (?)) + 2) = 3
-> Result (cost=0.00..431.00 rows=1 width=8)
-> WindowAgg (cost=0.00..431.00 rows=1 width=8)
-> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=1)
-> Table Scan on window_preds (cost=0.00..431.00 rows=1 width=1)
-> Result (cost=0.00..431.00 rows=1 width=8)
Filter: ((row_number() OVER (?)) + 2) = 3
-> Result (cost=0.00..431.00 rows=1 width=8)
-> WindowAgg (cost=0.00..431.00 rows=1 width=8)
-> Gather Motion 3:1 (slice2; segments: 3) (cost=0.00..431.00 rows=1 width=1)
-> Table Scan on window_preds (cost=0.00..431.00 rows=1 width=1)
Optimizer: PQO version 2.55.20
(18 rows)
insert into window_preds select k from ( select row_number() over()+2 as k from window_preds union all select row_number() over()+2 as k from window_preds) as t where k = 3;
explain SELECT t.k FROM window_preds p1, window_preds p2, (SELECT ROW_NUMBER() OVER() AS k FROM window_preds union all SELECT ROW_NUMBER() OVER() AS k FROM window_preds) AS t WHERE t.k = 1 limit 1;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------
Limit (cost=0.00..1357132839.11 rows=1 width=8)
-> Nested Loop (cost=0.00..1357132839.11 rows=1 width=8)
Join Filter: true
-> Append (cost=0.00..862.00 rows=1 width=8)
-> Result (cost=0.00..431.00 rows=1 width=8)
Filter: (row_number() OVER (?)) = 1
-> WindowAgg (cost=0.00..431.00 rows=1 width=8)
-> Gather Motion 3:1 (slice3; segments: 3) (cost=0.00..431.00 rows=1 width=1)
-> Table Scan on window_preds (cost=0.00..431.00 rows=1 width=1)
-> Result (cost=0.00..431.00 rows=1 width=8)
Filter: (row_number() OVER (?)) = 1
-> WindowAgg (cost=0.00..431.00 rows=1 width=8)
-> Gather Motion 3:1 (slice4; segments: 3) (cost=0.00..431.00 rows=1 width=1)
-> Table Scan on window_preds (cost=0.00..431.00 rows=1 width=1)
-> Materialize (cost=0.00..1324032.04 rows=1 width=1)
-> Gather Motion 3:1 (slice2; segments: 3) (cost=0.00..1324032.04 rows=1 width=1)
-> Nested Loop (cost=0.00..1324032.04 rows=1 width=1)
Join Filter: true
-> Broadcast Motion 3:3 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=1)
-> Table Scan on window_preds (cost=0.00..431.00 rows=1 width=1)
-> Table Scan on window_preds (cost=0.00..431.00 rows=1 width=1)
Optimizer: PQO version 2.55.20
(22 rows)
SELECT t.k FROM window_preds p1, window_preds p2, (SELECT ROW_NUMBER() OVER() AS k FROM window_preds union all SELECT ROW_NUMBER() OVER() AS k FROM window_preds) AS t WHERE t.k = 1 limit 1;
k
---
1
(1 row)
explain with CTE as (select i, row_number() over (partition by j) j from window_preds union all select i, row_number() over (partition by j) from window_preds) select * from cte where j = 1;
QUERY PLAN
------------------------------------------------------------------------------------------------------------------
Gather Motion 3:1 (slice3; segments: 3) (cost=0.00..862.00 rows=1 width=12)
-> Append (cost=0.00..862.00 rows=1 width=12)
-> Result (cost=0.00..431.00 rows=1 width=12)
Filter: (row_number() OVER (?)) = 1
-> WindowAgg (cost=0.00..431.00 rows=1 width=12)
Partition By: olap_window_seq.window_preds.i
-> Sort (cost=0.00..431.00 rows=1 width=8)
Sort Key: olap_window_seq.window_preds.j
-> Redistribute Motion 3:3 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=8)
Hash Key: olap_window_seq.window_preds.j
-> Table Scan on window_preds (cost=0.00..431.00 rows=1 width=8)
-> Result (cost=0.00..431.00 rows=1 width=12)
Filter: (row_number() OVER (?)) = 1
-> WindowAgg (cost=0.00..431.00 rows=1 width=12)
Partition By: olap_window_seq.window_preds.i
-> Sort (cost=0.00..431.00 rows=1 width=8)
Sort Key: olap_window_seq.window_preds.j
-> Redistribute Motion 3:3 (slice2; segments: 3) (cost=0.00..431.00 rows=1 width=8)
Hash Key: olap_window_seq.window_preds.j
-> Table Scan on window_preds (cost=0.00..431.00 rows=1 width=8)
Optimizer: PQO version 2.55.20
(21 rows)
insert into window_preds with CTE as (select i, row_number() over (partition by j) j from window_preds union all select i, row_number() over (partition by j) from window_preds) select * from cte where j = 1;
-- qual k = 1 should be pushed down
explain select k from ( select k from (select row_number() over() as k from window_preds) f union all select 1::bigint as k from window_preds) as t where k = 1;
QUERY PLAN
------------------------------------------------------------------------------------------------
Append (cost=0.00..862.00 rows=1 width=8)
-> Result (cost=0.00..431.00 rows=1 width=8)
Filter: (row_number() OVER (?)) = 1
-> WindowAgg (cost=0.00..431.00 rows=1 width=8)
-> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=1)
-> Table Scan on window_preds (cost=0.00..431.00 rows=1 width=1)
-> Gather Motion 3:1 (slice2; segments: 3) (cost=0.00..431.00 rows=1 width=8)
-> Result (cost=0.00..431.00 rows=1 width=8)
Filter: "outer".k = 1
-> Result (cost=0.00..431.00 rows=1 width=8)
-> Table Scan on window_preds (cost=0.00..431.00 rows=1 width=1)
Optimizer: PQO version 2.55.20
(12 rows)
select k from ( select k from (select row_number() over() as k from window_preds) f union all select 1::bigint as k from window_preds) as t where k = 1;
k
---
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
(23 rows)
explain insert into window_preds select k from ( select k from (select row_number() over() as k from window_preds) f union all select 1::bigint as k from window_preds) as t where k = 1;
QUERY PLAN
------------------------------------------------------------------------------------------------------------------
Insert (cost=0.00..862.04 rows=1 width=4)
-> Redistribute Motion 1:3 (slice3) (cost=0.00..862.00 rows=2 width=16)
Hash Key: (int4((row_number() OVER (?))))
-> Result (cost=0.00..862.00 rows=1 width=16)
-> Append (cost=0.00..862.00 rows=1 width=8)
-> Result (cost=0.00..431.00 rows=1 width=8)
Filter: (row_number() OVER (?)) = 1
-> WindowAgg (cost=0.00..431.00 rows=1 width=8)
-> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=1)
-> Table Scan on window_preds (cost=0.00..431.00 rows=1 width=1)
-> Gather Motion 3:1 (slice2; segments: 3) (cost=0.00..431.00 rows=1 width=8)
-> Result (cost=0.00..431.00 rows=1 width=8)
Filter: "outer".k = 1
-> Result (cost=0.00..431.00 rows=1 width=8)
-> Table Scan on window_preds (cost=0.00..431.00 rows=1 width=1)
Optimizer: PQO version 2.55.20
(16 rows)
insert into window_preds select k from ( select k from (select row_number() over() as k from window_preds) f union all select 1::bigint as k from window_preds) as t where k = 1;
explain with CTE as (select i, row_number() over (partition by j) j from window_preds union all select i, row_number() over (partition by j) from window_preds) select * from cte where i = 1;
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------
Gather Motion 3:1 (slice3; segments: 3) (cost=0.00..862.00 rows=2 width=12)
-> Result (cost=0.00..862.00 rows=1 width=12)
Filter: olap_window_seq.window_preds.i = 1
-> Append (cost=0.00..862.00 rows=1 width=12)
-> Result (cost=0.00..431.00 rows=1 width=12)
-> WindowAgg (cost=0.00..431.00 rows=1 width=12)
Partition By: row_number() OVER (?)
-> Sort (cost=0.00..431.00 rows=1 width=8)
Sort Key: olap_window_seq.window_preds.j
-> Redistribute Motion 3:3 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=8)
Hash Key: olap_window_seq.window_preds.j
-> Table Scan on window_preds (cost=0.00..431.00 rows=1 width=8)
-> Result (cost=0.00..431.00 rows=1 width=12)
-> WindowAgg (cost=0.00..431.00 rows=1 width=12)
Partition By: row_number() OVER (?)
-> Sort (cost=0.00..431.00 rows=1 width=8)
Sort Key: olap_window_seq.window_preds.j
-> Redistribute Motion 3:3 (slice2; segments: 3) (cost=0.00..431.00 rows=1 width=8)
Hash Key: olap_window_seq.window_preds.j
-> Table Scan on window_preds (cost=0.00..431.00 rows=1 width=8)
Optimizer: PQO version 2.55.20
(21 rows)
insert into window_preds with CTE as (select i, row_number() over (partition by j) j from window_preds union all select i, row_number() over (partition by j) from window_preds) select * from cte where i = 1;
-- End of Test
......@@ -1660,3 +1660,36 @@ EXPLAIN SELECT count(*) over (PARTITION BY a ORDER BY b, c, d) as count1,
count(*) over (PARTITION BY a ORDER BY c, b, d) as count3
FROM foo;
drop table foo;
-- test predicate push down in subqueries for quals containing windowref nodes
-- start_ignore
drop table if exists window_preds;
create table window_preds(i int, j int, k int);
insert into window_preds values(1,2,3);
insert into window_preds values(2,3,4);
insert into window_preds values(3,4,5);
insert into window_preds values(4,5,6);
insert into window_preds values(5,6,7);
insert into window_preds values(6,7,8);
-- end_ignore
-- for planner qual k = 1 should not be pushed down in the subquery as it has window refs at top level of subquery. orca is able to push down the predicate to appropriate node
explain select k from ( select row_number() over()+2 as k from window_preds union all select row_number() over()+2 as k from window_preds) as t where k = 3;
select k from ( select row_number() over()+2 as k from window_preds union all select row_number() over()+2 as k from window_preds) as t where k = 3;
explain insert into window_preds select k from ( select row_number() over()+2 as k from window_preds union all select row_number() over()+2 as k from window_preds) as t where k = 3;
insert into window_preds select k from ( select row_number() over()+2 as k from window_preds union all select row_number() over()+2 as k from window_preds) as t where k = 3;
explain SELECT t.k FROM window_preds p1, window_preds p2, (SELECT ROW_NUMBER() OVER() AS k FROM window_preds union all SELECT ROW_NUMBER() OVER() AS k FROM window_preds) AS t WHERE t.k = 1 limit 1;
SELECT t.k FROM window_preds p1, window_preds p2, (SELECT ROW_NUMBER() OVER() AS k FROM window_preds union all SELECT ROW_NUMBER() OVER() AS k FROM window_preds) AS t WHERE t.k = 1 limit 1;
explain with CTE as (select i, row_number() over (partition by j) j from window_preds union all select i, row_number() over (partition by j) from window_preds) select * from cte where j = 1;
insert into window_preds with CTE as (select i, row_number() over (partition by j) j from window_preds union all select i, row_number() over (partition by j) from window_preds) select * from cte where j = 1;
-- qual k = 1 should be pushed down
explain select k from ( select k from (select row_number() over() as k from window_preds) f union all select 1::bigint as k from window_preds) as t where k = 1;
select k from ( select k from (select row_number() over() as k from window_preds) f union all select 1::bigint as k from window_preds) as t where k = 1;
explain insert into window_preds select k from ( select k from (select row_number() over() as k from window_preds) f union all select 1::bigint as k from window_preds) as t where k = 1;
insert into window_preds select k from ( select k from (select row_number() over() as k from window_preds) f union all select 1::bigint as k from window_preds) as t where k = 1;
explain with CTE as (select i, row_number() over (partition by j) j from window_preds union all select i, row_number() over (partition by j) from window_preds) select * from cte where i = 1;
insert into window_preds with CTE as (select i, row_number() over (partition by j) j from window_preds union all select i, row_number() over (partition by j) from window_preds) select * from cte where i = 1;
-- End of Test
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册