1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-07 19:06:32 +03:00

Introduce 64-bit hash functions with a 64-bit seed.

This will be useful for hash partitioning, which needs a way to seed
the hash functions to avoid problems such as a hash index on a hash
partitioned table clumping all values into a small portion of the
bucket space; it's also useful for anything that wants a 64-bit hash
value rather than a 32-bit hash value.

Just in case somebody wants a 64-bit hash value that is compatible
with the existing 32-bit hash values, make the low 32-bits of the
64-bit hash value match the 32-bit hash value when the seed is 0.

Robert Haas and Amul Sul

Discussion: http://postgr.es/m/CA+Tgmoafx2yoJuhCQQOL5CocEi-w_uG4S2xT0EtgiJnPGcHW3g@mail.gmail.com
This commit is contained in:
Robert Haas
2017-08-31 22:21:21 -04:00
parent 2d44c58c79
commit 81c5e46c49
33 changed files with 1555 additions and 42 deletions

View File

@@ -29,7 +29,7 @@
#include "utils/syscache.h"
static bool check_hash_func_signature(Oid funcid, Oid restype, Oid argtype);
static bool check_hash_func_signature(Oid funcid, int16 amprocnum, Oid argtype);
/*
@@ -105,8 +105,9 @@ hashvalidate(Oid opclassoid)
/* Check procedure numbers and function signatures */
switch (procform->amprocnum)
{
case HASHPROC:
if (!check_hash_func_signature(procform->amproc, INT4OID,
case HASHSTANDARD_PROC:
case HASHEXTENDED_PROC:
if (!check_hash_func_signature(procform->amproc, procform->amprocnum,
procform->amproclefttype))
{
ereport(INFO,
@@ -264,19 +265,37 @@ hashvalidate(Oid opclassoid)
* hacks in the core hash opclass definitions.
*/
static bool
check_hash_func_signature(Oid funcid, Oid restype, Oid argtype)
check_hash_func_signature(Oid funcid, int16 amprocnum, Oid argtype)
{
bool result = true;
Oid restype;
int16 nargs;
HeapTuple tp;
Form_pg_proc procform;
switch (amprocnum)
{
case HASHSTANDARD_PROC:
restype = INT4OID;
nargs = 1;
break;
case HASHEXTENDED_PROC:
restype = INT8OID;
nargs = 2;
break;
default:
elog(ERROR, "invalid amprocnum");
}
tp = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
if (!HeapTupleIsValid(tp))
elog(ERROR, "cache lookup failed for function %u", funcid);
procform = (Form_pg_proc) GETSTRUCT(tp);
if (procform->prorettype != restype || procform->proretset ||
procform->pronargs != 1)
procform->pronargs != nargs)
result = false;
if (!IsBinaryCoercible(argtype, procform->proargtypes.values[0]))
@@ -290,24 +309,29 @@ check_hash_func_signature(Oid funcid, Oid restype, Oid argtype)
* identity, not just its input type, because hashvarlena() takes
* INTERNAL and allowing any such function seems too scary.
*/
if (funcid == F_HASHINT4 &&
if ((funcid == F_HASHINT4 || funcid == F_HASHINT4EXTENDED) &&
(argtype == DATEOID ||
argtype == ABSTIMEOID || argtype == RELTIMEOID ||
argtype == XIDOID || argtype == CIDOID))
/* okay, allowed use of hashint4() */ ;
else if (funcid == F_TIMESTAMP_HASH &&
else if ((funcid == F_TIMESTAMP_HASH ||
funcid == F_TIMESTAMP_HASH_EXTENDED) &&
argtype == TIMESTAMPTZOID)
/* okay, allowed use of timestamp_hash() */ ;
else if (funcid == F_HASHCHAR &&
else if ((funcid == F_HASHCHAR || funcid == F_HASHCHAREXTENDED) &&
argtype == BOOLOID)
/* okay, allowed use of hashchar() */ ;
else if (funcid == F_HASHVARLENA &&
else if ((funcid == F_HASHVARLENA || funcid == F_HASHVARLENAEXTENDED) &&
argtype == BYTEAOID)
/* okay, allowed use of hashvarlena() */ ;
else
result = false;
}
/* If function takes a second argument, it must be for a 64-bit salt. */
if (nargs == 2 && procform->proargtypes.values[1] != INT8OID)
result = false;
ReleaseSysCache(tp);
return result;
}