blob: 149edfe92af7ed43149cc64a894e2eae865dbe41 [file] [log] [blame]
drop table if exists with_test1 cascade;
create table with_test1 (i int, t text, value int) distributed by (i);
insert into with_test1 select i%10, 'text' || i%20, i%30 from generate_series(0, 99) i;
analyze with_test1;
drop table if exists with_test2 cascade;
create table with_test2 (i int, t text, value int);
insert into with_test2 select i%100, 'text' || i%200, i%300 from generate_series(0, 999) i;
analyze with_test2;
-- With clause with one common table expression
--begin_equivalent
with my_sum(total) as (select sum(value) from with_test1)
select *
from my_sum;
select sum(value) as total from with_test1;
--end_equivalent
-- With clause with two common table expression
--begin_equivalent
with my_sum(total) as (select sum(value) from with_test1),
my_count(cnt) as (select count(*) from with_test1)
select cnt, total
from my_sum, my_count;
select cnt, total
from (select sum(value) as total from with_test1) tmp1,
(select count(*) as cnt from with_test1) tmp2;
--end_equivalent
-- With clause with one common table expression that is referenced twice
--begin_equivalent
with my_group_sum(i, total) as (select i, sum(value) from with_test1 group by i)
select gs1.i, gs1.total, gs2.total
from my_group_sum gs1, my_group_sum gs2
where gs1.i = gs2.i + 1;
select gs1.i, gs1.total, gs2.total
from (select i, sum(value) as total from with_test1 group by i) gs1,
(select i, sum(value) as total from with_test1 group by i) gs2
where gs1.i = gs2.i + 1;
--end_equivalent
-- With clause with one common table expression that contains the other common table expression
--begin_equivalent
with my_count(i, cnt) as (select i, count(*) from with_test1 group by i),
my_sum(total) as (select sum(cnt) from my_count)
select *
from my_sum;
select sum(cnt) as total from (select i, count(*) as cnt from with_test1 group by i) my_count;
--end_equivalent
-- WITH query contains WITH
--begin_equivalent
with my_sum(total) as (
with my_group_sum(total) as (select sum(value) from with_test1 group by i)
select sum(total) from my_group_sum)
select *
from my_sum;
select sum(total) from (select sum(value) as total from with_test1 group by i) my_group_sum;
--end_equivalent
-- pathkeys
explain (costs off)
with my_order as (select * from with_test1 order by i)
select i, count(*)
from my_order
group by i order by i;
with my_order as (select * from with_test1 order by i)
select i, count(*)
from my_order
group by i order by i;
-- WITH query used in InitPlan
--begin_equivalent
with my_max(maximum) as (select max(value) from with_test1)
select * from with_test2
where value < (select * from my_max);
select * from with_test2
where value < (with my_max(maximum) as (select max(value) from with_test1)
select * from my_max);
select * from with_test2
where value < (select max(value) from with_test1);
--end_equivalent
-- WITH query used in InitPlan and the main query at the same time
--begin_equivalent
with my_max(maximum) as (select max(value) from with_test1)
select with_test2.* from with_test2, my_max
where value < (select * from my_max)
and i < maximum and i > maximum - 10;
select with_test2.* from with_test2, (select max(value) as maximum from with_test1) as my_max
where value < (select max(value) from with_test1)
and i < maximum and i > maximum - 10;
--end_equivalent
-- WITH query used in subplan
--begin_equivalent
with my_groupmax(i, maximum) as (select i, max(value) from with_test1 group by i)
select * from with_test2
where value < all (select maximum from my_groupmax);
select * from with_test2
where value < all (select max(value) from with_test1 group by i);
--end_equivalent
-- WITH query used in subplan and the main query at the same time
--begin_equivalent
with my_groupmax(i, maximum) as (select i, max(value) from with_test1 group by i)
select * from with_test2, my_groupmax
where with_test2.i = my_groupmax.i
and value < all (select maximum from my_groupmax);
select * from with_test2, (select i, max(value) as maximum from with_test1 group by i) as my_groupmax
where with_test2.i = my_groupmax.i
and value < all (select max(value) from with_test1 group by i);
--end_equivalent
--begin_equivalent
with my_groupmax(i, maximum) as (select i, max(value) from with_test1 group by i)
SELECT count(*) FROM my_groupmax WHERE maximum > (SELECT sum(maximum)/100 FROM my_groupmax);
select count(*) from (select i, max(value) as maximum from with_test1 group by i) as my_groupmax
where maximum > (SELECT sum(maximum)/100 FROM (select i, max(value) as maximum from with_test1 group by i) as tmp);
--end_equivalent
-- name resolution
--begin_equivalent
with my_max(maximum) as (select max(value) from with_test2)
select * from with_test1, my_max
where value < (with my_max(maximum) as (select max(i) from with_test1)
select * from my_max);
select * from with_test1, (select max(value) as maximum from with_test2) as my_max
where value < (select max(i) from with_test1);
--end_equivalent
-- INSERT
insert into with_test2
with my_sum(i, total) as (select i, sum(value) from with_test1 group by i)
select i, i || '', total
from my_sum;
-- CREATE TABLE AS
drop table if exists with_test3;
create table with_test3 as
with my_sum(i, total) as (select i, sum(value) from with_test1 group by i)
select *
from my_sum;
-- view
drop view if exists my_view;
create view my_view (total) as
with my_sum(total) as (select sum(value) from with_test1)
select *
from my_sum;
SELECT pg_get_viewdef('my_view'::regclass);
SELECT pg_get_viewdef('my_view'::regclass, true);
drop view if exists my_view;
create view my_view(total) as
with my_sum(total) as (
with my_group_sum(total) as (select sum(value) from with_test1 group by i)
select sum(total) from my_group_sum)
select *
from my_sum;
SELECT pg_get_viewdef('my_view'::regclass);
SELECT pg_get_viewdef('my_view'::regclass, true);
drop view if exists my_view;
create view my_view(i, total) as (
select i, sum(value) from with_test1 group by i);
with my_sum(total) as (select sum(total) from my_view)
select * from my_sum;
-- WITH query not used in the main query
--begin_equivalent
with my_sum(total) as (select sum(value) from with_test1)
select count(*) from with_test2;
select count(*) from with_test2;
--end_equivalent
-- WITH used in CURSOR query
begin;
declare c cursor for with my_sum(total) as (select sum(value) from with_test1 group by i) select * from my_sum order by 1;
fetch 10 from c;
close c;
end;
-- Returning
create temporary table y (i int);
insert into y
with t as (select i from with_test1)
select i+20 from t returning *;
select * from y;
drop table y;
-- WITH used in SETOP
with my_sum(total) as (select sum(value) from with_test1)
select * from my_sum
union all
select * from my_sum;
-- ERROR cases
-- duplicate CTE name
with my_sum(total) as (select sum(value) from with_test1),
my_sum(group_total) as (select sum(value) from with_test1 group by i)
select *
from my_sum;
-- INTO clause
with my_sum(total) as (select sum(value) from with_test1 into total_value)
select *
from my_sum;
-- name resolution
select * from with_test1, my_max
where value < (with my_max(maximum) as (select max(i) from with_test1)
select * from my_max);
with my_sum(total) as (select sum(total) from my_group_sum),
my_group_sum(i, total) as (select i, sum(total) from with_test1 group by i)
select *
from my_sum;
-- two WITH clauses
with my_sum(total) as (select sum(total) from with_test1),
with my_group_sum(i, total) as (select i, sum(total) from with_test1 group by i)
select *
from my_sum;
-- Test behavior with an unknown-type literal in the WITH
-- Remove undocumented IS [NOT] OF syntax
-- WITH q AS (SELECT 'foo' AS x)
-- SELECT x, x IS OF (unknown) as is_unknown, x IS OF (text) as is_text FROM q;
with cte(foo) as ( select 42 ) select * from ((select foo from cte)) q;
select ( with cte(foo) as ( values(i) )
select (select foo from cte) )
from with_test1
order by 1 limit 10;
select ( with cte(foo) as ( values(i) )
values((select foo from cte)) )
from with_test1
order by 1 limit 10;
-- WITH query using Window functions
--begin_equivalent
with my_rank as (select i, t, value, rank() over (order by value) from with_test1)
select my_rank.* from with_test2, my_rank
where with_test2.i = my_rank.i
order by my_rank.i, my_rank.t, my_rank.value limit 100; -- order 1,2,3
select my_rank.* from with_test2, (select i, t, value, rank() over (order by value) from with_test1) as my_rank
where with_test2.i = my_rank.i
order by my_rank.i, my_rank.t, my_rank.value limit 100; -- order 1,2,3
--end_equivalent
-- WITH query and CSQ
--begin_equivalent
with my_group_sum(i, total) as (select i, sum(value) from with_test1 group by i)
select with_test2.* from with_test2
where value < any (select total from my_group_sum where my_group_sum.i = with_test2.i);
select with_test2.* from with_test2
where value < any (select total from (select i, sum(value) as total from with_test1 group by i) as tmp where tmp.i = with_test2.i);
--end_equivalent
--begin_equivalent
with my_group_sum(i, total) as (select i, sum(value) from with_test1 group by i)
select with_test2.* from with_test2, my_group_sum
where value < any (select total from my_group_sum where my_group_sum.i = with_test2.i)
and with_test2.i = my_group_sum.i;
select with_test2.* from with_test2, (select i, sum(value) from with_test1 group by i) as my_group_sum
where value < any (select total from (select i, sum(value) as total from with_test1 group by i) as tmp where tmp.i = with_test2.i)
and with_test2.i = my_group_sum.i;
--end_equivalent
--begin_equivalent
with my_group_sum(i, total) as (select i, sum(value) from with_test1 group by i)
select with_test2.* from with_test2
where value < all (select total from my_group_sum where my_group_sum.i = with_test2.i)
order by 1,2,3
limit 60; --order 1,2,3
select with_test2.* from with_test2
where value < all (select total from (select i, sum(value) as total from with_test1 group by i) as tmp where tmp.i = with_test2.i)
order by 1,2,3
limit 60; --order 1,2,3
--end_equivalent
drop table if exists d;
drop table if exists b;
create table with_b (i integer) distributed by (i);
insert into with_b values (1), (2);
--begin_equivalent
with b1 as (select * from with_b) select * from (select * from b1 where b1.i =1) AS FOO, b1 FOO2;
select * from (select * from (select * from with_b) as b1 where b1.i = 1) AS FOO, (select * from with_b) as foo2;
--end_equivalent
-- qual push down test
explain (costs off) with t as (select * from with_test1) select * from t where i = 10;
-- Test to validate an old bug which caused incorrect results when a subquery
-- in the WITH clause appears under a nested-loop join in the query plan when
-- gp_cte_sharing was set to off. (MPP-17848)
CREATE TABLE x (a integer) DISTRIBUTED BY (a);
insert into x values(1), (2);
CREATE TABLE y (m integer NOT NULL, n smallint) DISTRIBUTED BY (m);
insert into y values(10, 1);
insert into y values(20, 1);
with yy as (
select m
from y,
(select 1 as p) iv
where n = iv.p
)
select * from x, yy;
-- Check that WITH query is run to completion even if outer query isn't.
-- This is a test which exists in the upstream 'with' test suite in a section
-- which is currently under an ignore block. It has been copied here to avoid
-- merge conflicts since enabling it in the upstream test suite would require
-- altering the test output (as it depends on earlier tests which are failing
-- in GPDB currently).
DELETE FROM y;
INSERT INTO y SELECT generate_series(1,15) m;
WITH t AS (
UPDATE y SET m = m * 100 RETURNING *
)
SELECT m BETWEEN 100 AND 1500 FROM t LIMIT 1;
SELECT * FROM y;
-- Nested RECURSIVE queries with double self-referential joins are planned by
-- joining two WorkTableScans, which GPDB cannot do yet. Ensure that we error
-- out with a descriptive message.
WITH RECURSIVE r1 AS (
SELECT 1 AS a
UNION ALL
(
WITH RECURSIVE r2 AS (
SELECT 2 AS b
UNION ALL
SELECT b FROM r1, r2
)
SELECT b FROM r2
)
)
SELECT * FROM r1 LIMIT 1;
-- GPDB
-- Greenplum does not support window functions in recursive part's target list
-- See issue https://github.com/greenplum-db/gpdb/issues/13299 for details.
-- Previously the following SQL will PANIC or Assert Fail if compiled with assert.
create table t_window_ordered_set_agg_rte(a bigint, b bigint, c bigint);
insert into t_window_ordered_set_agg_rte select i,i,i from generate_series(1, 10)i;
-- should error out during parse-analyze
with recursive rcte(x,y) as
(
select a, b from t_window_ordered_set_agg_rte
union all
select (first_value(c) over (partition by b))::int, a+x
from rcte,
t_window_ordered_set_agg_rte as t
where t.b = x
)
select * from rcte limit 10;
-- should error out during parse-analyze
with recursive rcte(x,y) as
(
select a, b from t_window_ordered_set_agg_rte
union all
select first_value(c) over (partition by b), a+x
from rcte,
t_window_ordered_set_agg_rte as t
where t.b = x
)
select * from rcte limit 10;
-- This used to deadlock, before the IPC between ShareInputScans across
-- slices was rewritten.
set gp_cte_sharing=on;
CREATE TEMP TABLE foo (i int, j int);
INSERT INTO foo SELECT g, g FROM generate_series(1, 2) g;
ANALYZE foo;
WITH a1 as (select * from foo),
a2 as (select * from foo)
SELECT a1.i
FROM a1
INNER JOIN a2 ON a2.i = a1.i
UNION ALL
SELECT count(a1.i)
FROM a1
INNER JOIN a2 ON a2.i = a1.i;
explain (costs off)
WITH a1 as (select * from foo),
a2 as (select * from foo)
SELECT a1.i
FROM a1
INNER JOIN a2 ON a2.i = a1.i
UNION ALL
SELECT count(a1.i)
FROM a1
INNER JOIN a2 ON a2.i = a1.i;
-- Another cross-slice ShareInputScan test. There is one producing slice,
-- and two consumers in second slice. Make sure the Share Input Scan
-- consumer slice doesn't prematurely notify the producer that it's done,
-- when one of the Scans in the consumer slice finishes, but there are still
-- Scans left in the same slice.
explain (costs off)
WITH cte AS (SELECT * FROM foo)
-- This branch runs on different slice. It is the producer slice.
(SELECT DISTINCT 'a' as branch, j FROM cte)
UNION ALL
-- This branch runs in the consumer slice. It contains a join. A join
-- causes the input to be squelched when it reaches the end.
(SELECT 'b', x.i FROM cte x, cte y WHERE x.i = y.i)
UNION ALL
-- Sleep a bit between executing the previous slice and the next slice,
-- so that if the squelch from the join incorrectly sent a "done" message
-- to the producer slice, the producer has a chance to finish and remove
-- the tuplestore, before the next branch tries to open the shared
-- tuplestore again.
SELECT 'sleep', 1 where pg_sleep(1) is not null
UNION ALL
-- Consumer, runs in same slice as the join above.
SELECT 'c', j FROM cte;
WITH cte AS (SELECT * FROM foo)
(SELECT DISTINCT 'a' as branch, j FROM cte)
UNION ALL
(SELECT 'b', x.i FROM cte x, cte y WHERE x.i = y.i)
UNION ALL
SELECT 'sleep', 1 where pg_sleep(1) is not null
UNION ALL
SELECT 'c', j FROM cte;
-- Test issue from PR#1204
-- Executor used to fail to execute this query
CREATE TABLE foo_issue_1204_test (a INT, b INT, c INT, d INT, e INT, f INT);
INSERT INTO foo_issue_1204_test SELECT generate_series(1,10000);
ANALYZE foo_issue_1204_test;
-- Assert than plan uses Merge Append strategy, and has Share Input Scan node.
-- Also we are not actaully interested in output so discard it using SELECT EXISTS() hack
EXPLAIN (COSTS OFF, TIMING OFF, BUFFERS OFF)
SELECT EXISTS(
with inp as MATERIALIZED (select * from foo_issue_1204_test ) select a,b,c, count(distinct d), count(distinct e), count(distinct f) from inp group by 1,2,3
UNION ALL
select a,b,c, count(distinct d), count(distinct e), count(distinct f) from foo_issue_1204_test group by 1,2,3
ORDER BY 1
);
-- Check execution is ok
SELECT EXISTS(
with inp as MATERIALIZED (select * from foo_issue_1204_test ) select a,b,c, count(distinct d), count(distinct e), count(distinct f) from inp group by 1,2,3
UNION ALL
select a,b,c, count(distinct d), count(distinct e), count(distinct f) from foo_issue_1204_test group by 1,2,3
ORDER BY 1
);
DROP TABLE foo_issue_1204_test;