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
Message: Re: [HACKERS] advanced partition matching algorithm for partition-wise join

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