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:
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user