@ -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 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 . 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_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 ;