diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2019-04-15 16:47:09 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2019-04-15 16:47:09 -0400 |
commit | 4b40e44f07c727c7a82b291d3b60098dd99f3f64 (patch) | |
tree | ad519fb91fbcdad32a7d2ab5ce1018ad1181a6b1 | |
parent | 47169c25500a70a7d04076860717f2f4f0ea83a7 (diff) | |
download | postgresql-4b40e44f07c727c7a82b291d3b60098dd99f3f64.tar.gz postgresql-4b40e44f07c727c7a82b291d3b60098dd99f3f64.zip |
Fix failure with textual partition hash keys.
Commit 5e1963fb7 overlooked two places in partbounds.c that now
need to pass a collation identifier to the hash functions for
a partition key column.
Amit Langote, per report from Jesper Pedersen
Discussion: https://postgr.es/m/a620f85a-42ab-e0f3-3337-b04b97e2e2f5@redhat.com
-rw-r--r-- | src/backend/partitioning/partbounds.c | 28 | ||||
-rw-r--r-- | src/test/regress/expected/hash_part.out | 14 | ||||
-rw-r--r-- | src/test/regress/sql/hash_part.sql | 10 |
3 files changed, 39 insertions, 13 deletions
diff --git a/src/backend/partitioning/partbounds.c b/src/backend/partitioning/partbounds.c index c8770ccfee0..0e33a370c64 100644 --- a/src/backend/partitioning/partbounds.c +++ b/src/backend/partitioning/partbounds.c @@ -2742,7 +2742,8 @@ compute_partition_hash_value(int partnatts, FmgrInfo *partsupfunc, Oid *partcoll * datatype-specific hash functions of each partition key * attribute. */ - hash = FunctionCall2Coll(&partsupfunc[i], partcollation[i], values[i], seed); + hash = FunctionCall2Coll(&partsupfunc[i], partcollation[i], + values[i], seed); /* Form a single 64-bit hash value */ rowHash = hash_combine64(rowHash, DatumGetUInt64(hash)); @@ -2777,7 +2778,8 @@ satisfies_hash_partition(PG_FUNCTION_ARGS) int16 variadic_typlen; bool variadic_typbyval; char variadic_typalign; - FmgrInfo partsupfunc[PARTITION_MAX_KEYS]; + Oid partcollid[PARTITION_MAX_KEYS]; + FmgrInfo partsupfunc[FLEXIBLE_ARRAY_MEMBER]; } ColumnsHashData; Oid parentId; int modulus; @@ -2850,6 +2852,8 @@ satisfies_hash_partition(PG_FUNCTION_ARGS) my_extra = (ColumnsHashData *) fcinfo->flinfo->fn_extra; my_extra->relid = parentId; my_extra->nkeys = key->partnatts; + memcpy(my_extra->partcollid, key->partcollation, + key->partnatts * sizeof(Oid)); /* check argument types and save fmgr_infos */ for (j = 0; j < key->partnatts; ++j) @@ -2866,7 +2870,6 @@ satisfies_hash_partition(PG_FUNCTION_ARGS) &key->partsupfunc[j], fcinfo->flinfo->fn_mcxt); } - } else { @@ -2885,6 +2888,7 @@ satisfies_hash_partition(PG_FUNCTION_ARGS) &my_extra->variadic_typlen, &my_extra->variadic_typbyval, &my_extra->variadic_typalign); + my_extra->partcollid[0] = key->partcollation[0]; /* check argument types */ for (j = 0; j < key->partnatts; ++j) @@ -2926,11 +2930,10 @@ satisfies_hash_partition(PG_FUNCTION_ARGS) if (PG_ARGISNULL(argno)) continue; - 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)); @@ -2965,11 +2968,10 @@ satisfies_hash_partition(PG_FUNCTION_ARGS) if (isnull[i]) continue; - Assert(OidIsValid(my_extra->partsupfunc[0].fn_oid)); - - hash = FunctionCall2(&my_extra->partsupfunc[0], - datum[i], - seed); + hash = FunctionCall2Coll(&my_extra->partsupfunc[0], + my_extra->partcollid[0], + datum[i], + 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 731d26fc3d8..8db316be27e 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 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; + 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 f457ac344c5..30601b913e0 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; |