diff options
author | Robert Haas <rhaas@postgresql.org> | 2011-05-23 15:17:18 -0400 |
---|---|---|
committer | Robert Haas <rhaas@postgresql.org> | 2011-05-23 15:17:18 -0400 |
commit | 7149b128dc12ece64c182962dc4f882ea7559d0c (patch) | |
tree | dbe68fac36d6d610886a29d4947ce0b31d413550 /src/backend/utils/adt/arrayfuncs.c | |
parent | c58b945e23e63a0baca67b216a5225b34de84cce (diff) | |
download | postgresql-7149b128dc12ece64c182962dc4f882ea7559d0c.tar.gz postgresql-7149b128dc12ece64c182962dc4f882ea7559d0c.zip |
Improve hash_array() logic for combining hash values.
The new logic is less vulnerable to transpositions.
This invalidates the contents of hash indexes built with the old
functions; hence, bump catversion.
Dean Rasheed
Diffstat (limited to 'src/backend/utils/adt/arrayfuncs.c')
-rw-r--r-- | src/backend/utils/adt/arrayfuncs.c | 16 |
1 files changed, 11 insertions, 5 deletions
diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c index a8af6f09537..3e43e951e10 100644 --- a/src/backend/utils/adt/arrayfuncs.c +++ b/src/backend/utils/adt/arrayfuncs.c @@ -3533,7 +3533,7 @@ hash_array(PG_FUNCTION_ARGS) int ndims = ARR_NDIM(array); int *dims = ARR_DIMS(array); Oid element_type = ARR_ELEMTYPE(array); - uint32 result = 0; + uint32 result = 1; int nitems; TypeCacheEntry *typentry; int typlen; @@ -3617,11 +3617,17 @@ hash_array(PG_FUNCTION_ARGS) } /* - * Combine hash values of successive elements by rotating the previous - * value left 1 bit, then XOR'ing in the new element's hash value. + * Combine hash values of successive elements by multiplying the + * current value by 31 and adding on the new element's hash value. + * + * The result is a sum in which each element's hash value is + * multiplied by a different power of 31. This is modulo 2^32 + * arithmetic, and the powers of 31 modulo 2^32 form a cyclic group of + * order 2^27. So for arrays of up to 2^27 elements, each element's + * hash value is multiplied by a different (odd) number, resulting in + * a good mixing of all the elements' hash values. */ - result = (result << 1) | (result >> 31); - result ^= elthash; + result = (result << 5) - result + elthash; } /* Avoid leaking memory when handed toasted input. */ |