From b65bc94d63f453ac0e2e757bcd28661cabc6c549 Mon Sep 17 00:00:00 2001 From: Etsuro Fujita 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 e71eb3793b..637e05e5ca 100644 --- a/src/backend/partitioning/partbounds.c +++ b/src/backend/partitioning/partbounds.c @@ -106,6 +106,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 @@ -654,6 +657,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? * @@ -682,41 +742,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