|
|
|
@ -445,11 +445,638 @@ SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_n t1 JOIN prt2_n t2 ON (t1.c = t2.c) JOI
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_n t1 FULL JOIN prt1 t2 ON (t1.c = t2.c);
|
|
|
|
|
|
|
|
|
|
-- partitionwise join can not be applied if only one of joining tables has
|
|
|
|
|
-- default partition
|
|
|
|
|
ALTER TABLE prt2 DETACH PARTITION prt2_p3;
|
|
|
|
|
ALTER TABLE prt2 ATTACH PARTITION prt2_p3 FOR VALUES FROM (500) TO (600);
|
|
|
|
|
ANALYZE prt2;
|
|
|
|
|
|
|
|
|
|
--
|
|
|
|
|
-- Test advanced partition-matching algorithm for partitioned join
|
|
|
|
|
--
|
|
|
|
|
|
|
|
|
|
-- Tests for range-partitioned tables
|
|
|
|
|
CREATE TABLE prt1_adv (a int, b int, c varchar) PARTITION BY RANGE (a);
|
|
|
|
|
CREATE TABLE prt1_adv_p1 PARTITION OF prt1_adv FOR VALUES FROM (100) TO (200);
|
|
|
|
|
CREATE TABLE prt1_adv_p2 PARTITION OF prt1_adv FOR VALUES FROM (200) TO (300);
|
|
|
|
|
CREATE TABLE prt1_adv_p3 PARTITION OF prt1_adv FOR VALUES FROM (300) TO (400);
|
|
|
|
|
CREATE INDEX prt1_adv_a_idx ON prt1_adv (a);
|
|
|
|
|
INSERT INTO prt1_adv SELECT i, i % 25, to_char(i, 'FM0000') FROM generate_series(100, 399) i;
|
|
|
|
|
ANALYZE prt1_adv;
|
|
|
|
|
|
|
|
|
|
CREATE TABLE prt2_adv (a int, b int, c varchar) PARTITION BY RANGE (b);
|
|
|
|
|
CREATE TABLE prt2_adv_p1 PARTITION OF prt2_adv FOR VALUES FROM (100) TO (150);
|
|
|
|
|
CREATE TABLE prt2_adv_p2 PARTITION OF prt2_adv FOR VALUES FROM (200) TO (300);
|
|
|
|
|
CREATE TABLE prt2_adv_p3 PARTITION OF prt2_adv FOR VALUES FROM (350) TO (500);
|
|
|
|
|
CREATE INDEX prt2_adv_b_idx ON prt2_adv (b);
|
|
|
|
|
INSERT INTO prt2_adv_p1 SELECT i % 25, i, to_char(i, 'FM0000') FROM generate_series(100, 149) i;
|
|
|
|
|
INSERT INTO prt2_adv_p2 SELECT i % 25, i, to_char(i, 'FM0000') FROM generate_series(200, 299) i;
|
|
|
|
|
INSERT INTO prt2_adv_p3 SELECT i % 25, i, to_char(i, 'FM0000') FROM generate_series(350, 499) i;
|
|
|
|
|
ANALYZE prt2_adv;
|
|
|
|
|
|
|
|
|
|
-- inner join
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 INNER JOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.b = 0 ORDER BY t1.a, t2.b;
|
|
|
|
|
SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 INNER JOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.b = 0 ORDER BY t1.a, t2.b;
|
|
|
|
|
|
|
|
|
|
-- semi join
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.* FROM prt1_adv t1 WHERE EXISTS (SELECT 1 FROM prt2_adv t2 WHERE t1.a = t2.b) AND t1.b = 0 ORDER BY t1.a;
|
|
|
|
|
SELECT t1.* FROM prt1_adv t1 WHERE EXISTS (SELECT 1 FROM prt2_adv t2 WHERE t1.a = t2.b) AND t1.b = 0 ORDER BY t1.a;
|
|
|
|
|
|
|
|
|
|
-- left join
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 LEFT JOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.b = 0 ORDER BY t1.a, t2.b;
|
|
|
|
|
SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 LEFT JOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.b = 0 ORDER BY t1.a, t2.b;
|
|
|
|
|
|
|
|
|
|
-- anti join
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.* FROM prt1_adv t1 WHERE NOT EXISTS (SELECT 1 FROM prt2_adv t2 WHERE t1.a = t2.b) AND t1.b = 0 ORDER BY t1.a;
|
|
|
|
|
SELECT t1.* FROM prt1_adv t1 WHERE NOT EXISTS (SELECT 1 FROM prt2_adv t2 WHERE t1.a = t2.b) AND t1.b = 0 ORDER BY t1.a;
|
|
|
|
|
|
|
|
|
|
-- full join
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT 175 phv, * FROM prt1_adv WHERE prt1_adv.b = 0) t1 FULL JOIN (SELECT 425 phv, * FROM prt2_adv WHERE prt2_adv.a = 0) t2 ON (t1.a = t2.b) WHERE t1.phv = t1.a OR t2.phv = t2.b ORDER BY t1.a, t2.b;
|
|
|
|
|
SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT 175 phv, * FROM prt1_adv WHERE prt1_adv.b = 0) t1 FULL JOIN (SELECT 425 phv, * FROM prt2_adv WHERE prt2_adv.a = 0) t2 ON (t1.a = t2.b) WHERE t1.phv = t1.a OR t2.phv = t2.b ORDER BY t1.a, t2.b;
|
|
|
|
|
|
|
|
|
|
-- Test cases where one side has an extra partition
|
|
|
|
|
CREATE TABLE prt2_adv_extra PARTITION OF prt2_adv FOR VALUES FROM (500) TO (MAXVALUE);
|
|
|
|
|
INSERT INTO prt2_adv SELECT i % 25, i, to_char(i, 'FM0000') FROM generate_series(500, 599) i;
|
|
|
|
|
ANALYZE prt2_adv;
|
|
|
|
|
|
|
|
|
|
-- inner join
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 INNER JOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.b = 0 ORDER BY t1.a, t2.b;
|
|
|
|
|
SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 INNER JOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.b = 0 ORDER BY t1.a, t2.b;
|
|
|
|
|
|
|
|
|
|
-- semi join
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.* FROM prt1_adv t1 WHERE EXISTS (SELECT 1 FROM prt2_adv t2 WHERE t1.a = t2.b) AND t1.b = 0 ORDER BY t1.a;
|
|
|
|
|
SELECT t1.* FROM prt1_adv t1 WHERE EXISTS (SELECT 1 FROM prt2_adv t2 WHERE t1.a = t2.b) AND t1.b = 0 ORDER BY t1.a;
|
|
|
|
|
|
|
|
|
|
-- left join
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 LEFT JOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.b = 0 ORDER BY t1.a, t2.b;
|
|
|
|
|
SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 LEFT JOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.b = 0 ORDER BY t1.a, t2.b;
|
|
|
|
|
|
|
|
|
|
-- left join; currently we can't do partitioned join if there are no matched
|
|
|
|
|
-- partitions on the nullable side
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.b, t1.c, t2.a, t2.c FROM prt2_adv t1 LEFT JOIN prt1_adv t2 ON (t1.b = t2.a) WHERE t1.a = 0 ORDER BY t1.b, t2.a;
|
|
|
|
|
|
|
|
|
|
-- anti join
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.* FROM prt1_adv t1 WHERE NOT EXISTS (SELECT 1 FROM prt2_adv t2 WHERE t1.a = t2.b) AND t1.b = 0 ORDER BY t1.a;
|
|
|
|
|
SELECT t1.* FROM prt1_adv t1 WHERE NOT EXISTS (SELECT 1 FROM prt2_adv t2 WHERE t1.a = t2.b) AND t1.b = 0 ORDER BY t1.a;
|
|
|
|
|
|
|
|
|
|
-- anti join; currently we can't do partitioned join if there are no matched
|
|
|
|
|
-- partitions on the nullable side
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.* FROM prt2_adv t1 WHERE NOT EXISTS (SELECT 1 FROM prt1_adv t2 WHERE t1.b = t2.a) AND t1.a = 0 ORDER BY t1.b;
|
|
|
|
|
|
|
|
|
|
-- full join; currently we can't do partitioned join if there are no matched
|
|
|
|
|
-- partitions on the nullable side
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT 175 phv, * FROM prt1_adv WHERE prt1_adv.b = 0) t1 FULL JOIN (SELECT 425 phv, * FROM prt2_adv WHERE prt2_adv.a = 0) t2 ON (t1.a = t2.b) WHERE t1.phv = t1.a OR t2.phv = t2.b ORDER BY t1.a, t2.b;
|
|
|
|
|
|
|
|
|
|
-- 3-way join where not every pair of relations can do partitioned join
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.b, t1.c, t2.a, t2.c, t3.a, t3.c FROM prt2_adv t1 LEFT JOIN prt1_adv t2 ON (t1.b = t2.a) INNER JOIN prt1_adv t3 ON (t1.b = t3.a) WHERE t1.a = 0 ORDER BY t1.b, t2.a, t3.a;
|
|
|
|
|
SELECT t1.b, t1.c, t2.a, t2.c, t3.a, t3.c FROM prt2_adv t1 LEFT JOIN prt1_adv t2 ON (t1.b = t2.a) INNER JOIN prt1_adv t3 ON (t1.b = t3.a) WHERE t1.a = 0 ORDER BY t1.b, t2.a, t3.a;
|
|
|
|
|
|
|
|
|
|
DROP TABLE prt2_adv_extra;
|
|
|
|
|
|
|
|
|
|
-- Test cases where a partition on one side matches multiple partitions on
|
|
|
|
|
-- the other side; we currently can't do partitioned join in such cases
|
|
|
|
|
ALTER TABLE prt2_adv DETACH PARTITION prt2_adv_p3;
|
|
|
|
|
-- Split prt2_adv_p3 into two partitions so that prt1_adv_p3 matches both
|
|
|
|
|
CREATE TABLE prt2_adv_p3_1 PARTITION OF prt2_adv FOR VALUES FROM (350) TO (375);
|
|
|
|
|
CREATE TABLE prt2_adv_p3_2 PARTITION OF prt2_adv FOR VALUES FROM (375) TO (500);
|
|
|
|
|
INSERT INTO prt2_adv SELECT i % 25, i, to_char(i, 'FM0000') FROM generate_series(350, 499) i;
|
|
|
|
|
ANALYZE prt2_adv;
|
|
|
|
|
|
|
|
|
|
-- inner join
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 INNER JOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.b = 0 ORDER BY t1.a, t2.b;
|
|
|
|
|
|
|
|
|
|
-- semi join
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.* FROM prt1_adv t1 WHERE EXISTS (SELECT 1 FROM prt2_adv t2 WHERE t1.a = t2.b) AND t1.b = 0 ORDER BY t1.a;
|
|
|
|
|
|
|
|
|
|
-- left join
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 LEFT JOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.b = 0 ORDER BY t1.a, t2.b;
|
|
|
|
|
|
|
|
|
|
-- anti join
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.* FROM prt1_adv t1 WHERE NOT EXISTS (SELECT 1 FROM prt2_adv t2 WHERE t1.a = t2.b) AND t1.b = 0 ORDER BY t1.a;
|
|
|
|
|
|
|
|
|
|
-- full join
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT 175 phv, * FROM prt1_adv WHERE prt1_adv.b = 0) t1 FULL JOIN (SELECT 425 phv, * FROM prt2_adv WHERE prt2_adv.a = 0) t2 ON (t1.a = t2.b) WHERE t1.phv = t1.a OR t2.phv = t2.b ORDER BY t1.a, t2.b;
|
|
|
|
|
|
|
|
|
|
DROP TABLE prt2_adv_p3_1;
|
|
|
|
|
DROP TABLE prt2_adv_p3_2;
|
|
|
|
|
ANALYZE prt2_adv;
|
|
|
|
|
|
|
|
|
|
-- Test default partitions
|
|
|
|
|
ALTER TABLE prt1_adv DETACH PARTITION prt1_adv_p1;
|
|
|
|
|
-- Change prt1_adv_p1 to the default partition
|
|
|
|
|
ALTER TABLE prt1_adv ATTACH PARTITION prt1_adv_p1 DEFAULT;
|
|
|
|
|
ALTER TABLE prt1_adv DETACH PARTITION prt1_adv_p3;
|
|
|
|
|
ANALYZE prt1_adv;
|
|
|
|
|
|
|
|
|
|
-- We can do partitioned join even if only one of relations has the default
|
|
|
|
|
-- partition
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 INNER JOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.b = 0 ORDER BY t1.a, t2.b;
|
|
|
|
|
SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 INNER JOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.b = 0 ORDER BY t1.a, t2.b;
|
|
|
|
|
|
|
|
|
|
-- Restore prt1_adv_p3
|
|
|
|
|
ALTER TABLE prt1_adv ATTACH PARTITION prt1_adv_p3 FOR VALUES FROM (300) TO (400);
|
|
|
|
|
ANALYZE prt1_adv;
|
|
|
|
|
|
|
|
|
|
-- Restore prt2_adv_p3
|
|
|
|
|
ALTER TABLE prt2_adv ATTACH PARTITION prt2_adv_p3 FOR VALUES FROM (350) TO (500);
|
|
|
|
|
ANALYZE prt2_adv;
|
|
|
|
|
|
|
|
|
|
-- Partitioned join can't be applied because the default partition of prt1_adv
|
|
|
|
|
-- matches prt2_adv_p1 and prt2_adv_p3
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 INNER JOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.b = 0 ORDER BY t1.a, t2.b;
|
|
|
|
|
|
|
|
|
|
ALTER TABLE prt2_adv DETACH PARTITION prt2_adv_p3;
|
|
|
|
|
-- Change prt2_adv_p3 to the default partition
|
|
|
|
|
ALTER TABLE prt2_adv ATTACH PARTITION prt2_adv_p3 DEFAULT;
|
|
|
|
|
ANALYZE prt2_adv;
|
|
|
|
|
|
|
|
|
|
-- Partitioned join can't be applied because the default partition of prt1_adv
|
|
|
|
|
-- matches prt2_adv_p1 and prt2_adv_p3
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 INNER JOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.b = 0 ORDER BY t1.a, t2.b;
|
|
|
|
|
|
|
|
|
|
DROP TABLE prt1_adv_p3;
|
|
|
|
|
ANALYZE prt1_adv;
|
|
|
|
|
|
|
|
|
|
DROP TABLE prt2_adv_p3;
|
|
|
|
|
ANALYZE prt2_adv;
|
|
|
|
|
|
|
|
|
|
CREATE TABLE prt3_adv (a int, b int, c varchar) PARTITION BY RANGE (a);
|
|
|
|
|
CREATE TABLE prt3_adv_p1 PARTITION OF prt3_adv FOR VALUES FROM (200) TO (300);
|
|
|
|
|
CREATE TABLE prt3_adv_p2 PARTITION OF prt3_adv FOR VALUES FROM (300) TO (400);
|
|
|
|
|
CREATE INDEX prt3_adv_a_idx ON prt3_adv (a);
|
|
|
|
|
INSERT INTO prt3_adv SELECT i, i % 25, to_char(i, 'FM0000') FROM generate_series(200, 399) i;
|
|
|
|
|
ANALYZE prt3_adv;
|
|
|
|
|
|
|
|
|
|
-- 3-way join to test the default partition of a join relation
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.a, t1.c, t2.b, t2.c, t3.a, t3.c FROM prt1_adv t1 LEFT JOIN prt2_adv t2 ON (t1.a = t2.b) LEFT JOIN prt3_adv t3 ON (t1.a = t3.a) WHERE t1.b = 0 ORDER BY t1.a, t2.b, t3.a;
|
|
|
|
|
SELECT t1.a, t1.c, t2.b, t2.c, t3.a, t3.c FROM prt1_adv t1 LEFT JOIN prt2_adv t2 ON (t1.a = t2.b) LEFT JOIN prt3_adv t3 ON (t1.a = t3.a) WHERE t1.b = 0 ORDER BY t1.a, t2.b, t3.a;
|
|
|
|
|
|
|
|
|
|
DROP TABLE prt1_adv;
|
|
|
|
|
DROP TABLE prt2_adv;
|
|
|
|
|
DROP TABLE prt3_adv;
|
|
|
|
|
|
|
|
|
|
-- Test interaction of partitioned join with partition pruning
|
|
|
|
|
CREATE TABLE prt1_adv (a int, b int, c varchar) PARTITION BY RANGE (a);
|
|
|
|
|
CREATE TABLE prt1_adv_p1 PARTITION OF prt1_adv FOR VALUES FROM (100) TO (200);
|
|
|
|
|
CREATE TABLE prt1_adv_p2 PARTITION OF prt1_adv FOR VALUES FROM (200) TO (300);
|
|
|
|
|
CREATE TABLE prt1_adv_p3 PARTITION OF prt1_adv FOR VALUES FROM (300) TO (400);
|
|
|
|
|
CREATE INDEX prt1_adv_a_idx ON prt1_adv (a);
|
|
|
|
|
INSERT INTO prt1_adv SELECT i, i % 25, to_char(i, 'FM0000') FROM generate_series(100, 399) i;
|
|
|
|
|
ANALYZE prt1_adv;
|
|
|
|
|
|
|
|
|
|
CREATE TABLE prt2_adv (a int, b int, c varchar) PARTITION BY RANGE (b);
|
|
|
|
|
CREATE TABLE prt2_adv_p1 PARTITION OF prt2_adv FOR VALUES FROM (100) TO (200);
|
|
|
|
|
CREATE TABLE prt2_adv_p2 PARTITION OF prt2_adv FOR VALUES FROM (200) TO (400);
|
|
|
|
|
CREATE INDEX prt2_adv_b_idx ON prt2_adv (b);
|
|
|
|
|
INSERT INTO prt2_adv SELECT i % 25, i, to_char(i, 'FM0000') FROM generate_series(100, 399) i;
|
|
|
|
|
ANALYZE prt2_adv;
|
|
|
|
|
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 t2 WHERE t1.a = t2.b AND t1.b = 0 ORDER BY t1.a, t2.b;
|
|
|
|
|
SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 INNER JOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.a < 300 AND t1.b = 0 ORDER BY t1.a, t2.b;
|
|
|
|
|
SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 INNER JOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.a < 300 AND t1.b = 0 ORDER BY t1.a, t2.b;
|
|
|
|
|
|
|
|
|
|
DROP TABLE prt1_adv_p3;
|
|
|
|
|
CREATE TABLE prt1_adv_default PARTITION OF prt1_adv DEFAULT;
|
|
|
|
|
ANALYZE prt1_adv;
|
|
|
|
|
|
|
|
|
|
CREATE TABLE prt2_adv_default PARTITION OF prt2_adv DEFAULT;
|
|
|
|
|
ANALYZE prt2_adv;
|
|
|
|
|
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 INNER JOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.a >= 100 AND t1.a < 300 AND t1.b = 0 ORDER BY t1.a, t2.b;
|
|
|
|
|
SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 INNER JOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.a >= 100 AND t1.a < 300 AND t1.b = 0 ORDER BY t1.a, t2.b;
|
|
|
|
|
|
|
|
|
|
DROP TABLE prt1_adv;
|
|
|
|
|
DROP TABLE prt2_adv;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- Tests for list-partitioned tables
|
|
|
|
|
CREATE TABLE plt1_adv (a int, b int, c text) PARTITION BY LIST (c);
|
|
|
|
|
CREATE TABLE plt1_adv_p1 PARTITION OF plt1_adv FOR VALUES IN ('0001', '0003');
|
|
|
|
|
CREATE TABLE plt1_adv_p2 PARTITION OF plt1_adv FOR VALUES IN ('0004', '0006');
|
|
|
|
|
CREATE TABLE plt1_adv_p3 PARTITION OF plt1_adv FOR VALUES IN ('0008', '0009');
|
|
|
|
|
INSERT INTO plt1_adv SELECT i, i, to_char(i % 10, 'FM0000') FROM generate_series(1, 299) i WHERE i % 10 IN (1, 3, 4, 6, 8, 9);
|
|
|
|
|
ANALYZE plt1_adv;
|
|
|
|
|
|
|
|
|
|
CREATE TABLE plt2_adv (a int, b int, c text) PARTITION BY LIST (c);
|
|
|
|
|
CREATE TABLE plt2_adv_p1 PARTITION OF plt2_adv FOR VALUES IN ('0002', '0003');
|
|
|
|
|
CREATE TABLE plt2_adv_p2 PARTITION OF plt2_adv FOR VALUES IN ('0004', '0006');
|
|
|
|
|
CREATE TABLE plt2_adv_p3 PARTITION OF plt2_adv FOR VALUES IN ('0007', '0009');
|
|
|
|
|
INSERT INTO plt2_adv SELECT i, i, to_char(i % 10, 'FM0000') FROM generate_series(1, 299) i WHERE i % 10 IN (2, 3, 4, 6, 7, 9);
|
|
|
|
|
ANALYZE plt2_adv;
|
|
|
|
|
|
|
|
|
|
-- inner join
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNER JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNER JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
|
|
|
|
|
-- semi join
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.* FROM plt1_adv t1 WHERE EXISTS (SELECT 1 FROM plt2_adv t2 WHERE t1.a = t2.a AND t1.c = t2.c) AND t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
SELECT t1.* FROM plt1_adv t1 WHERE EXISTS (SELECT 1 FROM plt2_adv t2 WHERE t1.a = t2.a AND t1.c = t2.c) AND t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
|
|
|
|
|
-- left join
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 LEFT JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 LEFT JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
|
|
|
|
|
-- anti join
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.* FROM plt1_adv t1 WHERE NOT EXISTS (SELECT 1 FROM plt2_adv t2 WHERE t1.a = t2.a AND t1.c = t2.c) AND t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
SELECT t1.* FROM plt1_adv t1 WHERE NOT EXISTS (SELECT 1 FROM plt2_adv t2 WHERE t1.a = t2.a AND t1.c = t2.c) AND t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
|
|
|
|
|
-- full join
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 FULL JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE coalesce(t1.b, 0) < 10 AND coalesce(t2.b, 0) < 10 ORDER BY t1.a, t2.a;
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 FULL JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE coalesce(t1.b, 0) < 10 AND coalesce(t2.b, 0) < 10 ORDER BY t1.a, t2.a;
|
|
|
|
|
|
|
|
|
|
-- Test cases where one side has an extra partition
|
|
|
|
|
CREATE TABLE plt2_adv_extra PARTITION OF plt2_adv FOR VALUES IN ('0000');
|
|
|
|
|
INSERT INTO plt2_adv_extra VALUES (0, 0, '0000');
|
|
|
|
|
ANALYZE plt2_adv;
|
|
|
|
|
|
|
|
|
|
-- inner join
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNER JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNER JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
|
|
|
|
|
-- semi join
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.* FROM plt1_adv t1 WHERE EXISTS (SELECT 1 FROM plt2_adv t2 WHERE t1.a = t2.a AND t1.c = t2.c) AND t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
SELECT t1.* FROM plt1_adv t1 WHERE EXISTS (SELECT 1 FROM plt2_adv t2 WHERE t1.a = t2.a AND t1.c = t2.c) AND t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
|
|
|
|
|
-- left join
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 LEFT JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 LEFT JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
|
|
|
|
|
-- left join; currently we can't do partitioned join if there are no matched
|
|
|
|
|
-- partitions on the nullable side
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c FROM plt2_adv t1 LEFT JOIN plt1_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
|
|
|
|
|
-- anti join
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.* FROM plt1_adv t1 WHERE NOT EXISTS (SELECT 1 FROM plt2_adv t2 WHERE t1.a = t2.a AND t1.c = t2.c) AND t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
SELECT t1.* FROM plt1_adv t1 WHERE NOT EXISTS (SELECT 1 FROM plt2_adv t2 WHERE t1.a = t2.a AND t1.c = t2.c) AND t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
|
|
|
|
|
-- anti join; currently we can't do partitioned join if there are no matched
|
|
|
|
|
-- partitions on the nullable side
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.* FROM plt2_adv t1 WHERE NOT EXISTS (SELECT 1 FROM plt1_adv t2 WHERE t1.a = t2.a AND t1.c = t2.c) AND t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
|
|
|
|
|
-- full join; currently we can't do partitioned join if there are no matched
|
|
|
|
|
-- partitions on the nullable side
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 FULL JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE coalesce(t1.b, 0) < 10 AND coalesce(t2.b, 0) < 10 ORDER BY t1.a, t2.a;
|
|
|
|
|
|
|
|
|
|
DROP TABLE plt2_adv_extra;
|
|
|
|
|
|
|
|
|
|
-- Test cases where a partition on one side matches multiple partitions on
|
|
|
|
|
-- the other side; we currently can't do partitioned join in such cases
|
|
|
|
|
ALTER TABLE plt2_adv DETACH PARTITION plt2_adv_p2;
|
|
|
|
|
-- Split plt2_adv_p2 into two partitions so that plt1_adv_p2 matches both
|
|
|
|
|
CREATE TABLE plt2_adv_p2_1 PARTITION OF plt2_adv FOR VALUES IN ('0004');
|
|
|
|
|
CREATE TABLE plt2_adv_p2_2 PARTITION OF plt2_adv FOR VALUES IN ('0006');
|
|
|
|
|
INSERT INTO plt2_adv SELECT i, i, to_char(i % 10, 'FM0000') FROM generate_series(1, 299) i WHERE i % 10 IN (4, 6);
|
|
|
|
|
ANALYZE plt2_adv;
|
|
|
|
|
|
|
|
|
|
-- inner join
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNER JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
|
|
|
|
|
-- semi join
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.* FROM plt1_adv t1 WHERE EXISTS (SELECT 1 FROM plt2_adv t2 WHERE t1.a = t2.a AND t1.c = t2.c) AND t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
|
|
|
|
|
-- left join
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 LEFT JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
|
|
|
|
|
-- anti join
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.* FROM plt1_adv t1 WHERE NOT EXISTS (SELECT 1 FROM plt2_adv t2 WHERE t1.a = t2.a AND t1.c = t2.c) AND t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
|
|
|
|
|
-- full join
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 FULL JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE coalesce(t1.b, 0) < 10 AND coalesce(t2.b, 0) < 10 ORDER BY t1.a, t2.a;
|
|
|
|
|
|
|
|
|
|
DROP TABLE plt2_adv_p2_1;
|
|
|
|
|
DROP TABLE plt2_adv_p2_2;
|
|
|
|
|
-- Restore plt2_adv_p2
|
|
|
|
|
ALTER TABLE plt2_adv ATTACH PARTITION plt2_adv_p2 FOR VALUES IN ('0004', '0006');
|
|
|
|
|
|
|
|
|
|
-- Test NULL partitions
|
|
|
|
|
ALTER TABLE plt1_adv DETACH PARTITION plt1_adv_p1;
|
|
|
|
|
-- Change plt1_adv_p1 to the NULL partition
|
|
|
|
|
CREATE TABLE plt1_adv_p1_null PARTITION OF plt1_adv FOR VALUES IN (NULL, '0001', '0003');
|
|
|
|
|
INSERT INTO plt1_adv SELECT i, i, to_char(i % 10, 'FM0000') FROM generate_series(1, 299) i WHERE i % 10 IN (1, 3);
|
|
|
|
|
INSERT INTO plt1_adv VALUES (-1, -1, NULL);
|
|
|
|
|
ANALYZE plt1_adv;
|
|
|
|
|
|
|
|
|
|
ALTER TABLE plt2_adv DETACH PARTITION plt2_adv_p3;
|
|
|
|
|
-- Change plt2_adv_p3 to the NULL partition
|
|
|
|
|
CREATE TABLE plt2_adv_p3_null PARTITION OF plt2_adv FOR VALUES IN (NULL, '0007', '0009');
|
|
|
|
|
INSERT INTO plt2_adv SELECT i, i, to_char(i % 10, 'FM0000') FROM generate_series(1, 299) i WHERE i % 10 IN (7, 9);
|
|
|
|
|
INSERT INTO plt2_adv VALUES (-1, -1, NULL);
|
|
|
|
|
ANALYZE plt2_adv;
|
|
|
|
|
|
|
|
|
|
-- inner join
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNER JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNER JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
|
|
|
|
|
-- semi join
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.* FROM plt1_adv t1 WHERE EXISTS (SELECT 1 FROM plt2_adv t2 WHERE t1.a = t2.a AND t1.c = t2.c) AND t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
SELECT t1.* FROM plt1_adv t1 WHERE EXISTS (SELECT 1 FROM plt2_adv t2 WHERE t1.a = t2.a AND t1.c = t2.c) AND t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
|
|
|
|
|
-- left join
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 LEFT JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 LEFT JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
|
|
|
|
|
-- anti join
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.* FROM plt1_adv t1 WHERE NOT EXISTS (SELECT 1 FROM plt2_adv t2 WHERE t1.a = t2.a AND t1.c = t2.c) AND t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
SELECT t1.* FROM plt1_adv t1 WHERE NOT EXISTS (SELECT 1 FROM plt2_adv t2 WHERE t1.a = t2.a AND t1.c = t2.c) AND t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
|
|
|
|
|
-- full join
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 FULL JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE coalesce(t1.b, 0) < 10 AND coalesce(t2.b, 0) < 10 ORDER BY t1.a, t2.a;
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 FULL JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE coalesce(t1.b, 0) < 10 AND coalesce(t2.b, 0) < 10 ORDER BY t1.a, t2.a;
|
|
|
|
|
|
|
|
|
|
DROP TABLE plt1_adv_p1_null;
|
|
|
|
|
-- Restore plt1_adv_p1
|
|
|
|
|
ALTER TABLE plt1_adv ATTACH PARTITION plt1_adv_p1 FOR VALUES IN ('0001', '0003');
|
|
|
|
|
-- Add to plt1_adv the extra NULL partition containing only NULL values as the
|
|
|
|
|
-- key values
|
|
|
|
|
CREATE TABLE plt1_adv_extra PARTITION OF plt1_adv FOR VALUES IN (NULL);
|
|
|
|
|
INSERT INTO plt1_adv VALUES (-1, -1, NULL);
|
|
|
|
|
ANALYZE plt1_adv;
|
|
|
|
|
|
|
|
|
|
DROP TABLE plt2_adv_p3_null;
|
|
|
|
|
-- Restore plt2_adv_p3
|
|
|
|
|
ALTER TABLE plt2_adv ATTACH PARTITION plt2_adv_p3 FOR VALUES IN ('0007', '0009');
|
|
|
|
|
ANALYZE plt2_adv;
|
|
|
|
|
|
|
|
|
|
-- inner join
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNER JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNER JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
|
|
|
|
|
-- left join; currently we can't do partitioned join if there are no matched
|
|
|
|
|
-- partitions on the nullable side
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 LEFT JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
|
|
|
|
|
-- full join; currently we can't do partitioned join if there are no matched
|
|
|
|
|
-- partitions on the nullable side
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 FULL JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE coalesce(t1.b, 0) < 10 AND coalesce(t2.b, 0) < 10 ORDER BY t1.a, t2.a;
|
|
|
|
|
|
|
|
|
|
-- Add to plt2_adv the extra NULL partition containing only NULL values as the
|
|
|
|
|
-- key values
|
|
|
|
|
CREATE TABLE plt2_adv_extra PARTITION OF plt2_adv FOR VALUES IN (NULL);
|
|
|
|
|
INSERT INTO plt2_adv VALUES (-1, -1, NULL);
|
|
|
|
|
ANALYZE plt2_adv;
|
|
|
|
|
|
|
|
|
|
-- inner join
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNER JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNER JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
|
|
|
|
|
-- left join
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 LEFT JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 LEFT JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
|
|
|
|
|
-- full join
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 FULL JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE coalesce(t1.b, 0) < 10 AND coalesce(t2.b, 0) < 10 ORDER BY t1.a, t2.a;
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 FULL JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE coalesce(t1.b, 0) < 10 AND coalesce(t2.b, 0) < 10 ORDER BY t1.a, t2.a;
|
|
|
|
|
|
|
|
|
|
-- 3-way join to test the NULL partition of a join relation
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c, t3.a, t3.c FROM plt1_adv t1 LEFT JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) LEFT JOIN plt1_adv t3 ON (t1.a = t3.a AND t1.c = t3.c) WHERE t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c, t3.a, t3.c FROM plt1_adv t1 LEFT JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) LEFT JOIN plt1_adv t3 ON (t1.a = t3.a AND t1.c = t3.c) WHERE t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
|
|
|
|
|
DROP TABLE plt1_adv_extra;
|
|
|
|
|
DROP TABLE plt2_adv_extra;
|
|
|
|
|
|
|
|
|
|
-- Test default partitions
|
|
|
|
|
ALTER TABLE plt1_adv DETACH PARTITION plt1_adv_p1;
|
|
|
|
|
-- Change plt1_adv_p1 to the default partition
|
|
|
|
|
ALTER TABLE plt1_adv ATTACH PARTITION plt1_adv_p1 DEFAULT;
|
|
|
|
|
DROP TABLE plt1_adv_p3;
|
|
|
|
|
ANALYZE plt1_adv;
|
|
|
|
|
|
|
|
|
|
DROP TABLE plt2_adv_p3;
|
|
|
|
|
ANALYZE plt2_adv;
|
|
|
|
|
|
|
|
|
|
-- We can do partitioned join even if only one of relations has the default
|
|
|
|
|
-- partition
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNER JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNER JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
|
|
|
|
|
ALTER TABLE plt2_adv DETACH PARTITION plt2_adv_p2;
|
|
|
|
|
-- Change plt2_adv_p2 to contain '0005' in addition to '0004' and '0006' as
|
|
|
|
|
-- the key values
|
|
|
|
|
CREATE TABLE plt2_adv_p2_ext PARTITION OF plt2_adv FOR VALUES IN ('0004', '0005', '0006');
|
|
|
|
|
INSERT INTO plt2_adv SELECT i, i, to_char(i % 10, 'FM0000') FROM generate_series(1, 299) i WHERE i % 10 IN (4, 5, 6);
|
|
|
|
|
ANALYZE plt2_adv;
|
|
|
|
|
|
|
|
|
|
-- Partitioned join can't be applied because the default partition of plt1_adv
|
|
|
|
|
-- matches plt2_adv_p1 and plt2_adv_p2_ext
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNER JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
|
|
|
|
|
ALTER TABLE plt2_adv DETACH PARTITION plt2_adv_p2_ext;
|
|
|
|
|
-- Change plt2_adv_p2_ext to the default partition
|
|
|
|
|
ALTER TABLE plt2_adv ATTACH PARTITION plt2_adv_p2_ext DEFAULT;
|
|
|
|
|
ANALYZE plt2_adv;
|
|
|
|
|
|
|
|
|
|
-- Partitioned join can't be applied because the default partition of plt1_adv
|
|
|
|
|
-- matches plt2_adv_p1 and plt2_adv_p2_ext
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNER JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
|
|
|
|
|
DROP TABLE plt2_adv_p2_ext;
|
|
|
|
|
-- Restore plt2_adv_p2
|
|
|
|
|
ALTER TABLE plt2_adv ATTACH PARTITION plt2_adv_p2 FOR VALUES IN ('0004', '0006');
|
|
|
|
|
ANALYZE plt2_adv;
|
|
|
|
|
|
|
|
|
|
CREATE TABLE plt3_adv (a int, b int, c text) PARTITION BY LIST (c);
|
|
|
|
|
CREATE TABLE plt3_adv_p1 PARTITION OF plt3_adv FOR VALUES IN ('0004', '0006');
|
|
|
|
|
CREATE TABLE plt3_adv_p2 PARTITION OF plt3_adv FOR VALUES IN ('0007', '0009');
|
|
|
|
|
INSERT INTO plt3_adv SELECT i, i, to_char(i % 10, 'FM0000') FROM generate_series(1, 299) i WHERE i % 10 IN (4, 6, 7, 9);
|
|
|
|
|
ANALYZE plt3_adv;
|
|
|
|
|
|
|
|
|
|
-- 3-way join to test the default partition of a join relation
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c, t3.a, t3.c FROM plt1_adv t1 LEFT JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) LEFT JOIN plt3_adv t3 ON (t1.a = t3.a AND t1.c = t3.c) WHERE t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c, t3.a, t3.c FROM plt1_adv t1 LEFT JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) LEFT JOIN plt3_adv t3 ON (t1.a = t3.a AND t1.c = t3.c) WHERE t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
|
|
|
|
|
-- Test cases where one side has the default partition while the other side
|
|
|
|
|
-- has the NULL partition
|
|
|
|
|
DROP TABLE plt2_adv_p1;
|
|
|
|
|
-- Add the NULL partition to plt2_adv
|
|
|
|
|
CREATE TABLE plt2_adv_p1_null PARTITION OF plt2_adv FOR VALUES IN (NULL, '0001', '0003');
|
|
|
|
|
INSERT INTO plt2_adv SELECT i, i, to_char(i % 10, 'FM0000') FROM generate_series(1, 299) i WHERE i % 10 IN (1, 3);
|
|
|
|
|
INSERT INTO plt2_adv VALUES (-1, -1, NULL);
|
|
|
|
|
ANALYZE plt2_adv;
|
|
|
|
|
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNER JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNER JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
|
|
|
|
|
DROP TABLE plt2_adv_p1_null;
|
|
|
|
|
-- Add the NULL partition that contains only NULL values as the key values
|
|
|
|
|
CREATE TABLE plt2_adv_p1_null PARTITION OF plt2_adv FOR VALUES IN (NULL);
|
|
|
|
|
INSERT INTO plt2_adv VALUES (-1, -1, NULL);
|
|
|
|
|
ANALYZE plt2_adv;
|
|
|
|
|
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNER JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNER JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
|
|
|
|
|
DROP TABLE plt1_adv;
|
|
|
|
|
DROP TABLE plt2_adv;
|
|
|
|
|
DROP TABLE plt3_adv;
|
|
|
|
|
|
|
|
|
|
-- Test interaction of partitioned join with partition pruning
|
|
|
|
|
CREATE TABLE plt1_adv (a int, b int, c text) PARTITION BY LIST (c);
|
|
|
|
|
CREATE TABLE plt1_adv_p1 PARTITION OF plt1_adv FOR VALUES IN ('0001');
|
|
|
|
|
CREATE TABLE plt1_adv_p2 PARTITION OF plt1_adv FOR VALUES IN ('0002');
|
|
|
|
|
CREATE TABLE plt1_adv_p3 PARTITION OF plt1_adv FOR VALUES IN ('0003');
|
|
|
|
|
CREATE TABLE plt1_adv_p4 PARTITION OF plt1_adv FOR VALUES IN (NULL, '0004', '0005');
|
|
|
|
|
INSERT INTO plt1_adv SELECT i, i, to_char(i % 10, 'FM0000') FROM generate_series(1, 299) i WHERE i % 10 IN (1, 2, 3, 4, 5);
|
|
|
|
|
INSERT INTO plt1_adv VALUES (-1, -1, NULL);
|
|
|
|
|
ANALYZE plt1_adv;
|
|
|
|
|
|
|
|
|
|
CREATE TABLE plt2_adv (a int, b int, c text) PARTITION BY LIST (c);
|
|
|
|
|
CREATE TABLE plt2_adv_p1 PARTITION OF plt2_adv FOR VALUES IN ('0001', '0002');
|
|
|
|
|
CREATE TABLE plt2_adv_p2 PARTITION OF plt2_adv FOR VALUES IN (NULL);
|
|
|
|
|
CREATE TABLE plt2_adv_p3 PARTITION OF plt2_adv FOR VALUES IN ('0003');
|
|
|
|
|
CREATE TABLE plt2_adv_p4 PARTITION OF plt2_adv FOR VALUES IN ('0004', '0005');
|
|
|
|
|
INSERT INTO plt2_adv SELECT i, i, to_char(i % 10, 'FM0000') FROM generate_series(1, 299) i WHERE i % 10 IN (1, 2, 3, 4, 5);
|
|
|
|
|
INSERT INTO plt2_adv VALUES (-1, -1, NULL);
|
|
|
|
|
ANALYZE plt2_adv;
|
|
|
|
|
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNER JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.c IN ('0003', '0004', '0005') AND t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNER JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.c IN ('0003', '0004', '0005') AND t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 LEFT JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.c IS NULL AND t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 LEFT JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.c IS NULL AND t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
|
|
|
|
|
CREATE TABLE plt1_adv_default PARTITION OF plt1_adv DEFAULT;
|
|
|
|
|
ANALYZE plt1_adv;
|
|
|
|
|
|
|
|
|
|
CREATE TABLE plt2_adv_default PARTITION OF plt2_adv DEFAULT;
|
|
|
|
|
ANALYZE plt2_adv;
|
|
|
|
|
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNER JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.c IN ('0003', '0004', '0005') AND t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNER JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.c IN ('0003', '0004', '0005') AND t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 LEFT JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.c IS NULL AND t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 LEFT JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.c IS NULL AND t1.b < 10 ORDER BY t1.a;
|
|
|
|
|
|
|
|
|
|
DROP TABLE plt1_adv;
|
|
|
|
|
DROP TABLE plt2_adv;
|
|
|
|
|
|
|
|
|
|
-- Test the process_outer_partition() code path
|
|
|
|
|
CREATE TABLE plt1_adv (a int, b int, c text) PARTITION BY LIST (c);
|
|
|
|
|
CREATE TABLE plt1_adv_p1 PARTITION OF plt1_adv FOR VALUES IN ('0000', '0001', '0002');
|
|
|
|
|
CREATE TABLE plt1_adv_p2 PARTITION OF plt1_adv FOR VALUES IN ('0003', '0004');
|
|
|
|
|
INSERT INTO plt1_adv SELECT i, i, to_char(i % 5, 'FM0000') FROM generate_series(0, 24) i;
|
|
|
|
|
ANALYZE plt1_adv;
|
|
|
|
|
|
|
|
|
|
CREATE TABLE plt2_adv (a int, b int, c text) PARTITION BY LIST (c);
|
|
|
|
|
CREATE TABLE plt2_adv_p1 PARTITION OF plt2_adv FOR VALUES IN ('0002');
|
|
|
|
|
CREATE TABLE plt2_adv_p2 PARTITION OF plt2_adv FOR VALUES IN ('0003', '0004');
|
|
|
|
|
INSERT INTO plt2_adv SELECT i, i, to_char(i % 5, 'FM0000') FROM generate_series(0, 24) i WHERE i % 5 IN (2, 3, 4);
|
|
|
|
|
ANALYZE plt2_adv;
|
|
|
|
|
|
|
|
|
|
CREATE TABLE plt3_adv (a int, b int, c text) PARTITION BY LIST (c);
|
|
|
|
|
CREATE TABLE plt3_adv_p1 PARTITION OF plt3_adv FOR VALUES IN ('0001');
|
|
|
|
|
CREATE TABLE plt3_adv_p2 PARTITION OF plt3_adv FOR VALUES IN ('0003', '0004');
|
|
|
|
|
INSERT INTO plt3_adv SELECT i, i, to_char(i % 5, 'FM0000') FROM generate_series(0, 24) i WHERE i % 5 IN (1, 3, 4);
|
|
|
|
|
ANALYZE plt3_adv;
|
|
|
|
|
|
|
|
|
|
-- This tests that when merging partitions from plt1_adv and plt2_adv in
|
|
|
|
|
-- merge_list_bounds(), process_outer_partition() returns an already-assigned
|
|
|
|
|
-- merged partition when re-called with plt1_adv_p1 for the second list value
|
|
|
|
|
-- '0001' of that partitin
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c, t3.a, t3.c FROM (plt1_adv t1 LEFT JOIN plt2_adv t2 ON (t1.c = t2.c)) FULL JOIN plt3_adv t3 ON (t1.c = t3.c) WHERE coalesce(t1.a, 0) % 5 != 3 AND coalesce(t1.a, 0) % 5 != 4 ORDER BY t1.c, t1.a, t2.a, t3.a;
|
|
|
|
|
SELECT t1.a, t1.c, t2.a, t2.c, t3.a, t3.c FROM (plt1_adv t1 LEFT JOIN plt2_adv t2 ON (t1.c = t2.c)) FULL JOIN plt3_adv t3 ON (t1.c = t3.c) WHERE coalesce(t1.a, 0) % 5 != 3 AND coalesce(t1.a, 0) % 5 != 4 ORDER BY t1.c, t1.a, t2.a, t3.a;
|
|
|
|
|
|
|
|
|
|
DROP TABLE plt1_adv;
|
|
|
|
|
DROP TABLE plt2_adv;
|
|
|
|
|
DROP TABLE plt3_adv;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-- Tests for multi-level partitioned tables
|
|
|
|
|
CREATE TABLE alpha (a double precision, b int, c text) PARTITION BY RANGE (a);
|
|
|
|
|
CREATE TABLE alpha_neg PARTITION OF alpha FOR VALUES FROM ('-Infinity') TO (0) PARTITION BY RANGE (b);
|
|
|
|
|
CREATE TABLE alpha_pos PARTITION OF alpha FOR VALUES FROM (0) TO (10.0) PARTITION BY LIST (c);
|
|
|
|
|
CREATE TABLE alpha_neg_p1 PARTITION OF alpha_neg FOR VALUES FROM (100) TO (200);
|
|
|
|
|
CREATE TABLE alpha_neg_p2 PARTITION OF alpha_neg FOR VALUES FROM (200) TO (300);
|
|
|
|
|
CREATE TABLE alpha_neg_p3 PARTITION OF alpha_neg FOR VALUES FROM (300) TO (400);
|
|
|
|
|
CREATE TABLE alpha_pos_p1 PARTITION OF alpha_pos FOR VALUES IN ('0001', '0003');
|
|
|
|
|
CREATE TABLE alpha_pos_p2 PARTITION OF alpha_pos FOR VALUES IN ('0004', '0006');
|
|
|
|
|
CREATE TABLE alpha_pos_p3 PARTITION OF alpha_pos FOR VALUES IN ('0008', '0009');
|
|
|
|
|
INSERT INTO alpha_neg SELECT -1.0, i, to_char(i % 10, 'FM0000') FROM generate_series(100, 399) i WHERE i % 10 IN (1, 3, 4, 6, 8, 9);
|
|
|
|
|
INSERT INTO alpha_pos SELECT 1.0, i, to_char(i % 10, 'FM0000') FROM generate_series(100, 399) i WHERE i % 10 IN (1, 3, 4, 6, 8, 9);
|
|
|
|
|
ANALYZE alpha;
|
|
|
|
|
|
|
|
|
|
CREATE TABLE beta (a double precision, b int, c text) PARTITION BY RANGE (a);
|
|
|
|
|
CREATE TABLE beta_neg PARTITION OF beta FOR VALUES FROM (-10.0) TO (0) PARTITION BY RANGE (b);
|
|
|
|
|
CREATE TABLE beta_pos PARTITION OF beta FOR VALUES FROM (0) TO ('Infinity') PARTITION BY LIST (c);
|
|
|
|
|
CREATE TABLE beta_neg_p1 PARTITION OF beta_neg FOR VALUES FROM (100) TO (150);
|
|
|
|
|
CREATE TABLE beta_neg_p2 PARTITION OF beta_neg FOR VALUES FROM (200) TO (300);
|
|
|
|
|
CREATE TABLE beta_neg_p3 PARTITION OF beta_neg FOR VALUES FROM (350) TO (500);
|
|
|
|
|
CREATE TABLE beta_pos_p1 PARTITION OF beta_pos FOR VALUES IN ('0002', '0003');
|
|
|
|
|
CREATE TABLE beta_pos_p2 PARTITION OF beta_pos FOR VALUES IN ('0004', '0006');
|
|
|
|
|
CREATE TABLE beta_pos_p3 PARTITION OF beta_pos FOR VALUES IN ('0007', '0009');
|
|
|
|
|
INSERT INTO beta_neg SELECT -1.0, i, to_char(i % 10, 'FM0000') FROM generate_series(100, 149) i WHERE i % 10 IN (2, 3, 4, 6, 7, 9);
|
|
|
|
|
INSERT INTO beta_neg SELECT -1.0, i, to_char(i % 10, 'FM0000') FROM generate_series(200, 299) i WHERE i % 10 IN (2, 3, 4, 6, 7, 9);
|
|
|
|
|
INSERT INTO beta_neg SELECT -1.0, i, to_char(i % 10, 'FM0000') FROM generate_series(350, 499) i WHERE i % 10 IN (2, 3, 4, 6, 7, 9);
|
|
|
|
|
INSERT INTO beta_pos SELECT 1.0, i, to_char(i % 10, 'FM0000') FROM generate_series(100, 149) i WHERE i % 10 IN (2, 3, 4, 6, 7, 9);
|
|
|
|
|
INSERT INTO beta_pos SELECT 1.0, i, to_char(i % 10, 'FM0000') FROM generate_series(200, 299) i WHERE i % 10 IN (2, 3, 4, 6, 7, 9);
|
|
|
|
|
INSERT INTO beta_pos SELECT 1.0, i, to_char(i % 10, 'FM0000') FROM generate_series(350, 499) i WHERE i % 10 IN (2, 3, 4, 6, 7, 9);
|
|
|
|
|
ANALYZE beta;
|
|
|
|
|
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.*, t2.* FROM alpha t1 INNER JOIN beta t2 ON (t1.a = t2.a AND t1.b = t2.b) WHERE t1.b >= 125 AND t1.b < 225 ORDER BY t1.a, t1.b;
|
|
|
|
|
SELECT t1.*, t2.* FROM alpha t1 INNER JOIN beta t2 ON (t1.a = t2.a AND t1.b = t2.b) WHERE t1.b >= 125 AND t1.b < 225 ORDER BY t1.a, t1.b;
|
|
|
|
|
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.*, t2.* FROM alpha t1 INNER JOIN beta t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE ((t1.b >= 100 AND t1.b < 110) OR (t1.b >= 200 AND t1.b < 210)) AND ((t2.b >= 100 AND t2.b < 110) OR (t2.b >= 200 AND t2.b < 210)) AND t1.c IN ('0004', '0009') ORDER BY t1.a, t1.b, t2.b;
|
|
|
|
|
SELECT t1.*, t2.* FROM alpha t1 INNER JOIN beta t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE ((t1.b >= 100 AND t1.b < 110) OR (t1.b >= 200 AND t1.b < 210)) AND ((t2.b >= 100 AND t2.b < 110) OR (t2.b >= 200 AND t2.b < 210)) AND t1.c IN ('0004', '0009') ORDER BY t1.a, t1.b, t2.b;
|
|
|
|
|
|
|
|
|
|
EXPLAIN (COSTS OFF)
|
|
|
|
|
SELECT t1.*, t2.* FROM alpha t1 INNER JOIN beta t2 ON (t1.a = t2.a AND t1.b = t2.b AND t1.c = t2.c) WHERE ((t1.b >= 100 AND t1.b < 110) OR (t1.b >= 200 AND t1.b < 210)) AND ((t2.b >= 100 AND t2.b < 110) OR (t2.b >= 200 AND t2.b < 210)) AND t1.c IN ('0004', '0009') ORDER BY t1.a, t1.b;
|
|
|
|
|
SELECT t1.*, t2.* FROM alpha t1 INNER JOIN beta t2 ON (t1.a = t2.a AND t1.b = t2.b AND t1.c = t2.c) WHERE ((t1.b >= 100 AND t1.b < 110) OR (t1.b >= 200 AND t1.b < 210)) AND ((t2.b >= 100 AND t2.b < 110) OR (t2.b >= 200 AND t2.b < 210)) AND t1.c IN ('0004', '0009') ORDER BY t1.a, t1.b;
|
|
|
|
|