mirror of
https://github.com/postgres/postgres.git
synced 2025-05-05 09:19:17 +03:00
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
This commit is contained in:
parent
47169c2550
commit
4b40e44f07
@ -2742,7 +2742,8 @@ compute_partition_hash_value(int partnatts, FmgrInfo *partsupfunc, Oid *partcoll
|
|||||||
* datatype-specific hash functions of each partition key
|
* datatype-specific hash functions of each partition key
|
||||||
* attribute.
|
* 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 */
|
/* Form a single 64-bit hash value */
|
||||||
rowHash = hash_combine64(rowHash, DatumGetUInt64(hash));
|
rowHash = hash_combine64(rowHash, DatumGetUInt64(hash));
|
||||||
@ -2777,7 +2778,8 @@ satisfies_hash_partition(PG_FUNCTION_ARGS)
|
|||||||
int16 variadic_typlen;
|
int16 variadic_typlen;
|
||||||
bool variadic_typbyval;
|
bool variadic_typbyval;
|
||||||
char variadic_typalign;
|
char variadic_typalign;
|
||||||
FmgrInfo partsupfunc[PARTITION_MAX_KEYS];
|
Oid partcollid[PARTITION_MAX_KEYS];
|
||||||
|
FmgrInfo partsupfunc[FLEXIBLE_ARRAY_MEMBER];
|
||||||
} ColumnsHashData;
|
} ColumnsHashData;
|
||||||
Oid parentId;
|
Oid parentId;
|
||||||
int modulus;
|
int modulus;
|
||||||
@ -2850,6 +2852,8 @@ satisfies_hash_partition(PG_FUNCTION_ARGS)
|
|||||||
my_extra = (ColumnsHashData *) fcinfo->flinfo->fn_extra;
|
my_extra = (ColumnsHashData *) fcinfo->flinfo->fn_extra;
|
||||||
my_extra->relid = parentId;
|
my_extra->relid = parentId;
|
||||||
my_extra->nkeys = key->partnatts;
|
my_extra->nkeys = key->partnatts;
|
||||||
|
memcpy(my_extra->partcollid, key->partcollation,
|
||||||
|
key->partnatts * sizeof(Oid));
|
||||||
|
|
||||||
/* check argument types and save fmgr_infos */
|
/* check argument types and save fmgr_infos */
|
||||||
for (j = 0; j < key->partnatts; ++j)
|
for (j = 0; j < key->partnatts; ++j)
|
||||||
@ -2866,7 +2870,6 @@ satisfies_hash_partition(PG_FUNCTION_ARGS)
|
|||||||
&key->partsupfunc[j],
|
&key->partsupfunc[j],
|
||||||
fcinfo->flinfo->fn_mcxt);
|
fcinfo->flinfo->fn_mcxt);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -2885,6 +2888,7 @@ satisfies_hash_partition(PG_FUNCTION_ARGS)
|
|||||||
&my_extra->variadic_typlen,
|
&my_extra->variadic_typlen,
|
||||||
&my_extra->variadic_typbyval,
|
&my_extra->variadic_typbyval,
|
||||||
&my_extra->variadic_typalign);
|
&my_extra->variadic_typalign);
|
||||||
|
my_extra->partcollid[0] = key->partcollation[0];
|
||||||
|
|
||||||
/* check argument types */
|
/* check argument types */
|
||||||
for (j = 0; j < key->partnatts; ++j)
|
for (j = 0; j < key->partnatts; ++j)
|
||||||
@ -2926,9 +2930,8 @@ satisfies_hash_partition(PG_FUNCTION_ARGS)
|
|||||||
if (PG_ARGISNULL(argno))
|
if (PG_ARGISNULL(argno))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Assert(OidIsValid(my_extra->partsupfunc[i].fn_oid));
|
hash = FunctionCall2Coll(&my_extra->partsupfunc[i],
|
||||||
|
my_extra->partcollid[i],
|
||||||
hash = FunctionCall2(&my_extra->partsupfunc[i],
|
|
||||||
PG_GETARG_DATUM(argno),
|
PG_GETARG_DATUM(argno),
|
||||||
seed);
|
seed);
|
||||||
|
|
||||||
@ -2965,9 +2968,8 @@ satisfies_hash_partition(PG_FUNCTION_ARGS)
|
|||||||
if (isnull[i])
|
if (isnull[i])
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Assert(OidIsValid(my_extra->partsupfunc[0].fn_oid));
|
hash = FunctionCall2Coll(&my_extra->partsupfunc[0],
|
||||||
|
my_extra->partcollid[0],
|
||||||
hash = FunctionCall2(&my_extra->partsupfunc[0],
|
|
||||||
datum[i],
|
datum[i],
|
||||||
seed);
|
seed);
|
||||||
|
|
||||||
|
@ -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,
|
SELECT satisfies_hash_partition('mcinthash'::regclass, 4, 0,
|
||||||
variadic array[now(), now()]);
|
variadic array[now(), now()]);
|
||||||
ERROR: column 1 of the partition key has type "integer", but supplied value is of type "timestamp with time zone"
|
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
|
-- cleanup
|
||||||
DROP TABLE mchash;
|
DROP TABLE mchash;
|
||||||
DROP TABLE mcinthash;
|
DROP TABLE mcinthash;
|
||||||
|
DROP TABLE text_hashp;
|
||||||
|
@ -75,6 +75,16 @@ SELECT satisfies_hash_partition('mcinthash'::regclass, 4, 0,
|
|||||||
SELECT satisfies_hash_partition('mcinthash'::regclass, 4, 0,
|
SELECT satisfies_hash_partition('mcinthash'::regclass, 4, 0,
|
||||||
variadic array[now(), now()]);
|
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
|
-- cleanup
|
||||||
DROP TABLE mchash;
|
DROP TABLE mchash;
|
||||||
DROP TABLE mcinthash;
|
DROP TABLE mcinthash;
|
||||||
|
DROP TABLE text_hashp;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user