]> granicus.if.org Git - postgresql/commitdiff
Move hash_any prototype from access/hash.h to utils/hashutils.h
authorAlvaro Herrera <alvherre@alvh.no-ip.org>
Mon, 11 Mar 2019 16:17:50 +0000 (13:17 -0300)
committerAlvaro Herrera <alvherre@alvh.no-ip.org>
Mon, 11 Mar 2019 16:17:50 +0000 (13:17 -0300)
... as well as its implementation from backend/access/hash/hashfunc.c to
backend/utils/hash/hashfn.c.

access/hash is the place for the hash index AM, not really appropriate
for generic facilities, which is what hash_any is; having things the old
way meant that anything using hash_any had to include the AM's include
file, pointlessly polluting its namespace with unrelated, unnecessary
cruft.

Also move the HTEqual strategy number to access/stratnum.h from
access/hash.h.

To avoid breaking third-party extension code, add an #include
"utils/hashutils.h" to access/hash.h.  (An easily removed line by
committers who enjoy their asbestos suits to protect them from angry
extension authors.)

Discussion: https://postgr.es/m/201901251935.ser5e4h6djt2@alvherre.pgsql

40 files changed:
contrib/citext/citext.c
contrib/hstore/hstore_op.c
contrib/pg_stat_statements/pg_stat_statements.c
contrib/sepgsql/uavc.c
src/backend/access/common/tupdesc.c
src/backend/access/hash/hashfunc.c
src/backend/access/tablesample/bernoulli.c
src/backend/access/tablesample/system.c
src/backend/catalog/pg_publication.c
src/backend/commands/publicationcmds.c
src/backend/executor/execGrouping.c
src/backend/executor/nodeSamplescan.c
src/backend/lib/bloomfilter.c
src/backend/nodes/bitmapset.c
src/backend/storage/file/sharedfileset.c
src/backend/tsearch/ts_typanalyze.c
src/backend/utils/adt/acl.c
src/backend/utils/adt/arrayfuncs.c
src/backend/utils/adt/date.c
src/backend/utils/adt/jsonb_gin.c
src/backend/utils/adt/jsonb_util.c
src/backend/utils/adt/mac.c
src/backend/utils/adt/mac8.c
src/backend/utils/adt/network.c
src/backend/utils/adt/numeric.c
src/backend/utils/adt/pg_lsn.c
src/backend/utils/adt/rangetypes.c
src/backend/utils/adt/tid.c
src/backend/utils/adt/timestamp.c
src/backend/utils/adt/uuid.c
src/backend/utils/adt/varchar.c
src/backend/utils/adt/varlena.c
src/backend/utils/cache/catcache.c
src/backend/utils/cache/relcache.c
src/backend/utils/hash/hashfn.c
src/backend/utils/resowner/resowner.c
src/backend/utils/sort/tuplesort.c
src/include/access/hash.h
src/include/access/stratnum.h
src/include/utils/hashutils.h

index 24ceeb11fc248f47e0eb6a857361d7443fbc0a72..a4adafe89588ff8c9c3b12ca5bf23e371df24493 100644 (file)
@@ -3,10 +3,10 @@
  */
 #include "postgres.h"
 
-#include "access/hash.h"
 #include "catalog/pg_collation.h"
 #include "utils/builtins.h"
 #include "utils/formatting.h"
+#include "utils/hashutils.h"
 #include "utils/varlena.h"
 
 PG_MODULE_MAGIC;
index b852fb5a8ac4e19ebb5af27dd799655dceb41c45..87f1aef3a34f25752e0131309b2165e2c8381a7d 100644 (file)
@@ -3,11 +3,11 @@
  */
 #include "postgres.h"
 
-#include "access/hash.h"
 #include "access/htup_details.h"
 #include "catalog/pg_type.h"
 #include "funcapi.h"
 #include "utils/builtins.h"
+#include "utils/hashutils.h"
 #include "utils/memutils.h"
 
 #include "hstore.h"
index 7b39283c899d767e6ff57960a8ee97a20684785c..16b8074a00670d1af1d1d436f89eb139ac33d790 100644 (file)
@@ -61,7 +61,6 @@
 #include <sys/stat.h>
 #include <unistd.h>
 
-#include "access/hash.h"
 #include "catalog/pg_authid.h"
 #include "executor/instrument.h"
 #include "funcapi.h"
@@ -78,6 +77,7 @@
 #include "tcop/utility.h"
 #include "utils/acl.h"
 #include "utils/builtins.h"
+#include "utils/hashutils.h"
 #include "utils/memutils.h"
 
 PG_MODULE_MAGIC;
index fce6e9878542a4bf2183bbd07d73c45703a17434..7d94c31e56ead841dd8dd28653fc89216e7e53b0 100644 (file)
  */
 #include "postgres.h"
 
-#include "access/hash.h"
 #include "catalog/pg_proc.h"
 #include "commands/seclabel.h"
 #include "storage/ipc.h"
 #include "utils/guc.h"
+#include "utils/hashutils.h"
 #include "utils/memutils.h"
 
 #include "sepgsql.h"
index 832c3e9af6c8f322a00cd53d740aafa076fafed0..0158950a432a6d8e8d9204a2d421a2b19bdd0fb9 100644 (file)
@@ -19,7 +19,6 @@
 
 #include "postgres.h"
 
-#include "access/hash.h"
 #include "access/htup_details.h"
 #include "access/tupdesc_details.h"
 #include "catalog/pg_collation.h"
index 63005ddc4df10013d9beae30b26347ff88fdd6d0..e5f3d42e0454859fff2c31cb52a6d5cc8b591f54 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "access/hash.h"
 #include "utils/builtins.h"
+#include "utils/hashutils.h"
 
 /*
  * Datatype-specific hash functions.
@@ -307,629 +308,3 @@ hashvarlenaextended(PG_FUNCTION_ARGS)
 
        return result;
 }
-
-/*
- * This hash function was written by Bob Jenkins
- * (bob_jenkins@burtleburtle.net), and superficially adapted
- * for PostgreSQL by Neil Conway. For more information on this
- * hash function, see http://burtleburtle.net/bob/hash/doobs.html,
- * or Bob's article in Dr. Dobb's Journal, Sept. 1997.
- *
- * In the current code, we have adopted Bob's 2006 update of his hash
- * function to fetch the data a word at a time when it is suitably aligned.
- * This makes for a useful speedup, at the cost of having to maintain
- * four code paths (aligned vs unaligned, and little-endian vs big-endian).
- * It also uses two separate mixing functions mix() and final(), instead
- * of a slower multi-purpose function.
- */
-
-/* Get a bit mask of the bits set in non-uint32 aligned addresses */
-#define UINT32_ALIGN_MASK (sizeof(uint32) - 1)
-
-/* Rotate a uint32 value left by k bits - note multiple evaluation! */
-#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
-
-/*----------
- * mix -- mix 3 32-bit values reversibly.
- *
- * This is reversible, so any information in (a,b,c) before mix() is
- * still in (a,b,c) after mix().
- *
- * If four pairs of (a,b,c) inputs are run through mix(), or through
- * mix() in reverse, there are at least 32 bits of the output that
- * are sometimes the same for one pair and different for another pair.
- * This was tested for:
- * * pairs that differed by one bit, by two bits, in any combination
- *      of top bits of (a,b,c), or in any combination of bottom bits of
- *      (a,b,c).
- * * "differ" is defined as +, -, ^, or ~^.  For + and -, I transformed
- *      the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
- *      is commonly produced by subtraction) look like a single 1-bit
- *      difference.
- * * the base values were pseudorandom, all zero but one bit set, or
- *      all zero plus a counter that starts at zero.
- *
- * This does not achieve avalanche.  There are input bits of (a,b,c)
- * that fail to affect some output bits of (a,b,c), especially of a.  The
- * most thoroughly mixed value is c, but it doesn't really even achieve
- * avalanche in c.
- *
- * This allows some parallelism.  Read-after-writes are good at doubling
- * the number of bits affected, so the goal of mixing pulls in the opposite
- * direction from the goal of parallelism.  I did what I could.  Rotates
- * seem to cost as much as shifts on every machine I could lay my hands on,
- * and rotates are much kinder to the top and bottom bits, so I used rotates.
- *----------
- */
-#define mix(a,b,c) \
-{ \
-  a -= c;  a ^= rot(c, 4);     c += b; \
-  b -= a;  b ^= rot(a, 6);     a += c; \
-  c -= b;  c ^= rot(b, 8);     b += a; \
-  a -= c;  a ^= rot(c,16);     c += b; \
-  b -= a;  b ^= rot(a,19);     a += c; \
-  c -= b;  c ^= rot(b, 4);     b += a; \
-}
-
-/*----------
- * final -- final mixing of 3 32-bit values (a,b,c) into c
- *
- * Pairs of (a,b,c) values differing in only a few bits will usually
- * produce values of c that look totally different.  This was tested for
- * * pairs that differed by one bit, by two bits, in any combination
- *      of top bits of (a,b,c), or in any combination of bottom bits of
- *      (a,b,c).
- * * "differ" is defined as +, -, ^, or ~^.  For + and -, I transformed
- *      the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
- *      is commonly produced by subtraction) look like a single 1-bit
- *      difference.
- * * the base values were pseudorandom, all zero but one bit set, or
- *      all zero plus a counter that starts at zero.
- *
- * The use of separate functions for mix() and final() allow for a
- * substantial performance increase since final() does not need to
- * do well in reverse, but is does need to affect all output bits.
- * mix(), on the other hand, does not need to affect all output
- * bits (affecting 32 bits is enough).  The original hash function had
- * a single mixing operation that had to satisfy both sets of requirements
- * and was slower as a result.
- *----------
- */
-#define final(a,b,c) \
-{ \
-  c ^= b; c -= rot(b,14); \
-  a ^= c; a -= rot(c,11); \
-  b ^= a; b -= rot(a,25); \
-  c ^= b; c -= rot(b,16); \
-  a ^= c; a -= rot(c, 4); \
-  b ^= a; b -= rot(a,14); \
-  c ^= b; c -= rot(b,24); \
-}
-
-/*
- * hash_any() -- hash a variable-length key into a 32-bit value
- *             k               : the key (the unaligned variable-length array of bytes)
- *             len             : the length of the key, counting by bytes
- *
- * Returns a uint32 value.  Every bit of the key affects every bit of
- * the return value.  Every 1-bit and 2-bit delta achieves avalanche.
- * About 6*len+35 instructions. The best hash table sizes are powers
- * of 2.  There is no need to do mod a prime (mod is sooo slow!).
- * If you need less than 32 bits, use a bitmask.
- *
- * This procedure must never throw elog(ERROR); the ResourceOwner code
- * relies on this not to fail.
- *
- * Note: we could easily change this function to return a 64-bit hash value
- * by using the final values of both b and c.  b is perhaps a little less
- * well mixed than c, however.
- */
-Datum
-hash_any(register const unsigned char *k, register int keylen)
-{
-       register uint32 a,
-                               b,
-                               c,
-                               len;
-
-       /* Set up the internal state */
-       len = keylen;
-       a = b = c = 0x9e3779b9 + len + 3923095;
-
-       /* If the source pointer is word-aligned, we use word-wide fetches */
-       if (((uintptr_t) k & UINT32_ALIGN_MASK) == 0)
-       {
-               /* Code path for aligned source data */
-               register const uint32 *ka = (const uint32 *) k;
-
-               /* handle most of the key */
-               while (len >= 12)
-               {
-                       a += ka[0];
-                       b += ka[1];
-                       c += ka[2];
-                       mix(a, b, c);
-                       ka += 3;
-                       len -= 12;
-               }
-
-               /* handle the last 11 bytes */
-               k = (const unsigned char *) ka;
-#ifdef WORDS_BIGENDIAN
-               switch (len)
-               {
-                       case 11:
-                               c += ((uint32) k[10] << 8);
-                               /* fall through */
-                       case 10:
-                               c += ((uint32) k[9] << 16);
-                               /* fall through */
-                       case 9:
-                               c += ((uint32) k[8] << 24);
-                               /* fall through */
-                       case 8:
-                               /* the lowest byte of c is reserved for the length */
-                               b += ka[1];
-                               a += ka[0];
-                               break;
-                       case 7:
-                               b += ((uint32) k[6] << 8);
-                               /* fall through */
-                       case 6:
-                               b += ((uint32) k[5] << 16);
-                               /* fall through */
-                       case 5:
-                               b += ((uint32) k[4] << 24);
-                               /* fall through */
-                       case 4:
-                               a += ka[0];
-                               break;
-                       case 3:
-                               a += ((uint32) k[2] << 8);
-                               /* fall through */
-                       case 2:
-                               a += ((uint32) k[1] << 16);
-                               /* fall through */
-                       case 1:
-                               a += ((uint32) k[0] << 24);
-                               /* case 0: nothing left to add */
-               }
-#else                                                  /* !WORDS_BIGENDIAN */
-               switch (len)
-               {
-                       case 11:
-                               c += ((uint32) k[10] << 24);
-                               /* fall through */
-                       case 10:
-                               c += ((uint32) k[9] << 16);
-                               /* fall through */
-                       case 9:
-                               c += ((uint32) k[8] << 8);
-                               /* fall through */
-                       case 8:
-                               /* the lowest byte of c is reserved for the length */
-                               b += ka[1];
-                               a += ka[0];
-                               break;
-                       case 7:
-                               b += ((uint32) k[6] << 16);
-                               /* fall through */
-                       case 6:
-                               b += ((uint32) k[5] << 8);
-                               /* fall through */
-                       case 5:
-                               b += k[4];
-                               /* fall through */
-                       case 4:
-                               a += ka[0];
-                               break;
-                       case 3:
-                               a += ((uint32) k[2] << 16);
-                               /* fall through */
-                       case 2:
-                               a += ((uint32) k[1] << 8);
-                               /* fall through */
-                       case 1:
-                               a += k[0];
-                               /* case 0: nothing left to add */
-               }
-#endif                                                 /* WORDS_BIGENDIAN */
-       }
-       else
-       {
-               /* Code path for non-aligned source data */
-
-               /* handle most of the key */
-               while (len >= 12)
-               {
-#ifdef WORDS_BIGENDIAN
-                       a += (k[3] + ((uint32) k[2] << 8) + ((uint32) k[1] << 16) + ((uint32) k[0] << 24));
-                       b += (k[7] + ((uint32) k[6] << 8) + ((uint32) k[5] << 16) + ((uint32) k[4] << 24));
-                       c += (k[11] + ((uint32) k[10] << 8) + ((uint32) k[9] << 16) + ((uint32) k[8] << 24));
-#else                                                  /* !WORDS_BIGENDIAN */
-                       a += (k[0] + ((uint32) k[1] << 8) + ((uint32) k[2] << 16) + ((uint32) k[3] << 24));
-                       b += (k[4] + ((uint32) k[5] << 8) + ((uint32) k[6] << 16) + ((uint32) k[7] << 24));
-                       c += (k[8] + ((uint32) k[9] << 8) + ((uint32) k[10] << 16) + ((uint32) k[11] << 24));
-#endif                                                 /* WORDS_BIGENDIAN */
-                       mix(a, b, c);
-                       k += 12;
-                       len -= 12;
-               }
-
-               /* handle the last 11 bytes */
-#ifdef WORDS_BIGENDIAN
-               switch (len)
-               {
-                       case 11:
-                               c += ((uint32) k[10] << 8);
-                               /* fall through */
-                       case 10:
-                               c += ((uint32) k[9] << 16);
-                               /* fall through */
-                       case 9:
-                               c += ((uint32) k[8] << 24);
-                               /* fall through */
-                       case 8:
-                               /* the lowest byte of c is reserved for the length */
-                               b += k[7];
-                               /* fall through */
-                       case 7:
-                               b += ((uint32) k[6] << 8);
-                               /* fall through */
-                       case 6:
-                               b += ((uint32) k[5] << 16);
-                               /* fall through */
-                       case 5:
-                               b += ((uint32) k[4] << 24);
-                               /* fall through */
-                       case 4:
-                               a += k[3];
-                               /* fall through */
-                       case 3:
-                               a += ((uint32) k[2] << 8);
-                               /* fall through */
-                       case 2:
-                               a += ((uint32) k[1] << 16);
-                               /* fall through */
-                       case 1:
-                               a += ((uint32) k[0] << 24);
-                               /* case 0: nothing left to add */
-               }
-#else                                                  /* !WORDS_BIGENDIAN */
-               switch (len)
-               {
-                       case 11:
-                               c += ((uint32) k[10] << 24);
-                               /* fall through */
-                       case 10:
-                               c += ((uint32) k[9] << 16);
-                               /* fall through */
-                       case 9:
-                               c += ((uint32) k[8] << 8);
-                               /* fall through */
-                       case 8:
-                               /* the lowest byte of c is reserved for the length */
-                               b += ((uint32) k[7] << 24);
-                               /* fall through */
-                       case 7:
-                               b += ((uint32) k[6] << 16);
-                               /* fall through */
-                       case 6:
-                               b += ((uint32) k[5] << 8);
-                               /* fall through */
-                       case 5:
-                               b += k[4];
-                               /* fall through */
-                       case 4:
-                               a += ((uint32) k[3] << 24);
-                               /* fall through */
-                       case 3:
-                               a += ((uint32) k[2] << 16);
-                               /* fall through */
-                       case 2:
-                               a += ((uint32) k[1] << 8);
-                               /* fall through */
-                       case 1:
-                               a += k[0];
-                               /* case 0: nothing left to add */
-               }
-#endif                                                 /* WORDS_BIGENDIAN */
-       }
-
-       final(a, b, c);
-
-       /* report the result */
-       return UInt32GetDatum(c);
-}
-
-/*
- * hash_any_extended() -- hash into a 64-bit value, using an optional seed
- *             k               : the key (the unaligned variable-length array of bytes)
- *             len             : the length of the key, counting by bytes
- *             seed    : a 64-bit seed (0 means no seed)
- *
- * Returns a uint64 value.  Otherwise similar to hash_any.
- */
-Datum
-hash_any_extended(register const unsigned char *k, register int keylen,
-                                 uint64 seed)
-{
-       register uint32 a,
-                               b,
-                               c,
-                               len;
-
-       /* Set up the internal state */
-       len = keylen;
-       a = b = c = 0x9e3779b9 + len + 3923095;
-
-       /* If the seed is non-zero, use it to perturb the internal state. */
-       if (seed != 0)
-       {
-               /*
-                * In essence, the seed is treated as part of the data being hashed,
-                * but for simplicity, we pretend that it's padded with four bytes of
-                * zeroes so that the seed constitutes a 12-byte chunk.
-                */
-               a += (uint32) (seed >> 32);
-               b += (uint32) seed;
-               mix(a, b, c);
-       }
-
-       /* If the source pointer is word-aligned, we use word-wide fetches */
-       if (((uintptr_t) k & UINT32_ALIGN_MASK) == 0)
-       {
-               /* Code path for aligned source data */
-               register const uint32 *ka = (const uint32 *) k;
-
-               /* handle most of the key */
-               while (len >= 12)
-               {
-                       a += ka[0];
-                       b += ka[1];
-                       c += ka[2];
-                       mix(a, b, c);
-                       ka += 3;
-                       len -= 12;
-               }
-
-               /* handle the last 11 bytes */
-               k = (const unsigned char *) ka;
-#ifdef WORDS_BIGENDIAN
-               switch (len)
-               {
-                       case 11:
-                               c += ((uint32) k[10] << 8);
-                               /* fall through */
-                       case 10:
-                               c += ((uint32) k[9] << 16);
-                               /* fall through */
-                       case 9:
-                               c += ((uint32) k[8] << 24);
-                               /* fall through */
-                       case 8:
-                               /* the lowest byte of c is reserved for the length */
-                               b += ka[1];
-                               a += ka[0];
-                               break;
-                       case 7:
-                               b += ((uint32) k[6] << 8);
-                               /* fall through */
-                       case 6:
-                               b += ((uint32) k[5] << 16);
-                               /* fall through */
-                       case 5:
-                               b += ((uint32) k[4] << 24);
-                               /* fall through */
-                       case 4:
-                               a += ka[0];
-                               break;
-                       case 3:
-                               a += ((uint32) k[2] << 8);
-                               /* fall through */
-                       case 2:
-                               a += ((uint32) k[1] << 16);
-                               /* fall through */
-                       case 1:
-                               a += ((uint32) k[0] << 24);
-                               /* case 0: nothing left to add */
-               }
-#else                                                  /* !WORDS_BIGENDIAN */
-               switch (len)
-               {
-                       case 11:
-                               c += ((uint32) k[10] << 24);
-                               /* fall through */
-                       case 10:
-                               c += ((uint32) k[9] << 16);
-                               /* fall through */
-                       case 9:
-                               c += ((uint32) k[8] << 8);
-                               /* fall through */
-                       case 8:
-                               /* the lowest byte of c is reserved for the length */
-                               b += ka[1];
-                               a += ka[0];
-                               break;
-                       case 7:
-                               b += ((uint32) k[6] << 16);
-                               /* fall through */
-                       case 6:
-                               b += ((uint32) k[5] << 8);
-                               /* fall through */
-                       case 5:
-                               b += k[4];
-                               /* fall through */
-                       case 4:
-                               a += ka[0];
-                               break;
-                       case 3:
-                               a += ((uint32) k[2] << 16);
-                               /* fall through */
-                       case 2:
-                               a += ((uint32) k[1] << 8);
-                               /* fall through */
-                       case 1:
-                               a += k[0];
-                               /* case 0: nothing left to add */
-               }
-#endif                                                 /* WORDS_BIGENDIAN */
-       }
-       else
-       {
-               /* Code path for non-aligned source data */
-
-               /* handle most of the key */
-               while (len >= 12)
-               {
-#ifdef WORDS_BIGENDIAN
-                       a += (k[3] + ((uint32) k[2] << 8) + ((uint32) k[1] << 16) + ((uint32) k[0] << 24));
-                       b += (k[7] + ((uint32) k[6] << 8) + ((uint32) k[5] << 16) + ((uint32) k[4] << 24));
-                       c += (k[11] + ((uint32) k[10] << 8) + ((uint32) k[9] << 16) + ((uint32) k[8] << 24));
-#else                                                  /* !WORDS_BIGENDIAN */
-                       a += (k[0] + ((uint32) k[1] << 8) + ((uint32) k[2] << 16) + ((uint32) k[3] << 24));
-                       b += (k[4] + ((uint32) k[5] << 8) + ((uint32) k[6] << 16) + ((uint32) k[7] << 24));
-                       c += (k[8] + ((uint32) k[9] << 8) + ((uint32) k[10] << 16) + ((uint32) k[11] << 24));
-#endif                                                 /* WORDS_BIGENDIAN */
-                       mix(a, b, c);
-                       k += 12;
-                       len -= 12;
-               }
-
-               /* handle the last 11 bytes */
-#ifdef WORDS_BIGENDIAN
-               switch (len)
-               {
-                       case 11:
-                               c += ((uint32) k[10] << 8);
-                               /* fall through */
-                       case 10:
-                               c += ((uint32) k[9] << 16);
-                               /* fall through */
-                       case 9:
-                               c += ((uint32) k[8] << 24);
-                               /* fall through */
-                       case 8:
-                               /* the lowest byte of c is reserved for the length */
-                               b += k[7];
-                               /* fall through */
-                       case 7:
-                               b += ((uint32) k[6] << 8);
-                               /* fall through */
-                       case 6:
-                               b += ((uint32) k[5] << 16);
-                               /* fall through */
-                       case 5:
-                               b += ((uint32) k[4] << 24);
-                               /* fall through */
-                       case 4:
-                               a += k[3];
-                               /* fall through */
-                       case 3:
-                               a += ((uint32) k[2] << 8);
-                               /* fall through */
-                       case 2:
-                               a += ((uint32) k[1] << 16);
-                               /* fall through */
-                       case 1:
-                               a += ((uint32) k[0] << 24);
-                               /* case 0: nothing left to add */
-               }
-#else                                                  /* !WORDS_BIGENDIAN */
-               switch (len)
-               {
-                       case 11:
-                               c += ((uint32) k[10] << 24);
-                               /* fall through */
-                       case 10:
-                               c += ((uint32) k[9] << 16);
-                               /* fall through */
-                       case 9:
-                               c += ((uint32) k[8] << 8);
-                               /* fall through */
-                       case 8:
-                               /* the lowest byte of c is reserved for the length */
-                               b += ((uint32) k[7] << 24);
-                               /* fall through */
-                       case 7:
-                               b += ((uint32) k[6] << 16);
-                               /* fall through */
-                       case 6:
-                               b += ((uint32) k[5] << 8);
-                               /* fall through */
-                       case 5:
-                               b += k[4];
-                               /* fall through */
-                       case 4:
-                               a += ((uint32) k[3] << 24);
-                               /* fall through */
-                       case 3:
-                               a += ((uint32) k[2] << 16);
-                               /* fall through */
-                       case 2:
-                               a += ((uint32) k[1] << 8);
-                               /* fall through */
-                       case 1:
-                               a += k[0];
-                               /* case 0: nothing left to add */
-               }
-#endif                                                 /* WORDS_BIGENDIAN */
-       }
-
-       final(a, b, c);
-
-       /* report the result */
-       PG_RETURN_UINT64(((uint64) b << 32) | c);
-}
-
-/*
- * hash_uint32() -- hash a 32-bit value to a 32-bit value
- *
- * This has the same result as
- *             hash_any(&k, sizeof(uint32))
- * but is faster and doesn't force the caller to store k into memory.
- */
-Datum
-hash_uint32(uint32 k)
-{
-       register uint32 a,
-                               b,
-                               c;
-
-       a = b = c = 0x9e3779b9 + (uint32) sizeof(uint32) + 3923095;
-       a += k;
-
-       final(a, b, c);
-
-       /* report the result */
-       return UInt32GetDatum(c);
-}
-
-/*
- * hash_uint32_extended() -- hash a 32-bit value to a 64-bit value, with a seed
- *
- * Like hash_uint32, this is a convenience function.
- */
-Datum
-hash_uint32_extended(uint32 k, uint64 seed)
-{
-       register uint32 a,
-                               b,
-                               c;
-
-       a = b = c = 0x9e3779b9 + (uint32) sizeof(uint32) + 3923095;
-
-       if (seed != 0)
-       {
-               a += (uint32) (seed >> 32);
-               b += (uint32) seed;
-               mix(a, b, c);
-       }
-
-       a += k;
-
-       final(a, b, c);
-
-       /* report the result */
-       PG_RETURN_UINT64(((uint64) b << 32) | c);
-}
index 9360b5bbc99e806f79af9fe19ae872f447eb1f5e..42d373ab83ba30f373d3dc619e03c9094ad32167 100644 (file)
 
 #include <math.h>
 
-#include "access/hash.h"
 #include "access/tsmapi.h"
 #include "catalog/pg_type.h"
 #include "optimizer/optimizer.h"
 #include "utils/builtins.h"
+#include "utils/hashutils.h"
 
 
 /* Private state */
index 298e0ab4a097fc5d9333edd46fbb8913835ba464..fb1a56342441289925bf42d41ec34c253e6a503b 100644 (file)
 
 #include <math.h>
 
-#include "access/hash.h"
 #include "access/heapam.h"
 #include "access/relscan.h"
 #include "access/tsmapi.h"
 #include "catalog/pg_type.h"
 #include "optimizer/optimizer.h"
 #include "utils/builtins.h"
+#include "utils/hashutils.h"
 
 
 /* Private state */
index 96f92750728e59b5da30e7bb6248bcf07ece9476..a994d7bb6d8246a005ab3ed0b084517a4bd3d33a 100644 (file)
@@ -18,7 +18,6 @@
 #include "miscadmin.h"
 
 #include "access/genam.h"
-#include "access/hash.h"
 #include "access/heapam.h"
 #include "access/htup_details.h"
 #include "access/xact.h"
index eb9a093ea035e9e60005f3d668769b05a3fe6fe0..4d48be0b92ee1b91591178150500d81679014ac2 100644 (file)
@@ -18,7 +18,6 @@
 #include "miscadmin.h"
 
 #include "access/genam.h"
-#include "access/hash.h"
 #include "access/htup_details.h"
 #include "access/table.h"
 #include "access/xact.h"
index a9d80e692b5913bc1f5d0b7289fe22efa6025c64..417e971ec88db254254b67e3b6511396d01de1cf 100644 (file)
@@ -18,7 +18,6 @@
  */
 #include "postgres.h"
 
-#include "access/hash.h"
 #include "access/parallel.h"
 #include "executor/executor.h"
 #include "miscadmin.h"
index da4a65fd30ad99b65027ece482844f62f8b0ec91..65ad959641703a6eccdc98ccc5c17474b83ebffe 100644 (file)
@@ -14,7 +14,6 @@
  */
 #include "postgres.h"
 
-#include "access/hash.h"
 #include "access/heapam.h"
 #include "access/relscan.h"
 #include "access/tsmapi.h"
@@ -22,6 +21,7 @@
 #include "executor/nodeSamplescan.h"
 #include "miscadmin.h"
 #include "pgstat.h"
+#include "storage/bufmgr.h"
 #include "storage/predicate.h"
 #include "utils/builtins.h"
 #include "utils/rel.h"
index e2c1276f219ff2bff31f056d96e55ef87aedc7a6..d82420bd68ce9207d14d00488ea179930d0663f9 100644 (file)
@@ -35,9 +35,9 @@
 
 #include <math.h>
 
-#include "access/hash.h"
 #include "lib/bloomfilter.h"
 #include "port/pg_bitutils.h"
+#include "utils/hashutils.h"
 
 #define MAX_HASH_FUNCS         10
 
index 54f8567c01c8d79eefab581f2c251d7eaebb7218..07e6f03a8718581a14daf8795405d7637bb88a1e 100644 (file)
  */
 #include "postgres.h"
 
-#include "access/hash.h"
+#include "nodes/bitmapset.h"
 #include "nodes/pg_list.h"
 #include "port/pg_bitutils.h"
+#include "utils/hashutils.h"
 
 
 #define WORDNUM(x)     ((x) / BITS_PER_BITMAPWORD)
index 9d923027ad061c018e8ef2abc0b9769e438bd067..e922431a4afd1208dee0b089529ec47fc160500a 100644 (file)
 
 #include "postgres.h"
 
-#include "access/hash.h"
+#include <limits.h>
+
 #include "catalog/pg_tablespace.h"
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "storage/dsm.h"
 #include "storage/sharedfileset.h"
 #include "utils/builtins.h"
+#include "utils/hashutils.h"
 
 static void SharedFileSetOnDetach(dsm_segment *segment, Datum datum);
 static void SharedFileSetPath(char *path, SharedFileSet *fileset, Oid tablespace);
index 28495a1e2d05fc55821f70ff53a8b2a920b36a1c..530f1ccddb04b4bf171e28856e9c5e03f287eb1c 100644 (file)
  */
 #include "postgres.h"
 
-#include "access/hash.h"
 #include "catalog/pg_collation.h"
 #include "catalog/pg_operator.h"
 #include "commands/vacuum.h"
 #include "tsearch/ts_type.h"
 #include "utils/builtins.h"
+#include "utils/hashutils.h"
 
 
 /* A hash key for lexemes */
index 967b033d209b46f03783097e85530df991a48e45..83c35a4d8b3296bfca2e3ae1cbe5cb5477a5e50f 100644 (file)
@@ -16,7 +16,6 @@
 
 #include <ctype.h>
 
-#include "access/hash.h"
 #include "access/htup_details.h"
 #include "catalog/catalog.h"
 #include "catalog/namespace.h"
@@ -33,6 +32,7 @@
 #include "utils/acl.h"
 #include "utils/builtins.h"
 #include "utils/catcache.h"
+#include "utils/hashutils.h"
 #include "utils/inval.h"
 #include "utils/lsyscache.h"
 #include "utils/memutils.h"
index 5b2917d1594d330950524ce2d88eff27c938c433..a34605ac94adc56169f838d64ecef8ebd05cea24 100644 (file)
@@ -17,7 +17,6 @@
 #include <ctype.h>
 #include <math.h>
 
-#include "access/hash.h"
 #include "access/htup_details.h"
 #include "catalog/pg_type.h"
 #include "funcapi.h"
index cf5a1c6039e4730a3e401508747f1e318a1072d6..1ff3cfea8b9804ebc947a3d6f8d4bbe74e21f428 100644 (file)
@@ -20,7 +20,6 @@
 #include <float.h>
 #include <time.h>
 
-#include "access/hash.h"
 #include "access/xact.h"
 #include "libpq/pqformat.h"
 #include "miscadmin.h"
@@ -30,6 +29,7 @@
 #include "utils/builtins.h"
 #include "utils/date.h"
 #include "utils/datetime.h"
+#include "utils/hashutils.h"
 #include "utils/sortsupport.h"
 
 /*
index a7f73b6960ef6292e8d2c118cd22e22f8081acec..bae5287f705766c6337e39a88f90f93c486ece18 100644 (file)
 #include "postgres.h"
 
 #include "access/gin.h"
-#include "access/hash.h"
 #include "access/stratnum.h"
 #include "catalog/pg_collation.h"
 #include "catalog/pg_type.h"
 #include "utils/builtins.h"
+#include "utils/hashutils.h"
 #include "utils/jsonb.h"
 #include "utils/varlena.h"
 
index 6695363a4b0325f6fc197171ed0590850d6f4254..84796a11eb75aff3ea846f6e88a926ada5763d75 100644 (file)
  */
 #include "postgres.h"
 
-#include "access/hash.h"
 #include "catalog/pg_collation.h"
 #include "miscadmin.h"
 #include "utils/builtins.h"
+#include "utils/hashutils.h"
 #include "utils/jsonb.h"
 #include "utils/memutils.h"
 #include "utils/varlena.h"
index a65c1129ac6cbd000b51de4ef13a7f85b4131b56..3bfeb75fa2aabc9f2783be2a60e84aa0ba18677d 100644 (file)
 
 #include "postgres.h"
 
-#include "access/hash.h"
 #include "lib/hyperloglog.h"
 #include "libpq/pqformat.h"
 #include "port/pg_bswap.h"
 #include "utils/builtins.h"
 #include "utils/guc.h"
+#include "utils/hashutils.h"
 #include "utils/inet.h"
 #include "utils/sortsupport.h"
 
index 867e90ca4e38cf9f3484a4217cf132913db3c588..0b1fe4978ea809bce38640de1cb13c0622f34cd8 100644 (file)
@@ -21,9 +21,9 @@
 
 #include "postgres.h"
 
-#include "access/hash.h"
 #include "libpq/pqformat.h"
 #include "utils/builtins.h"
+#include "utils/hashutils.h"
 #include "utils/inet.h"
 
 /*
index 7f3ca7f930d524d42f1b077efae1f6e1b31fcde3..db9dfcbb7dc76651504ed8c5ed1bf2f5c20074b9 100644 (file)
@@ -12,7 +12,7 @@
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
-#include "access/hash.h"
+#include "access/stratnum.h"
 #include "catalog/pg_opfamily.h"
 #include "catalog/pg_type.h"
 #include "common/ip.h"
@@ -24,6 +24,7 @@
 #include "nodes/supportnodes.h"
 #include "utils/builtins.h"
 #include "utils/fmgroids.h"
+#include "utils/hashutils.h"
 #include "utils/inet.h"
 #include "utils/lsyscache.h"
 
index 1c9deebc1dda18c3f1897c2bd804fa8365c0d48d..0765f2cdb597d51c74ddd17880065af056259f97 100644 (file)
@@ -26,7 +26,6 @@
 #include <limits.h>
 #include <math.h>
 
-#include "access/hash.h"
 #include "catalog/pg_type.h"
 #include "common/int.h"
 #include "funcapi.h"
@@ -39,6 +38,7 @@
 #include "utils/builtins.h"
 #include "utils/float.h"
 #include "utils/guc.h"
+#include "utils/hashutils.h"
 #include "utils/int8.h"
 #include "utils/numeric.h"
 #include "utils/sortsupport.h"
index 2880e33b6564d04633c23c5ae881dd121537b54b..7242d3cfed485148edfcc73fdb3830d5e617688f 100644 (file)
@@ -13,7 +13,6 @@
  */
 #include "postgres.h"
 
-#include "access/hash.h"
 #include "funcapi.h"
 #include "libpq/pqformat.h"
 #include "utils/builtins.h"
index c171c7db28a8d1069fda10d172424d848cf58dc3..72c450c70ee3af2de904f4c837387b3b7e273e1f 100644 (file)
  */
 #include "postgres.h"
 
-#include "access/hash.h"
+#include "access/tupmacs.h"
 #include "lib/stringinfo.h"
 #include "libpq/pqformat.h"
 #include "miscadmin.h"
 #include "utils/builtins.h"
 #include "utils/date.h"
+#include "utils/hashutils.h"
 #include "utils/int8.h"
 #include "utils/lsyscache.h"
 #include "utils/rangetypes.h"
index f5ffd12cfc9f664a84f72979ec78d07f60318e4b..8c62771261d716e53bf3f6f12e306e8d13b6b614 100644 (file)
@@ -20,7 +20,6 @@
 #include <math.h>
 #include <limits.h>
 
-#include "access/hash.h"
 #include "access/heapam.h"
 #include "access/sysattr.h"
 #include "catalog/namespace.h"
@@ -30,6 +29,7 @@
 #include "parser/parsetree.h"
 #include "utils/acl.h"
 #include "utils/builtins.h"
+#include "utils/hashutils.h"
 #include "utils/rel.h"
 #include "utils/snapmgr.h"
 #include "utils/varlena.h"
index 1b0effa92492b3fe3253834670eda3c37c79bfda..e5ac371fa0f3c6c280d311cc8438355bea32601e 100644 (file)
@@ -20,7 +20,6 @@
 #include <limits.h>
 #include <sys/time.h>
 
-#include "access/hash.h"
 #include "access/xact.h"
 #include "catalog/pg_type.h"
 #include "common/int128.h"
index ca98429d796fec74ae5c9854370944f539ef34cc..09aa6b6daab197ee21d55f5fd7396cfcae20146a 100644 (file)
 
 #include "postgres.h"
 
-#include "access/hash.h"
 #include "lib/hyperloglog.h"
 #include "libpq/pqformat.h"
 #include "port/pg_bswap.h"
 #include "utils/builtins.h"
 #include "utils/guc.h"
+#include "utils/hashutils.h"
 #include "utils/sortsupport.h"
 #include "utils/uuid.h"
 
index c866af022f2bbc5bd0dff60830c9c2a2036fd761..440fc8ed66362dbf1c4b45964b98f88a242dfd0a 100644 (file)
@@ -14,8 +14,6 @@
  */
 #include "postgres.h"
 
-
-#include "access/hash.h"
 #include "access/tuptoaster.h"
 #include "catalog/pg_collation.h"
 #include "catalog/pg_type.h"
@@ -24,6 +22,7 @@
 #include "nodes/supportnodes.h"
 #include "utils/array.h"
 #include "utils/builtins.h"
+#include "utils/hashutils.h"
 #include "utils/varlena.h"
 #include "mb/pg_wchar.h"
 
index 693ccc5149aac274802b89a28040c750c4923140..39c394331b6d65c7d1c9ae1820ec03a86942fbb3 100644 (file)
@@ -17,7 +17,6 @@
 #include <ctype.h>
 #include <limits.h>
 
-#include "access/hash.h"
 #include "access/tuptoaster.h"
 #include "catalog/pg_collation.h"
 #include "catalog/pg_type.h"
@@ -30,6 +29,7 @@
 #include "regex/regex.h"
 #include "utils/builtins.h"
 #include "utils/bytea.h"
+#include "utils/hashutils.h"
 #include "utils/lsyscache.h"
 #include "utils/memutils.h"
 #include "utils/pg_locale.h"
index 78dd5714fa40f96e094976d0c0d3bbfdc731961b..07e1cd76962fd02136484287cd8d14d9417ef68a 100644 (file)
@@ -15,7 +15,6 @@
 #include "postgres.h"
 
 #include "access/genam.h"
-#include "access/hash.h"
 #include "access/relscan.h"
 #include "access/sysattr.h"
 #include "access/table.h"
index d9ffb784843beaa32753358980c247e2089d5829..6b28c243bda09eab66eb76d5895999749290b65f 100644 (file)
@@ -30,7 +30,6 @@
 #include <fcntl.h>
 #include <unistd.h>
 
-#include "access/hash.h"
 #include "access/htup_details.h"
 #include "access/multixact.h"
 #include "access/nbtree.h"
index de754146e527a75025dc93274c203321ec8c1fee..9f5e2925dec92f30d0081027a29bfdbb3a56573b 100644 (file)
@@ -1,7 +1,8 @@
 /*-------------------------------------------------------------------------
  *
  * hashfn.c
- *             Hash functions for use in dynahash.c hashtables
+ *             Generic hashing functions, and hash functions for use in dynahash.c
+ *             hashtables
  *
  *
  * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
  */
 #include "postgres.h"
 
-#include "access/hash.h"
+#include "fmgr.h"
+#include "nodes/bitmapset.h"
+#include "utils/hashutils.h"
 #include "utils/hsearch.h"
 
 
+/*
+ * This hash function was written by Bob Jenkins
+ * (bob_jenkins@burtleburtle.net), and superficially adapted
+ * for PostgreSQL by Neil Conway. For more information on this
+ * hash function, see http://burtleburtle.net/bob/hash/doobs.html,
+ * or Bob's article in Dr. Dobb's Journal, Sept. 1997.
+ *
+ * In the current code, we have adopted Bob's 2006 update of his hash
+ * function to fetch the data a word at a time when it is suitably aligned.
+ * This makes for a useful speedup, at the cost of having to maintain
+ * four code paths (aligned vs unaligned, and little-endian vs big-endian).
+ * It also uses two separate mixing functions mix() and final(), instead
+ * of a slower multi-purpose function.
+ */
+
+/* Get a bit mask of the bits set in non-uint32 aligned addresses */
+#define UINT32_ALIGN_MASK (sizeof(uint32) - 1)
+
+/* Rotate a uint32 value left by k bits - note multiple evaluation! */
+#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
+
+/*----------
+ * mix -- mix 3 32-bit values reversibly.
+ *
+ * This is reversible, so any information in (a,b,c) before mix() is
+ * still in (a,b,c) after mix().
+ *
+ * If four pairs of (a,b,c) inputs are run through mix(), or through
+ * mix() in reverse, there are at least 32 bits of the output that
+ * are sometimes the same for one pair and different for another pair.
+ * This was tested for:
+ * * pairs that differed by one bit, by two bits, in any combination
+ *      of top bits of (a,b,c), or in any combination of bottom bits of
+ *      (a,b,c).
+ * * "differ" is defined as +, -, ^, or ~^.  For + and -, I transformed
+ *      the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
+ *      is commonly produced by subtraction) look like a single 1-bit
+ *      difference.
+ * * the base values were pseudorandom, all zero but one bit set, or
+ *      all zero plus a counter that starts at zero.
+ *
+ * This does not achieve avalanche.  There are input bits of (a,b,c)
+ * that fail to affect some output bits of (a,b,c), especially of a.  The
+ * most thoroughly mixed value is c, but it doesn't really even achieve
+ * avalanche in c.
+ *
+ * This allows some parallelism.  Read-after-writes are good at doubling
+ * the number of bits affected, so the goal of mixing pulls in the opposite
+ * direction from the goal of parallelism.  I did what I could.  Rotates
+ * seem to cost as much as shifts on every machine I could lay my hands on,
+ * and rotates are much kinder to the top and bottom bits, so I used rotates.
+ *----------
+ */
+#define mix(a,b,c) \
+{ \
+  a -= c;  a ^= rot(c, 4);     c += b; \
+  b -= a;  b ^= rot(a, 6);     a += c; \
+  c -= b;  c ^= rot(b, 8);     b += a; \
+  a -= c;  a ^= rot(c,16);     c += b; \
+  b -= a;  b ^= rot(a,19);     a += c; \
+  c -= b;  c ^= rot(b, 4);     b += a; \
+}
+
+/*----------
+ * final -- final mixing of 3 32-bit values (a,b,c) into c
+ *
+ * Pairs of (a,b,c) values differing in only a few bits will usually
+ * produce values of c that look totally different.  This was tested for
+ * * pairs that differed by one bit, by two bits, in any combination
+ *      of top bits of (a,b,c), or in any combination of bottom bits of
+ *      (a,b,c).
+ * * "differ" is defined as +, -, ^, or ~^.  For + and -, I transformed
+ *      the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
+ *      is commonly produced by subtraction) look like a single 1-bit
+ *      difference.
+ * * the base values were pseudorandom, all zero but one bit set, or
+ *      all zero plus a counter that starts at zero.
+ *
+ * The use of separate functions for mix() and final() allow for a
+ * substantial performance increase since final() does not need to
+ * do well in reverse, but is does need to affect all output bits.
+ * mix(), on the other hand, does not need to affect all output
+ * bits (affecting 32 bits is enough).  The original hash function had
+ * a single mixing operation that had to satisfy both sets of requirements
+ * and was slower as a result.
+ *----------
+ */
+#define final(a,b,c) \
+{ \
+  c ^= b; c -= rot(b,14); \
+  a ^= c; a -= rot(c,11); \
+  b ^= a; b -= rot(a,25); \
+  c ^= b; c -= rot(b,16); \
+  a ^= c; a -= rot(c, 4); \
+  b ^= a; b -= rot(a,14); \
+  c ^= b; c -= rot(b,24); \
+}
+
+/*
+ * hash_any() -- hash a variable-length key into a 32-bit value
+ *             k               : the key (the unaligned variable-length array of bytes)
+ *             len             : the length of the key, counting by bytes
+ *
+ * Returns a uint32 value.  Every bit of the key affects every bit of
+ * the return value.  Every 1-bit and 2-bit delta achieves avalanche.
+ * About 6*len+35 instructions. The best hash table sizes are powers
+ * of 2.  There is no need to do mod a prime (mod is sooo slow!).
+ * If you need less than 32 bits, use a bitmask.
+ *
+ * This procedure must never throw elog(ERROR); the ResourceOwner code
+ * relies on this not to fail.
+ *
+ * Note: we could easily change this function to return a 64-bit hash value
+ * by using the final values of both b and c.  b is perhaps a little less
+ * well mixed than c, however.
+ */
+Datum
+hash_any(register const unsigned char *k, register int keylen)
+{
+       register uint32 a,
+                               b,
+                               c,
+                               len;
+
+       /* Set up the internal state */
+       len = keylen;
+       a = b = c = 0x9e3779b9 + len + 3923095;
+
+       /* If the source pointer is word-aligned, we use word-wide fetches */
+       if (((uintptr_t) k & UINT32_ALIGN_MASK) == 0)
+       {
+               /* Code path for aligned source data */
+               register const uint32 *ka = (const uint32 *) k;
+
+               /* handle most of the key */
+               while (len >= 12)
+               {
+                       a += ka[0];
+                       b += ka[1];
+                       c += ka[2];
+                       mix(a, b, c);
+                       ka += 3;
+                       len -= 12;
+               }
+
+               /* handle the last 11 bytes */
+               k = (const unsigned char *) ka;
+#ifdef WORDS_BIGENDIAN
+               switch (len)
+               {
+                       case 11:
+                               c += ((uint32) k[10] << 8);
+                               /* fall through */
+                       case 10:
+                               c += ((uint32) k[9] << 16);
+                               /* fall through */
+                       case 9:
+                               c += ((uint32) k[8] << 24);
+                               /* fall through */
+                       case 8:
+                               /* the lowest byte of c is reserved for the length */
+                               b += ka[1];
+                               a += ka[0];
+                               break;
+                       case 7:
+                               b += ((uint32) k[6] << 8);
+                               /* fall through */
+                       case 6:
+                               b += ((uint32) k[5] << 16);
+                               /* fall through */
+                       case 5:
+                               b += ((uint32) k[4] << 24);
+                               /* fall through */
+                       case 4:
+                               a += ka[0];
+                               break;
+                       case 3:
+                               a += ((uint32) k[2] << 8);
+                               /* fall through */
+                       case 2:
+                               a += ((uint32) k[1] << 16);
+                               /* fall through */
+                       case 1:
+                               a += ((uint32) k[0] << 24);
+                               /* case 0: nothing left to add */
+               }
+#else                                                  /* !WORDS_BIGENDIAN */
+               switch (len)
+               {
+                       case 11:
+                               c += ((uint32) k[10] << 24);
+                               /* fall through */
+                       case 10:
+                               c += ((uint32) k[9] << 16);
+                               /* fall through */
+                       case 9:
+                               c += ((uint32) k[8] << 8);
+                               /* fall through */
+                       case 8:
+                               /* the lowest byte of c is reserved for the length */
+                               b += ka[1];
+                               a += ka[0];
+                               break;
+                       case 7:
+                               b += ((uint32) k[6] << 16);
+                               /* fall through */
+                       case 6:
+                               b += ((uint32) k[5] << 8);
+                               /* fall through */
+                       case 5:
+                               b += k[4];
+                               /* fall through */
+                       case 4:
+                               a += ka[0];
+                               break;
+                       case 3:
+                               a += ((uint32) k[2] << 16);
+                               /* fall through */
+                       case 2:
+                               a += ((uint32) k[1] << 8);
+                               /* fall through */
+                       case 1:
+                               a += k[0];
+                               /* case 0: nothing left to add */
+               }
+#endif                                                 /* WORDS_BIGENDIAN */
+       }
+       else
+       {
+               /* Code path for non-aligned source data */
+
+               /* handle most of the key */
+               while (len >= 12)
+               {
+#ifdef WORDS_BIGENDIAN
+                       a += (k[3] + ((uint32) k[2] << 8) + ((uint32) k[1] << 16) + ((uint32) k[0] << 24));
+                       b += (k[7] + ((uint32) k[6] << 8) + ((uint32) k[5] << 16) + ((uint32) k[4] << 24));
+                       c += (k[11] + ((uint32) k[10] << 8) + ((uint32) k[9] << 16) + ((uint32) k[8] << 24));
+#else                                                  /* !WORDS_BIGENDIAN */
+                       a += (k[0] + ((uint32) k[1] << 8) + ((uint32) k[2] << 16) + ((uint32) k[3] << 24));
+                       b += (k[4] + ((uint32) k[5] << 8) + ((uint32) k[6] << 16) + ((uint32) k[7] << 24));
+                       c += (k[8] + ((uint32) k[9] << 8) + ((uint32) k[10] << 16) + ((uint32) k[11] << 24));
+#endif                                                 /* WORDS_BIGENDIAN */
+                       mix(a, b, c);
+                       k += 12;
+                       len -= 12;
+               }
+
+               /* handle the last 11 bytes */
+#ifdef WORDS_BIGENDIAN
+               switch (len)
+               {
+                       case 11:
+                               c += ((uint32) k[10] << 8);
+                               /* fall through */
+                       case 10:
+                               c += ((uint32) k[9] << 16);
+                               /* fall through */
+                       case 9:
+                               c += ((uint32) k[8] << 24);
+                               /* fall through */
+                       case 8:
+                               /* the lowest byte of c is reserved for the length */
+                               b += k[7];
+                               /* fall through */
+                       case 7:
+                               b += ((uint32) k[6] << 8);
+                               /* fall through */
+                       case 6:
+                               b += ((uint32) k[5] << 16);
+                               /* fall through */
+                       case 5:
+                               b += ((uint32) k[4] << 24);
+                               /* fall through */
+                       case 4:
+                               a += k[3];
+                               /* fall through */
+                       case 3:
+                               a += ((uint32) k[2] << 8);
+                               /* fall through */
+                       case 2:
+                               a += ((uint32) k[1] << 16);
+                               /* fall through */
+                       case 1:
+                               a += ((uint32) k[0] << 24);
+                               /* case 0: nothing left to add */
+               }
+#else                                                  /* !WORDS_BIGENDIAN */
+               switch (len)
+               {
+                       case 11:
+                               c += ((uint32) k[10] << 24);
+                               /* fall through */
+                       case 10:
+                               c += ((uint32) k[9] << 16);
+                               /* fall through */
+                       case 9:
+                               c += ((uint32) k[8] << 8);
+                               /* fall through */
+                       case 8:
+                               /* the lowest byte of c is reserved for the length */
+                               b += ((uint32) k[7] << 24);
+                               /* fall through */
+                       case 7:
+                               b += ((uint32) k[6] << 16);
+                               /* fall through */
+                       case 6:
+                               b += ((uint32) k[5] << 8);
+                               /* fall through */
+                       case 5:
+                               b += k[4];
+                               /* fall through */
+                       case 4:
+                               a += ((uint32) k[3] << 24);
+                               /* fall through */
+                       case 3:
+                               a += ((uint32) k[2] << 16);
+                               /* fall through */
+                       case 2:
+                               a += ((uint32) k[1] << 8);
+                               /* fall through */
+                       case 1:
+                               a += k[0];
+                               /* case 0: nothing left to add */
+               }
+#endif                                                 /* WORDS_BIGENDIAN */
+       }
+
+       final(a, b, c);
+
+       /* report the result */
+       return UInt32GetDatum(c);
+}
+
+/*
+ * hash_any_extended() -- hash into a 64-bit value, using an optional seed
+ *             k               : the key (the unaligned variable-length array of bytes)
+ *             len             : the length of the key, counting by bytes
+ *             seed    : a 64-bit seed (0 means no seed)
+ *
+ * Returns a uint64 value.  Otherwise similar to hash_any.
+ */
+Datum
+hash_any_extended(register const unsigned char *k, register int keylen,
+                                 uint64 seed)
+{
+       register uint32 a,
+                               b,
+                               c,
+                               len;
+
+       /* Set up the internal state */
+       len = keylen;
+       a = b = c = 0x9e3779b9 + len + 3923095;
+
+       /* If the seed is non-zero, use it to perturb the internal state. */
+       if (seed != 0)
+       {
+               /*
+                * In essence, the seed is treated as part of the data being hashed,
+                * but for simplicity, we pretend that it's padded with four bytes of
+                * zeroes so that the seed constitutes a 12-byte chunk.
+                */
+               a += (uint32) (seed >> 32);
+               b += (uint32) seed;
+               mix(a, b, c);
+       }
+
+       /* If the source pointer is word-aligned, we use word-wide fetches */
+       if (((uintptr_t) k & UINT32_ALIGN_MASK) == 0)
+       {
+               /* Code path for aligned source data */
+               register const uint32 *ka = (const uint32 *) k;
+
+               /* handle most of the key */
+               while (len >= 12)
+               {
+                       a += ka[0];
+                       b += ka[1];
+                       c += ka[2];
+                       mix(a, b, c);
+                       ka += 3;
+                       len -= 12;
+               }
+
+               /* handle the last 11 bytes */
+               k = (const unsigned char *) ka;
+#ifdef WORDS_BIGENDIAN
+               switch (len)
+               {
+                       case 11:
+                               c += ((uint32) k[10] << 8);
+                               /* fall through */
+                       case 10:
+                               c += ((uint32) k[9] << 16);
+                               /* fall through */
+                       case 9:
+                               c += ((uint32) k[8] << 24);
+                               /* fall through */
+                       case 8:
+                               /* the lowest byte of c is reserved for the length */
+                               b += ka[1];
+                               a += ka[0];
+                               break;
+                       case 7:
+                               b += ((uint32) k[6] << 8);
+                               /* fall through */
+                       case 6:
+                               b += ((uint32) k[5] << 16);
+                               /* fall through */
+                       case 5:
+                               b += ((uint32) k[4] << 24);
+                               /* fall through */
+                       case 4:
+                               a += ka[0];
+                               break;
+                       case 3:
+                               a += ((uint32) k[2] << 8);
+                               /* fall through */
+                       case 2:
+                               a += ((uint32) k[1] << 16);
+                               /* fall through */
+                       case 1:
+                               a += ((uint32) k[0] << 24);
+                               /* case 0: nothing left to add */
+               }
+#else                                                  /* !WORDS_BIGENDIAN */
+               switch (len)
+               {
+                       case 11:
+                               c += ((uint32) k[10] << 24);
+                               /* fall through */
+                       case 10:
+                               c += ((uint32) k[9] << 16);
+                               /* fall through */
+                       case 9:
+                               c += ((uint32) k[8] << 8);
+                               /* fall through */
+                       case 8:
+                               /* the lowest byte of c is reserved for the length */
+                               b += ka[1];
+                               a += ka[0];
+                               break;
+                       case 7:
+                               b += ((uint32) k[6] << 16);
+                               /* fall through */
+                       case 6:
+                               b += ((uint32) k[5] << 8);
+                               /* fall through */
+                       case 5:
+                               b += k[4];
+                               /* fall through */
+                       case 4:
+                               a += ka[0];
+                               break;
+                       case 3:
+                               a += ((uint32) k[2] << 16);
+                               /* fall through */
+                       case 2:
+                               a += ((uint32) k[1] << 8);
+                               /* fall through */
+                       case 1:
+                               a += k[0];
+                               /* case 0: nothing left to add */
+               }
+#endif                                                 /* WORDS_BIGENDIAN */
+       }
+       else
+       {
+               /* Code path for non-aligned source data */
+
+               /* handle most of the key */
+               while (len >= 12)
+               {
+#ifdef WORDS_BIGENDIAN
+                       a += (k[3] + ((uint32) k[2] << 8) + ((uint32) k[1] << 16) + ((uint32) k[0] << 24));
+                       b += (k[7] + ((uint32) k[6] << 8) + ((uint32) k[5] << 16) + ((uint32) k[4] << 24));
+                       c += (k[11] + ((uint32) k[10] << 8) + ((uint32) k[9] << 16) + ((uint32) k[8] << 24));
+#else                                                  /* !WORDS_BIGENDIAN */
+                       a += (k[0] + ((uint32) k[1] << 8) + ((uint32) k[2] << 16) + ((uint32) k[3] << 24));
+                       b += (k[4] + ((uint32) k[5] << 8) + ((uint32) k[6] << 16) + ((uint32) k[7] << 24));
+                       c += (k[8] + ((uint32) k[9] << 8) + ((uint32) k[10] << 16) + ((uint32) k[11] << 24));
+#endif                                                 /* WORDS_BIGENDIAN */
+                       mix(a, b, c);
+                       k += 12;
+                       len -= 12;
+               }
+
+               /* handle the last 11 bytes */
+#ifdef WORDS_BIGENDIAN
+               switch (len)
+               {
+                       case 11:
+                               c += ((uint32) k[10] << 8);
+                               /* fall through */
+                       case 10:
+                               c += ((uint32) k[9] << 16);
+                               /* fall through */
+                       case 9:
+                               c += ((uint32) k[8] << 24);
+                               /* fall through */
+                       case 8:
+                               /* the lowest byte of c is reserved for the length */
+                               b += k[7];
+                               /* fall through */
+                       case 7:
+                               b += ((uint32) k[6] << 8);
+                               /* fall through */
+                       case 6:
+                               b += ((uint32) k[5] << 16);
+                               /* fall through */
+                       case 5:
+                               b += ((uint32) k[4] << 24);
+                               /* fall through */
+                       case 4:
+                               a += k[3];
+                               /* fall through */
+                       case 3:
+                               a += ((uint32) k[2] << 8);
+                               /* fall through */
+                       case 2:
+                               a += ((uint32) k[1] << 16);
+                               /* fall through */
+                       case 1:
+                               a += ((uint32) k[0] << 24);
+                               /* case 0: nothing left to add */
+               }
+#else                                                  /* !WORDS_BIGENDIAN */
+               switch (len)
+               {
+                       case 11:
+                               c += ((uint32) k[10] << 24);
+                               /* fall through */
+                       case 10:
+                               c += ((uint32) k[9] << 16);
+                               /* fall through */
+                       case 9:
+                               c += ((uint32) k[8] << 8);
+                               /* fall through */
+                       case 8:
+                               /* the lowest byte of c is reserved for the length */
+                               b += ((uint32) k[7] << 24);
+                               /* fall through */
+                       case 7:
+                               b += ((uint32) k[6] << 16);
+                               /* fall through */
+                       case 6:
+                               b += ((uint32) k[5] << 8);
+                               /* fall through */
+                       case 5:
+                               b += k[4];
+                               /* fall through */
+                       case 4:
+                               a += ((uint32) k[3] << 24);
+                               /* fall through */
+                       case 3:
+                               a += ((uint32) k[2] << 16);
+                               /* fall through */
+                       case 2:
+                               a += ((uint32) k[1] << 8);
+                               /* fall through */
+                       case 1:
+                               a += k[0];
+                               /* case 0: nothing left to add */
+               }
+#endif                                                 /* WORDS_BIGENDIAN */
+       }
+
+       final(a, b, c);
+
+       /* report the result */
+       PG_RETURN_UINT64(((uint64) b << 32) | c);
+}
+
+/*
+ * hash_uint32() -- hash a 32-bit value to a 32-bit value
+ *
+ * This has the same result as
+ *             hash_any(&k, sizeof(uint32))
+ * but is faster and doesn't force the caller to store k into memory.
+ */
+Datum
+hash_uint32(uint32 k)
+{
+       register uint32 a,
+                               b,
+                               c;
+
+       a = b = c = 0x9e3779b9 + (uint32) sizeof(uint32) + 3923095;
+       a += k;
+
+       final(a, b, c);
+
+       /* report the result */
+       return UInt32GetDatum(c);
+}
+
+/*
+ * hash_uint32_extended() -- hash a 32-bit value to a 64-bit value, with a seed
+ *
+ * Like hash_uint32, this is a convenience function.
+ */
+Datum
+hash_uint32_extended(uint32 k, uint64 seed)
+{
+       register uint32 a,
+                               b,
+                               c;
+
+       a = b = c = 0x9e3779b9 + (uint32) sizeof(uint32) + 3923095;
+
+       if (seed != 0)
+       {
+               a += (uint32) (seed >> 32);
+               b += (uint32) seed;
+               mix(a, b, c);
+       }
+
+       a += k;
+
+       final(a, b, c);
+
+       /* report the result */
+       PG_RETURN_UINT64(((uint64) b << 32) | c);
+}
 /*
  * string_hash: hash function for keys that are NUL-terminated strings.
  *
index 84ddb44a410d6d4c1e071d2949f96d58b56282ef..f7597b0991bb60933d4822060ed5a3496a9bb4d2 100644 (file)
  */
 #include "postgres.h"
 
-#include "access/hash.h"
 #include "jit/jit.h"
+#include "storage/bufmgr.h"
 #include "storage/ipc.h"
 #include "storage/predicate.h"
 #include "storage/proc.h"
+#include "utils/hashutils.h"
 #include "utils/memutils.h"
 #include "utils/rel.h"
 #include "utils/resowner_private.h"
index 7b10fd2974c560644d34911ee97c0f8b30297fa4..2946b47b4651117d0a9e332569cefb2c79be1893 100644 (file)
@@ -96,9 +96,9 @@
 
 #include <limits.h>
 
+#include "access/hash.h"
 #include "access/htup_details.h"
 #include "access/nbtree.h"
-#include "access/hash.h"
 #include "catalog/index.h"
 #include "catalog/pg_am.h"
 #include "commands/tablespace.h"
index 0b8eb649114cdc289a76e5f9d2cdec1714cc4b00..a1b0ccc898d8b3480200346bc01af25296c8c646 100644 (file)
@@ -24,6 +24,7 @@
 #include "lib/stringinfo.h"
 #include "storage/bufmgr.h"
 #include "storage/lockdefs.h"
+#include "utils/hashutils.h"
 #include "utils/hsearch.h"
 #include "utils/relcache.h"
 
@@ -38,17 +39,6 @@ typedef uint32 Bucket;
 #define BUCKET_TO_BLKNO(metap,B) \
                ((BlockNumber) ((B) + ((B) ? (metap)->hashm_spares[_hash_spareindex((B)+1)-1] : 0)) + 1)
 
-/*
- * Rotate the high 32 bits and the low 32 bits separately.  The standard
- * hash function sometimes rotates the low 32 bits by one bit when
- * combining elements.  We want extended hash functions to be compatible with
- * that algorithm when the seed is 0, so we can't just do a normal rotation.
- * This works, though.
- */
-#define ROTATE_HIGH_AND_LOW_32BITS(v) \
-       ((((v) << 1) & UINT64CONST(0xfffffffefffffffe)) | \
-       (((v) >> 31) & UINT64CONST(0x100000001)))
-
 /*
  * Special space for hash index pages.
  *
@@ -333,12 +323,6 @@ typedef HashMetaPageData *HashMetaPage;
 #define HASH_WRITE             BUFFER_LOCK_EXCLUSIVE
 #define HASH_NOLOCK            (-1)
 
-/*
- *     Strategy number. There's only one valid strategy for hashing: equality.
- */
-#define HTEqualStrategyNumber                  1
-#define HTMaxStrategyNumber                            1
-
 /*
  * When a new operator class is declared, we require that the user supply
  * us with an amproc function for hashing a key of the new type, returning
@@ -380,12 +364,6 @@ extern IndexBulkDeleteResult *hashvacuumcleanup(IndexVacuumInfo *info,
 extern bytea *hashoptions(Datum reloptions, bool validate);
 extern bool hashvalidate(Oid opclassoid);
 
-extern Datum hash_any(register const unsigned char *k, register int keylen);
-extern Datum hash_any_extended(register const unsigned char *k,
-                                 register int keylen, uint64 seed);
-extern Datum hash_uint32(uint32 k);
-extern Datum hash_uint32_extended(uint32 k, uint64 seed);
-
 /* private routines */
 
 /* hashinsert.c */
index 8fdba2884b019bad78b91887a00c28d1b803c168..65b5223641664c6d08f33a0e53a4e595d5e18ab9 100644 (file)
@@ -34,6 +34,13 @@ typedef uint16 StrategyNumber;
 
 #define BTMaxStrategyNumber                            5
 
+/*
+ *     Strategy numbers for hash indexes. There's only one valid strategy for
+ *     hashing: equality.
+ */
+#define HTEqualStrategyNumber                  1
+
+#define HTMaxStrategyNumber                            1
 
 /*
  * Strategy numbers common to (some) GiST, SP-GiST and BRIN opclasses.
index 58bacbf19f19c06c6ff07dda444423793704ffda..aa90d4195ad3ad58c6a08d0cee5eaf9601c5cd72 100644 (file)
@@ -7,6 +7,25 @@
 #ifndef HASHUTILS_H
 #define HASHUTILS_H
 
+
+/*
+ * Rotate the high 32 bits and the low 32 bits separately.  The standard
+ * hash function sometimes rotates the low 32 bits by one bit when
+ * combining elements.  We want extended hash functions to be compatible with
+ * that algorithm when the seed is 0, so we can't just do a normal rotation.
+ * This works, though.
+ */
+#define ROTATE_HIGH_AND_LOW_32BITS(v) \
+       ((((v) << 1) & UINT64CONST(0xfffffffefffffffe)) | \
+       (((v) >> 31) & UINT64CONST(0x100000001)))
+
+
+extern Datum hash_any(register const unsigned char *k, register int keylen);
+extern Datum hash_any_extended(register const unsigned char *k,
+                                 register int keylen, uint64 seed);
+extern Datum hash_uint32(uint32 k);
+extern Datum hash_uint32_extended(uint32 k, uint64 seed);
+
 /*
  * Combine two 32-bit hash values, resulting in another hash value, with
  * decent bit mixing.