v30-0002-Fix-handling-of-NULL-partitions.patch
application/octet-stream
Filename: v30-0002-Fix-handling-of-NULL-partitions.patch
Type: application/octet-stream
Part: 1
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
Series: patch v30-0002
| File | + | − |
|---|---|---|
| src/backend/partitioning/partbounds.c | 12 | 14 |
| src/test/regress/expected/partition_join.out | 70 | 0 |
| src/test/regress/sql/partition_join.sql | 9 | 0 |
diff --git a/src/backend/partitioning/partbounds.c b/src/backend/partitioning/partbounds.c
index d619ab4486..0c1e4ab7f5 100644
--- a/src/backend/partitioning/partbounds.c
+++ b/src/backend/partitioning/partbounds.c
@@ -4528,8 +4528,8 @@ merge_null_partitions(PartitionMap *outer_map,
int *next_index,
int *null_index)
{
- bool merge_outer_null = false;
- bool merge_inner_null = false;
+ bool outer_null_unmerged = false;
+ bool inner_null_unmerged = false;
Assert(outer_has_null || inner_has_null);
Assert(*null_index == -1);
@@ -4554,7 +4554,7 @@ merge_null_partitions(PartitionMap *outer_map,
*/
Assert(outer_null >= 0 && outer_null < outer_map->nparts);
if (outer_map->merged_indexes[outer_null] == -1)
- merge_outer_null = true;
+ outer_null_unmerged = true;
}
if (inner_has_null)
{
@@ -4565,15 +4565,14 @@ merge_null_partitions(PartitionMap *outer_map,
* partition below.
*/
Assert(inner_null >= 0 && inner_null < inner_map->nparts);
- if (jointype == JOIN_FULL &&
- inner_map->merged_indexes[inner_null] == -1)
- merge_inner_null = true;
+ if (inner_map->merged_indexes[inner_null] == -1)
+ inner_null_unmerged = true;
}
- if (!merge_outer_null && !merge_inner_null)
+ if (!outer_null_unmerged && !inner_null_unmerged)
return;
- if (merge_outer_null && !merge_inner_null)
+ if (outer_null_unmerged && !inner_null_unmerged)
{
Assert(outer_has_null);
@@ -4584,24 +4583,23 @@ merge_null_partitions(PartitionMap *outer_map,
*null_index = merge_partition_with_dummy(outer_map, outer_null,
next_index);
}
- else if (!merge_outer_null && merge_inner_null)
+ else if (!outer_null_unmerged && inner_null_unmerged)
{
Assert(inner_has_null);
- Assert(jointype == JOIN_FULL);
/*
* Assign a new merged partition. The resulting partition should be
* the NULL partition of the joinrel.
*/
- *null_index = merge_partition_with_dummy(inner_map, inner_null,
- next_index);
+ if (jointype == JOIN_FULL)
+ *null_index = merge_partition_with_dummy(inner_map, inner_null,
+ next_index);
}
else
{
- Assert(merge_outer_null && merge_inner_null);
+ Assert(outer_null_unmerged && inner_null_unmerged);
Assert(outer_has_null);
Assert(inner_has_null);
- Assert(jointype == JOIN_FULL);
/*
* Merge the NULL partitions. Both partitions aren't merged yet, so
diff --git a/src/test/regress/expected/partition_join.out b/src/test/regress/expected/partition_join.out
index dc78bc2503..924cb99863 100644
--- a/src/test/regress/expected/partition_join.out
+++ b/src/test/regress/expected/partition_join.out
@@ -3673,6 +3673,32 @@ SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_ad t1 INNER JOIN plt2_ad t2 ON (t1.a = t
9 | 0009 | 9 | 0009
(4 rows)
+-- Partitioned join can't be applied because there isn't any partition on the
+-- plt2_ad side that matches the NULL partition of plt1_ad plt1_ad_extra
+EXPLAIN (COSTS OFF)
+SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_ad t1 LEFT JOIN plt2_ad t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
+ QUERY PLAN
+--------------------------------------------------------
+ Sort
+ Sort Key: t1.a
+ -> Hash Right Join
+ Hash Cond: ((t2.a = t1.a) AND (t2.c = t1.c))
+ -> Append
+ -> Seq Scan on plt2_ad_p1 t2_1
+ -> Seq Scan on plt2_ad_p2 t2_2
+ -> Seq Scan on plt2_ad_p3 t2_3
+ -> Hash
+ -> Append
+ -> Seq Scan on plt1_ad_p1 t1_1
+ Filter: (b < 10)
+ -> Seq Scan on plt1_ad_p2 t1_2
+ Filter: (b < 10)
+ -> Seq Scan on plt1_ad_p3 t1_3
+ Filter: (b < 10)
+ -> Seq Scan on plt1_ad_extra t1_4
+ Filter: (b < 10)
+(18 rows)
+
-- Partitioned join can't be applied because there isn't any partition on the
-- plt2_ad side that matches the NULL partition of plt1_ad plt1_ad_extra
EXPLAIN (COSTS OFF)
@@ -3737,6 +3763,50 @@ SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_ad t1 INNER JOIN plt2_ad t2 ON (t1.a = t
9 | 0009 | 9 | 0009
(4 rows)
+EXPLAIN (COSTS OFF)
+SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_ad t1 LEFT JOIN plt2_ad t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
+ QUERY PLAN
+----------------------------------------------------------------------
+ Sort
+ Sort Key: t1.a
+ -> Append
+ -> Hash Right Join
+ Hash Cond: ((t2_1.a = t1_1.a) AND (t2_1.c = t1_1.c))
+ -> Seq Scan on plt2_ad_p1 t2_1
+ -> Hash
+ -> Seq Scan on plt1_ad_p1 t1_1
+ Filter: (b < 10)
+ -> Hash Right Join
+ Hash Cond: ((t2_2.a = t1_2.a) AND (t2_2.c = t1_2.c))
+ -> Seq Scan on plt2_ad_p2 t2_2
+ -> Hash
+ -> Seq Scan on plt1_ad_p2 t1_2
+ Filter: (b < 10)
+ -> Hash Right Join
+ Hash Cond: ((t2_3.a = t1_3.a) AND (t2_3.c = t1_3.c))
+ -> Seq Scan on plt2_ad_p3 t2_3
+ -> Hash
+ -> Seq Scan on plt1_ad_p3 t1_3
+ Filter: (b < 10)
+ -> Nested Loop Left Join
+ Join Filter: ((t1_4.a = t2_4.a) AND (t1_4.c = t2_4.c))
+ -> Seq Scan on plt1_ad_extra t1_4
+ Filter: (b < 10)
+ -> Seq Scan on plt2_ad_extra t2_4
+(26 rows)
+
+SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_ad t1 LEFT JOIN plt2_ad t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
+ a | c | a | c
+----+------+---+------
+ -1 | | |
+ 1 | 0001 | |
+ 3 | 0003 | 3 | 0003
+ 4 | 0004 | 4 | 0004
+ 6 | 0006 | 6 | 0006
+ 8 | 0008 | |
+ 9 | 0009 | 9 | 0009
+(7 rows)
+
EXPLAIN (COSTS OFF)
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_ad t1 FULL JOIN plt2_ad t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE coalesce(t1.b, 0) < 10 AND coalesce(t2.b, 0) < 10 ORDER BY t1.a, t2.a;
QUERY PLAN
diff --git a/src/test/regress/sql/partition_join.sql b/src/test/regress/sql/partition_join.sql
index c3e47ee549..418ffa117f 100644
--- a/src/test/regress/sql/partition_join.sql
+++ b/src/test/regress/sql/partition_join.sql
@@ -815,6 +815,11 @@ EXPLAIN (COSTS OFF)
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_ad t1 INNER JOIN plt2_ad t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_ad t1 INNER JOIN plt2_ad t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
+-- Partitioned join can't be applied because there isn't any partition on the
+-- plt2_ad side that matches the NULL partition of plt1_ad plt1_ad_extra
+EXPLAIN (COSTS OFF)
+SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_ad t1 LEFT JOIN plt2_ad t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
+
-- Partitioned join can't be applied because there isn't any partition on the
-- plt2_ad side that matches the NULL partition of plt1_ad plt1_ad_extra
EXPLAIN (COSTS OFF)
@@ -830,6 +835,10 @@ EXPLAIN (COSTS OFF)
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_ad t1 INNER JOIN plt2_ad t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_ad t1 INNER JOIN plt2_ad t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
+EXPLAIN (COSTS OFF)
+SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_ad t1 LEFT JOIN plt2_ad t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
+SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_ad t1 LEFT JOIN plt2_ad t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10 ORDER BY t1.a;
+
EXPLAIN (COSTS OFF)
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_ad t1 FULL JOIN plt2_ad t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE coalesce(t1.b, 0) < 10 AND coalesce(t2.b, 0) < 10 ORDER BY t1.a, t2.a;
SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_ad t1 FULL JOIN plt2_ad t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE coalesce(t1.b, 0) < 10 AND coalesce(t2.b, 0) < 10 ORDER BY t1.a, t2.a;