v27-0002-Modify-partition_range_bounds_merge.patch
application/octet-stream
Filename: v27-0002-Modify-partition_range_bounds_merge.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: format-patch
Series: patch v27-0002
Subject: Modify partition_range_bounds_merge()
| File | + | − |
|---|---|---|
| src/backend/partitioning/partbounds.c | 266 | 328 |
From fa1dd52a2caec26d834fd3e80195140b1a125742 Mon Sep 17 00:00:00 2001
From: Etsuro Fujita <efujita@postgresql.org>
Date: Tue, 12 Nov 2019 21:58:34 +0900
Subject: [PATCH 2/2] Modify partition_range_bounds_merge()
---
src/backend/partitioning/partbounds.c | 594 ++++++++++++--------------
1 file changed, 266 insertions(+), 328 deletions(-)
diff --git a/src/backend/partitioning/partbounds.c b/src/backend/partitioning/partbounds.c
index f145851871..4aebc71ebb 100644
--- a/src/backend/partitioning/partbounds.c
+++ b/src/backend/partitioning/partbounds.c
@@ -81,6 +81,12 @@ typedef struct PartitionMap
* did_remapping */
} PartitionMap;
+#define compare_range_bounds(partnatts, partsupfunc, partcollations, \
+ bound1, bound2) \
+ (partition_rbound_cmp(partnatts, partsupfunc, partcollations, \
+ (bound1)->datums, (bound1)->kind, (bound1)->lower, \
+ bound2))
+
static int32 qsort_partition_hbound_cmp(const void *a, const void *b);
static int32 qsort_partition_list_value_cmp(const void *a, const void *b,
void *arg);
@@ -142,7 +148,6 @@ static bool process_outer_partition(PartitionMap *outer_map,
int outer_index,
int inner_default,
JoinType jointype,
- char strategy,
int *next_index,
int *default_index,
int *merged_index);
@@ -153,7 +158,6 @@ static bool process_inner_partition(PartitionMap *outer_map,
int inner_index,
int outer_default,
JoinType jointype,
- char strategy,
int *next_index,
int *default_index,
int *merged_index);
@@ -170,20 +174,31 @@ static PartitionBoundInfo build_merged_partition_bounds(char strategy,
List *merged_datums, List *merged_indexes,
List *merged_contents, int null_index,
int default_index);
-static int32 partition_range_bound_cmp(int partnatts, FmgrInfo *partsupfunc,
- Oid *collations, PartitionRangeBound *bound1,
- PartitionRangeBound *bound2);
-static bool partition_range_cmp(int partnatts, FmgrInfo *supfuncs,
- Oid *collations, PartitionRangeBound *lower_bound1,
- PartitionRangeBound *upper_bound1,
- PartitionRangeBound *lower_bound2,
- PartitionRangeBound *upper_bound2, int *ub_cmpval,
- int *lb_cmpval);
-static bool partition_range_merge_next_lb(int partnatts, FmgrInfo *supfuncs,
- Oid *collations, Datum *next_lb_datums,
- PartitionRangeDatumKind *next_lb_kind,
- List **merged_datums, List **merged_kinds,
- List **merged_indexes);
+static int get_range_partition(PartitionBoundInfo bi, int *lb_pos,
+ PartitionRangeBound *lb, PartitionRangeBound *ub);
+static bool compare_range_partitions(int partnatts, FmgrInfo *partsupfuncs,
+ Oid *partcollations,
+ PartitionRangeBound *lower_bound1,
+ PartitionRangeBound *upper_bound1,
+ PartitionRangeBound *lower_bound2,
+ PartitionRangeBound *upper_bound2,
+ int *ub_cmpval, int *lb_cmpval);
+static void get_merged_range_bounds(int partnatts, FmgrInfo *partsupfuncs,
+ Oid *partcollations, JoinType jointype,
+ PartitionRangeBound *left_lb,
+ PartitionRangeBound *left_ub,
+ PartitionRangeBound *right_lb,
+ PartitionRangeBound *right_ub,
+ PartitionRangeBound *merged_lb,
+ PartitionRangeBound *merged_ub);
+static void add_merged_range_bounds(int partnatts, FmgrInfo *partsupfuncs,
+ Oid *partcollations,
+ PartitionRangeBound *merged_lb,
+ PartitionRangeBound *merged_ub,
+ int merged_index,
+ List **merged_datums,
+ List **merged_kinds,
+ List **merged_indexes);
static bool merge_default_partitions(PartitionMap *outer_map,
PartitionMap *inner_map,
bool outer_has_default,
@@ -3164,83 +3179,60 @@ partition_bounds_merge(int partnatts,
}
/*
- * partition_get_range_bounds
+ * get_range_partition
+ * Returns the index of the range partition with the given lower bound
*
- * Given the index of lower bound in datums array, return lower and upper
- * bounds and the index of the partition with that lower bound.
+ * *lb and *ub are set to the lower and upper bounds of the range partition
+ * respectively, and *lb_index is advanced to the next lower bound, if any.
*/
static int
-partition_get_range_bounds(PartitionBoundInfo bi, int lb_index,
- PartitionRangeBound *lower,
- PartitionRangeBound *upper)
+get_range_partition(PartitionBoundInfo bi, int *lb_index,
+ PartitionRangeBound *lb, PartitionRangeBound *ub)
{
- int part_index;
+ /* Return the index as -1 if we've exhausted all the lower bounds. */
+ if (*lb_index >= bi->ndatums)
+ return -1;
/* A lower bound should have at least one more bound after it. */
- Assert(lb_index < bi->ndatums - 1);
-
- /* The lower bound should correspond to a valid partition. */
- part_index = bi->indexes[lb_index + 1];
- Assert(part_index >= 0);
-
- lower->kind = bi->kind[lb_index];
- lower->datums = bi->datums[lb_index];
- lower->lower = true;
- upper->kind = bi->kind[lb_index + 1];
- upper->datums = bi->datums[lb_index + 1];
- upper->lower = false;
+ Assert(*lb_index + 1 < bi->ndatums);
- return part_index;
-}
-
-/*
- * partition_range_get_next_lb_index
- *
- * Given the index of lower bound in datums array return the
- * index of lower bound of the next partition. When the given index corresponds
- * to the last partition, return number of datums (ndatums).
- */
-static int
-partition_range_get_next_lb_index(PartitionBoundInfo bi, int lb_index)
-{
- /* A lower bound should have at least one more bound after it. */
- Assert(lb_index < bi->ndatums - 1);
+ lb->index = bi->indexes[*lb_index];
+ lb->kind = bi->kind[*lb_index];
+ lb->datums = bi->datums[*lb_index];
+ lb->lower = true;
+ ub->index = bi->indexes[*lb_index + 1];
+ ub->kind = bi->kind[*lb_index + 1];
+ ub->datums = bi->datums[*lb_index + 1];
+ ub->lower = false;
- /* The partition index corresponding to the upper bound should be valid. */
- Assert(bi->indexes[lb_index + 1] >= 0);
+ /* The partition index of an upper bound should be valid. */
+ Assert(ub->index >= 0);
/*
- * If there are no bounds left beyond the upper bound, we have reached the
- * last partition.
+ * Advance the lower bound; if there are no bounds left beyond the upper
+ * bound, we have reached the last lower bound.
*/
- if (lb_index + 2 < bi->ndatums)
+ if (*lb_index + 2 >= bi->ndatums)
+ *lb_index = bi->ndatums;
+ else
{
/*
- * If the bound next to the upper bound corresponds to no partition,
- * that's the next lower bound of the next partition. Otherwise, the
- * current upper bound is the lower bound of the next partition.
+ * If the index assigned to the bound next to the upper bound isn't
+ * valid, that is the lower bound of the next range partition; else,
+ * the upper bound of the current range partition is also the lower
+ * bound of the next range partition.
*/
- if (bi->indexes[lb_index + 2] < 0)
- return lb_index + 2;
+ if (bi->indexes[*lb_index + 2] < 0)
+ *lb_index = *lb_index + 2;
else
- return lb_index + 1;
+ *lb_index = *lb_index + 1;
}
- else
- return bi->ndatums;
-}
-static int32
-partition_range_bound_cmp(int partnatts, FmgrInfo *partsupfunc,
- Oid *partcollations, PartitionRangeBound *bound1,
- PartitionRangeBound *bound2)
-{
- return partition_rbound_cmp(partnatts, partsupfunc, partcollations,
- bound1->datums, bound1->kind, bound1->lower,
- bound2);
+ return ub->index;
}
/*
- * partition_range_cmp
+ * compare_range_partitions
*
* Compare the bounds of two range partitions. Set ub_cmpval <, = or > 0, if the
* first partition's upper bound is lower than, equal to or higher than the
@@ -3251,12 +3243,13 @@ partition_range_bound_cmp(int partnatts, FmgrInfo *partsupfunc,
* Return true, if the ranges overlap, otherwise return false.
*/
static bool
-partition_range_cmp(int partnatts, FmgrInfo *partsupfuncs, Oid *partcollations,
- PartitionRangeBound *lower_bound1,
- PartitionRangeBound *upper_bound1,
- PartitionRangeBound *lower_bound2,
- PartitionRangeBound *upper_bound2, int *ub_cmpval,
- int *lb_cmpval)
+compare_range_partitions(int partnatts, FmgrInfo *partsupfuncs,
+ Oid *partcollations,
+ PartitionRangeBound *lower_bound1,
+ PartitionRangeBound *upper_bound1,
+ PartitionRangeBound *lower_bound2,
+ PartitionRangeBound *upper_bound2,
+ int *ub_cmpval, int *lb_cmpval)
{
bool overlap;
@@ -3266,15 +3259,15 @@ partition_range_cmp(int partnatts, FmgrInfo *partsupfuncs, Oid *partcollations,
* the partitions are not overlapping. All other cases indicate overlapping
* partitions.
*/
- if (partition_range_bound_cmp(partnatts, partsupfuncs, partcollations,
- lower_bound1, upper_bound2) > 0)
+ if (compare_range_bounds(partnatts, partsupfuncs, partcollations,
+ lower_bound1, upper_bound2) > 0)
{
overlap = false;
*ub_cmpval = 1;
*lb_cmpval = 1;
}
- else if (partition_range_bound_cmp(partnatts, partsupfuncs, partcollations,
- lower_bound2, upper_bound1) > 0)
+ else if (compare_range_bounds(partnatts, partsupfuncs, partcollations,
+ lower_bound2, upper_bound1) > 0)
{
overlap = false;
*ub_cmpval = -1;
@@ -3283,35 +3276,34 @@ partition_range_cmp(int partnatts, FmgrInfo *partsupfuncs, Oid *partcollations,
else
{
overlap = true;
- *ub_cmpval = partition_range_bound_cmp(partnatts, partsupfuncs,
- partcollations, upper_bound1,
- upper_bound2);
- *lb_cmpval = partition_range_bound_cmp(partnatts, partsupfuncs,
- partcollations, lower_bound1,
- lower_bound2);
+ *ub_cmpval = compare_range_bounds(partnatts, partsupfuncs,
+ partcollations, upper_bound1,
+ upper_bound2);
+ *lb_cmpval = compare_range_bounds(partnatts, partsupfuncs,
+ partcollations, lower_bound1,
+ lower_bound2);
}
return overlap;
}
/*
- * partition_range_merge
- *
- * Merge the partition bounds of given two partitions such that the join
- * between the given two partitions fits merged bounds.
+ * get_merged_range_bounds
+ * Given the bounds of range partitions to be join, determine the range
+ * bounds of the merged partition produced from the range partitions
*
- * "merged_upper" will be set to one of the given upper bounds and
- * "merged_lower" will be set to one of the given lower bounds.
+ * *merged_lb and *merged_ub are set to the lower and upper bounds of the
+ * merged partition.
*/
static void
-partition_range_merge(int partnatts, FmgrInfo *partsupfuncs,
- Oid *partcollations, JoinType jointype,
- PartitionRangeBound *left_lb,
- PartitionRangeBound *left_ub,
- PartitionRangeBound *right_lb,
- PartitionRangeBound *right_ub,
- PartitionRangeBound **merged_lb,
- PartitionRangeBound **merged_ub)
+get_merged_range_bounds(int partnatts, FmgrInfo *partsupfuncs,
+ Oid *partcollations, JoinType jointype,
+ PartitionRangeBound *left_lb,
+ PartitionRangeBound *left_ub,
+ PartitionRangeBound *right_lb,
+ PartitionRangeBound *right_ub,
+ PartitionRangeBound *merged_lb,
+ PartitionRangeBound *merged_ub)
{
/*
* An outer join will have all the rows from the outer side, so merged
@@ -3324,41 +3316,37 @@ partition_range_merge(int partnatts, FmgrInfo *partsupfuncs,
{
case JOIN_LEFT:
case JOIN_ANTI:
- *merged_ub = left_ub;
- *merged_lb = left_lb;
+ *merged_ub = *left_ub;
+ *merged_lb = *left_lb;
break;
case JOIN_INNER:
case JOIN_SEMI:
- if (partition_range_bound_cmp(partnatts, partsupfuncs,
- partcollations, left_ub,
- right_ub) < 0)
- *merged_ub = left_ub;
+ if (compare_range_bounds(partnatts, partsupfuncs, partcollations,
+ left_ub, right_ub) < 0)
+ *merged_ub = *left_ub;
else
- *merged_ub = right_ub;
+ *merged_ub = *right_ub;
- if (partition_range_bound_cmp(partnatts, partsupfuncs,
- partcollations, left_lb,
- right_lb) > 0)
- *merged_lb = left_lb;
+ if (compare_range_bounds(partnatts, partsupfuncs, partcollations,
+ left_lb, right_lb) > 0)
+ *merged_lb = *left_lb;
else
- *merged_lb = right_lb;
+ *merged_lb = *right_lb;
break;
case JOIN_FULL:
- if (partition_range_bound_cmp(partnatts, partsupfuncs,
- partcollations, left_ub,
- right_ub) > 0)
- *merged_ub = left_ub;
+ if (compare_range_bounds(partnatts, partsupfuncs, partcollations,
+ left_ub, right_ub) > 0)
+ *merged_ub = *left_ub;
else
- *merged_ub = right_ub;
+ *merged_ub = *right_ub;
- if (partition_range_bound_cmp(partnatts, partsupfuncs,
- partcollations, left_lb,
- right_lb) < 0)
- *merged_lb = left_lb;
+ if (compare_range_bounds(partnatts, partsupfuncs, partcollations,
+ left_lb, right_lb) < 0)
+ *merged_lb = *left_lb;
else
- *merged_lb = right_lb;
+ *merged_lb = *right_lb;
break;
default:
@@ -3367,16 +3355,19 @@ partition_range_merge(int partnatts, FmgrInfo *partsupfuncs,
}
/*
- * Add the lower bound of the next range to the list of bounds, if the lower
- * bound is higher or equal to the previous upper bound. If successful return
- * true, otherwise false.
+ * add_merged_range_bounds
+ * Add the range bounds of a merged partition to the lists of range
+ * bounds
*/
-static bool
-partition_range_merge_next_lb(int partnatts, FmgrInfo *partsupfuncs,
- Oid *partcollations, Datum *next_lb_datums,
- PartitionRangeDatumKind *next_lb_kind,
- List **merged_datums, List **merged_kinds,
- List **merged_indexes)
+static void
+add_merged_range_bounds(int partnatts, FmgrInfo *partsupfuncs,
+ Oid *partcollations,
+ PartitionRangeBound *merged_lb,
+ PartitionRangeBound *merged_ub,
+ int merged_index,
+ List **merged_datums,
+ List **merged_kinds,
+ List **merged_indexes)
{
int cmpval;
@@ -3389,38 +3380,43 @@ partition_range_merge_next_lb(int partnatts, FmgrInfo *partsupfuncs,
{
PartitionRangeBound prev_ub;
- prev_ub.datums = llast(*merged_datums);
- prev_ub.kind = llast(*merged_kinds);
+ Assert(*merged_kinds && *merged_indexes);
+
+ /* Get the last upper bound. */
+ prev_ub.index = llast_int(*merged_indexes);
+ prev_ub.datums = (Datum *) llast(*merged_datums);
+ prev_ub.kind = (PartitionRangeDatumKind *) llast(*merged_kinds);
prev_ub.lower = false;
+ /*
+ * We pass to partition_rbound_cmp() lower1 as false to prevent it
+ * from considering the last upper bound to be smaller than the lower
+ * bound of the merged partition when the values of the two range
+ * bounds compare equal.
+ */
cmpval = partition_rbound_cmp(partnatts, partsupfuncs, partcollations,
- next_lb_datums, next_lb_kind, false,
- &prev_ub);
+ merged_lb->datums, merged_lb->kind,
+ false, &prev_ub);
+ Assert(cmpval >= 0);
}
/*
- * The lower bound is lower than the last upper bound, thus does not fit
- * the bounds created so far and hence can not be merged with the existing
- * bounds.
- */
- if (cmpval < 0)
- return false;
-
- /*
- * Add bounds of the new merged partition. If the next lower bound is
- * higher than the last upper bound, add new range with index
- * corresponding to the lower bound as -1. If the merged lower bound
- * is same as the last merged upper bound, the last upper bound will be
- * reused as the lower bound of the next range.
+ * If the lower bound is higher than the last upper bound, add the lower
+ * bound with the index as -1 indicating that that is a lower bound; else,
+ * the last upper bound will be reused as the lower bound of the merged
+ * partition, so skip this.
*/
if (cmpval > 0)
{
- *merged_datums = lappend(*merged_datums, next_lb_datums);
- *merged_kinds = lappend(*merged_kinds, next_lb_kind);
+ *merged_datums = lappend(*merged_datums, merged_lb->datums);
+ *merged_kinds = lappend(*merged_kinds, merged_lb->kind);
*merged_indexes = lappend_int(*merged_indexes, -1);
}
- return true;
+ /* Add the upper bound and index of the merged partition. */
+ *merged_datums = lappend(*merged_datums, merged_ub->datums);
+ *merged_kinds = lappend(*merged_kinds, merged_ub->kind);
+ *merged_indexes = lappend_int(*merged_indexes, merged_index);
}
/*
@@ -3444,13 +3440,19 @@ partition_range_bounds_merge(int partnatts, FmgrInfo *partsupfuncs,
int inner_default = inner_bi->default_index;
PartitionMap outer_map;
PartitionMap inner_map;
+ int outer_part;
+ int inner_part;
+ int outer_lb_index;
+ int inner_lb_index;
+ PartitionRangeBound outer_lb;
+ PartitionRangeBound outer_ub;
+ PartitionRangeBound inner_lb;
+ PartitionRangeBound inner_ub;
int next_index = 0;
int default_index = -1;
List *merged_datums = NIL;
List *merged_kinds = NIL;
List *merged_indexes = NIL;
- int outer_lb_index;
- int inner_lb_index;
Assert(outer_bi->strategy == inner_bi->strategy &&
outer_bi->strategy == PARTITION_STRATEGY_RANGE);
@@ -3471,29 +3473,25 @@ partition_range_bounds_merge(int partnatts, FmgrInfo *partsupfuncs,
* datum in PartitionBoundInfo::datums of that side.
*/
outer_lb_index = inner_lb_index = 0;
- while (outer_lb_index < outer_bi->ndatums ||
- inner_lb_index < inner_bi->ndatums)
+ outer_part = get_range_partition(outer_bi, &outer_lb_index,
+ &outer_lb, &outer_ub);
+ inner_part = get_range_partition(inner_bi, &inner_lb_index,
+ &inner_lb, &inner_ub);
+ while (outer_part >= 0 || inner_part >= 0)
{
- PartitionRangeBound *merged_lb = NULL;
- PartitionRangeBound *merged_ub = NULL;
+ PartitionRangeBound merged_lb;
+ PartitionRangeBound merged_ub;
int merged_index = -1;
- PartitionRangeBound outer_lb;
- PartitionRangeBound outer_ub;
- PartitionRangeBound inner_lb;
- PartitionRangeBound inner_ub;
- int outer_part = -1;
- int inner_part = -1;
bool overlap;
int ub_cmpval;
int lb_cmpval;
- /* Get the range bounds of the next pair of partitions. */
- if (outer_lb_index < outer_bi->ndatums)
- outer_part = partition_get_range_bounds(outer_bi, outer_lb_index,
- &outer_lb, &outer_ub);
- if (inner_lb_index < inner_bi->ndatums)
- inner_part = partition_get_range_bounds(inner_bi, inner_lb_index,
- &inner_lb, &inner_ub);
+ if (outer_part >= 0)
+ Assert(outer_map.merged_indexes[outer_part] == -1 &&
+ outer_map.merged[outer_part] == false);
+ if (inner_part >= 0)
+ Assert(inner_map.merged_indexes[inner_part] == -1 &&
+ inner_map.merged[inner_part] == false);
/*
* We run this loop till both the sides finish. This allows to avoid
@@ -3505,25 +3503,30 @@ partition_range_bounds_merge(int partnatts, FmgrInfo *partsupfuncs,
* side. That way we advance the partitions on that side till all of
* them are exhausted.
*/
- if (outer_lb_index >= outer_bi->ndatums)
+ if (outer_part == -1)
{
overlap = false;
ub_cmpval = 1;
lb_cmpval = 1;
}
- else if (inner_lb_index >= inner_bi->ndatums)
+ else if (inner_part == -1)
{
overlap = false;
ub_cmpval = -1;
lb_cmpval = -1;
}
else
- overlap = partition_range_cmp(partnatts, partsupfuncs, partcollations,
- &outer_lb, &outer_ub, &inner_lb,
- &inner_ub, &ub_cmpval, &lb_cmpval);
+ overlap = compare_range_partitions(partnatts, partsupfuncs,
+ partcollations,
+ &outer_lb, &outer_ub,
+ &inner_lb, &inner_ub,
+ &ub_cmpval, &lb_cmpval);
if (overlap)
{
+ PartitionRangeBound save_outer_ub;
+ PartitionRangeBound save_inner_ub;
+
/*
* The rows from overlapping portion of ranges on both sides may
* join, hence the corresponding pair of partitions form a joining
@@ -3531,152 +3534,117 @@ partition_range_bounds_merge(int partnatts, FmgrInfo *partsupfuncs,
* and its index by merging the bounds according to the type of
* join.
*/
- partition_range_merge(partnatts, partsupfuncs, partcollations,
- jointype, &outer_lb, &outer_ub, &inner_lb,
- &inner_ub, &merged_lb, &merged_ub);
+ get_merged_range_bounds(partnatts, partsupfuncs, partcollations,
+ jointype, &outer_lb, &outer_ub, &inner_lb,
+ &inner_ub, &merged_lb, &merged_ub);
+ /*
+ * Both partitions are not merged yet, so they should be merged
+ * successfully.
+ */
merged_index = map_and_merge_partitions(&outer_map, &inner_map,
outer_part, inner_part,
&next_index);
+ Assert(merged_index >= 0);
- if (merged_index < 0)
- {
- /* Failed to match the partitions. */
- return NULL;
- }
+ /* Save the upper bounds of both partitions for use below. */
+ save_outer_ub = outer_ub;
+ save_inner_ub = inner_ub;
+
+ /* Move to the next pair of partitions. */
+ outer_part = get_range_partition(outer_bi, &outer_lb_index,
+ &outer_lb, &outer_ub);
+ inner_part = get_range_partition(inner_bi, &inner_lb_index,
+ &inner_lb, &inner_ub);
/*
- * If the ranges overlap but don't exactly match, a row from
- * non-overlapping portion of the range from one side of join may
- * find its join partner in the previous or next overlapping
- * partition or default partition on the other side , if such a
- * partition exists. All those cases, if true, will cause one
- * partition from that side to match at least two partitions on the
- * other side; a case that we do not support now. Previous
- * partition has been delt with in the previous iteration of this
- * loop, next partition will be delt in the next iteration. We will
- * deal with the default partition here.
+ * If the range of a partition on one side overlaps the range of
+ * the next partition on the other side, that will cause the
+ * partition on one side to match at least two partitions on the
+ * other side, which is the case that we currently don't support
+ * partitioned join for; give up.
*/
- if ((lb_cmpval < 0 && inner_has_default) ||
- /* Non-overlapping range on the lower side of outer range. */
- (lb_cmpval > 0 && outer_has_default) ||
- /* Non-overlapping range on the lower side of inner range. */
- (ub_cmpval < 0 && outer_has_default) ||
- /* Non-overlapping range on the upper side of inner range. */
- (ub_cmpval > 0 && inner_has_default))
- /* Non-overlapping range on the upper side of outer range. */
+ if (ub_cmpval > 0 && inner_part >= 0 &&
+ compare_range_bounds(partnatts, partsupfuncs, partcollations,
+ &save_outer_ub, &inner_lb) > 0)
+ return NULL;
+ if (ub_cmpval < 0 && outer_part >= 0 &&
+ compare_range_bounds(partnatts, partsupfuncs, partcollations,
+ &outer_lb, &save_inner_ub) < 0)
return NULL;
- }
-
- if (ub_cmpval == 0)
- {
- /* Upper bounds of both the ranges match. */
- Assert(overlap);
- /* Move to the next pair of partitions. */
- Assert(outer_lb_index < outer_bi->ndatums);
- Assert(inner_lb_index < inner_bi->ndatums);
- outer_lb_index = partition_range_get_next_lb_index(outer_bi,
- outer_lb_index);
- inner_lb_index = partition_range_get_next_lb_index(inner_bi,
- inner_lb_index);
+ /*
+ * A row from a non-overlapping portion (if any) of a partition
+ * on one side might find its join partner in the default
+ * partition (if any) on the other side, causing the same
+ * situation as above; if so, give up.
+ */
+ if ((outer_has_default && (lb_cmpval > 0 || ub_cmpval < 0)) ||
+ (inner_has_default && (lb_cmpval < 0 || ub_cmpval > 0)))
+ return NULL;
}
else if (ub_cmpval < 0)
{
/* Upper bound of inner range higher than that of the outer. */
- if (overlap)
- {
- /* We have already dealt with overlapping ranges. */
- }
- else
- {
- if (inner_has_default || IS_OUTER_JOIN(jointype))
- {
- if (!process_outer_partition(&outer_map,
- &inner_map,
- outer_has_default,
- inner_has_default,
- outer_part,
- inner_default,
- jointype,
- outer_bi->strategy,
- &next_index,
- &default_index,
- &merged_index))
- return NULL;
- }
+ merged_lb = outer_lb;
+ merged_ub = outer_ub;
- merged_lb = &outer_lb;
- merged_ub = &outer_ub;
+ if (inner_has_default || IS_OUTER_JOIN(jointype))
+ {
+ if (!process_outer_partition(&outer_map,
+ &inner_map,
+ outer_has_default,
+ inner_has_default,
+ outer_part,
+ inner_default,
+ jointype,
+ &next_index,
+ &default_index,
+ &merged_index))
+ return NULL;
}
/* Move to the next partition on the outer side. */
- Assert(outer_lb_index < outer_bi->ndatums);
- outer_lb_index = partition_range_get_next_lb_index(outer_bi,
- outer_lb_index);
+ outer_part = get_range_partition(outer_bi, &outer_lb_index,
+ &outer_lb, &outer_ub);
}
else
{
+ /* Upper bound of outer range higher than that of the inner. */
Assert(ub_cmpval > 0);
- /* Upper bound of outer range higher than that of the inner. */
- if (overlap)
- {
- /* We have already dealt with overlapping ranges. */
- }
- else
- {
- if (outer_has_default || jointype == JOIN_FULL)
- {
- if (!process_inner_partition(&outer_map,
- &inner_map,
- outer_has_default,
- inner_has_default,
- inner_part,
- outer_default,
- jointype,
- outer_bi->strategy,
- &next_index,
- &default_index,
- &merged_index))
- return NULL;
- }
+ merged_lb = inner_lb;
+ merged_ub = inner_ub;
- merged_lb = &inner_lb;
- merged_ub = &inner_ub;
+ if (outer_has_default || jointype == JOIN_FULL)
+ {
+ if (!process_inner_partition(&outer_map,
+ &inner_map,
+ outer_has_default,
+ inner_has_default,
+ inner_part,
+ outer_default,
+ jointype,
+ &next_index,
+ &default_index,
+ &merged_index))
+ return NULL;
}
/* Move to the next partition on the inner side. */
- Assert(inner_lb_index < inner_bi->ndatums);
- inner_lb_index = partition_range_get_next_lb_index(inner_bi,
- inner_lb_index);
+ inner_part = get_range_partition(inner_bi, &inner_lb_index,
+ &inner_lb, &inner_ub);
}
- if (merged_index < 0)
+ if (merged_index >= 0)
{
- /* We didn't find a new merged partition. */
- continue;
+ /* Add the range bounds of the merged partition. */
+ add_merged_range_bounds(partnatts, partsupfuncs, partcollations,
+ &merged_lb, &merged_ub, merged_index,
+ &merged_datums, &merged_kinds,
+ &merged_indexes);
}
-
- /*
- * We have a valid partition index for the next partition of join. The
- * partition should have valid range.
- */
- Assert(merged_lb && merged_ub);
-
- /* Try merging new lower bound with the last upper bound. */
- if (!partition_range_merge_next_lb(partnatts, partsupfuncs,
- partcollations,
- merged_lb->datums,
- merged_lb->kind, &merged_datums,
- &merged_kinds, &merged_indexes))
- return NULL;
-
- /* Add upper bound with the merged partition index. */
- merged_datums = lappend(merged_datums, merged_ub->datums);
- merged_kinds = lappend(merged_kinds, merged_ub->kind);
- merged_indexes = lappend_int(merged_indexes, merged_index);
}
/* Merge default partitions if any. */
@@ -3696,6 +3664,10 @@ partition_range_bounds_merge(int partnatts, FmgrInfo *partsupfuncs,
else
Assert(default_index == -1);
+ /*
+ * Unlike the case for list partitioning, we wouldn't have re-merged
+ * partitions, so did_remapping should be left alone.
+ */
Assert(!outer_map.did_remapping && !inner_map.did_remapping);
/* Use maps to match partition from the joining relations. */
@@ -3856,7 +3828,6 @@ partition_list_bounds_merge(FmgrInfo *partsupfunc, Oid *partcollation,
o_index,
inner_default,
jointype,
- outer_bi->strategy,
&next_index,
&default_index,
&merged_index))
@@ -3886,7 +3857,6 @@ partition_list_bounds_merge(FmgrInfo *partsupfunc, Oid *partcollation,
i_index,
outer_default,
jointype,
- outer_bi->strategy,
&next_index,
&default_index,
&merged_index))
@@ -4150,7 +4120,6 @@ process_outer_partition(PartitionMap *outer_map,
int outer_index,
int inner_default,
JoinType jointype,
- char strategy,
int *next_index,
int *default_index,
int *merged_index)
@@ -4203,22 +4172,8 @@ process_outer_partition(PartitionMap *outer_map,
Assert(IS_OUTER_JOIN(jointype));
Assert(jointype != JOIN_RIGHT);
- /*
- * In range partitioning, if the given outer partition is already
- * merged (eg, because we found an overlapping range earlier), we know
- * where it fits in the join result; nothing to do in that case. Else
- * create a new merged partition.
- */
if (outer_map->merged_indexes[outer_index] >= 0)
- {
- if (strategy == PARTITION_STRATEGY_LIST)
- *merged_index = outer_map->merged_indexes[outer_index];
- else
- {
- Assert(strategy == PARTITION_STRATEGY_RANGE);
- *merged_index = -1;
- }
- }
+ *merged_index = outer_map->merged_indexes[outer_index];
else
*merged_index = merge_partition_with_dummy(outer_map, outer_index,
next_index);
@@ -4242,7 +4197,6 @@ process_inner_partition(PartitionMap *outer_map,
int inner_index,
int outer_default,
JoinType jointype,
- char strategy,
int *next_index,
int *default_index,
int *merged_index)
@@ -4295,22 +4249,8 @@ process_inner_partition(PartitionMap *outer_map,
{
Assert(jointype == JOIN_FULL);
- /*
- * In range partitioning, if the given inner partition is already
- * merged (eg, because we found an overlapping range earlier), we know
- * where it fits in the join result; nothing to do in that case. Else
- * create a new merged partition.
- */
if (inner_map->merged_indexes[inner_index] >= 0)
- {
- if (strategy == PARTITION_STRATEGY_LIST)
- *merged_index = inner_map->merged_indexes[inner_index];
- else
- {
- Assert(strategy == PARTITION_STRATEGY_RANGE);
- *merged_index = -1;
- }
- }
+ *merged_index = inner_map->merged_indexes[inner_index];
else
*merged_index = merge_partition_with_dummy(inner_map, inner_index,
next_index);
@@ -4628,7 +4568,6 @@ merge_null_partitions(PartitionBoundInfo outer_bi, PartitionBoundInfo inner_bi,
outer_bi->null_index,
inner_bi->default_index,
jointype,
- outer_bi->strategy,
next_index,
default_index,
&merged_index))
@@ -4655,7 +4594,6 @@ merge_null_partitions(PartitionBoundInfo outer_bi, PartitionBoundInfo inner_bi,
inner_bi->null_index,
outer_bi->default_index,
jointype,
- outer_bi->strategy,
next_index,
default_index,
&merged_index))
--
2.19.2