diff --git a/src/backend/partitioning/partbounds.c b/src/backend/partitioning/partbounds.c index c8770ccfee..331dab3954 100644 --- a/src/backend/partitioning/partbounds.c +++ b/src/backend/partitioning/partbounds.c @@ -2778,6 +2778,7 @@ satisfies_hash_partition(PG_FUNCTION_ARGS) bool variadic_typbyval; char variadic_typalign; FmgrInfo partsupfunc[PARTITION_MAX_KEYS]; + Oid partcollid[PARTITION_MAX_KEYS]; } ColumnsHashData; Oid parentId; int modulus; @@ -2865,6 +2866,7 @@ satisfies_hash_partition(PG_FUNCTION_ARGS) fmgr_info_copy(&my_extra->partsupfunc[j], &key->partsupfunc[j], fcinfo->flinfo->fn_mcxt); + my_extra->partcollid[j] = key->partcollation[j]; } } @@ -2888,6 +2890,7 @@ satisfies_hash_partition(PG_FUNCTION_ARGS) /* check argument types */ for (j = 0; j < key->partnatts; ++j) + { if (key->parttypid[j] != my_extra->variadic_type) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), @@ -2895,6 +2898,8 @@ satisfies_hash_partition(PG_FUNCTION_ARGS) j + 1, format_type_be(key->parttypid[j]), format_type_be(my_extra->variadic_type)))); + my_extra->partcollid[j] = key->partcollation[j]; + } fmgr_info_copy(&my_extra->partsupfunc[0], &key->partsupfunc[0], @@ -2928,9 +2933,10 @@ satisfies_hash_partition(PG_FUNCTION_ARGS) Assert(OidIsValid(my_extra->partsupfunc[i].fn_oid)); - hash = FunctionCall2(&my_extra->partsupfunc[i], - PG_GETARG_DATUM(argno), - seed); + hash = FunctionCall2Coll(&my_extra->partsupfunc[i], + my_extra->partcollid[i], + PG_GETARG_DATUM(argno), + seed); /* Form a single 64-bit hash value */ rowHash = hash_combine64(rowHash, DatumGetUInt64(hash)); diff --git a/src/test/regress/expected/hash_part.out b/src/test/regress/expected/hash_part.out index 731d26fc3d..b536b6955c 100644 --- a/src/test/regress/expected/hash_part.out +++ b/src/test/regress/expected/hash_part.out @@ -99,6 +99,20 @@ ERROR: number of partitioning columns (2) does not match number of partition ke SELECT satisfies_hash_partition('mcinthash'::regclass, 4, 0, variadic array[now(), now()]); ERROR: column 1 of the partition key has type "integer", but supplied value is of type "timestamp with time zone" +-- check satisfies_hash_partition passes correct collation +create table text_hashp (a text) partition by hash (a); +create table text_hashp0 partition of text_hashp for values with (modulus 2, remainder 0); +create table text_hashp1 partition of text_hashp for values with (modulus 2, remainder 1); +-- The result here should always be true, because 'xxx' must belong at least +-- one of the partitions +select satisfies_hash_partition('text_hashp'::regclass, 2, 0, 'xxx'::text) OR + satisfies_hash_partition('text_hashp'::regclass, 2, 1, 'xxx'::text) AS satisfies; + satisfies +----------- + t +(1 row) + -- cleanup DROP TABLE mchash; DROP TABLE mcinthash; +DROP TABLE text_hashp; diff --git a/src/test/regress/sql/hash_part.sql b/src/test/regress/sql/hash_part.sql index f457ac344c..30601b913e 100644 --- a/src/test/regress/sql/hash_part.sql +++ b/src/test/regress/sql/hash_part.sql @@ -75,6 +75,16 @@ SELECT satisfies_hash_partition('mcinthash'::regclass, 4, 0, SELECT satisfies_hash_partition('mcinthash'::regclass, 4, 0, variadic array[now(), now()]); +-- check satisfies_hash_partition passes correct collation +create table text_hashp (a text) partition by hash (a); +create table text_hashp0 partition of text_hashp for values with (modulus 2, remainder 0); +create table text_hashp1 partition of text_hashp for values with (modulus 2, remainder 1); +-- The result here should always be true, because 'xxx' must belong to +-- one of the two defined partitions +select satisfies_hash_partition('text_hashp'::regclass, 2, 0, 'xxx'::text) OR + satisfies_hash_partition('text_hashp'::regclass, 2, 1, 'xxx'::text) AS satisfies; + -- cleanup DROP TABLE mchash; DROP TABLE mcinthash; +DROP TABLE text_hashp;