From 454857f3a7f0b8e53e506fb81f4bc6b3fe1c6a15 Mon Sep 17 00:00:00 2001 From: aykutbozkurt Date: Sun, 15 Jan 2023 20:04:52 +0300 Subject: [PATCH] add tests for append and range distributed tables --- .../distributed/planner/multi_join_order.c | 17 +- .../expected/non_colocated_outer_joins.out | 837 ++++++++++++++++-- .../regress/sql/non_colocated_outer_joins.sql | 201 ++++- 3 files changed, 921 insertions(+), 134 deletions(-) diff --git a/src/backend/distributed/planner/multi_join_order.c b/src/backend/distributed/planner/multi_join_order.c index eb6ae87a6..5282b250c 100644 --- a/src/backend/distributed/planner/multi_join_order.c +++ b/src/backend/distributed/planner/multi_join_order.c @@ -1208,11 +1208,24 @@ SinglePartitionJoin(JoinOrderNode *currentJoinNode, TableEntry *candidateTable, return NULL; } + /* + * we only allow single range redistribution if both tables are range distributed. + * The reason is that we cannot guarantee all values in nonrange distributed table + * will be inside the shard ranges of range distributed table. + */ + if ((currentPartitionMethod == DISTRIBUTE_BY_RANGE && candidatePartitionMethod != + DISTRIBUTE_BY_RANGE) || + (candidatePartitionMethod == DISTRIBUTE_BY_RANGE && currentPartitionMethod != + DISTRIBUTE_BY_RANGE)) + { + return NULL; + } + OpExpr *joinClause = SinglePartitionJoinClause(currentPartitionColumnList, applicableJoinClauses); if (joinClause != NULL) { - if (currentPartitionMethod == DISTRIBUTE_BY_HASH) + if (currentPartitionMethod != DISTRIBUTE_BY_RANGE) { /* * Single hash repartitioning may perform worse than dual hash @@ -1250,7 +1263,7 @@ SinglePartitionJoin(JoinOrderNode *currentJoinNode, TableEntry *candidateTable, applicableJoinClauses); if (joinClause != NULL) { - if (candidatePartitionMethod == DISTRIBUTE_BY_HASH) + if (candidatePartitionMethod != DISTRIBUTE_BY_RANGE) { /* * Single hash repartitioning may perform worse than dual hash diff --git a/src/test/regress/expected/non_colocated_outer_joins.out b/src/test/regress/expected/non_colocated_outer_joins.out index 117f605c6..579c81d17 100644 --- a/src/test/regress/expected/non_colocated_outer_joins.out +++ b/src/test/regress/expected/non_colocated_outer_joins.out @@ -1,36 +1,36 @@ CREATE SCHEMA non_colocated_outer_joins; SET search_path TO non_colocated_outer_joins; -CREATE TABLE t1(col1 INT, col2 INT); -SELECT create_distributed_table('t1', 'col1'); +CREATE TABLE test_hash1(col1 INT, col2 INT); +SELECT create_distributed_table('test_hash1', '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'); +INSERT INTO test_hash1 SELECT i, i FROM generate_series(1,10) i; +CREATE TABLE test_hash2(col1 INT, col2 INT); +SELECT create_distributed_table('test_hash2', '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'); +INSERT INTO test_hash2 SELECT i, i FROM generate_series(6,15) i; +CREATE TABLE test_hash3(col1 INT, col2 INT); +SELECT create_distributed_table('test_hash3', 'col1'); create_distributed_table --------------------------------------------------------------------- (1 row) -INSERT INTO t3 SELECT i, i FROM generate_series(11,20) i; +INSERT INTO test_hash3 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" ] +SELECT t1.*, t2.* FROM test_hash1 t1 LEFT JOIN test_hash2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +LOG: join order: [ "test_hash1" ][ dual partition join(LEFT) "test_hash2" ] col1 | col2 | col1 | col2 --------------------------------------------------------------------- 1 | 1 | | @@ -46,8 +46,8 @@ LOG: join order: [ "t1" ][ dual partition join(LEFT) "t2" ] (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" ] +SELECT t1.*, t2.* FROM test_hash1 t1 LEFT JOIN test_hash2 t2 ON (t1.col2 = t2.col2) ORDER BY 1,2,3,4; +LOG: join order: [ "test_hash1" ][ dual partition join(LEFT) "test_hash2" ] col1 | col2 | col1 | col2 --------------------------------------------------------------------- 1 | 1 | | @@ -63,8 +63,8 @@ LOG: join order: [ "t1" ][ dual partition join(LEFT) "t2" ] (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" ] +SELECT t1.*, t2.* FROM test_hash1 t1 LEFT JOIN test_hash2 t2 ON (t1.col2 = t2.col1) ORDER BY 1,2,3,4; +LOG: join order: [ "test_hash1" ][ dual partition join(LEFT) "test_hash2" ] col1 | col2 | col1 | col2 --------------------------------------------------------------------- 1 | 1 | | @@ -81,8 +81,8 @@ LOG: join order: [ "t1" ][ dual partition join(LEFT) "t2" ] -- 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" ] +SELECT t1.*, t2.* FROM test_hash1 t1 RIGHT JOIN test_hash2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +LOG: join order: [ "test_hash2" ][ dual partition join(LEFT) "test_hash1" ] col1 | col2 | col1 | col2 --------------------------------------------------------------------- 6 | 6 | 6 | 6 @@ -98,8 +98,8 @@ LOG: join order: [ "t2" ][ dual partition join(LEFT) "t1" ] (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" ] +SELECT t1.*, t2.* FROM test_hash1 t1 RIGHT JOIN test_hash2 t2 ON (t1.col2 = t2.col2) ORDER BY 1,2,3,4; +LOG: join order: [ "test_hash2" ][ dual partition join(LEFT) "test_hash1" ] col1 | col2 | col1 | col2 --------------------------------------------------------------------- 6 | 6 | 6 | 6 @@ -115,8 +115,8 @@ LOG: join order: [ "t2" ][ dual partition join(LEFT) "t1" ] (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" ] +SELECT t1.*, t2.* FROM test_hash1 t1 RIGHT JOIN test_hash2 t2 ON (t1.col2 = t2.col1) ORDER BY 1,2,3,4; +LOG: join order: [ "test_hash2" ][ dual partition join(LEFT) "test_hash1" ] col1 | col2 | col1 | col2 --------------------------------------------------------------------- 6 | 6 | 6 | 6 @@ -133,8 +133,8 @@ LOG: join order: [ "t2" ][ dual partition join(LEFT) "t1" ] -- 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" ] +SELECT t1.*, t2.* FROM test_hash1 t1 FULL JOIN test_hash2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +LOG: join order: [ "test_hash1" ][ dual partition join(FULL) "test_hash2" ] col1 | col2 | col1 | col2 --------------------------------------------------------------------- 1 | 1 | | @@ -155,8 +155,8 @@ LOG: join order: [ "t1" ][ dual partition join(FULL) "t2" ] (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" ] +SELECT t1.*, t2.* FROM test_hash1 t1 FULL JOIN test_hash2 t2 ON (t1.col2 = t2.col2) ORDER BY 1,2,3,4; +LOG: join order: [ "test_hash1" ][ dual partition join(FULL) "test_hash2" ] col1 | col2 | col1 | col2 --------------------------------------------------------------------- 1 | 1 | | @@ -177,8 +177,8 @@ LOG: join order: [ "t1" ][ dual partition join(FULL) "t2" ] (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" ] +SELECT t1.*, t2.* FROM test_hash1 t1 FULL JOIN test_hash2 t2 ON (t1.col2 = t2.col1) ORDER BY 1,2,3,4; +LOG: join order: [ "test_hash1" ][ dual partition join(FULL) "test_hash2" ] col1 | col2 | col1 | col2 --------------------------------------------------------------------- 1 | 1 | | @@ -199,14 +199,14 @@ LOG: join order: [ "t1" ][ dual partition join(FULL) "t2" ] (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" ] +SELECT t1.*, t2.*, t3.* FROM test_hash1 t1 RIGHT JOIN test_hash2 t2 ON (t1.col1 = t2.col1) INNER JOIN test_hash3 t3 ON (t3.col1 = t1.col1) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "test_hash1" ][ local partition join(INNER) "test_hash3" ][ dual partition join(INNER) "test_hash2" ] 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" ] +SELECT t1.*, t2.*, t3.* FROM test_hash1 t1 RIGHT JOIN test_hash2 t2 ON (t1.col1 = t2.col1) INNER JOIN test_hash3 t3 ON (t3.col1 = t2.col1) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "test_hash2" ][ dual partition join(LEFT) "test_hash1" ][ dual partition join(INNER) "test_hash3" ] col1 | col2 | col1 | col2 | col1 | col2 --------------------------------------------------------------------- | | 11 | 11 | 11 | 11 @@ -216,14 +216,14 @@ LOG: join order: [ "t2" ][ dual partition join(LEFT) "t1" ][ dual partition joi | | 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" ] +SELECT t1.*, t2.*, t3.* FROM test_hash1 t1 RIGHT JOIN test_hash2 t2 ON (t1.col2 = t2.col2) INNER JOIN test_hash3 t3 ON (t3.col2 = t1.col2) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "test_hash1" ][ dual partition join(INNER) "test_hash2" ][ dual partition join(INNER) "test_hash3" ] 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" ] +SELECT t1.*, t2.*, t3.* FROM test_hash1 t1 RIGHT JOIN test_hash2 t2 ON (t1.col2 = t2.col2) INNER JOIN test_hash3 t3 ON (t3.col2 = t2.col2) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "test_hash2" ][ dual partition join(LEFT) "test_hash1" ][ dual partition join(INNER) "test_hash3" ] col1 | col2 | col1 | col2 | col1 | col2 --------------------------------------------------------------------- | | 11 | 11 | 11 | 11 @@ -233,14 +233,14 @@ LOG: join order: [ "t2" ][ dual partition join(LEFT) "t1" ][ dual partition joi | | 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" ] +SELECT t1.*, t2.*, t3.* FROM test_hash1 t1 RIGHT JOIN test_hash2 t2 ON (t1.col2 = t2.col1) INNER JOIN test_hash3 t3 ON (t3.col2 = t1.col1) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "test_hash1" ][ dual partition join(INNER) "test_hash2" ][ dual partition join(INNER) "test_hash3" ] 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" ] +SELECT t1.*, t2.*, t3.* FROM test_hash1 t1 RIGHT JOIN test_hash2 t2 ON (t1.col2 = t2.col1) INNER JOIN test_hash3 t3 ON (t3.col2 = t2.col1) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "test_hash2" ][ dual partition join(LEFT) "test_hash1" ][ dual partition join(INNER) "test_hash3" ] col1 | col2 | col1 | col2 | col1 | col2 --------------------------------------------------------------------- | | 11 | 11 | 11 | 11 @@ -250,14 +250,14 @@ LOG: join order: [ "t2" ][ dual partition join(LEFT) "t1" ][ dual partition joi | | 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" ] +SELECT t1.*, t2.*, t3.* FROM test_hash2 t2 LEFT JOIN test_hash1 t1 ON (t1.col1 = t2.col1) INNER JOIN test_hash3 t3 ON (t3.col1 = t1.col1) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "test_hash1" ][ local partition join(INNER) "test_hash3" ][ dual partition join(INNER) "test_hash2" ] 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" ] +SELECT t1.*, t2.*, t3.* FROM test_hash2 t2 LEFT JOIN test_hash1 t1 ON (t1.col1 = t2.col1) INNER JOIN test_hash3 t3 ON (t3.col1 = t2.col1) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "test_hash2" ][ dual partition join(LEFT) "test_hash1" ][ dual partition join(INNER) "test_hash3" ] col1 | col2 | col1 | col2 | col1 | col2 --------------------------------------------------------------------- | | 11 | 11 | 11 | 11 @@ -267,14 +267,14 @@ LOG: join order: [ "t2" ][ dual partition join(LEFT) "t1" ][ dual partition joi | | 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" ] +SELECT t1.*, t2.*, t3.* FROM test_hash2 t2 LEFT JOIN test_hash1 t1 ON (t1.col2 = t2.col2) INNER JOIN test_hash3 t3 ON (t3.col2 = t1.col2) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "test_hash2" ][ dual partition join(INNER) "test_hash1" ][ dual partition join(INNER) "test_hash3" ] 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" ] +SELECT t1.*, t2.*, t3.* FROM test_hash2 t2 LEFT JOIN test_hash1 t1 ON (t1.col2 = t2.col2) INNER JOIN test_hash3 t3 ON (t3.col2 = t2.col2) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "test_hash2" ][ dual partition join(LEFT) "test_hash1" ][ dual partition join(INNER) "test_hash3" ] col1 | col2 | col1 | col2 | col1 | col2 --------------------------------------------------------------------- | | 11 | 11 | 11 | 11 @@ -284,14 +284,14 @@ LOG: join order: [ "t2" ][ dual partition join(LEFT) "t1" ][ dual partition joi | | 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" ] +SELECT t1.*, t2.*, t3.* FROM test_hash2 t2 LEFT JOIN test_hash1 t1 ON (t1.col2 = t2.col1) INNER JOIN test_hash3 t3 ON (t3.col2 = t1.col1) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "test_hash2" ][ dual partition join(INNER) "test_hash1" ][ dual partition join(INNER) "test_hash3" ] 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" ] +SELECT t1.*, t2.*, t3.* FROM test_hash2 t2 LEFT JOIN test_hash1 t1 ON (t1.col2 = t2.col1) INNER JOIN test_hash3 t3 ON (t3.col2 = t2.col1) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "test_hash2" ][ dual partition join(LEFT) "test_hash1" ][ dual partition join(INNER) "test_hash3" ] col1 | col2 | col1 | col2 | col1 | col2 --------------------------------------------------------------------- | | 11 | 11 | 11 | 11 @@ -301,14 +301,14 @@ LOG: join order: [ "t2" ][ dual partition join(LEFT) "t1" ][ dual partition joi | | 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" ] +SELECT t1.*, t2.*, t3.* FROM test_hash1 t1 FULL JOIN test_hash2 t2 ON (t1.col1 = t2.col1) INNER JOIN test_hash3 t3 ON (t3.col1 = t1.col1) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "test_hash1" ][ dual partition join(LEFT) "test_hash2" ][ dual partition join(INNER) "test_hash3" ] 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" ] +SELECT t1.*, t2.*, t3.* FROM test_hash1 t1 FULL JOIN test_hash2 t2 ON (t1.col1 = t2.col1) INNER JOIN test_hash3 t3 ON (t3.col1 = t2.col1) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "test_hash2" ][ dual partition join(LEFT) "test_hash1" ][ dual partition join(INNER) "test_hash3" ] col1 | col2 | col1 | col2 | col1 | col2 --------------------------------------------------------------------- | | 11 | 11 | 11 | 11 @@ -318,14 +318,14 @@ LOG: join order: [ "t2" ][ dual partition join(LEFT) "t1" ][ dual partition joi | | 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" ] +SELECT t1.*, t2.*, t3.* FROM test_hash1 t1 FULL JOIN test_hash2 t2 ON (t1.col2 = t2.col2) INNER JOIN test_hash3 t3 ON (t3.col2 = t1.col2) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "test_hash1" ][ dual partition join(LEFT) "test_hash2" ][ dual partition join(INNER) "test_hash3" ] 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" ] +SELECT t1.*, t2.*, t3.* FROM test_hash1 t1 FULL JOIN test_hash2 t2 ON (t1.col2 = t2.col2) INNER JOIN test_hash3 t3 ON (t3.col2 = t2.col2) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "test_hash2" ][ dual partition join(LEFT) "test_hash1" ][ dual partition join(INNER) "test_hash3" ] col1 | col2 | col1 | col2 | col1 | col2 --------------------------------------------------------------------- | | 11 | 11 | 11 | 11 @@ -335,14 +335,14 @@ LOG: join order: [ "t2" ][ dual partition join(LEFT) "t1" ][ dual partition joi | | 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" ] +SELECT t1.*, t2.*, t3.* FROM test_hash1 t1 FULL JOIN test_hash2 t2 ON (t1.col2 = t2.col1) INNER JOIN test_hash3 t3 ON (t3.col2 = t1.col1) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "test_hash1" ][ dual partition join(LEFT) "test_hash2" ][ dual partition join(INNER) "test_hash3" ] 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" ] +SELECT t1.*, t2.*, t3.* FROM test_hash1 t1 FULL JOIN test_hash2 t2 ON (t1.col2 = t2.col1) INNER JOIN test_hash3 t3 ON (t3.col2 = t2.col1) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "test_hash2" ][ dual partition join(LEFT) "test_hash1" ][ dual partition join(INNER) "test_hash3" ] col1 | col2 | col1 | col2 | col1 | col2 --------------------------------------------------------------------- | | 11 | 11 | 11 | 11 @@ -353,8 +353,8 @@ LOG: join order: [ "t2" ][ dual partition join(LEFT) "t1" ][ dual partition joi (5 rows) -- join order planner handles left outer join between tables with nonsimple join or where clause -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" ] +SELECT t1.*, t2.* FROM test_hash1 t1 LEFT JOIN test_hash2 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: [ "test_hash1" ][ dual partition join(LEFT) "test_hash2" ] col1 | col2 | col1 | col2 --------------------------------------------------------------------- 1 | 1 | | @@ -364,8 +364,8 @@ LOG: join order: [ "t1" ][ dual partition join(LEFT) "t2" ] 5 | 5 | | (5 rows) -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" ] +SELECT t1.*, t2.* FROM test_hash1 t1 LEFT JOIN test_hash2 t2 ON (t1.col1 = t2.col1 and t1.col1 < 0) ORDER BY 1,2,3,4; +LOG: join order: [ "test_hash1" ][ dual partition join(LEFT) "test_hash2" ] col1 | col2 | col1 | col2 --------------------------------------------------------------------- 1 | 1 | | @@ -380,40 +380,711 @@ LOG: join order: [ "t1" ][ dual partition join(LEFT) "t2" ] 10 | 10 | | (10 rows) +-- join order planner supports repartition join between append distributed tables +CREATE TABLE test_append1 (col1 INT, col2 INT); +SELECT create_distributed_table('test_append1', 'col1', 'append'); + create_distributed_table +--------------------------------------------------------------------- + +(1 row) + +SELECT master_create_empty_shard('test_append1') AS new_shard_id \gset +UPDATE pg_dist_shard SET shardminvalue = 1, shardmaxvalue = 5 WHERE shardid = :new_shard_id; +SELECT master_create_empty_shard('test_append1') AS new_shard_id \gset +UPDATE pg_dist_shard SET shardminvalue = 6, shardmaxvalue = 10 WHERE shardid = :new_shard_id; +INSERT INTO test_append1 VALUES (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9),(10,10); +CREATE TABLE test_append2 (col1 INT, col2 INT); +SELECT create_distributed_table('test_append2', 'col2', 'append'); + create_distributed_table +--------------------------------------------------------------------- + +(1 row) + +SELECT master_create_empty_shard('test_append2') AS new_shard_id \gset +UPDATE pg_dist_shard SET shardminvalue = 6, shardmaxvalue = 10 WHERE shardid = :new_shard_id; +SELECT master_create_empty_shard('test_append2') AS new_shard_id \gset +UPDATE pg_dist_shard SET shardminvalue = 11, shardmaxvalue = 15 WHERE shardid = :new_shard_id; +INSERT INTO test_append2 VALUES (6,6),(7,7),(8,8),(9,9),(10,10),(11,11),(12,12),(13,13),(14,14),(15,15); +CREATE TABLE test_append3(col1 INT, col2 INT); +SELECT create_distributed_table('test_append3', 'col1', 'append'); + create_distributed_table +--------------------------------------------------------------------- + +(1 row) + +SELECT master_create_empty_shard('test_append3') AS new_shard_id \gset +UPDATE pg_dist_shard SET shardminvalue = 11, shardmaxvalue = 15 WHERE shardid = :new_shard_id; +SELECT master_create_empty_shard('test_append3') AS new_shard_id \gset +UPDATE pg_dist_shard SET shardminvalue = 16, shardmaxvalue = 20 WHERE shardid = :new_shard_id; +INSERT INTO test_append3 VALUES (11,11),(12,12),(13,13),(14,14),(15,15),(16,16),(17,17),(18,18),(19,19),(20,20); +-- join order planner supports repartition join between append-append distributed tables +SELECT t1.*, t2.* FROM test_append1 t1 LEFT JOIN test_append2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +LOG: join order: [ "test_append1" ][ dual partition join(LEFT) "test_append2" ] + 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) + +SELECT t1.*, t2.* FROM test_append1 t1 RIGHT JOIN test_append2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +LOG: join order: [ "test_append2" ][ dual partition join(LEFT) "test_append1" ] + 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) + +SELECT t1.*, t2.* FROM test_append1 t1 FULL JOIN test_append2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +LOG: join order: [ "test_append1" ][ dual partition join(FULL) "test_append2" ] + 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) + +SELECT t1.*, t2.*, t3.* FROM test_append1 t1 RIGHT JOIN test_append2 t2 ON (t1.col1 = t2.col1) INNER JOIN test_append3 t3 ON (t3.col1 = t2.col1) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "test_append2" ][ dual partition join(LEFT) "test_append1" ][ dual partition join(INNER) "test_append3" ] + 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 test_append2 t2 LEFT JOIN test_append1 t1 ON (t1.col1 = t2.col1) INNER JOIN test_append3 t3 ON (t3.col1 = t2.col1) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "test_append2" ][ dual partition join(LEFT) "test_append1" ][ dual partition join(INNER) "test_append3" ] + 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 test_append1 t1 FULL JOIN test_append2 t2 ON (t1.col1 = t2.col1) INNER JOIN test_append3 t3 ON (t3.col1 = t2.col1) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "test_append2" ][ dual partition join(LEFT) "test_append1" ][ dual partition join(INNER) "test_append3" ] + 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 supports repartition join between append-hash distributed tables +SELECT t1.*, t2.* FROM test_append1 t1 LEFT JOIN test_hash2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +LOG: join order: [ "test_append1" ][ dual partition join(LEFT) "test_hash2" ] + 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) + +SELECT t1.*, t2.* FROM test_hash1 t1 LEFT JOIN test_append2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +LOG: join order: [ "test_hash1" ][ dual partition join(LEFT) "test_append2" ] + 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) + +SELECT t1.*, t2.* FROM test_append1 t1 RIGHT JOIN test_hash2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +LOG: join order: [ "test_hash2" ][ dual partition join(LEFT) "test_append1" ] + 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) + +SELECT t1.*, t2.* FROM test_hash1 t1 RIGHT JOIN test_append2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +LOG: join order: [ "test_append2" ][ dual partition join(LEFT) "test_hash1" ] + 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) + +SELECT t1.*, t2.* FROM test_append1 t1 FULL JOIN test_hash2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +LOG: join order: [ "test_append1" ][ dual partition join(FULL) "test_hash2" ] + 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) + +SELECT t1.*, t2.* FROM test_hash1 t1 FULL JOIN test_append2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +LOG: join order: [ "test_hash1" ][ dual partition join(FULL) "test_append2" ] + 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) + +SELECT t1.*, t2.*, t3.* FROM test_hash1 t1 RIGHT JOIN test_append2 t2 ON (t1.col1 = t2.col1) INNER JOIN test_hash3 t3 ON (t3.col1 = t2.col1) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "test_append2" ][ dual partition join(LEFT) "test_hash1" ][ dual partition join(INNER) "test_hash3" ] + 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 test_append2 t2 LEFT JOIN test_hash1 t1 ON (t1.col1 = t2.col1) INNER JOIN test_hash3 t3 ON (t3.col1 = t2.col1) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "test_append2" ][ dual partition join(LEFT) "test_hash1" ][ dual partition join(INNER) "test_hash3" ] + 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 test_hash1 t1 FULL JOIN test_append2 t2 ON (t1.col1 = t2.col1) INNER JOIN test_hash3 t3 ON (t3.col1 = t2.col1) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "test_append2" ][ dual partition join(LEFT) "test_hash1" ][ dual partition join(INNER) "test_hash3" ] + 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 supports repartition join between range distributed tables +CREATE TABLE test_range1(col1 INT, col2 INT); +SELECT create_distributed_table('test_range1', 'col1', 'range'); + create_distributed_table +--------------------------------------------------------------------- + +(1 row) + +CALL public.create_range_partitioned_shards('test_range1', + '{0,6,11,16}', + '{5,10,15,20}'); +INSERT INTO test_range1 SELECT i, i FROM generate_series(1,10) i; +CREATE TABLE test_range2(col1 INT, col2 INT); +SELECT create_distributed_table('test_range2', 'col2', 'range'); + create_distributed_table +--------------------------------------------------------------------- + +(1 row) + +CALL public.create_range_partitioned_shards('test_range2', + '{0,6,11,16}', + '{5,10,15,20}'); +INSERT INTO test_range2 SELECT i, i FROM generate_series(6,15) i; +CREATE TABLE test_range3(col1 INT, col2 INT); +SELECT create_distributed_table('test_range3', 'col1', 'range'); + create_distributed_table +--------------------------------------------------------------------- + +(1 row) + +CALL public.create_range_partitioned_shards('test_range3', + '{0,6,11,16}', + '{5,10,15,20}'); +INSERT INTO test_range3 SELECT i, i FROM generate_series(11,20) i; +-- join order planner supports repartition join between range-range distributed tables +SELECT t1.*, t2.* FROM test_range1 t1 LEFT JOIN test_range2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +LOG: join order: [ "test_range1" ][ single range partition join(LEFT) "test_range2" ] + 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) + +SELECT t1.*, t2.* FROM test_range1 t1 RIGHT JOIN test_range2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +LOG: join order: [ "test_range2" ][ single range partition join(LEFT) "test_range1" ] + 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) + +SELECT t1.*, t2.* FROM test_range1 t1 FULL JOIN test_range2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +LOG: join order: [ "test_range1" ][ single range partition join(FULL) "test_range2" ] + 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) + +SELECT t1.*, t2.*, t3.* FROM test_range1 t1 RIGHT JOIN test_range2 t2 ON (t1.col1 = t2.col1) INNER JOIN test_range3 t3 ON (t3.col1 = t2.col1) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "test_range2" ][ single range partition join(LEFT) "test_range1" ][ single range partition join(INNER) "test_range3" ] + 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 test_range2 t2 LEFT JOIN test_range1 t1 ON (t1.col1 = t2.col1) INNER JOIN test_range3 t3 ON (t3.col1 = t2.col1) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "test_range2" ][ single range partition join(LEFT) "test_range1" ][ single range partition join(INNER) "test_range3" ] + 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 test_range1 t1 FULL JOIN test_range2 t2 ON (t1.col1 = t2.col1) INNER JOIN test_range3 t3 ON (t3.col1 = t2.col1) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "test_range2" ][ single range partition join(LEFT) "test_range1" ][ single range partition join(INNER) "test_range3" ] + 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 supports repartition join between range-hash distributed tables +SELECT t1.*, t2.* FROM test_range1 t1 LEFT JOIN test_hash2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +LOG: join order: [ "test_range1" ][ dual partition join(LEFT) "test_hash2" ] + 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) + +SELECT t1.*, t2.* FROM test_hash1 t1 LEFT JOIN test_range2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +LOG: join order: [ "test_hash1" ][ dual partition join(LEFT) "test_range2" ] + 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) + +SELECT t1.*, t2.* FROM test_range1 t1 RIGHT JOIN test_hash2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +LOG: join order: [ "test_hash2" ][ dual partition join(LEFT) "test_range1" ] + 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) + +SELECT t1.*, t2.* FROM test_hash1 t1 RIGHT JOIN test_range2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +LOG: join order: [ "test_range2" ][ dual partition join(LEFT) "test_hash1" ] + 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) + +SELECT t1.*, t2.* FROM test_range1 t1 FULL JOIN test_hash2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +LOG: join order: [ "test_range1" ][ dual partition join(FULL) "test_hash2" ] + 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) + +SELECT t1.*, t2.* FROM test_hash1 t1 FULL JOIN test_range2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +LOG: join order: [ "test_hash1" ][ dual partition join(FULL) "test_range2" ] + 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) + +SELECT t1.*, t2.*, t3.* FROM test_hash1 t1 RIGHT JOIN test_range2 t2 ON (t1.col1 = t2.col1) INNER JOIN test_hash3 t3 ON (t3.col1 = t2.col1) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "test_range2" ][ dual partition join(LEFT) "test_hash1" ][ dual partition join(INNER) "test_hash3" ] + 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 test_range2 t2 LEFT JOIN test_hash1 t1 ON (t1.col1 = t2.col1) INNER JOIN test_hash3 t3 ON (t3.col1 = t2.col1) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "test_range2" ][ dual partition join(LEFT) "test_hash1" ][ dual partition join(INNER) "test_hash3" ] + 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 test_hash1 t1 FULL JOIN test_range2 t2 ON (t1.col1 = t2.col1) INNER JOIN test_hash3 t3 ON (t3.col1 = t2.col1) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "test_range2" ][ dual partition join(LEFT) "test_hash1" ][ dual partition join(INNER) "test_hash3" ] + 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 supports repartition join between range-append distributed tables +SELECT t1.*, t2.* FROM test_range1 t1 LEFT JOIN test_append2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +LOG: join order: [ "test_range1" ][ dual partition join(LEFT) "test_append2" ] + 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) + +SELECT t1.*, t2.* FROM test_append1 t1 LEFT JOIN test_range2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +LOG: join order: [ "test_append1" ][ dual partition join(LEFT) "test_range2" ] + 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) + +SELECT t1.*, t2.* FROM test_range1 t1 RIGHT JOIN test_append2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +LOG: join order: [ "test_append2" ][ dual partition join(LEFT) "test_range1" ] + 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) + +SELECT t1.*, t2.* FROM test_append1 t1 RIGHT JOIN test_range2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +LOG: join order: [ "test_range2" ][ dual partition join(LEFT) "test_append1" ] + 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) + +SELECT t1.*, t2.* FROM test_range1 t1 FULL JOIN test_append2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +LOG: join order: [ "test_range1" ][ dual partition join(FULL) "test_append2" ] + 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) + +SELECT t1.*, t2.* FROM test_append1 t1 FULL JOIN test_range2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +LOG: join order: [ "test_append1" ][ dual partition join(FULL) "test_range2" ] + 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) + +SELECT t1.*, t2.*, t3.* FROM test_append1 t1 RIGHT JOIN test_range2 t2 ON (t1.col1 = t2.col1) INNER JOIN test_hash3 t3 ON (t3.col1 = t2.col1) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "test_range2" ][ dual partition join(LEFT) "test_append1" ][ dual partition join(INNER) "test_hash3" ] + 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 test_range2 t2 LEFT JOIN test_append1 t1 ON (t1.col1 = t2.col1) INNER JOIN test_hash3 t3 ON (t3.col1 = t2.col1) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "test_range2" ][ dual partition join(LEFT) "test_append1" ][ dual partition join(INNER) "test_hash3" ] + 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 test_append1 t1 FULL JOIN test_range2 t2 ON (t1.col1 = t2.col1) INNER JOIN test_hash3 t3 ON (t3.col1 = t2.col1) ORDER BY 1,2,3,4,5,6; +LOG: join order: [ "test_range2" ][ dual partition join(LEFT) "test_append1" ][ dual partition join(INNER) "test_hash3" ] + 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; +SELECT t1.* FROM test_hash1 t1 WHERE EXISTS (SELECT * FROM test_hash2 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; +SELECT t1.* FROM test_hash1 t1 WHERE EXISTS (SELECT * FROM test_hash2 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; +SELECT t2.* FROM test_hash2 t2 WHERE EXISTS (SELECT * FROM test_hash1 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; +SELECT t2.* FROM test_hash2 t2 WHERE EXISTS (SELECT * FROM test_hash1 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 anti joins -SELECT t1.* FROM t1 WHERE NOT EXISTS (SELECT * FROM t2 WHERE t1.col1 = t2.col1) ORDER BY 1,2; +SELECT t1.* FROM test_hash1 t1 WHERE NOT EXISTS (SELECT * FROM test_hash2 t2 WHERE t1.col1 = t2.col1) ORDER BY 1,2; ERROR: complex joins are only supported when all distributed tables are joined on their distribution columns with equal operator -SELECT t1.* FROM t1 WHERE NOT EXISTS (SELECT * FROM t2 WHERE t1.col2 = t2.col2) ORDER BY 1,2; +SELECT t1.* FROM test_hash1 t1 WHERE NOT EXISTS (SELECT * FROM test_hash2 t2 WHERE t1.col2 = t2.col2) ORDER BY 1,2; ERROR: complex joins are only supported when all distributed tables are joined on their distribution columns with equal operator -SELECT t2.* FROM t2 WHERE NOT EXISTS (SELECT * FROM t1 WHERE t1.col1 = t2.col1) ORDER BY 1,2; +SELECT t2.* FROM test_hash2 t2 WHERE NOT EXISTS (SELECT * FROM test_hash1 t1 WHERE t1.col1 = t2.col1) ORDER BY 1,2; ERROR: complex joins are only supported when all distributed tables are joined on their distribution columns with equal operator -SELECT t2.* FROM t2 WHERE NOT EXISTS (SELECT * FROM t1 WHERE t1.col2 = t2.col2) ORDER BY 1,2; +SELECT t2.* FROM test_hash2 t2 WHERE NOT EXISTS (SELECT * FROM test_hash1 t1 WHERE t1.col2 = t2.col2) ORDER BY 1,2; ERROR: complex joins are only supported when all distributed tables are joined on their distribution columns with equal operator -- join order planner cannot handle lateral outer joins -SELECT t1.*, tt2.* FROM t1 LEFT JOIN LATERAL (SELECT * FROM t2 WHERE t1.col1 = t2.col1) tt2 ON (t1.col1 = tt2.col1) ORDER BY 1,2,3,4; +SELECT t1.*, tt2.* FROM test_hash1 t1 LEFT JOIN LATERAL (SELECT * FROM test_hash2 t2 WHERE t1.col1 = t2.col1) tt2 ON (t1.col1 = tt2.col1) ORDER BY 1,2,3,4; ERROR: complex joins are only supported when all distributed tables are joined on their distribution columns with equal operator -- join order planner cannot handle cartesian joins -SELECT tt1.*, t3.* FROM (SELECT t1.* FROM t1,t2) tt1 LEFT JOIN t3 ON (tt1.col1 = t3.col1) ORDER BY 1,2,3,4; -LOG: join order: [ "t1" ][ cartesian product(INNER) "t2" ] +SELECT tt1.*, t3.* FROM (SELECT t1.* FROM test_hash1 t1, test_hash2 t2) tt1 LEFT JOIN test_hash3 t3 ON (tt1.col1 = t3.col1) ORDER BY 1,2,3,4; +LOG: join order: [ "test_hash1" ][ cartesian product(INNER) "test_hash2" ] ERROR: cannot perform distributed planning on this query DETAIL: Cartesian products are currently unsupported -- join order planner cannot handle right recursive joins -SELECT t1.*, t2.* FROM t1 LEFT JOIN ( t2 JOIN t3 ON t2.col2 = t3.col1) ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +SELECT t1.*, t2.* FROM test_hash1 t1 LEFT JOIN ( test_hash2 t2 JOIN test_hash3 t3 ON t2.col2 = t3.col1) ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; ERROR: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns DROP SCHEMA non_colocated_outer_joins CASCADE; -NOTICE: drop cascades to 3 other objects -DETAIL: drop cascades to table t1 -drop cascades to table t2 -drop cascades to table t3 +NOTICE: drop cascades to 9 other objects +DETAIL: drop cascades to table test_hash1 +drop cascades to table test_hash2 +drop cascades to table test_hash3 +drop cascades to table test_append1 +drop cascades to table test_append2 +drop cascades to table test_append3 +drop cascades to table test_range1 +drop cascades to table test_range2 +drop cascades to table test_range3 RESET client_min_messages; RESET citus.log_multi_join_order; RESET citus.enable_repartition_joins; diff --git a/src/test/regress/sql/non_colocated_outer_joins.sql b/src/test/regress/sql/non_colocated_outer_joins.sql index 9c6f72cec..836c64ed7 100644 --- a/src/test/regress/sql/non_colocated_outer_joins.sql +++ b/src/test/regress/sql/non_colocated_outer_joins.sql @@ -1,17 +1,17 @@ CREATE SCHEMA non_colocated_outer_joins; SET search_path TO non_colocated_outer_joins; -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 test_hash1(col1 INT, col2 INT); +SELECT create_distributed_table('test_hash1', 'col1'); +INSERT INTO test_hash1 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 test_hash2(col1 INT, col2 INT); +SELECT create_distributed_table('test_hash2', 'col2'); +INSERT INTO test_hash2 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; +CREATE TABLE test_hash3(col1 INT, col2 INT); +SELECT create_distributed_table('test_hash3', 'col1'); +INSERT INTO test_hash3 SELECT i, i FROM generate_series(11,20) i; SET citus.enable_repartition_joins TO ON; SET citus.log_multi_join_order TO ON; @@ -21,86 +21,189 @@ 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; +SELECT t1.*, t2.* FROM test_hash1 t1 LEFT JOIN test_hash2 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; +SELECT t1.*, t2.* FROM test_hash1 t1 LEFT JOIN test_hash2 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; +SELECT t1.*, t2.* FROM test_hash1 t1 LEFT JOIN test_hash2 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; +SELECT t1.*, t2.* FROM test_hash1 t1 RIGHT JOIN test_hash2 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; +SELECT t1.*, t2.* FROM test_hash1 t1 RIGHT JOIN test_hash2 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; +SELECT t1.*, t2.* FROM test_hash1 t1 RIGHT JOIN test_hash2 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; +SELECT t1.*, t2.* FROM test_hash1 t1 FULL JOIN test_hash2 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; +SELECT t1.*, t2.* FROM test_hash1 t1 FULL JOIN test_hash2 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; +SELECT t1.*, t2.* FROM test_hash1 t1 FULL JOIN test_hash2 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 test_hash1 t1 RIGHT JOIN test_hash2 t2 ON (t1.col1 = t2.col1) INNER JOIN test_hash3 t3 ON (t3.col1 = t1.col1) ORDER BY 1,2,3,4,5,6; +SELECT t1.*, t2.*, t3.* FROM test_hash1 t1 RIGHT JOIN test_hash2 t2 ON (t1.col1 = t2.col1) INNER JOIN test_hash3 t3 ON (t3.col1 = t2.col1) ORDER BY 1,2,3,4,5,6; +SELECT t1.*, t2.*, t3.* FROM test_hash1 t1 RIGHT JOIN test_hash2 t2 ON (t1.col2 = t2.col2) INNER JOIN test_hash3 t3 ON (t3.col2 = t1.col2) ORDER BY 1,2,3,4,5,6; +SELECT t1.*, t2.*, t3.* FROM test_hash1 t1 RIGHT JOIN test_hash2 t2 ON (t1.col2 = t2.col2) INNER JOIN test_hash3 t3 ON (t3.col2 = t2.col2) ORDER BY 1,2,3,4,5,6; +SELECT t1.*, t2.*, t3.* FROM test_hash1 t1 RIGHT JOIN test_hash2 t2 ON (t1.col2 = t2.col1) INNER JOIN test_hash3 t3 ON (t3.col2 = t1.col1) ORDER BY 1,2,3,4,5,6; +SELECT t1.*, t2.*, t3.* FROM test_hash1 t1 RIGHT JOIN test_hash2 t2 ON (t1.col2 = t2.col1) INNER JOIN test_hash3 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 test_hash2 t2 LEFT JOIN test_hash1 t1 ON (t1.col1 = t2.col1) INNER JOIN test_hash3 t3 ON (t3.col1 = t1.col1) ORDER BY 1,2,3,4,5,6; +SELECT t1.*, t2.*, t3.* FROM test_hash2 t2 LEFT JOIN test_hash1 t1 ON (t1.col1 = t2.col1) INNER JOIN test_hash3 t3 ON (t3.col1 = t2.col1) ORDER BY 1,2,3,4,5,6; +SELECT t1.*, t2.*, t3.* FROM test_hash2 t2 LEFT JOIN test_hash1 t1 ON (t1.col2 = t2.col2) INNER JOIN test_hash3 t3 ON (t3.col2 = t1.col2) ORDER BY 1,2,3,4,5,6; +SELECT t1.*, t2.*, t3.* FROM test_hash2 t2 LEFT JOIN test_hash1 t1 ON (t1.col2 = t2.col2) INNER JOIN test_hash3 t3 ON (t3.col2 = t2.col2) ORDER BY 1,2,3,4,5,6; +SELECT t1.*, t2.*, t3.* FROM test_hash2 t2 LEFT JOIN test_hash1 t1 ON (t1.col2 = t2.col1) INNER JOIN test_hash3 t3 ON (t3.col2 = t1.col1) ORDER BY 1,2,3,4,5,6; +SELECT t1.*, t2.*, t3.* FROM test_hash2 t2 LEFT JOIN test_hash1 t1 ON (t1.col2 = t2.col1) INNER JOIN test_hash3 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; +SELECT t1.*, t2.*, t3.* FROM test_hash1 t1 FULL JOIN test_hash2 t2 ON (t1.col1 = t2.col1) INNER JOIN test_hash3 t3 ON (t3.col1 = t1.col1) ORDER BY 1,2,3,4,5,6; +SELECT t1.*, t2.*, t3.* FROM test_hash1 t1 FULL JOIN test_hash2 t2 ON (t1.col1 = t2.col1) INNER JOIN test_hash3 t3 ON (t3.col1 = t2.col1) ORDER BY 1,2,3,4,5,6; +SELECT t1.*, t2.*, t3.* FROM test_hash1 t1 FULL JOIN test_hash2 t2 ON (t1.col2 = t2.col2) INNER JOIN test_hash3 t3 ON (t3.col2 = t1.col2) ORDER BY 1,2,3,4,5,6; +SELECT t1.*, t2.*, t3.* FROM test_hash1 t1 FULL JOIN test_hash2 t2 ON (t1.col2 = t2.col2) INNER JOIN test_hash3 t3 ON (t3.col2 = t2.col2) ORDER BY 1,2,3,4,5,6; +SELECT t1.*, t2.*, t3.* FROM test_hash1 t1 FULL JOIN test_hash2 t2 ON (t1.col2 = t2.col1) INNER JOIN test_hash3 t3 ON (t3.col2 = t1.col1) ORDER BY 1,2,3,4,5,6; +SELECT t1.*, t2.*, t3.* FROM test_hash1 t1 FULL JOIN test_hash2 t2 ON (t1.col2 = t2.col1) INNER JOIN test_hash3 t3 ON (t3.col2 = t2.col1) ORDER BY 1,2,3,4,5,6; -- join order planner handles left outer join between tables with nonsimple join or where clause -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; -SELECT t1.*, t2.* FROM t1 LEFT JOIN t2 ON (t1.col1 = t2.col1 and t1.col1 < 0) ORDER BY 1,2,3,4; +SELECT t1.*, t2.* FROM test_hash1 t1 LEFT JOIN test_hash2 t2 ON (t1.col1 = t2.col1) WHERE (t1.col1 IS NULL or t2.col2 IS NULL) ORDER BY 1,2,3,4; +SELECT t1.*, t2.* FROM test_hash1 t1 LEFT JOIN test_hash2 t2 ON (t1.col1 = t2.col1 and t1.col1 < 0) ORDER BY 1,2,3,4; + +-- join order planner supports repartition join between append distributed tables + +CREATE TABLE test_append1 (col1 INT, col2 INT); +SELECT create_distributed_table('test_append1', 'col1', 'append'); +SELECT master_create_empty_shard('test_append1') AS new_shard_id \gset +UPDATE pg_dist_shard SET shardminvalue = 1, shardmaxvalue = 5 WHERE shardid = :new_shard_id; +SELECT master_create_empty_shard('test_append1') AS new_shard_id \gset +UPDATE pg_dist_shard SET shardminvalue = 6, shardmaxvalue = 10 WHERE shardid = :new_shard_id; +INSERT INTO test_append1 VALUES (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9),(10,10); + +CREATE TABLE test_append2 (col1 INT, col2 INT); +SELECT create_distributed_table('test_append2', 'col2', 'append'); +SELECT master_create_empty_shard('test_append2') AS new_shard_id \gset +UPDATE pg_dist_shard SET shardminvalue = 6, shardmaxvalue = 10 WHERE shardid = :new_shard_id; +SELECT master_create_empty_shard('test_append2') AS new_shard_id \gset +UPDATE pg_dist_shard SET shardminvalue = 11, shardmaxvalue = 15 WHERE shardid = :new_shard_id; +INSERT INTO test_append2 VALUES (6,6),(7,7),(8,8),(9,9),(10,10),(11,11),(12,12),(13,13),(14,14),(15,15); + +CREATE TABLE test_append3(col1 INT, col2 INT); +SELECT create_distributed_table('test_append3', 'col1', 'append'); +SELECT master_create_empty_shard('test_append3') AS new_shard_id \gset +UPDATE pg_dist_shard SET shardminvalue = 11, shardmaxvalue = 15 WHERE shardid = :new_shard_id; +SELECT master_create_empty_shard('test_append3') AS new_shard_id \gset +UPDATE pg_dist_shard SET shardminvalue = 16, shardmaxvalue = 20 WHERE shardid = :new_shard_id; +INSERT INTO test_append3 VALUES (11,11),(12,12),(13,13),(14,14),(15,15),(16,16),(17,17),(18,18),(19,19),(20,20); + +-- join order planner supports repartition join between append-append distributed tables + +SELECT t1.*, t2.* FROM test_append1 t1 LEFT JOIN test_append2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +SELECT t1.*, t2.* FROM test_append1 t1 RIGHT JOIN test_append2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +SELECT t1.*, t2.* FROM test_append1 t1 FULL JOIN test_append2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +SELECT t1.*, t2.*, t3.* FROM test_append1 t1 RIGHT JOIN test_append2 t2 ON (t1.col1 = t2.col1) INNER JOIN test_append3 t3 ON (t3.col1 = t2.col1) ORDER BY 1,2,3,4,5,6; +SELECT t1.*, t2.*, t3.* FROM test_append2 t2 LEFT JOIN test_append1 t1 ON (t1.col1 = t2.col1) INNER JOIN test_append3 t3 ON (t3.col1 = t2.col1) ORDER BY 1,2,3,4,5,6; +SELECT t1.*, t2.*, t3.* FROM test_append1 t1 FULL JOIN test_append2 t2 ON (t1.col1 = t2.col1) INNER JOIN test_append3 t3 ON (t3.col1 = t2.col1) ORDER BY 1,2,3,4,5,6; + +-- join order planner supports repartition join between append-hash distributed tables + +SELECT t1.*, t2.* FROM test_append1 t1 LEFT JOIN test_hash2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +SELECT t1.*, t2.* FROM test_hash1 t1 LEFT JOIN test_append2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +SELECT t1.*, t2.* FROM test_append1 t1 RIGHT JOIN test_hash2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +SELECT t1.*, t2.* FROM test_hash1 t1 RIGHT JOIN test_append2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +SELECT t1.*, t2.* FROM test_append1 t1 FULL JOIN test_hash2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +SELECT t1.*, t2.* FROM test_hash1 t1 FULL JOIN test_append2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +SELECT t1.*, t2.*, t3.* FROM test_hash1 t1 RIGHT JOIN test_append2 t2 ON (t1.col1 = t2.col1) INNER JOIN test_hash3 t3 ON (t3.col1 = t2.col1) ORDER BY 1,2,3,4,5,6; +SELECT t1.*, t2.*, t3.* FROM test_append2 t2 LEFT JOIN test_hash1 t1 ON (t1.col1 = t2.col1) INNER JOIN test_hash3 t3 ON (t3.col1 = t2.col1) ORDER BY 1,2,3,4,5,6; +SELECT t1.*, t2.*, t3.* FROM test_hash1 t1 FULL JOIN test_append2 t2 ON (t1.col1 = t2.col1) INNER JOIN test_hash3 t3 ON (t3.col1 = t2.col1) ORDER BY 1,2,3,4,5,6; + +-- join order planner supports repartition join between range distributed tables + +CREATE TABLE test_range1(col1 INT, col2 INT); +SELECT create_distributed_table('test_range1', 'col1', 'range'); +CALL public.create_range_partitioned_shards('test_range1', + '{0,6,11,16}', + '{5,10,15,20}'); +INSERT INTO test_range1 SELECT i, i FROM generate_series(1,10) i; + +CREATE TABLE test_range2(col1 INT, col2 INT); +SELECT create_distributed_table('test_range2', 'col2', 'range'); +CALL public.create_range_partitioned_shards('test_range2', + '{0,6,11,16}', + '{5,10,15,20}'); +INSERT INTO test_range2 SELECT i, i FROM generate_series(6,15) i; + +CREATE TABLE test_range3(col1 INT, col2 INT); +SELECT create_distributed_table('test_range3', 'col1', 'range'); +CALL public.create_range_partitioned_shards('test_range3', + '{0,6,11,16}', + '{5,10,15,20}'); +INSERT INTO test_range3 SELECT i, i FROM generate_series(11,20) i; + +-- join order planner supports repartition join between range-range distributed tables + +SELECT t1.*, t2.* FROM test_range1 t1 LEFT JOIN test_range2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +SELECT t1.*, t2.* FROM test_range1 t1 RIGHT JOIN test_range2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +SELECT t1.*, t2.* FROM test_range1 t1 FULL JOIN test_range2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +SELECT t1.*, t2.*, t3.* FROM test_range1 t1 RIGHT JOIN test_range2 t2 ON (t1.col1 = t2.col1) INNER JOIN test_range3 t3 ON (t3.col1 = t2.col1) ORDER BY 1,2,3,4,5,6; +SELECT t1.*, t2.*, t3.* FROM test_range2 t2 LEFT JOIN test_range1 t1 ON (t1.col1 = t2.col1) INNER JOIN test_range3 t3 ON (t3.col1 = t2.col1) ORDER BY 1,2,3,4,5,6; +SELECT t1.*, t2.*, t3.* FROM test_range1 t1 FULL JOIN test_range2 t2 ON (t1.col1 = t2.col1) INNER JOIN test_range3 t3 ON (t3.col1 = t2.col1) ORDER BY 1,2,3,4,5,6; + +-- join order planner supports repartition join between range-hash distributed tables + +SELECT t1.*, t2.* FROM test_range1 t1 LEFT JOIN test_hash2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +SELECT t1.*, t2.* FROM test_hash1 t1 LEFT JOIN test_range2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +SELECT t1.*, t2.* FROM test_range1 t1 RIGHT JOIN test_hash2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +SELECT t1.*, t2.* FROM test_hash1 t1 RIGHT JOIN test_range2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +SELECT t1.*, t2.* FROM test_range1 t1 FULL JOIN test_hash2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +SELECT t1.*, t2.* FROM test_hash1 t1 FULL JOIN test_range2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +SELECT t1.*, t2.*, t3.* FROM test_hash1 t1 RIGHT JOIN test_range2 t2 ON (t1.col1 = t2.col1) INNER JOIN test_hash3 t3 ON (t3.col1 = t2.col1) ORDER BY 1,2,3,4,5,6; +SELECT t1.*, t2.*, t3.* FROM test_range2 t2 LEFT JOIN test_hash1 t1 ON (t1.col1 = t2.col1) INNER JOIN test_hash3 t3 ON (t3.col1 = t2.col1) ORDER BY 1,2,3,4,5,6; +SELECT t1.*, t2.*, t3.* FROM test_hash1 t1 FULL JOIN test_range2 t2 ON (t1.col1 = t2.col1) INNER JOIN test_hash3 t3 ON (t3.col1 = t2.col1) ORDER BY 1,2,3,4,5,6; + +-- join order planner supports repartition join between range-append distributed tables + +SELECT t1.*, t2.* FROM test_range1 t1 LEFT JOIN test_append2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +SELECT t1.*, t2.* FROM test_append1 t1 LEFT JOIN test_range2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +SELECT t1.*, t2.* FROM test_range1 t1 RIGHT JOIN test_append2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +SELECT t1.*, t2.* FROM test_append1 t1 RIGHT JOIN test_range2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +SELECT t1.*, t2.* FROM test_range1 t1 FULL JOIN test_append2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +SELECT t1.*, t2.* FROM test_append1 t1 FULL JOIN test_range2 t2 ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +SELECT t1.*, t2.*, t3.* FROM test_append1 t1 RIGHT JOIN test_range2 t2 ON (t1.col1 = t2.col1) INNER JOIN test_hash3 t3 ON (t3.col1 = t2.col1) ORDER BY 1,2,3,4,5,6; +SELECT t1.*, t2.*, t3.* FROM test_range2 t2 LEFT JOIN test_append1 t1 ON (t1.col1 = t2.col1) INNER JOIN test_hash3 t3 ON (t3.col1 = t2.col1) ORDER BY 1,2,3,4,5,6; +SELECT t1.*, t2.*, t3.* FROM test_append1 t1 FULL JOIN test_range2 t2 ON (t1.col1 = t2.col1) INNER JOIN test_hash3 t3 ON (t3.col1 = 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; +SELECT t1.* FROM test_hash1 t1 WHERE EXISTS (SELECT * FROM test_hash2 t2 WHERE t1.col1 = t2.col1) ORDER BY 1,2; +SELECT t1.* FROM test_hash1 t1 WHERE EXISTS (SELECT * FROM test_hash2 t2 WHERE t1.col2 = t2.col2) ORDER BY 1,2; +SELECT t2.* FROM test_hash2 t2 WHERE EXISTS (SELECT * FROM test_hash1 t1 WHERE t1.col1 = t2.col1) ORDER BY 1,2; +SELECT t2.* FROM test_hash2 t2 WHERE EXISTS (SELECT * FROM test_hash1 t1 WHERE t1.col2 = t2.col2) ORDER BY 1,2; -- join order planner cannot handle anti joins -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; +SELECT t1.* FROM test_hash1 t1 WHERE NOT EXISTS (SELECT * FROM test_hash2 t2 WHERE t1.col1 = t2.col1) ORDER BY 1,2; +SELECT t1.* FROM test_hash1 t1 WHERE NOT EXISTS (SELECT * FROM test_hash2 t2 WHERE t1.col2 = t2.col2) ORDER BY 1,2; +SELECT t2.* FROM test_hash2 t2 WHERE NOT EXISTS (SELECT * FROM test_hash1 t1 WHERE t1.col1 = t2.col1) ORDER BY 1,2; +SELECT t2.* FROM test_hash2 t2 WHERE NOT EXISTS (SELECT * FROM test_hash1 t1 WHERE t1.col2 = t2.col2) ORDER BY 1,2; -- join order planner cannot handle lateral outer joins -SELECT t1.*, tt2.* FROM t1 LEFT JOIN LATERAL (SELECT * FROM t2 WHERE t1.col1 = t2.col1) tt2 ON (t1.col1 = tt2.col1) ORDER BY 1,2,3,4; +SELECT t1.*, tt2.* FROM test_hash1 t1 LEFT JOIN LATERAL (SELECT * FROM test_hash2 t2 WHERE t1.col1 = t2.col1) tt2 ON (t1.col1 = tt2.col1) ORDER BY 1,2,3,4; -- join order planner cannot handle cartesian joins -SELECT tt1.*, t3.* FROM (SELECT t1.* FROM t1,t2) tt1 LEFT JOIN t3 ON (tt1.col1 = t3.col1) ORDER BY 1,2,3,4; +SELECT tt1.*, t3.* FROM (SELECT t1.* FROM test_hash1 t1, test_hash2 t2) tt1 LEFT JOIN test_hash3 t3 ON (tt1.col1 = t3.col1) ORDER BY 1,2,3,4; -- join order planner cannot handle right recursive joins -SELECT t1.*, t2.* FROM t1 LEFT JOIN ( t2 JOIN t3 ON t2.col2 = t3.col1) ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; +SELECT t1.*, t2.* FROM test_hash1 t1 LEFT JOIN ( test_hash2 t2 JOIN test_hash3 t3 ON t2.col2 = t3.col1) ON (t1.col1 = t2.col1) ORDER BY 1,2,3,4; DROP SCHEMA non_colocated_outer_joins CASCADE; RESET client_min_messages;