From df87e688e0a9ac1f0b4820a3e5b920a08fe3196b Mon Sep 17 00:00:00 2001
From: Etsuro Fujita <efujita@postgresql.org>
Date: Thu, 31 Jan 2019 19:18:18 +0900
Subject: [PATCH 1/3] Hash partition bound equality refactoring.

Separate the code to check whether two given hash bounds are equal into a
separate function, so that it can be called from multiple places. Right now
it's only caller is partition_bounds_equal() but later we will use it for
merging partition bounds.

Ashutosh Bapat, reviewed by Dmitry Dolgov
---
 src/backend/partitioning/partbounds.c | 95 +++++++++++++++++----------
 1 file changed, 61 insertions(+), 34 deletions(-)

diff --git a/src/backend/partitioning/partbounds.c b/src/backend/partitioning/partbounds.c
index 0e33a370c6..35c03f611a 100644
--- a/src/backend/partitioning/partbounds.c
+++ b/src/backend/partitioning/partbounds.c
@@ -108,6 +108,9 @@ static void get_range_key_properties(PartitionKey key, int keynum,
 						 Expr **keyCol,
 						 Const **lower_val, Const **upper_val);
 static List *get_range_nulltest(PartitionKey key);
+static bool partition_hbounds_equal(PartitionBoundInfo b1,
+									PartitionBoundInfo b2);
+
 
 /*
  * get_qual_from_partbound
@@ -656,6 +659,63 @@ create_range_bounds(PartitionBoundSpec **boundspecs, int nparts,
 	return boundinfo;
 }
 
+/*
+ * Are two hash partition bound collections logically equal?
+ *
+ * Hash partition bounds store modulus and remainder in datums array which are
+ * always integers irrespective of the number of partition keys and their data
+ * types. Hence we can compare the hash bound collection without any partition
+ * key specific information. Separating this logic in a function which does not
+ * require partition key specific information allows it be called from places
+ * where the partition key specific information is not completely available.
+ */
+static bool
+partition_hbounds_equal(PartitionBoundInfo b1, PartitionBoundInfo b2)
+{
+	int			greatest_modulus = get_hash_partition_greatest_modulus(b1);
+	int			i;
+
+	Assert(b1->strategy == PARTITION_STRATEGY_HASH &&
+		   b2->strategy == PARTITION_STRATEGY_HASH);
+
+	/*
+	 * If two hash partitioned tables have different greatest moduli,
+	 * their partition schemes don't match.  For hash partitioned table,
+	 * the greatest modulus is given by the last datum and number of
+	 * partitions is given by ndatums.
+	 */
+	if (greatest_modulus != get_hash_partition_greatest_modulus(b2))
+		return false;
+
+	/*
+	 * We arrange the partitions in the ascending order of their modulus and
+	 * remainders.  Also every modulus is factor of next larger modulus.
+	 * Therefore we can safely store index of a given partition in indexes
+	 * array at remainder of that partition.  Also entries at (remainder + N *
+	 * modulus) positions in indexes array are all same for (modulus,
+	 * remainder) specification for any partition.  Thus datums array from both
+	 * the given bounds are same, if and only if their indexes array will be
+	 * same.  So, it suffices to compare indexes array.
+	 */
+	for (i = 0; i < greatest_modulus; i++)
+		if (b1->indexes[i] != b2->indexes[i])
+			return false;
+
+#ifdef USE_ASSERT_CHECKING
+
+	/*
+	 * Nonetheless make sure that the bounds are indeed same when the indexes
+	 * match.  Hash partition bound stores modulus and remainder at
+	 * b1->datums[i][0] and b1->datums[i][1] position respectively.
+	 */
+	for (i = 0; i < b1->ndatums; i++)
+		Assert((b1->datums[i][0] == b2->datums[i][0] &&
+				b1->datums[i][1] == b2->datums[i][1]));
+#endif
+
+	return true;
+}
+
 /*
  * Are two partition bound collections logically equal?
  *
@@ -684,41 +744,8 @@ partition_bounds_equal(int partnatts, int16 *parttyplen, bool *parttypbyval,
 
 	if (b1->strategy == PARTITION_STRATEGY_HASH)
 	{
-		int			greatest_modulus = get_hash_partition_greatest_modulus(b1);
-
-		/*
-		 * If two hash partitioned tables have different greatest moduli,
-		 * their partition schemes don't match.
-		 */
-		if (greatest_modulus != get_hash_partition_greatest_modulus(b2))
+		if (!partition_hbounds_equal(b1, b2))
 			return false;
-
-		/*
-		 * We arrange the partitions in the ascending order of their moduli
-		 * and remainders.  Also every modulus is factor of next larger
-		 * modulus.  Therefore we can safely store index of a given partition
-		 * in indexes array at remainder of that partition.  Also entries at
-		 * (remainder + N * modulus) positions in indexes array are all same
-		 * for (modulus, remainder) specification for any partition.  Thus
-		 * datums array from both the given bounds are same, if and only if
-		 * their indexes array will be same.  So, it suffices to compare
-		 * indexes array.
-		 */
-		for (i = 0; i < greatest_modulus; i++)
-			if (b1->indexes[i] != b2->indexes[i])
-				return false;
-
-#ifdef USE_ASSERT_CHECKING
-
-		/*
-		 * Nonetheless make sure that the bounds are indeed same when the
-		 * indexes match.  Hash partition bound stores modulus and remainder
-		 * at b1->datums[i][0] and b1->datums[i][1] position respectively.
-		 */
-		for (i = 0; i < b1->ndatums; i++)
-			Assert((b1->datums[i][0] == b2->datums[i][0] &&
-					b1->datums[i][1] == b2->datums[i][1]));
-#endif
 	}
 	else
 	{
-- 
2.18.0

