diff --git a/src/test/regress/expected/non_colocated_outer_joins.out b/src/test/regress/expected/non_colocated_outer_joins.out new file mode 100644 index 000000000..19af405af --- /dev/null +++ b/src/test/regress/expected/non_colocated_outer_joins.out @@ -0,0 +1,406 @@ +CREATE TABLE t1(col1 INT, col2 INT); +SELECT create_distributed_table('t1', 'col1'); + create_distributed_table +--------------------------------------------------------------------- + +(1 row) + +INSERT INTO t1 SELECT i, i FROM generate_series(1,10) i; +CREATE TABLE t2(col1 INT, col2 INT); +SELECT create_distributed_table('t2', 'col2'); + create_distributed_table +--------------------------------------------------------------------- + +(1 row) + +INSERT INTO t2 SELECT i, i FROM generate_series(6,15) i; +CREATE TABLE t3(col1 INT, col2 INT); +SELECT create_distributed_table('t3', 'col1'); + create_distributed_table +--------------------------------------------------------------------- + +(1 row) + +INSERT INTO t3 SELECT i, i FROM generate_series(11,20) i; +SET citus.enable_repartition_joins TO ON; +SET citus.log_multi_join_order TO ON; +SET client_min_messages TO LOG; +-- join order planner can handle left outer join between tables with simple join clause +-- outer table restricted on partition column whereas inner one is not restricted on the partition column +SELECT t1.*, t2.* FROM t1 LEFT JOIN t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +LOG: join order: [ "t1" ][ dual partition join(LEFT) "t2" ] + col1 | col2 | col1 | col2 +--------------------------------------------------------------------- + 1 | 1 | | + 2 | 2 | | + 3 | 3 | | + 4 | 4 | | + 5 | 5 | | + 6 | 6 | 6 | 6 + 7 | 7 | 7 | 7 + 8 | 8 | 8 | 8 + 9 | 9 | 9 | 9 + 10 | 10 | 10 | 10 +(10 rows) + +-- inner table restricted on partition column whereas outer one is not restricted on the partition column +SELECT t1.*, t2.* FROM t1 LEFT JOIN t2 ON (t1.col2 = t2.col2) ORDER BY 1,2,3,4; +LOG: join order: [ "t1" ][ dual partition join(LEFT) "t2" ] + col1 | col2 | col1 | col2 +--------------------------------------------------------------------- + 1 | 1 | | + 2 | 2 | | + 3 | 3 | | + 4 | 4 | | + 5 | 5 | | + 6 | 6 | 6 | 6 + 7 | 7 | 7 | 7 + 8 | 8 | 8 | 8 + 9 | 9 | 9 | 9 + 10 | 10 | 10 | 10 +(10 rows) + +-- both tables are not restricted on partition column +SELECT t1.*, t2.* FROM t1 LEFT JOIN t2 ON (t1.col2 = t2.col1) ORDER BY 1,2,3,4; +LOG: join order: [ "t1" ][ dual partition join(LEFT) "t2" ] + col1 | col2 | col1 | col2 +--------------------------------------------------------------------- + 1 | 1 | | + 2 | 2 | | + 3 | 3 | | + 4 | 4 | | + 5 | 5 | | + 6 | 6 | 6 | 6 + 7 | 7 | 7 | 7 + 8 | 8 | 8 | 8 + 9 | 9 | 9 | 9 + 10 | 10 | 10 | 10 +(10 rows) + +-- join order planner can handle right outer join between tables with simple join clause +-- outer table restricted on partition column whereas inner one is not restricted on the partition column +SELECT t1.*, t2.* FROM t1 RIGHT JOIN t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +LOG: join order: [ "t2" ][ dual partition join(LEFT) "t1" ] + col1 | col2 | col1 | col2 +--------------------------------------------------------------------- + 6 | 6 | 6 | 6 + 7 | 7 | 7 | 7 + 8 | 8 | 8 | 8 + 9 | 9 | 9 | 9 + 10 | 10 | 10 | 10 + | | 11 | 11 + | | 12 | 12 + | | 13 | 13 + | | 14 | 14 + | | 15 | 15 +(10 rows) + +-- inner table restricted on partition column whereas outer one is not restricted on the partition column +SELECT t1.*, t2.* FROM t1 RIGHT JOIN t2 ON (t1.col2 = t2.col2) ORDER BY 1,2,3,4; +LOG: join order: [ "t2" ][ dual partition join(LEFT) "t1" ] + col1 | col2 | col1 | col2 +--------------------------------------------------------------------- + 6 | 6 | 6 | 6 + 7 | 7 | 7 | 7 + 8 | 8 | 8 | 8 + 9 | 9 | 9 | 9 + 10 | 10 | 10 | 10 + | | 11 | 11 + | | 12 | 12 + | | 13 | 13 + | | 14 | 14 + | | 15 | 15 +(10 rows) + +-- both tables are not restricted on partition column +SELECT t1.*, t2.* FROM t1 RIGHT JOIN t2 ON (t1.col2 = t2.col1) ORDER BY 1,2,3,4; +LOG: join order: [ "t2" ][ dual partition join(LEFT) "t1" ] + col1 | col2 | col1 | col2 +--------------------------------------------------------------------- + 6 | 6 | 6 | 6 + 7 | 7 | 7 | 7 + 8 | 8 | 8 | 8 + 9 | 9 | 9 | 9 + 10 | 10 | 10 | 10 + | | 11 | 11 + | | 12 | 12 + | | 13 | 13 + | | 14 | 14 + | | 15 | 15 +(10 rows) + +-- join order planner can handle full outer join between tables with simple join clause +-- left outer table restricted on partition column whereas right outer one is not restricted on the partition column +SELECT t1.*, t2.* FROM t1 FULL JOIN t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +LOG: join order: [ "t1" ][ dual partition join(FULL) "t2" ] + col1 | col2 | col1 | col2 +--------------------------------------------------------------------- + 1 | 1 | | + 2 | 2 | | + 3 | 3 | | + 4 | 4 | | + 5 | 5 | | + 6 | 6 | 6 | 6 + 7 | 7 | 7 | 7 + 8 | 8 | 8 | 8 + 9 | 9 | 9 | 9 + 10 | 10 | 10 | 10 + | | 11 | 11 + | | 12 | 12 + | | 13 | 13 + | | 14 | 14 + | | 15 | 15 +(15 rows) + +-- right outer table restricted on partition column whereas left outer one is not restricted on the partition column +SELECT t1.*, t2.* FROM t1 FULL JOIN t2 ON (t1.col2 = t2.col2) ORDER BY 1,2,3,4; +LOG: join order: [ "t1" ][ dual partition join(FULL) "t2" ] + col1 | col2 | col1 | col2 +--------------------------------------------------------------------- + 1 | 1 | | + 2 | 2 | | + 3 | 3 | | + 4 | 4 | | + 5 | 5 | | + 6 | 6 | 6 | 6 + 7 | 7 | 7 | 7 + 8 | 8 | 8 | 8 + 9 | 9 | 9 | 9 + 10 | 10 | 10 | 10 + | | 11 | 11 + | | 12 | 12 + | | 13 | 13 + | | 14 | 14 + | | 15 | 15 +(15 rows) + +-- both tables are not restricted on partition column +SELECT t1.*, t2.* FROM t1 FULL JOIN t2 ON (t1.col2 = t2.col1) ORDER BY 1,2,3,4; +LOG: join order: [ "t1" ][ dual partition join(FULL) "t2" ] + col1 | col2 | col1 | col2 +--------------------------------------------------------------------- + 1 | 1 | | + 2 | 2 | | + 3 | 3 | | + 4 | 4 | | + 5 | 5 | | + 6 | 6 | 6 | 6 + 7 | 7 | 7 | 7 + 8 | 8 | 8 | 8 + 9 | 9 | 9 | 9 + 10 | 10 | 10 | 10 + | | 11 | 11 + | | 12 | 12 + | | 13 | 13 + | | 14 | 14 + | | 15 | 15 +(15 rows) + +-- join order planner can handle queries with multi joins consisting of outer joins with simple join clause +SELECT t1.*, t2.*, t3.* FROM t1 RIGHT JOIN t2 ON (t1.col1 = t2.col1) INNER JOIN t3 ON (t3.col1 = t1.col1) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "t1" ][ local partition join(INNER) "t3" ][ dual partition join(INNER) "t2" ] + col1 | col2 | col1 | col2 | col1 | col2 +--------------------------------------------------------------------- +(0 rows) + +SELECT t1.*, t2.*, t3.* FROM t1 RIGHT JOIN t2 ON (t1.col1 = t2.col1) INNER JOIN t3 ON (t3.col1 = t2.col1) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "t2" ][ dual partition join(LEFT) "t1" ][ dual partition join(INNER) "t3" ] + col1 | col2 | col1 | col2 | col1 | col2 +--------------------------------------------------------------------- + | | 11 | 11 | 11 | 11 + | | 12 | 12 | 12 | 12 + | | 13 | 13 | 13 | 13 + | | 14 | 14 | 14 | 14 + | | 15 | 15 | 15 | 15 +(5 rows) + +SELECT t1.*, t2.*, t3.* FROM t1 RIGHT JOIN t2 ON (t1.col2 = t2.col2) INNER JOIN t3 ON (t3.col2 = t1.col2) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "t1" ][ dual partition join(INNER) "t2" ][ dual partition join(INNER) "t3" ] + col1 | col2 | col1 | col2 | col1 | col2 +--------------------------------------------------------------------- +(0 rows) + +SELECT t1.*, t2.*, t3.* FROM t1 RIGHT JOIN t2 ON (t1.col2 = t2.col2) INNER JOIN t3 ON (t3.col2 = t2.col2) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "t2" ][ dual partition join(LEFT) "t1" ][ dual partition join(INNER) "t3" ] + col1 | col2 | col1 | col2 | col1 | col2 +--------------------------------------------------------------------- + | | 11 | 11 | 11 | 11 + | | 12 | 12 | 12 | 12 + | | 13 | 13 | 13 | 13 + | | 14 | 14 | 14 | 14 + | | 15 | 15 | 15 | 15 +(5 rows) + +SELECT t1.*, t2.*, t3.* FROM t1 RIGHT JOIN t2 ON (t1.col2 = t2.col1) INNER JOIN t3 ON (t3.col2 = t1.col1) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "t1" ][ dual partition join(INNER) "t2" ][ dual partition join(INNER) "t3" ] + col1 | col2 | col1 | col2 | col1 | col2 +--------------------------------------------------------------------- +(0 rows) + +SELECT t1.*, t2.*, t3.* FROM t1 RIGHT JOIN t2 ON (t1.col2 = t2.col1) INNER JOIN t3 ON (t3.col2 = t2.col1) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "t2" ][ dual partition join(LEFT) "t1" ][ dual partition join(INNER) "t3" ] + col1 | col2 | col1 | col2 | col1 | col2 +--------------------------------------------------------------------- + | | 11 | 11 | 11 | 11 + | | 12 | 12 | 12 | 12 + | | 13 | 13 | 13 | 13 + | | 14 | 14 | 14 | 14 + | | 15 | 15 | 15 | 15 +(5 rows) + +SELECT t1.*, t2.*, t3.* FROM t2 LEFT JOIN t1 ON (t1.col1 = t2.col1) INNER JOIN t3 ON (t3.col1 = t1.col1) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "t1" ][ local partition join(INNER) "t3" ][ dual partition join(INNER) "t2" ] + col1 | col2 | col1 | col2 | col1 | col2 +--------------------------------------------------------------------- +(0 rows) + +SELECT t1.*, t2.*, t3.* FROM t2 LEFT JOIN t1 ON (t1.col1 = t2.col1) INNER JOIN t3 ON (t3.col1 = t2.col1) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "t2" ][ dual partition join(LEFT) "t1" ][ dual partition join(INNER) "t3" ] + col1 | col2 | col1 | col2 | col1 | col2 +--------------------------------------------------------------------- + | | 11 | 11 | 11 | 11 + | | 12 | 12 | 12 | 12 + | | 13 | 13 | 13 | 13 + | | 14 | 14 | 14 | 14 + | | 15 | 15 | 15 | 15 +(5 rows) + +SELECT t1.*, t2.*, t3.* FROM t2 LEFT JOIN t1 ON (t1.col2 = t2.col2) INNER JOIN t3 ON (t3.col2 = t1.col2) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "t2" ][ dual partition join(INNER) "t1" ][ dual partition join(INNER) "t3" ] + col1 | col2 | col1 | col2 | col1 | col2 +--------------------------------------------------------------------- +(0 rows) + +SELECT t1.*, t2.*, t3.* FROM t2 LEFT JOIN t1 ON (t1.col2 = t2.col2) INNER JOIN t3 ON (t3.col2 = t2.col2) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "t2" ][ dual partition join(LEFT) "t1" ][ dual partition join(INNER) "t3" ] + col1 | col2 | col1 | col2 | col1 | col2 +--------------------------------------------------------------------- + | | 11 | 11 | 11 | 11 + | | 12 | 12 | 12 | 12 + | | 13 | 13 | 13 | 13 + | | 14 | 14 | 14 | 14 + | | 15 | 15 | 15 | 15 +(5 rows) + +SELECT t1.*, t2.*, t3.* FROM t2 LEFT JOIN t1 ON (t1.col2 = t2.col1) INNER JOIN t3 ON (t3.col2 = t1.col1) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "t2" ][ dual partition join(INNER) "t1" ][ dual partition join(INNER) "t3" ] + col1 | col2 | col1 | col2 | col1 | col2 +--------------------------------------------------------------------- +(0 rows) + +SELECT t1.*, t2.*, t3.* FROM t2 LEFT JOIN t1 ON (t1.col2 = t2.col1) INNER JOIN t3 ON (t3.col2 = t2.col1) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "t2" ][ dual partition join(LEFT) "t1" ][ dual partition join(INNER) "t3" ] + col1 | col2 | col1 | col2 | col1 | col2 +--------------------------------------------------------------------- + | | 11 | 11 | 11 | 11 + | | 12 | 12 | 12 | 12 + | | 13 | 13 | 13 | 13 + | | 14 | 14 | 14 | 14 + | | 15 | 15 | 15 | 15 +(5 rows) + +SELECT t1.*, t2.*, t3.* FROM t1 FULL JOIN t2 ON (t1.col1 = t2.col1) INNER JOIN t3 ON (t3.col1 = t1.col1) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "t1" ][ dual partition join(LEFT) "t2" ][ dual partition join(INNER) "t3" ] + col1 | col2 | col1 | col2 | col1 | col2 +--------------------------------------------------------------------- +(0 rows) + +SELECT t1.*, t2.*, t3.* FROM t1 FULL JOIN t2 ON (t1.col1 = t2.col1) INNER JOIN t3 ON (t3.col1 = t2.col1) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "t2" ][ dual partition join(LEFT) "t1" ][ dual partition join(INNER) "t3" ] + col1 | col2 | col1 | col2 | col1 | col2 +--------------------------------------------------------------------- + | | 11 | 11 | 11 | 11 + | | 12 | 12 | 12 | 12 + | | 13 | 13 | 13 | 13 + | | 14 | 14 | 14 | 14 + | | 15 | 15 | 15 | 15 +(5 rows) + +SELECT t1.*, t2.*, t3.* FROM t1 FULL JOIN t2 ON (t1.col2 = t2.col2) INNER JOIN t3 ON (t3.col2 = t1.col2) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "t1" ][ dual partition join(LEFT) "t2" ][ dual partition join(INNER) "t3" ] + col1 | col2 | col1 | col2 | col1 | col2 +--------------------------------------------------------------------- +(0 rows) + +SELECT t1.*, t2.*, t3.* FROM t1 FULL JOIN t2 ON (t1.col2 = t2.col2) INNER JOIN t3 ON (t3.col2 = t2.col2) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "t2" ][ dual partition join(LEFT) "t1" ][ dual partition join(INNER) "t3" ] + col1 | col2 | col1 | col2 | col1 | col2 +--------------------------------------------------------------------- + | | 11 | 11 | 11 | 11 + | | 12 | 12 | 12 | 12 + | | 13 | 13 | 13 | 13 + | | 14 | 14 | 14 | 14 + | | 15 | 15 | 15 | 15 +(5 rows) + +SELECT t1.*, t2.*, t3.* FROM t1 FULL JOIN t2 ON (t1.col2 = t2.col1) INNER JOIN t3 ON (t3.col2 = t1.col1) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "t1" ][ dual partition join(LEFT) "t2" ][ dual partition join(INNER) "t3" ] + col1 | col2 | col1 | col2 | col1 | col2 +--------------------------------------------------------------------- +(0 rows) + +SELECT t1.*, t2.*, t3.* FROM t1 FULL JOIN t2 ON (t1.col2 = t2.col1) INNER JOIN t3 ON (t3.col2 = t2.col1) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "t2" ][ dual partition join(LEFT) "t1" ][ dual partition join(INNER) "t3" ] + col1 | col2 | col1 | col2 | col1 | col2 +--------------------------------------------------------------------- + | | 11 | 11 | 11 | 11 + | | 12 | 12 | 12 | 12 + | | 13 | 13 | 13 | 13 + | | 14 | 14 | 14 | 14 + | | 15 | 15 | 15 | 15 +(5 rows) + +-- join order planner cannot handle semi joins +SELECT t1.* FROM t1 WHERE EXISTS (SELECT * FROM t2 WHERE t1.col1 = t2.col1) ORDER BY 1,2; +ERROR: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns +SELECT t1.* FROM t1 WHERE EXISTS (SELECT * FROM t2 WHERE t1.col2 = t2.col2) ORDER BY 1,2; +ERROR: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns +SELECT t2.* FROM t2 WHERE EXISTS (SELECT * FROM t1 WHERE t1.col1 = t2.col1) ORDER BY 1,2; +ERROR: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns +SELECT t2.* FROM t2 WHERE EXISTS (SELECT * FROM t1 WHERE t1.col2 = t2.col2) ORDER BY 1,2; +ERROR: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns +------------------------- wrong results below, should not be supported if there exists nonsimple join clause +-- join order planner cannot handle anti join between tables with simple join clause +SELECT t1.* FROM t1 WHERE NOT EXISTS (SELECT * FROM t2 WHERE t1.col1 = t2.col1) ORDER BY 1,2; +ERROR: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns +SELECT t1.* FROM t1 WHERE NOT EXISTS (SELECT * FROM t2 WHERE t1.col2 = t2.col2) ORDER BY 1,2; +ERROR: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns +SELECT t2.* FROM t2 WHERE NOT EXISTS (SELECT * FROM t1 WHERE t1.col1 = t2.col1) ORDER BY 1,2; +ERROR: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns +SELECT t2.* FROM t2 WHERE NOT EXISTS (SELECT * FROM t1 WHERE t1.col2 = t2.col2) ORDER BY 1,2; +ERROR: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns +-- join order planner cannot handle left outer join between tables with nonsimple join clause +-- where constraint(t1.col1 IS NULL or t2.col2 IS NULL) is considered as join constraint +SELECT t1.*, t2.* FROM t1 LEFT JOIN t2 ON (t1.col1 = t2.col1) WHERE (t1.col1 IS NULL or t2.col2 IS NULL) ORDER BY 1,2,3,4; +LOG: join order: [ "t1" ][ dual partition join(LEFT) "t2" ] + col1 | col2 | col1 | col2 +--------------------------------------------------------------------- + 1 | 1 | | + 2 | 2 | | + 3 | 3 | | + 4 | 4 | | + 5 | 5 | | + 6 | 6 | | + 7 | 7 | | + 8 | 8 | | + 9 | 9 | | + 10 | 10 | | +(10 rows) + +-- join constraint(t1.col1 < 0) is considered as where constraint +SELECT t1.*, t2.* FROM t1 LEFT JOIN t2 ON (t1.col1 = t2.col1 and t1.col1 < 0) ORDER BY 1,2,3,4; +LOG: join order: [ "t1" ][ dual partition join(LEFT) "t2" ] + col1 | col2 | col1 | col2 +--------------------------------------------------------------------- + 1 | 1 | | + 2 | 2 | | + 3 | 3 | | + 4 | 4 | | + 5 | 5 | | + 6 | 6 | 6 | 6 + 7 | 7 | 7 | 7 + 8 | 8 | 8 | 8 + 9 | 9 | 9 | 9 + 10 | 10 | 10 | 10 +(10 rows) + diff --git a/src/test/regress/sql/non_colocated_outer_joins.sql b/src/test/regress/sql/non_colocated_outer_joins.sql new file mode 100644 index 000000000..4c81c213e --- /dev/null +++ b/src/test/regress/sql/non_colocated_outer_joins.sql @@ -0,0 +1,93 @@ +CREATE TABLE t1(col1 INT, col2 INT); +SELECT create_distributed_table('t1', 'col1'); +INSERT INTO t1 SELECT i, i FROM generate_series(1,10) i; + +CREATE TABLE t2(col1 INT, col2 INT); +SELECT create_distributed_table('t2', 'col2'); +INSERT INTO t2 SELECT i, i FROM generate_series(6,15) i; + +CREATE TABLE t3(col1 INT, col2 INT); +SELECT create_distributed_table('t3', 'col1'); +INSERT INTO t3 SELECT i, i FROM generate_series(11,20) i; + +SET citus.enable_repartition_joins TO ON; +SET citus.log_multi_join_order TO ON; +SET client_min_messages TO LOG; + + +-- join order planner can handle left outer join between tables with simple join clause + +-- outer table restricted on partition column whereas inner one is not restricted on the partition column +SELECT t1.*, t2.* FROM t1 LEFT JOIN t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +-- inner table restricted on partition column whereas outer one is not restricted on the partition column +SELECT t1.*, t2.* FROM t1 LEFT JOIN t2 ON (t1.col2 = t2.col2) ORDER BY 1,2,3,4; +-- both tables are not restricted on partition column +SELECT t1.*, t2.* FROM t1 LEFT JOIN t2 ON (t1.col2 = t2.col1) ORDER BY 1,2,3,4; + + +-- join order planner can handle right outer join between tables with simple join clause + +-- outer table restricted on partition column whereas inner one is not restricted on the partition column +SELECT t1.*, t2.* FROM t1 RIGHT JOIN t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +-- inner table restricted on partition column whereas outer one is not restricted on the partition column +SELECT t1.*, t2.* FROM t1 RIGHT JOIN t2 ON (t1.col2 = t2.col2) ORDER BY 1,2,3,4; +-- both tables are not restricted on partition column +SELECT t1.*, t2.* FROM t1 RIGHT JOIN t2 ON (t1.col2 = t2.col1) ORDER BY 1,2,3,4; + + +-- join order planner can handle full outer join between tables with simple join clause + +-- left outer table restricted on partition column whereas right outer one is not restricted on the partition column +SELECT t1.*, t2.* FROM t1 FULL JOIN t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +-- right outer table restricted on partition column whereas left outer one is not restricted on the partition column +SELECT t1.*, t2.* FROM t1 FULL JOIN t2 ON (t1.col2 = t2.col2) ORDER BY 1,2,3,4; +-- both tables are not restricted on partition column +SELECT t1.*, t2.* FROM t1 FULL JOIN t2 ON (t1.col2 = t2.col1) ORDER BY 1,2,3,4; + + +-- join order planner can handle queries with multi joins consisting of outer joins with simple join clause + +SELECT t1.*, t2.*, t3.* FROM t1 RIGHT JOIN t2 ON (t1.col1 = t2.col1) INNER JOIN t3 ON (t3.col1 = t1.col1) ORDER BY 1,2,3,4,5,6; +SELECT t1.*, t2.*, t3.* FROM t1 RIGHT JOIN t2 ON (t1.col1 = t2.col1) INNER JOIN t3 ON (t3.col1 = t2.col1) ORDER BY 1,2,3,4,5,6; +SELECT t1.*, t2.*, t3.* FROM t1 RIGHT JOIN t2 ON (t1.col2 = t2.col2) INNER JOIN t3 ON (t3.col2 = t1.col2) ORDER BY 1,2,3,4,5,6; +SELECT t1.*, t2.*, t3.* FROM t1 RIGHT JOIN t2 ON (t1.col2 = t2.col2) INNER JOIN t3 ON (t3.col2 = t2.col2) ORDER BY 1,2,3,4,5,6; +SELECT t1.*, t2.*, t3.* FROM t1 RIGHT JOIN t2 ON (t1.col2 = t2.col1) INNER JOIN t3 ON (t3.col2 = t1.col1) ORDER BY 1,2,3,4,5,6; +SELECT t1.*, t2.*, t3.* FROM t1 RIGHT JOIN t2 ON (t1.col2 = t2.col1) INNER JOIN t3 ON (t3.col2 = t2.col1) ORDER BY 1,2,3,4,5,6; + +SELECT t1.*, t2.*, t3.* FROM t2 LEFT JOIN t1 ON (t1.col1 = t2.col1) INNER JOIN t3 ON (t3.col1 = t1.col1) ORDER BY 1,2,3,4,5,6; +SELECT t1.*, t2.*, t3.* FROM t2 LEFT JOIN t1 ON (t1.col1 = t2.col1) INNER JOIN t3 ON (t3.col1 = t2.col1) ORDER BY 1,2,3,4,5,6; +SELECT t1.*, t2.*, t3.* FROM t2 LEFT JOIN t1 ON (t1.col2 = t2.col2) INNER JOIN t3 ON (t3.col2 = t1.col2) ORDER BY 1,2,3,4,5,6; +SELECT t1.*, t2.*, t3.* FROM t2 LEFT JOIN t1 ON (t1.col2 = t2.col2) INNER JOIN t3 ON (t3.col2 = t2.col2) ORDER BY 1,2,3,4,5,6; +SELECT t1.*, t2.*, t3.* FROM t2 LEFT JOIN t1 ON (t1.col2 = t2.col1) INNER JOIN t3 ON (t3.col2 = t1.col1) ORDER BY 1,2,3,4,5,6; +SELECT t1.*, t2.*, t3.* FROM t2 LEFT JOIN t1 ON (t1.col2 = t2.col1) INNER JOIN t3 ON (t3.col2 = t2.col1) ORDER BY 1,2,3,4,5,6; + +SELECT t1.*, t2.*, t3.* FROM t1 FULL JOIN t2 ON (t1.col1 = t2.col1) INNER JOIN t3 ON (t3.col1 = t1.col1) ORDER BY 1,2,3,4,5,6; +SELECT t1.*, t2.*, t3.* FROM t1 FULL JOIN t2 ON (t1.col1 = t2.col1) INNER JOIN t3 ON (t3.col1 = t2.col1) ORDER BY 1,2,3,4,5,6; +SELECT t1.*, t2.*, t3.* FROM t1 FULL JOIN t2 ON (t1.col2 = t2.col2) INNER JOIN t3 ON (t3.col2 = t1.col2) ORDER BY 1,2,3,4,5,6; +SELECT t1.*, t2.*, t3.* FROM t1 FULL JOIN t2 ON (t1.col2 = t2.col2) INNER JOIN t3 ON (t3.col2 = t2.col2) ORDER BY 1,2,3,4,5,6; +SELECT t1.*, t2.*, t3.* FROM t1 FULL JOIN t2 ON (t1.col2 = t2.col1) INNER JOIN t3 ON (t3.col2 = t1.col1) ORDER BY 1,2,3,4,5,6; +SELECT t1.*, t2.*, t3.* FROM t1 FULL JOIN t2 ON (t1.col2 = t2.col1) INNER JOIN t3 ON (t3.col2 = t2.col1) ORDER BY 1,2,3,4,5,6; + +-- join order planner cannot handle semi joins + +SELECT t1.* FROM t1 WHERE EXISTS (SELECT * FROM t2 WHERE t1.col1 = t2.col1) ORDER BY 1,2; +SELECT t1.* FROM t1 WHERE EXISTS (SELECT * FROM t2 WHERE t1.col2 = t2.col2) ORDER BY 1,2; +SELECT t2.* FROM t2 WHERE EXISTS (SELECT * FROM t1 WHERE t1.col1 = t2.col1) ORDER BY 1,2; +SELECT t2.* FROM t2 WHERE EXISTS (SELECT * FROM t1 WHERE t1.col2 = t2.col2) ORDER BY 1,2; + + +------------------------- wrong results below, should not be supported if there exists nonsimple join clause + +-- join order planner cannot handle anti join between tables with simple join clause + +SELECT t1.* FROM t1 WHERE NOT EXISTS (SELECT * FROM t2 WHERE t1.col1 = t2.col1) ORDER BY 1,2; +SELECT t1.* FROM t1 WHERE NOT EXISTS (SELECT * FROM t2 WHERE t1.col2 = t2.col2) ORDER BY 1,2; +SELECT t2.* FROM t2 WHERE NOT EXISTS (SELECT * FROM t1 WHERE t1.col1 = t2.col1) ORDER BY 1,2; +SELECT t2.* FROM t2 WHERE NOT EXISTS (SELECT * FROM t1 WHERE t1.col2 = t2.col2) ORDER BY 1,2; + +-- join order planner cannot handle left outer join between tables with nonsimple join clause + +-- where constraint(t1.col1 IS NULL or t2.col2 IS NULL) is considered as join constraint +SELECT t1.*, t2.* FROM t1 LEFT JOIN t2 ON (t1.col1 = t2.col1) WHERE (t1.col1 IS NULL or t2.col2 IS NULL) ORDER BY 1,2,3,4; +-- join constraint(t1.col1 < 0) is considered as where constraint +SELECT t1.*, t2.* FROM t1 LEFT JOIN t2 ON (t1.col1 = t2.col1 and t1.col1 < 0) ORDER BY 1,2,3,4;