Fix failure with textual partition hash keys.
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 15 Apr 2019 20:47:09 +0000 (16:47 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 15 Apr 2019 20:47:09 +0000 (16:47 -0400)
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

src/backend/partitioning/partbounds.c
src/test/regress/expected/hash_part.out
src/test/regress/sql/hash_part.sql

index c8770ccfee031906925490850195bc3138f521ae..0e33a370c641c085c02e1601f931b59bf888882f 100644 (file)
@@ -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));
index 731d26fc3d8bcf4f9d68a0cc4ff2bae2881cd39a..8db316be27e4d85d55b1e6d2d3c416dc5425a8ce 100644 (file)
@@ -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;
index f457ac344c577b927a59adc22b5255eb92897172..30601b913e0eebd7d2d9372ca02f3e14b0bcacbd 100644 (file)
@@ -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;