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:
parent
2d44c58c79
commit
81c5e46c49
|
@ -436,7 +436,8 @@
|
|||
</table>
|
||||
|
||||
<para>
|
||||
Hash indexes require one support function, shown in <xref
|
||||
Hash indexes require one support function, and allow a second one to be
|
||||
supplied at the operator class author's option, as shown in <xref
|
||||
linkend="xindex-hash-support-table">.
|
||||
</para>
|
||||
|
||||
|
@ -451,9 +452,17 @@
|
|||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>Compute the hash value for a key</entry>
|
||||
<entry>Compute the 32-bit hash value for a key</entry>
|
||||
<entry>1</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>
|
||||
Compute the 64-bit hash value for a key given a 64-bit salt; if
|
||||
the salt is 0, the low 32 bits will match the value that would
|
||||
have been computed by function 1
|
||||
</entry>
|
||||
<entry>2</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
|
|
@ -46,18 +46,36 @@ hashchar(PG_FUNCTION_ARGS)
|
|||
return hash_uint32((int32) PG_GETARG_CHAR(0));
|
||||
}
|
||||
|
||||
Datum
|
||||
hashcharextended(PG_FUNCTION_ARGS)
|
||||
{
|
||||
return hash_uint32_extended((int32) PG_GETARG_CHAR(0), PG_GETARG_INT64(1));
|
||||
}
|
||||
|
||||
Datum
|
||||
hashint2(PG_FUNCTION_ARGS)
|
||||
{
|
||||
return hash_uint32((int32) PG_GETARG_INT16(0));
|
||||
}
|
||||
|
||||
Datum
|
||||
hashint2extended(PG_FUNCTION_ARGS)
|
||||
{
|
||||
return hash_uint32_extended((int32) PG_GETARG_INT16(0), PG_GETARG_INT64(1));
|
||||
}
|
||||
|
||||
Datum
|
||||
hashint4(PG_FUNCTION_ARGS)
|
||||
{
|
||||
return hash_uint32(PG_GETARG_INT32(0));
|
||||
}
|
||||
|
||||
Datum
|
||||
hashint4extended(PG_FUNCTION_ARGS)
|
||||
{
|
||||
return hash_uint32_extended(PG_GETARG_INT32(0), PG_GETARG_INT64(1));
|
||||
}
|
||||
|
||||
Datum
|
||||
hashint8(PG_FUNCTION_ARGS)
|
||||
{
|
||||
|
@ -78,18 +96,43 @@ hashint8(PG_FUNCTION_ARGS)
|
|||
return hash_uint32(lohalf);
|
||||
}
|
||||
|
||||
Datum
|
||||
hashint8extended(PG_FUNCTION_ARGS)
|
||||
{
|
||||
/* Same approach as hashint8 */
|
||||
int64 val = PG_GETARG_INT64(0);
|
||||
uint32 lohalf = (uint32) val;
|
||||
uint32 hihalf = (uint32) (val >> 32);
|
||||
|
||||
lohalf ^= (val >= 0) ? hihalf : ~hihalf;
|
||||
|
||||
return hash_uint32_extended(lohalf, PG_GETARG_INT64(1));
|
||||
}
|
||||
|
||||
Datum
|
||||
hashoid(PG_FUNCTION_ARGS)
|
||||
{
|
||||
return hash_uint32((uint32) PG_GETARG_OID(0));
|
||||
}
|
||||
|
||||
Datum
|
||||
hashoidextended(PG_FUNCTION_ARGS)
|
||||
{
|
||||
return hash_uint32_extended((uint32) PG_GETARG_OID(0), PG_GETARG_INT64(1));
|
||||
}
|
||||
|
||||
Datum
|
||||
hashenum(PG_FUNCTION_ARGS)
|
||||
{
|
||||
return hash_uint32((uint32) PG_GETARG_OID(0));
|
||||
}
|
||||
|
||||
Datum
|
||||
hashenumextended(PG_FUNCTION_ARGS)
|
||||
{
|
||||
return hash_uint32_extended((uint32) PG_GETARG_OID(0), PG_GETARG_INT64(1));
|
||||
}
|
||||
|
||||
Datum
|
||||
hashfloat4(PG_FUNCTION_ARGS)
|
||||
{
|
||||
|
@ -116,6 +159,21 @@ hashfloat4(PG_FUNCTION_ARGS)
|
|||
return hash_any((unsigned char *) &key8, sizeof(key8));
|
||||
}
|
||||
|
||||
Datum
|
||||
hashfloat4extended(PG_FUNCTION_ARGS)
|
||||
{
|
||||
float4 key = PG_GETARG_FLOAT4(0);
|
||||
uint64 seed = PG_GETARG_INT64(1);
|
||||
float8 key8;
|
||||
|
||||
/* Same approach as hashfloat4 */
|
||||
if (key == (float4) 0)
|
||||
PG_RETURN_UINT64(seed);
|
||||
key8 = key;
|
||||
|
||||
return hash_any_extended((unsigned char *) &key8, sizeof(key8), seed);
|
||||
}
|
||||
|
||||
Datum
|
||||
hashfloat8(PG_FUNCTION_ARGS)
|
||||
{
|
||||
|
@ -132,6 +190,19 @@ hashfloat8(PG_FUNCTION_ARGS)
|
|||
return hash_any((unsigned char *) &key, sizeof(key));
|
||||
}
|
||||
|
||||
Datum
|
||||
hashfloat8extended(PG_FUNCTION_ARGS)
|
||||
{
|
||||
float8 key = PG_GETARG_FLOAT8(0);
|
||||
uint64 seed = PG_GETARG_INT64(1);
|
||||
|
||||
/* Same approach as hashfloat8 */
|
||||
if (key == (float8) 0)
|
||||
PG_RETURN_UINT64(seed);
|
||||
|
||||
return hash_any_extended((unsigned char *) &key, sizeof(key), seed);
|
||||
}
|
||||
|
||||
Datum
|
||||
hashoidvector(PG_FUNCTION_ARGS)
|
||||
{
|
||||
|
@ -140,6 +211,16 @@ hashoidvector(PG_FUNCTION_ARGS)
|
|||
return hash_any((unsigned char *) key->values, key->dim1 * sizeof(Oid));
|
||||
}
|
||||
|
||||
Datum
|
||||
hashoidvectorextended(PG_FUNCTION_ARGS)
|
||||
{
|
||||
oidvector *key = (oidvector *) PG_GETARG_POINTER(0);
|
||||
|
||||
return hash_any_extended((unsigned char *) key->values,
|
||||
key->dim1 * sizeof(Oid),
|
||||
PG_GETARG_INT64(1));
|
||||
}
|
||||
|
||||
Datum
|
||||
hashname(PG_FUNCTION_ARGS)
|
||||
{
|
||||
|
@ -148,6 +229,15 @@ hashname(PG_FUNCTION_ARGS)
|
|||
return hash_any((unsigned char *) key, strlen(key));
|
||||
}
|
||||
|
||||
Datum
|
||||
hashnameextended(PG_FUNCTION_ARGS)
|
||||
{
|
||||
char *key = NameStr(*PG_GETARG_NAME(0));
|
||||
|
||||
return hash_any_extended((unsigned char *) key, strlen(key),
|
||||
PG_GETARG_INT64(1));
|
||||
}
|
||||
|
||||
Datum
|
||||
hashtext(PG_FUNCTION_ARGS)
|
||||
{
|
||||
|
@ -168,6 +258,22 @@ hashtext(PG_FUNCTION_ARGS)
|
|||
return result;
|
||||
}
|
||||
|
||||
Datum
|
||||
hashtextextended(PG_FUNCTION_ARGS)
|
||||
{
|
||||
text *key = PG_GETARG_TEXT_PP(0);
|
||||
Datum result;
|
||||
|
||||
/* Same approach as hashtext */
|
||||
result = hash_any_extended((unsigned char *) VARDATA_ANY(key),
|
||||
VARSIZE_ANY_EXHDR(key),
|
||||
PG_GETARG_INT64(1));
|
||||
|
||||
PG_FREE_IF_COPY(key, 0);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* hashvarlena() can be used for any varlena datatype in which there are
|
||||
* no non-significant bits, ie, distinct bitpatterns never compare as equal.
|
||||
|
@ -187,6 +293,21 @@ hashvarlena(PG_FUNCTION_ARGS)
|
|||
return result;
|
||||
}
|
||||
|
||||
Datum
|
||||
hashvarlenaextended(PG_FUNCTION_ARGS)
|
||||
{
|
||||
struct varlena *key = PG_GETARG_VARLENA_PP(0);
|
||||
Datum result;
|
||||
|
||||
result = hash_any_extended((unsigned char *) VARDATA_ANY(key),
|
||||
VARSIZE_ANY_EXHDR(key),
|
||||
PG_GETARG_INT64(1));
|
||||
|
||||
PG_FREE_IF_COPY(key, 0);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* This hash function was written by Bob Jenkins
|
||||
* (bob_jenkins@burtleburtle.net), and superficially adapted
|
||||
|
@ -502,7 +623,227 @@ hash_any(register const unsigned char *k, register int keylen)
|
|||
}
|
||||
|
||||
/*
|
||||
* hash_uint32() -- hash a 32-bit value
|
||||
* 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);
|
||||
/* the lowest byte of c is reserved for the length */
|
||||
/* fall through */
|
||||
case 8:
|
||||
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);
|
||||
/* the lowest byte of c is reserved for the length */
|
||||
/* fall through */
|
||||
case 8:
|
||||
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) /* all the case statements fall through */
|
||||
{
|
||||
case 11:
|
||||
c += ((uint32) k[10] << 8);
|
||||
case 10:
|
||||
c += ((uint32) k[9] << 16);
|
||||
case 9:
|
||||
c += ((uint32) k[8] << 24);
|
||||
/* the lowest byte of c is reserved for the length */
|
||||
case 8:
|
||||
b += k[7];
|
||||
case 7:
|
||||
b += ((uint32) k[6] << 8);
|
||||
case 6:
|
||||
b += ((uint32) k[5] << 16);
|
||||
case 5:
|
||||
b += ((uint32) k[4] << 24);
|
||||
case 4:
|
||||
a += k[3];
|
||||
case 3:
|
||||
a += ((uint32) k[2] << 8);
|
||||
case 2:
|
||||
a += ((uint32) k[1] << 16);
|
||||
case 1:
|
||||
a += ((uint32) k[0] << 24);
|
||||
/* case 0: nothing left to add */
|
||||
}
|
||||
#else /* !WORDS_BIGENDIAN */
|
||||
switch (len) /* all the case statements fall through */
|
||||
{
|
||||
case 11:
|
||||
c += ((uint32) k[10] << 24);
|
||||
case 10:
|
||||
c += ((uint32) k[9] << 16);
|
||||
case 9:
|
||||
c += ((uint32) k[8] << 8);
|
||||
/* the lowest byte of c is reserved for the length */
|
||||
case 8:
|
||||
b += ((uint32) k[7] << 24);
|
||||
case 7:
|
||||
b += ((uint32) k[6] << 16);
|
||||
case 6:
|
||||
b += ((uint32) k[5] << 8);
|
||||
case 5:
|
||||
b += k[4];
|
||||
case 4:
|
||||
a += ((uint32) k[3] << 24);
|
||||
case 3:
|
||||
a += ((uint32) k[2] << 16);
|
||||
case 2:
|
||||
a += ((uint32) k[1] << 8);
|
||||
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))
|
||||
|
@ -523,3 +864,32 @@ hash_uint32(uint32 k)
|
|||
/* 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);
|
||||
}
|
||||
|
|
|
@ -373,7 +373,7 @@ _hash_init(Relation rel, double num_tuples, ForkNumber forkNum)
|
|||
if (ffactor < 10)
|
||||
ffactor = 10;
|
||||
|
||||
procid = index_getprocid(rel, 1, HASHPROC);
|
||||
procid = index_getprocid(rel, 1, HASHSTANDARD_PROC);
|
||||
|
||||
/*
|
||||
* We initialize the metapage, the first N bucket pages, and the first
|
||||
|
|
|
@ -85,7 +85,7 @@ _hash_datum2hashkey(Relation rel, Datum key)
|
|||
Oid collation;
|
||||
|
||||
/* XXX assumes index has only one attribute */
|
||||
procinfo = index_getprocinfo(rel, 1, HASHPROC);
|
||||
procinfo = index_getprocinfo(rel, 1, HASHSTANDARD_PROC);
|
||||
collation = rel->rd_indcollation[0];
|
||||
|
||||
return DatumGetUInt32(FunctionCall1Coll(procinfo, collation, key));
|
||||
|
@ -108,10 +108,10 @@ _hash_datum2hashkey_type(Relation rel, Datum key, Oid keytype)
|
|||
hash_proc = get_opfamily_proc(rel->rd_opfamily[0],
|
||||
keytype,
|
||||
keytype,
|
||||
HASHPROC);
|
||||
HASHSTANDARD_PROC);
|
||||
if (!RegProcedureIsValid(hash_proc))
|
||||
elog(ERROR, "missing support function %d(%u,%u) for index \"%s\"",
|
||||
HASHPROC, keytype, keytype,
|
||||
HASHSTANDARD_PROC, keytype, keytype,
|
||||
RelationGetRelationName(rel));
|
||||
collation = rel->rd_indcollation[0];
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <limits.h>
|
||||
|
||||
#include "access/genam.h"
|
||||
#include "access/hash.h"
|
||||
#include "access/heapam.h"
|
||||
#include "access/nbtree.h"
|
||||
#include "access/htup_details.h"
|
||||
|
@ -1129,7 +1130,8 @@ assignProcTypes(OpFamilyMember *member, Oid amoid, Oid typeoid)
|
|||
/*
|
||||
* btree comparison procs must be 2-arg procs returning int4, while btree
|
||||
* sortsupport procs must take internal and return void. hash support
|
||||
* procs must be 1-arg procs returning int4. Otherwise we don't know.
|
||||
* proc 1 must be a 1-arg proc returning int4, while proc 2 must be a
|
||||
* 2-arg proc returning int8. Otherwise we don't know.
|
||||
*/
|
||||
if (amoid == BTREE_AM_OID)
|
||||
{
|
||||
|
@ -1172,14 +1174,28 @@ assignProcTypes(OpFamilyMember *member, Oid amoid, Oid typeoid)
|
|||
}
|
||||
else if (amoid == HASH_AM_OID)
|
||||
{
|
||||
if (procform->pronargs != 1)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
||||
errmsg("hash procedures must have one argument")));
|
||||
if (procform->prorettype != INT4OID)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
||||
errmsg("hash procedures must return integer")));
|
||||
if (member->number == HASHSTANDARD_PROC)
|
||||
{
|
||||
if (procform->pronargs != 1)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
||||
errmsg("hash procedure 1 must have one argument")));
|
||||
if (procform->prorettype != INT4OID)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
||||
errmsg("hash procedure 1 must return integer")));
|
||||
}
|
||||
else if (member->number == HASHEXTENDED_PROC)
|
||||
{
|
||||
if (procform->pronargs != 2)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
||||
errmsg("hash procedure 2 must have two arguments")));
|
||||
if (procform->prorettype != INT8OID)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
||||
errmsg("hash procedure 2 must return bigint")));
|
||||
}
|
||||
|
||||
/*
|
||||
* If lefttype/righttype isn't specified, use the proc's input type
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include <ctype.h>
|
||||
|
||||
#include "access/hash.h"
|
||||
#include "access/htup_details.h"
|
||||
#include "catalog/catalog.h"
|
||||
#include "catalog/namespace.h"
|
||||
|
@ -717,6 +718,20 @@ hash_aclitem(PG_FUNCTION_ARGS)
|
|||
PG_RETURN_UINT32((uint32) (a->ai_privs + a->ai_grantee + a->ai_grantor));
|
||||
}
|
||||
|
||||
/*
|
||||
* 64-bit hash function for aclitem.
|
||||
*
|
||||
* Similar to hash_aclitem, but accepts a seed and returns a uint64 value.
|
||||
*/
|
||||
Datum
|
||||
hash_aclitem_extended(PG_FUNCTION_ARGS)
|
||||
{
|
||||
AclItem *a = PG_GETARG_ACLITEM_P(0);
|
||||
uint64 seed = PG_GETARG_INT64(1);
|
||||
uint32 sum = (uint32) (a->ai_privs + a->ai_grantee + a->ai_grantor);
|
||||
|
||||
return (seed == 0) ? UInt64GetDatum(sum) : hash_uint32_extended(sum, seed);
|
||||
}
|
||||
|
||||
/*
|
||||
* acldefault() --- create an ACL describing default access permissions
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#endif
|
||||
#include <math.h>
|
||||
|
||||
#include "access/hash.h"
|
||||
#include "access/htup_details.h"
|
||||
#include "catalog/pg_type.h"
|
||||
#include "funcapi.h"
|
||||
|
@ -4020,6 +4021,84 @@ hash_array(PG_FUNCTION_ARGS)
|
|||
PG_RETURN_UINT32(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns 64-bit value by hashing a value to a 64-bit value, with a seed.
|
||||
* Otherwise, similar to hash_array.
|
||||
*/
|
||||
Datum
|
||||
hash_array_extended(PG_FUNCTION_ARGS)
|
||||
{
|
||||
AnyArrayType *array = PG_GETARG_ANY_ARRAY(0);
|
||||
uint64 seed = PG_GETARG_INT64(1);
|
||||
int ndims = AARR_NDIM(array);
|
||||
int *dims = AARR_DIMS(array);
|
||||
Oid element_type = AARR_ELEMTYPE(array);
|
||||
uint64 result = 1;
|
||||
int nitems;
|
||||
TypeCacheEntry *typentry;
|
||||
int typlen;
|
||||
bool typbyval;
|
||||
char typalign;
|
||||
int i;
|
||||
array_iter iter;
|
||||
FunctionCallInfoData locfcinfo;
|
||||
|
||||
typentry = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
|
||||
if (typentry == NULL ||
|
||||
typentry->type_id != element_type)
|
||||
{
|
||||
typentry = lookup_type_cache(element_type,
|
||||
TYPECACHE_HASH_EXTENDED_PROC_FINFO);
|
||||
if (!OidIsValid(typentry->hash_extended_proc_finfo.fn_oid))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_FUNCTION),
|
||||
errmsg("could not identify an extended hash function for type %s",
|
||||
format_type_be(element_type))));
|
||||
fcinfo->flinfo->fn_extra = (void *) typentry;
|
||||
}
|
||||
typlen = typentry->typlen;
|
||||
typbyval = typentry->typbyval;
|
||||
typalign = typentry->typalign;
|
||||
|
||||
InitFunctionCallInfoData(locfcinfo, &typentry->hash_extended_proc_finfo, 2,
|
||||
InvalidOid, NULL, NULL);
|
||||
|
||||
/* Loop over source data */
|
||||
nitems = ArrayGetNItems(ndims, dims);
|
||||
array_iter_setup(&iter, array);
|
||||
|
||||
for (i = 0; i < nitems; i++)
|
||||
{
|
||||
Datum elt;
|
||||
bool isnull;
|
||||
uint64 elthash;
|
||||
|
||||
/* Get element, checking for NULL */
|
||||
elt = array_iter_next(&iter, &isnull, i, typlen, typbyval, typalign);
|
||||
|
||||
if (isnull)
|
||||
{
|
||||
elthash = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Apply the hash function */
|
||||
locfcinfo.arg[0] = elt;
|
||||
locfcinfo.arg[1] = seed;
|
||||
locfcinfo.argnull[0] = false;
|
||||
locfcinfo.argnull[1] = false;
|
||||
locfcinfo.isnull = false;
|
||||
elthash = DatumGetUInt64(FunctionCallInvoke(&locfcinfo));
|
||||
}
|
||||
|
||||
result = (result << 5) - result + elthash;
|
||||
}
|
||||
|
||||
AARR_FREE_IF_COPY(array, 0);
|
||||
|
||||
PG_RETURN_UINT64(result);
|
||||
}
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* array overlap/containment comparisons
|
||||
|
|
|
@ -1508,6 +1508,12 @@ time_hash(PG_FUNCTION_ARGS)
|
|||
return hashint8(fcinfo);
|
||||
}
|
||||
|
||||
Datum
|
||||
time_hash_extended(PG_FUNCTION_ARGS)
|
||||
{
|
||||
return hashint8extended(fcinfo);
|
||||
}
|
||||
|
||||
Datum
|
||||
time_larger(PG_FUNCTION_ARGS)
|
||||
{
|
||||
|
@ -2213,6 +2219,21 @@ timetz_hash(PG_FUNCTION_ARGS)
|
|||
PG_RETURN_UINT32(thash);
|
||||
}
|
||||
|
||||
Datum
|
||||
timetz_hash_extended(PG_FUNCTION_ARGS)
|
||||
{
|
||||
TimeTzADT *key = PG_GETARG_TIMETZADT_P(0);
|
||||
uint64 seed = PG_GETARG_DATUM(1);
|
||||
uint64 thash;
|
||||
|
||||
/* Same approach as timetz_hash */
|
||||
thash = DatumGetUInt64(DirectFunctionCall2(hashint8extended,
|
||||
Int64GetDatumFast(key->time),
|
||||
seed));
|
||||
thash ^= DatumGetUInt64(hash_uint32_extended(key->zone, seed));
|
||||
PG_RETURN_UINT64(thash);
|
||||
}
|
||||
|
||||
Datum
|
||||
timetz_larger(PG_FUNCTION_ARGS)
|
||||
{
|
||||
|
|
|
@ -291,3 +291,46 @@ jsonb_hash(PG_FUNCTION_ARGS)
|
|||
PG_FREE_IF_COPY(jb, 0);
|
||||
PG_RETURN_INT32(hash);
|
||||
}
|
||||
|
||||
Datum
|
||||
jsonb_hash_extended(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Jsonb *jb = PG_GETARG_JSONB(0);
|
||||
uint64 seed = PG_GETARG_INT64(1);
|
||||
JsonbIterator *it;
|
||||
JsonbValue v;
|
||||
JsonbIteratorToken r;
|
||||
uint64 hash = 0;
|
||||
|
||||
if (JB_ROOT_COUNT(jb) == 0)
|
||||
PG_RETURN_UINT64(seed);
|
||||
|
||||
it = JsonbIteratorInit(&jb->root);
|
||||
|
||||
while ((r = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
|
||||
{
|
||||
switch (r)
|
||||
{
|
||||
/* Rotation is left to JsonbHashScalarValueExtended() */
|
||||
case WJB_BEGIN_ARRAY:
|
||||
hash ^= ((UINT64CONST(JB_FARRAY) << 32) | UINT64CONST(JB_FARRAY));
|
||||
break;
|
||||
case WJB_BEGIN_OBJECT:
|
||||
hash ^= ((UINT64CONST(JB_FOBJECT) << 32) | UINT64CONST(JB_FOBJECT));
|
||||
break;
|
||||
case WJB_KEY:
|
||||
case WJB_VALUE:
|
||||
case WJB_ELEM:
|
||||
JsonbHashScalarValueExtended(&v, &hash, seed);
|
||||
break;
|
||||
case WJB_END_ARRAY:
|
||||
case WJB_END_OBJECT:
|
||||
break;
|
||||
default:
|
||||
elog(ERROR, "invalid JsonbIteratorNext rc: %d", (int) r);
|
||||
}
|
||||
}
|
||||
|
||||
PG_FREE_IF_COPY(jb, 0);
|
||||
PG_RETURN_UINT64(hash);
|
||||
}
|
||||
|
|
|
@ -1249,6 +1249,49 @@ JsonbHashScalarValue(const JsonbValue *scalarVal, uint32 *hash)
|
|||
*hash ^= tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Hash a value to a 64-bit value, with a seed. Otherwise, similar to
|
||||
* JsonbHashScalarValue.
|
||||
*/
|
||||
void
|
||||
JsonbHashScalarValueExtended(const JsonbValue *scalarVal, uint64 *hash,
|
||||
uint64 seed)
|
||||
{
|
||||
uint64 tmp;
|
||||
|
||||
switch (scalarVal->type)
|
||||
{
|
||||
case jbvNull:
|
||||
tmp = seed + 0x01;
|
||||
break;
|
||||
case jbvString:
|
||||
tmp = DatumGetUInt64(hash_any_extended((const unsigned char *) scalarVal->val.string.val,
|
||||
scalarVal->val.string.len,
|
||||
seed));
|
||||
break;
|
||||
case jbvNumeric:
|
||||
tmp = DatumGetUInt64(DirectFunctionCall2(hash_numeric_extended,
|
||||
NumericGetDatum(scalarVal->val.numeric),
|
||||
UInt64GetDatum(seed)));
|
||||
break;
|
||||
case jbvBool:
|
||||
if (seed)
|
||||
tmp = DatumGetUInt64(DirectFunctionCall2(hashcharextended,
|
||||
BoolGetDatum(scalarVal->val.boolean),
|
||||
UInt64GetDatum(seed)));
|
||||
else
|
||||
tmp = scalarVal->val.boolean ? 0x02 : 0x04;
|
||||
|
||||
break;
|
||||
default:
|
||||
elog(ERROR, "invalid jsonb scalar type");
|
||||
break;
|
||||
}
|
||||
|
||||
*hash = ROTATE_HIGH_AND_LOW_32BITS(*hash);
|
||||
*hash ^= tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Are two scalar JsonbValues of the same type a and b equal?
|
||||
*/
|
||||
|
|
|
@ -271,6 +271,15 @@ hashmacaddr(PG_FUNCTION_ARGS)
|
|||
return hash_any((unsigned char *) key, sizeof(macaddr));
|
||||
}
|
||||
|
||||
Datum
|
||||
hashmacaddrextended(PG_FUNCTION_ARGS)
|
||||
{
|
||||
macaddr *key = PG_GETARG_MACADDR_P(0);
|
||||
|
||||
return hash_any_extended((unsigned char *) key, sizeof(macaddr),
|
||||
PG_GETARG_INT64(1));
|
||||
}
|
||||
|
||||
/*
|
||||
* Arithmetic functions: bitwise NOT, AND, OR.
|
||||
*/
|
||||
|
|
|
@ -407,6 +407,15 @@ hashmacaddr8(PG_FUNCTION_ARGS)
|
|||
return hash_any((unsigned char *) key, sizeof(macaddr8));
|
||||
}
|
||||
|
||||
Datum
|
||||
hashmacaddr8extended(PG_FUNCTION_ARGS)
|
||||
{
|
||||
macaddr8 *key = PG_GETARG_MACADDR8_P(0);
|
||||
|
||||
return hash_any_extended((unsigned char *) key, sizeof(macaddr8),
|
||||
PG_GETARG_INT64(1));
|
||||
}
|
||||
|
||||
/*
|
||||
* Arithmetic functions: bitwise NOT, AND, OR.
|
||||
*/
|
||||
|
|
|
@ -486,6 +486,16 @@ hashinet(PG_FUNCTION_ARGS)
|
|||
return hash_any((unsigned char *) VARDATA_ANY(addr), addrsize + 2);
|
||||
}
|
||||
|
||||
Datum
|
||||
hashinetextended(PG_FUNCTION_ARGS)
|
||||
{
|
||||
inet *addr = PG_GETARG_INET_PP(0);
|
||||
int addrsize = ip_addrsize(addr);
|
||||
|
||||
return hash_any_extended((unsigned char *) VARDATA_ANY(addr), addrsize + 2,
|
||||
PG_GETARG_INT64(1));
|
||||
}
|
||||
|
||||
/*
|
||||
* Boolean network-inclusion tests.
|
||||
*/
|
||||
|
|
|
@ -2230,6 +2230,66 @@ hash_numeric(PG_FUNCTION_ARGS)
|
|||
PG_RETURN_DATUM(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns 64-bit value by hashing a value to a 64-bit value, with a seed.
|
||||
* Otherwise, similar to hash_numeric.
|
||||
*/
|
||||
Datum
|
||||
hash_numeric_extended(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Numeric key = PG_GETARG_NUMERIC(0);
|
||||
uint64 seed = PG_GETARG_INT64(1);
|
||||
Datum digit_hash;
|
||||
Datum result;
|
||||
int weight;
|
||||
int start_offset;
|
||||
int end_offset;
|
||||
int i;
|
||||
int hash_len;
|
||||
NumericDigit *digits;
|
||||
|
||||
if (NUMERIC_IS_NAN(key))
|
||||
PG_RETURN_UINT64(seed);
|
||||
|
||||
weight = NUMERIC_WEIGHT(key);
|
||||
start_offset = 0;
|
||||
end_offset = 0;
|
||||
|
||||
digits = NUMERIC_DIGITS(key);
|
||||
for (i = 0; i < NUMERIC_NDIGITS(key); i++)
|
||||
{
|
||||
if (digits[i] != (NumericDigit) 0)
|
||||
break;
|
||||
|
||||
start_offset++;
|
||||
|
||||
weight--;
|
||||
}
|
||||
|
||||
if (NUMERIC_NDIGITS(key) == start_offset)
|
||||
PG_RETURN_UINT64(seed - 1);
|
||||
|
||||
for (i = NUMERIC_NDIGITS(key) - 1; i >= 0; i--)
|
||||
{
|
||||
if (digits[i] != (NumericDigit) 0)
|
||||
break;
|
||||
|
||||
end_offset++;
|
||||
}
|
||||
|
||||
Assert(start_offset + end_offset < NUMERIC_NDIGITS(key));
|
||||
|
||||
hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset;
|
||||
digit_hash = hash_any_extended((unsigned char *) (NUMERIC_DIGITS(key)
|
||||
+ start_offset),
|
||||
hash_len * sizeof(NumericDigit),
|
||||
seed);
|
||||
|
||||
result = digit_hash ^ weight;
|
||||
|
||||
PG_RETURN_DATUM(result);
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
*
|
||||
|
|
|
@ -179,6 +179,12 @@ pg_lsn_hash(PG_FUNCTION_ARGS)
|
|||
return hashint8(fcinfo);
|
||||
}
|
||||
|
||||
Datum
|
||||
pg_lsn_hash_extended(PG_FUNCTION_ARGS)
|
||||
{
|
||||
return hashint8extended(fcinfo);
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------
|
||||
* Arithmetic operators on PostgreSQL LSNs.
|
||||
|
|
|
@ -1280,6 +1280,69 @@ hash_range(PG_FUNCTION_ARGS)
|
|||
PG_RETURN_INT32(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns 64-bit value by hashing a value to a 64-bit value, with a seed.
|
||||
* Otherwise, similar to hash_range.
|
||||
*/
|
||||
Datum
|
||||
hash_range_extended(PG_FUNCTION_ARGS)
|
||||
{
|
||||
RangeType *r = PG_GETARG_RANGE(0);
|
||||
uint64 seed = PG_GETARG_INT64(1);
|
||||
uint64 result;
|
||||
TypeCacheEntry *typcache;
|
||||
TypeCacheEntry *scache;
|
||||
RangeBound lower;
|
||||
RangeBound upper;
|
||||
bool empty;
|
||||
char flags;
|
||||
uint64 lower_hash;
|
||||
uint64 upper_hash;
|
||||
|
||||
check_stack_depth();
|
||||
|
||||
typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
|
||||
|
||||
range_deserialize(typcache, r, &lower, &upper, &empty);
|
||||
flags = range_get_flags(r);
|
||||
|
||||
scache = typcache->rngelemtype;
|
||||
if (!OidIsValid(scache->hash_extended_proc_finfo.fn_oid))
|
||||
{
|
||||
scache = lookup_type_cache(scache->type_id,
|
||||
TYPECACHE_HASH_EXTENDED_PROC_FINFO);
|
||||
if (!OidIsValid(scache->hash_extended_proc_finfo.fn_oid))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_FUNCTION),
|
||||
errmsg("could not identify a hash function for type %s",
|
||||
format_type_be(scache->type_id))));
|
||||
}
|
||||
|
||||
if (RANGE_HAS_LBOUND(flags))
|
||||
lower_hash = DatumGetUInt64(FunctionCall2Coll(&scache->hash_extended_proc_finfo,
|
||||
typcache->rng_collation,
|
||||
lower.val,
|
||||
seed));
|
||||
else
|
||||
lower_hash = 0;
|
||||
|
||||
if (RANGE_HAS_UBOUND(flags))
|
||||
upper_hash = DatumGetUInt64(FunctionCall2Coll(&scache->hash_extended_proc_finfo,
|
||||
typcache->rng_collation,
|
||||
upper.val,
|
||||
seed));
|
||||
else
|
||||
upper_hash = 0;
|
||||
|
||||
/* Merge hashes of flags and bounds */
|
||||
result = hash_uint32_extended((uint32) flags, seed);
|
||||
result ^= lower_hash;
|
||||
result = ROTATE_HIGH_AND_LOW_32BITS(result);
|
||||
result ^= upper_hash;
|
||||
|
||||
PG_RETURN_UINT64(result);
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------
|
||||
* CANONICAL FUNCTIONS
|
||||
|
|
|
@ -2113,6 +2113,11 @@ timestamp_hash(PG_FUNCTION_ARGS)
|
|||
return hashint8(fcinfo);
|
||||
}
|
||||
|
||||
Datum
|
||||
timestamp_hash_extended(PG_FUNCTION_ARGS)
|
||||
{
|
||||
return hashint8extended(fcinfo);
|
||||
}
|
||||
|
||||
/*
|
||||
* Cross-type comparison functions for timestamp vs timestamptz
|
||||
|
@ -2419,6 +2424,20 @@ interval_hash(PG_FUNCTION_ARGS)
|
|||
return DirectFunctionCall1(hashint8, Int64GetDatumFast(span64));
|
||||
}
|
||||
|
||||
Datum
|
||||
interval_hash_extended(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Interval *interval = PG_GETARG_INTERVAL_P(0);
|
||||
INT128 span = interval_cmp_value(interval);
|
||||
int64 span64;
|
||||
|
||||
/* Same approach as interval_hash */
|
||||
span64 = int128_to_int64(span);
|
||||
|
||||
return DirectFunctionCall2(hashint8extended, Int64GetDatumFast(span64),
|
||||
PG_GETARG_DATUM(1));
|
||||
}
|
||||
|
||||
/* overlaps_timestamp() --- implements the SQL OVERLAPS operator.
|
||||
*
|
||||
* Algorithm is per SQL spec. This is much harder than you'd think
|
||||
|
|
|
@ -408,3 +408,11 @@ uuid_hash(PG_FUNCTION_ARGS)
|
|||
|
||||
return hash_any(key->data, UUID_LEN);
|
||||
}
|
||||
|
||||
Datum
|
||||
uuid_hash_extended(PG_FUNCTION_ARGS)
|
||||
{
|
||||
pg_uuid_t *key = PG_GETARG_UUID_P(0);
|
||||
|
||||
return hash_any_extended(key->data, UUID_LEN, PG_GETARG_INT64(1));
|
||||
}
|
||||
|
|
|
@ -947,6 +947,24 @@ hashbpchar(PG_FUNCTION_ARGS)
|
|||
return result;
|
||||
}
|
||||
|
||||
Datum
|
||||
hashbpcharextended(PG_FUNCTION_ARGS)
|
||||
{
|
||||
BpChar *key = PG_GETARG_BPCHAR_PP(0);
|
||||
char *keydata;
|
||||
int keylen;
|
||||
Datum result;
|
||||
|
||||
keydata = VARDATA_ANY(key);
|
||||
keylen = bcTruelen(key);
|
||||
|
||||
result = hash_any_extended((unsigned char *) keydata, keylen,
|
||||
PG_GETARG_INT64(1));
|
||||
|
||||
PG_FREE_IF_COPY(key, 0);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* The following operators support character-by-character comparison
|
||||
|
|
|
@ -490,8 +490,8 @@ get_compatible_hash_operators(Oid opno,
|
|||
|
||||
/*
|
||||
* get_op_hash_functions
|
||||
* Get the OID(s) of hash support function(s) compatible with the given
|
||||
* operator, operating on its LHS and/or RHS datatype as required.
|
||||
* Get the OID(s) of the standard hash support function(s) compatible with
|
||||
* the given operator, operating on its LHS and/or RHS datatype as required.
|
||||
*
|
||||
* A function for the LHS type is sought and returned into *lhs_procno if
|
||||
* lhs_procno isn't NULL. Similarly, a function for the RHS type is sought
|
||||
|
@ -542,7 +542,7 @@ get_op_hash_functions(Oid opno,
|
|||
*lhs_procno = get_opfamily_proc(aform->amopfamily,
|
||||
aform->amoplefttype,
|
||||
aform->amoplefttype,
|
||||
HASHPROC);
|
||||
HASHSTANDARD_PROC);
|
||||
if (!OidIsValid(*lhs_procno))
|
||||
continue;
|
||||
/* Matching LHS found, done if caller doesn't want RHS */
|
||||
|
@ -564,7 +564,7 @@ get_op_hash_functions(Oid opno,
|
|||
*rhs_procno = get_opfamily_proc(aform->amopfamily,
|
||||
aform->amoprighttype,
|
||||
aform->amoprighttype,
|
||||
HASHPROC);
|
||||
HASHSTANDARD_PROC);
|
||||
if (!OidIsValid(*rhs_procno))
|
||||
{
|
||||
/* Forget any LHS function from this opfamily */
|
||||
|
|
|
@ -90,6 +90,7 @@ static TypeCacheEntry *firstDomainTypeEntry = NULL;
|
|||
#define TCFLAGS_HAVE_FIELD_EQUALITY 0x1000
|
||||
#define TCFLAGS_HAVE_FIELD_COMPARE 0x2000
|
||||
#define TCFLAGS_CHECKED_DOMAIN_CONSTRAINTS 0x4000
|
||||
#define TCFLAGS_CHECKED_HASH_EXTENDED_PROC 0x8000
|
||||
|
||||
/*
|
||||
* Data stored about a domain type's constraints. Note that we do not create
|
||||
|
@ -307,6 +308,8 @@ lookup_type_cache(Oid type_id, int flags)
|
|||
flags |= TYPECACHE_HASH_OPFAMILY;
|
||||
|
||||
if ((flags & (TYPECACHE_HASH_PROC | TYPECACHE_HASH_PROC_FINFO |
|
||||
TYPECACHE_HASH_EXTENDED_PROC |
|
||||
TYPECACHE_HASH_EXTENDED_PROC_FINFO |
|
||||
TYPECACHE_HASH_OPFAMILY)) &&
|
||||
!(typentry->flags & TCFLAGS_CHECKED_HASH_OPCLASS))
|
||||
{
|
||||
|
@ -329,6 +332,7 @@ lookup_type_cache(Oid type_id, int flags)
|
|||
* decision is still good.
|
||||
*/
|
||||
typentry->flags &= ~(TCFLAGS_CHECKED_HASH_PROC);
|
||||
typentry->flags &= ~(TCFLAGS_CHECKED_HASH_EXTENDED_PROC);
|
||||
typentry->flags |= TCFLAGS_CHECKED_HASH_OPCLASS;
|
||||
}
|
||||
|
||||
|
@ -372,11 +376,12 @@ lookup_type_cache(Oid type_id, int flags)
|
|||
typentry->eq_opr = eq_opr;
|
||||
|
||||
/*
|
||||
* Reset info about hash function whenever we pick up new info about
|
||||
* equality operator. This is so we can ensure that the hash function
|
||||
* matches the operator.
|
||||
* Reset info about hash functions whenever we pick up new info about
|
||||
* equality operator. This is so we can ensure that the hash functions
|
||||
* match the operator.
|
||||
*/
|
||||
typentry->flags &= ~(TCFLAGS_CHECKED_HASH_PROC);
|
||||
typentry->flags &= ~(TCFLAGS_CHECKED_HASH_EXTENDED_PROC);
|
||||
typentry->flags |= TCFLAGS_CHECKED_EQ_OPR;
|
||||
}
|
||||
if ((flags & TYPECACHE_LT_OPR) &&
|
||||
|
@ -467,7 +472,7 @@ lookup_type_cache(Oid type_id, int flags)
|
|||
hash_proc = get_opfamily_proc(typentry->hash_opf,
|
||||
typentry->hash_opintype,
|
||||
typentry->hash_opintype,
|
||||
HASHPROC);
|
||||
HASHSTANDARD_PROC);
|
||||
|
||||
/*
|
||||
* As above, make sure hash_array will succeed. We don't currently
|
||||
|
@ -485,6 +490,43 @@ lookup_type_cache(Oid type_id, int flags)
|
|||
typentry->hash_proc = hash_proc;
|
||||
typentry->flags |= TCFLAGS_CHECKED_HASH_PROC;
|
||||
}
|
||||
if ((flags & (TYPECACHE_HASH_EXTENDED_PROC |
|
||||
TYPECACHE_HASH_EXTENDED_PROC_FINFO)) &&
|
||||
!(typentry->flags & TCFLAGS_CHECKED_HASH_EXTENDED_PROC))
|
||||
{
|
||||
Oid hash_extended_proc = InvalidOid;
|
||||
|
||||
/*
|
||||
* We insist that the eq_opr, if one has been determined, match the
|
||||
* hash opclass; else report there is no hash function.
|
||||
*/
|
||||
if (typentry->hash_opf != InvalidOid &&
|
||||
(!OidIsValid(typentry->eq_opr) ||
|
||||
typentry->eq_opr == get_opfamily_member(typentry->hash_opf,
|
||||
typentry->hash_opintype,
|
||||
typentry->hash_opintype,
|
||||
HTEqualStrategyNumber)))
|
||||
hash_extended_proc = get_opfamily_proc(typentry->hash_opf,
|
||||
typentry->hash_opintype,
|
||||
typentry->hash_opintype,
|
||||
HASHEXTENDED_PROC);
|
||||
|
||||
/*
|
||||
* As above, make sure hash_array_extended will succeed. We don't
|
||||
* currently support hashing for composite types, but when we do,
|
||||
* we'll need more logic here to check that case too.
|
||||
*/
|
||||
if (hash_extended_proc == F_HASH_ARRAY_EXTENDED &&
|
||||
!array_element_has_hashing(typentry))
|
||||
hash_extended_proc = InvalidOid;
|
||||
|
||||
/* Force update of hash_proc_finfo only if we're changing state */
|
||||
if (typentry->hash_extended_proc != hash_extended_proc)
|
||||
typentry->hash_extended_proc_finfo.fn_oid = InvalidOid;
|
||||
|
||||
typentry->hash_extended_proc = hash_extended_proc;
|
||||
typentry->flags |= TCFLAGS_CHECKED_HASH_EXTENDED_PROC;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up fmgr lookup info as requested
|
||||
|
@ -523,6 +565,14 @@ lookup_type_cache(Oid type_id, int flags)
|
|||
fmgr_info_cxt(typentry->hash_proc, &typentry->hash_proc_finfo,
|
||||
CacheMemoryContext);
|
||||
}
|
||||
if ((flags & TYPECACHE_HASH_EXTENDED_PROC_FINFO) &&
|
||||
typentry->hash_extended_proc_finfo.fn_oid == InvalidOid &&
|
||||
typentry->hash_extended_proc != InvalidOid)
|
||||
{
|
||||
fmgr_info_cxt(typentry->hash_extended_proc,
|
||||
&typentry->hash_extended_proc_finfo,
|
||||
CacheMemoryContext);
|
||||
}
|
||||
|
||||
/*
|
||||
* If it's a composite type (row type), get tupdesc if requested
|
||||
|
|
|
@ -38,6 +38,17 @@ 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.
|
||||
*
|
||||
|
@ -289,12 +300,20 @@ typedef HashMetaPageData *HashMetaPage;
|
|||
#define HTMaxStrategyNumber 1
|
||||
|
||||
/*
|
||||
* When a new operator class is declared, we require that the user supply
|
||||
* us with an amproc procudure for hashing a key of the new type.
|
||||
* Since we only have one such proc in amproc, it's number 1.
|
||||
* When a new operator class is declared, we require that the user supply
|
||||
* us with an amproc procudure for hashing a key of the new type, returning
|
||||
* a 32-bit hash value. We call this the "standard" hash procedure. We
|
||||
* also allow an optional "extended" hash procedure which accepts a salt and
|
||||
* returns a 64-bit hash value. This is highly recommended but, for reasons
|
||||
* of backward compatibility, optional.
|
||||
*
|
||||
* When the salt is 0, the low 32 bits of the value returned by the extended
|
||||
* hash procedure should match the value that would have been returned by the
|
||||
* standard hash procedure.
|
||||
*/
|
||||
#define HASHPROC 1
|
||||
#define HASHNProcs 1
|
||||
#define HASHSTANDARD_PROC 1
|
||||
#define HASHEXTENDED_PROC 2
|
||||
#define HASHNProcs 2
|
||||
|
||||
|
||||
/* public routines */
|
||||
|
@ -322,7 +341,10 @@ 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 */
|
||||
|
||||
|
|
|
@ -53,6 +53,6 @@
|
|||
*/
|
||||
|
||||
/* yyyymmddN */
|
||||
#define CATALOG_VERSION_NO 201707211
|
||||
#define CATALOG_VERSION_NO 201708311
|
||||
|
||||
#endif
|
||||
|
|
|
@ -153,41 +153,77 @@ DATA(insert ( 4033 3802 3802 1 4044 ));
|
|||
|
||||
/* hash */
|
||||
DATA(insert ( 427 1042 1042 1 1080 ));
|
||||
DATA(insert ( 427 1042 1042 2 972 ));
|
||||
DATA(insert ( 431 18 18 1 454 ));
|
||||
DATA(insert ( 431 18 18 2 446 ));
|
||||
DATA(insert ( 435 1082 1082 1 450 ));
|
||||
DATA(insert ( 435 1082 1082 2 425 ));
|
||||
DATA(insert ( 627 2277 2277 1 626 ));
|
||||
DATA(insert ( 627 2277 2277 2 782 ));
|
||||
DATA(insert ( 1971 700 700 1 451 ));
|
||||
DATA(insert ( 1971 700 700 2 443 ));
|
||||
DATA(insert ( 1971 701 701 1 452 ));
|
||||
DATA(insert ( 1971 701 701 2 444 ));
|
||||
DATA(insert ( 1975 869 869 1 422 ));
|
||||
DATA(insert ( 1975 869 869 2 779 ));
|
||||
DATA(insert ( 1977 21 21 1 449 ));
|
||||
DATA(insert ( 1977 21 21 2 441 ));
|
||||
DATA(insert ( 1977 23 23 1 450 ));
|
||||
DATA(insert ( 1977 23 23 2 425 ));
|
||||
DATA(insert ( 1977 20 20 1 949 ));
|
||||
DATA(insert ( 1977 20 20 2 442 ));
|
||||
DATA(insert ( 1983 1186 1186 1 1697 ));
|
||||
DATA(insert ( 1983 1186 1186 2 3418 ));
|
||||
DATA(insert ( 1985 829 829 1 399 ));
|
||||
DATA(insert ( 1985 829 829 2 778 ));
|
||||
DATA(insert ( 1987 19 19 1 455 ));
|
||||
DATA(insert ( 1987 19 19 2 447 ));
|
||||
DATA(insert ( 1990 26 26 1 453 ));
|
||||
DATA(insert ( 1990 26 26 2 445 ));
|
||||
DATA(insert ( 1992 30 30 1 457 ));
|
||||
DATA(insert ( 1992 30 30 2 776 ));
|
||||
DATA(insert ( 1995 25 25 1 400 ));
|
||||
DATA(insert ( 1995 25 25 2 448));
|
||||
DATA(insert ( 1997 1083 1083 1 1688 ));
|
||||
DATA(insert ( 1997 1083 1083 2 3409 ));
|
||||
DATA(insert ( 1998 1700 1700 1 432 ));
|
||||
DATA(insert ( 1998 1700 1700 2 780 ));
|
||||
DATA(insert ( 1999 1184 1184 1 2039 ));
|
||||
DATA(insert ( 1999 1184 1184 2 3411 ));
|
||||
DATA(insert ( 2001 1266 1266 1 1696 ));
|
||||
DATA(insert ( 2001 1266 1266 2 3410 ));
|
||||
DATA(insert ( 2040 1114 1114 1 2039 ));
|
||||
DATA(insert ( 2040 1114 1114 2 3411 ));
|
||||
DATA(insert ( 2222 16 16 1 454 ));
|
||||
DATA(insert ( 2222 16 16 2 446 ));
|
||||
DATA(insert ( 2223 17 17 1 456 ));
|
||||
DATA(insert ( 2223 17 17 2 772 ));
|
||||
DATA(insert ( 2225 28 28 1 450 ));
|
||||
DATA(insert ( 2225 28 28 2 425));
|
||||
DATA(insert ( 2226 29 29 1 450 ));
|
||||
DATA(insert ( 2226 29 29 2 425 ));
|
||||
DATA(insert ( 2227 702 702 1 450 ));
|
||||
DATA(insert ( 2227 702 702 2 425 ));
|
||||
DATA(insert ( 2228 703 703 1 450 ));
|
||||
DATA(insert ( 2228 703 703 2 425 ));
|
||||
DATA(insert ( 2229 25 25 1 400 ));
|
||||
DATA(insert ( 2229 25 25 2 448 ));
|
||||
DATA(insert ( 2231 1042 1042 1 1080 ));
|
||||
DATA(insert ( 2231 1042 1042 2 972 ));
|
||||
DATA(insert ( 2235 1033 1033 1 329 ));
|
||||
DATA(insert ( 2235 1033 1033 2 777 ));
|
||||
DATA(insert ( 2969 2950 2950 1 2963 ));
|
||||
DATA(insert ( 2969 2950 2950 2 3412 ));
|
||||
DATA(insert ( 3254 3220 3220 1 3252 ));
|
||||
DATA(insert ( 3254 3220 3220 2 3413 ));
|
||||
DATA(insert ( 3372 774 774 1 328 ));
|
||||
DATA(insert ( 3372 774 774 2 781 ));
|
||||
DATA(insert ( 3523 3500 3500 1 3515 ));
|
||||
DATA(insert ( 3523 3500 3500 2 3414 ));
|
||||
DATA(insert ( 3903 3831 3831 1 3902 ));
|
||||
DATA(insert ( 3903 3831 3831 2 3417 ));
|
||||
DATA(insert ( 4034 3802 3802 1 4045 ));
|
||||
DATA(insert ( 4034 3802 3802 2 3416));
|
||||
|
||||
|
||||
/* gist */
|
||||
|
|
|
@ -668,36 +668,68 @@ DESCR("convert char(n) to name");
|
|||
|
||||
DATA(insert OID = 449 ( hashint2 PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 23 "21" _null_ _null_ _null_ _null_ _null_ hashint2 _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
DATA(insert OID = 441 ( hashint2extended PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 20 "21 20" _null_ _null_ _null_ _null_ _null_ hashint2extended _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
DATA(insert OID = 450 ( hashint4 PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 23 "23" _null_ _null_ _null_ _null_ _null_ hashint4 _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
DATA(insert OID = 425 ( hashint4extended PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 20 "23 20" _null_ _null_ _null_ _null_ _null_ hashint4extended _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
DATA(insert OID = 949 ( hashint8 PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 23 "20" _null_ _null_ _null_ _null_ _null_ hashint8 _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
DATA(insert OID = 442 ( hashint8extended PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 20 "20 20" _null_ _null_ _null_ _null_ _null_ hashint8extended _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
DATA(insert OID = 451 ( hashfloat4 PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 23 "700" _null_ _null_ _null_ _null_ _null_ hashfloat4 _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
DATA(insert OID = 443 ( hashfloat4extended PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 20 "700 20" _null_ _null_ _null_ _null_ _null_ hashfloat4extended _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
DATA(insert OID = 452 ( hashfloat8 PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 23 "701" _null_ _null_ _null_ _null_ _null_ hashfloat8 _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
DATA(insert OID = 444 ( hashfloat8extended PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 20 "701 20" _null_ _null_ _null_ _null_ _null_ hashfloat8extended _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
DATA(insert OID = 453 ( hashoid PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 23 "26" _null_ _null_ _null_ _null_ _null_ hashoid _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
DATA(insert OID = 445 ( hashoidextended PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 20 "26 20" _null_ _null_ _null_ _null_ _null_ hashoidextended _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
DATA(insert OID = 454 ( hashchar PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 23 "18" _null_ _null_ _null_ _null_ _null_ hashchar _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
DATA(insert OID = 446 ( hashcharextended PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 20 "18 20" _null_ _null_ _null_ _null_ _null_ hashcharextended _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
DATA(insert OID = 455 ( hashname PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 23 "19" _null_ _null_ _null_ _null_ _null_ hashname _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
DATA(insert OID = 447 ( hashnameextended PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 20 "19 20" _null_ _null_ _null_ _null_ _null_ hashnameextended _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
DATA(insert OID = 400 ( hashtext PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 23 "25" _null_ _null_ _null_ _null_ _null_ hashtext _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
DATA(insert OID = 448 ( hashtextextended PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 20 "25 20" _null_ _null_ _null_ _null_ _null_ hashtextextended _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
DATA(insert OID = 456 ( hashvarlena PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 23 "2281" _null_ _null_ _null_ _null_ _null_ hashvarlena _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
DATA(insert OID = 772 ( hashvarlenaextended PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 20 "2281 20" _null_ _null_ _null_ _null_ _null_ hashvarlenaextended _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
DATA(insert OID = 457 ( hashoidvector PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 23 "30" _null_ _null_ _null_ _null_ _null_ hashoidvector _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
DATA(insert OID = 776 ( hashoidvectorextended PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 20 "30 20" _null_ _null_ _null_ _null_ _null_ hashoidvectorextended _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
DATA(insert OID = 329 ( hash_aclitem PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 23 "1033" _null_ _null_ _null_ _null_ _null_ hash_aclitem _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
DATA(insert OID = 777 ( hash_aclitem_extended PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 20 "1033 20" _null_ _null_ _null_ _null_ _null_ hash_aclitem_extended _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
DATA(insert OID = 399 ( hashmacaddr PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 23 "829" _null_ _null_ _null_ _null_ _null_ hashmacaddr _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
DATA(insert OID = 778 ( hashmacaddrextended PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 20 "829 20" _null_ _null_ _null_ _null_ _null_ hashmacaddrextended _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
DATA(insert OID = 422 ( hashinet PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 23 "869" _null_ _null_ _null_ _null_ _null_ hashinet _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
DATA(insert OID = 779 ( hashinetextended PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 20 "869 20" _null_ _null_ _null_ _null_ _null_ hashinetextended _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
DATA(insert OID = 432 ( hash_numeric PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 23 "1700" _null_ _null_ _null_ _null_ _null_ hash_numeric _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
DATA(insert OID = 780 ( hash_numeric_extended PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 20 "1700 20" _null_ _null_ _null_ _null_ _null_ hash_numeric_extended _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
DATA(insert OID = 328 ( hashmacaddr8 PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 23 "774" _null_ _null_ _null_ _null_ _null_ hashmacaddr8 _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
DATA(insert OID = 781 ( hashmacaddr8extended PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 20 "774 20" _null_ _null_ _null_ _null_ _null_ hashmacaddr8extended _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
|
||||
DATA(insert OID = 438 ( num_nulls PGNSP PGUID 12 1 0 2276 0 f f f f f f i s 1 0 23 "2276" "{2276}" "{v}" _null_ _null_ _null_ pg_num_nulls _null_ _null_ _null_ ));
|
||||
DESCR("count the number of NULL arguments");
|
||||
|
@ -747,6 +779,8 @@ DESCR("convert float8 to int8");
|
|||
|
||||
DATA(insert OID = 626 ( hash_array PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 23 "2277" _null_ _null_ _null_ _null_ _null_ hash_array _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
DATA(insert OID = 782 ( hash_array_extended PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 20 "2277 20" _null_ _null_ _null_ _null_ _null_ hash_array_extended _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
|
||||
DATA(insert OID = 652 ( float4 PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 700 "20" _null_ _null_ _null_ _null_ _null_ i8tof _null_ _null_ _null_ ));
|
||||
DESCR("convert int8 to float4");
|
||||
|
@ -1155,6 +1189,8 @@ DATA(insert OID = 3328 ( bpchar_sortsupport PGNSP PGUID 12 1 0 0 0 f f f f t f i
|
|||
DESCR("sort support");
|
||||
DATA(insert OID = 1080 ( hashbpchar PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 23 "1042" _null_ _null_ _null_ _null_ _null_ hashbpchar _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
DATA(insert OID = 972 ( hashbpcharextended PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 20 "1042 20" _null_ _null_ _null_ _null_ _null_ hashbpcharextended _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
DATA(insert OID = 1081 ( format_type PGNSP PGUID 12 1 0 0 0 f f f f f f s s 2 0 25 "26 23" _null_ _null_ _null_ _null_ _null_ format_type _null_ _null_ _null_ ));
|
||||
DESCR("format a type oid and atttypmod to canonical SQL");
|
||||
DATA(insert OID = 1084 ( date_in PGNSP PGUID 12 1 0 0 0 f f f f t f s s 1 0 1082 "2275" _null_ _null_ _null_ _null_ _null_ date_in _null_ _null_ _null_ ));
|
||||
|
@ -2286,10 +2322,16 @@ DESCR("less-equal-greater");
|
|||
|
||||
DATA(insert OID = 1688 ( time_hash PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 23 "1083" _null_ _null_ _null_ _null_ _null_ time_hash _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
DATA(insert OID = 3409 ( time_hash_extended PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 20 "1083 20" _null_ _null_ _null_ _null_ _null_ time_hash_extended _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
DATA(insert OID = 1696 ( timetz_hash PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 23 "1266" _null_ _null_ _null_ _null_ _null_ timetz_hash _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
DATA(insert OID = 3410 ( timetz_hash_extended PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 20 "1266 20" _null_ _null_ _null_ _null_ _null_ timetz_hash_extended _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
DATA(insert OID = 1697 ( interval_hash PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 23 "1186" _null_ _null_ _null_ _null_ _null_ interval_hash _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
DATA(insert OID = 3418 ( interval_hash_extended PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 20 "1186 20" _null_ _null_ _null_ _null_ _null_ interval_hash_extended _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
|
||||
|
||||
/* OID's 1700 - 1799 NUMERIC data type */
|
||||
|
@ -3078,6 +3120,8 @@ DATA(insert OID = 2038 ( timezone PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0
|
|||
DESCR("adjust time with time zone to new zone");
|
||||
DATA(insert OID = 2039 ( timestamp_hash PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 23 "1114" _null_ _null_ _null_ _null_ _null_ timestamp_hash _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
DATA(insert OID = 3411 ( timestamp_hash_extended PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 20 "1114 20" _null_ _null_ _null_ _null_ _null_ timestamp_hash_extended _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
DATA(insert OID = 2041 ( overlaps PGNSP PGUID 12 1 0 0 0 f f f f f f i s 4 0 16 "1114 1114 1114 1114" _null_ _null_ _null_ _null_ _null_ overlaps_timestamp _null_ _null_ _null_ ));
|
||||
DESCR("intervals overlap?");
|
||||
DATA(insert OID = 2042 ( overlaps PGNSP PGUID 14 1 0 0 0 f f f f f f i s 4 0 16 "1114 1186 1114 1186" _null_ _null_ _null_ _null_ _null_ "select ($1, ($1 + $2)) overlaps ($3, ($3 + $4))" _null_ _null_ _null_ ));
|
||||
|
@ -4543,6 +4587,8 @@ DATA(insert OID = 2962 ( uuid_send PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1
|
|||
DESCR("I/O");
|
||||
DATA(insert OID = 2963 ( uuid_hash PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 23 "2950" _null_ _null_ _null_ _null_ _null_ uuid_hash _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
DATA(insert OID = 3412 ( uuid_hash_extended PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 20 "2950 20" _null_ _null_ _null_ _null_ _null_ uuid_hash_extended _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
|
||||
/* pg_lsn */
|
||||
DATA(insert OID = 3229 ( pg_lsn_in PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 3220 "2275" _null_ _null_ _null_ _null_ _null_ pg_lsn_in _null_ _null_ _null_ ));
|
||||
|
@ -4564,6 +4610,8 @@ DATA(insert OID = 3251 ( pg_lsn_cmp PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0
|
|||
DESCR("less-equal-greater");
|
||||
DATA(insert OID = 3252 ( pg_lsn_hash PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 23 "3220" _null_ _null_ _null_ _null_ _null_ pg_lsn_hash _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
DATA(insert OID = 3413 ( pg_lsn_hash_extended PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 20 "3220 20" _null_ _null_ _null_ _null_ _null_ pg_lsn_hash_extended _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
|
||||
/* enum related procs */
|
||||
DATA(insert OID = 3504 ( anyenum_in PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 3500 "2275" _null_ _null_ _null_ _null_ _null_ anyenum_in _null_ _null_ _null_ ));
|
||||
|
@ -4584,6 +4632,8 @@ DATA(insert OID = 3514 ( enum_cmp PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 2
|
|||
DESCR("less-equal-greater");
|
||||
DATA(insert OID = 3515 ( hashenum PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 23 "3500" _null_ _null_ _null_ _null_ _null_ hashenum _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
DATA(insert OID = 3414 ( hashenumextended PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 20 "3500 20" _null_ _null_ _null_ _null_ _null_ hashenumextended _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
DATA(insert OID = 3524 ( enum_smaller PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 3500 "3500 3500" _null_ _null_ _null_ _null_ _null_ enum_smaller _null_ _null_ _null_ ));
|
||||
DESCR("smaller of two");
|
||||
DATA(insert OID = 3525 ( enum_larger PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 3500 "3500 3500" _null_ _null_ _null_ _null_ _null_ enum_larger _null_ _null_ _null_ ));
|
||||
|
@ -4981,6 +5031,8 @@ DATA(insert OID = 4044 ( jsonb_cmp PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2
|
|||
DESCR("less-equal-greater");
|
||||
DATA(insert OID = 4045 ( jsonb_hash PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 23 "3802" _null_ _null_ _null_ _null_ _null_ jsonb_hash _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
DATA(insert OID = 3416 ( jsonb_hash_extended PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 20 "3802 20" _null_ _null_ _null_ _null_ _null_ jsonb_hash_extended _null_ _null_ _null_ ));
|
||||
DESCR("hash");
|
||||
DATA(insert OID = 4046 ( jsonb_contains PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 16 "3802 3802" _null_ _null_ _null_ _null_ _null_ jsonb_contains _null_ _null_ _null_ ));
|
||||
DATA(insert OID = 4047 ( jsonb_exists PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 16 "3802 25" _null_ _null_ _null_ _null_ _null_ jsonb_exists _null_ _null_ _null_ ));
|
||||
DATA(insert OID = 4048 ( jsonb_exists_any PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 16 "3802 1009" _null_ _null_ _null_ _null_ _null_ jsonb_exists_any _null_ _null_ _null_ ));
|
||||
|
@ -5171,6 +5223,8 @@ DATA(insert OID = 3881 ( range_gist_same PGNSP PGUID 12 1 0 0 0 f f f f t f i
|
|||
DESCR("GiST support");
|
||||
DATA(insert OID = 3902 ( hash_range PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 23 "3831" _null_ _null_ _null_ _null_ _null_ hash_range _null_ _null_ _null_ ));
|
||||
DESCR("hash a range");
|
||||
DATA(insert OID = 3417 ( hash_range_extended PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 20 "3831 20" _null_ _null_ _null_ _null_ _null_ hash_range_extended _null_ _null_ _null_ ));
|
||||
DESCR("hash a range");
|
||||
DATA(insert OID = 3916 ( range_typanalyze PGNSP PGUID 12 1 0 0 0 f f f f t f s s 1 0 16 "2281" _null_ _null_ _null_ _null_ _null_ range_typanalyze _null_ _null_ _null_ ));
|
||||
DESCR("range typanalyze");
|
||||
DATA(insert OID = 3169 ( rangesel PGNSP PGUID 12 1 0 0 0 f f f f t f s s 4 0 701 "2281 26 2281 23" _null_ _null_ _null_ _null_ _null_ rangesel _null_ _null_ _null_ ));
|
||||
|
|
|
@ -325,6 +325,7 @@ extern struct varlena *pg_detoast_datum_packed(struct varlena *datum);
|
|||
#define PG_RETURN_FLOAT4(x) return Float4GetDatum(x)
|
||||
#define PG_RETURN_FLOAT8(x) return Float8GetDatum(x)
|
||||
#define PG_RETURN_INT64(x) return Int64GetDatum(x)
|
||||
#define PG_RETURN_UINT64(x) return UInt64GetDatum(x)
|
||||
/* RETURN macros for other pass-by-ref types will typically look like this: */
|
||||
#define PG_RETURN_BYTEA_P(x) PG_RETURN_POINTER(x)
|
||||
#define PG_RETURN_TEXT_P(x) PG_RETURN_POINTER(x)
|
||||
|
|
|
@ -370,6 +370,8 @@ extern Jsonb *JsonbValueToJsonb(JsonbValue *val);
|
|||
extern bool JsonbDeepContains(JsonbIterator **val,
|
||||
JsonbIterator **mContained);
|
||||
extern void JsonbHashScalarValue(const JsonbValue *scalarVal, uint32 *hash);
|
||||
extern void JsonbHashScalarValueExtended(const JsonbValue *scalarVal,
|
||||
uint64 *hash, uint64 seed);
|
||||
|
||||
/* jsonb.c support functions */
|
||||
extern char *JsonbToCString(StringInfo out, JsonbContainer *in,
|
||||
|
|
|
@ -56,6 +56,7 @@ typedef struct TypeCacheEntry
|
|||
Oid gt_opr; /* the greater-than operator */
|
||||
Oid cmp_proc; /* the btree comparison function */
|
||||
Oid hash_proc; /* the hash calculation function */
|
||||
Oid hash_extended_proc; /* the extended hash calculation function */
|
||||
|
||||
/*
|
||||
* Pre-set-up fmgr call info for the equality operator, the btree
|
||||
|
@ -67,6 +68,7 @@ typedef struct TypeCacheEntry
|
|||
FmgrInfo eq_opr_finfo;
|
||||
FmgrInfo cmp_proc_finfo;
|
||||
FmgrInfo hash_proc_finfo;
|
||||
FmgrInfo hash_extended_proc_finfo;
|
||||
|
||||
/*
|
||||
* Tuple descriptor if it's a composite type (row type). NULL if not
|
||||
|
@ -120,6 +122,8 @@ typedef struct TypeCacheEntry
|
|||
#define TYPECACHE_HASH_OPFAMILY 0x0400
|
||||
#define TYPECACHE_RANGE_INFO 0x0800
|
||||
#define TYPECACHE_DOMAIN_INFO 0x1000
|
||||
#define TYPECACHE_HASH_EXTENDED_PROC 0x2000
|
||||
#define TYPECACHE_HASH_EXTENDED_PROC_FINFO 0x4000
|
||||
|
||||
/*
|
||||
* Callers wishing to maintain a long-lived reference to a domain's constraint
|
||||
|
|
|
@ -421,7 +421,7 @@ BEGIN TRANSACTION;
|
|||
CREATE OPERATOR FAMILY alt_opf13 USING hash;
|
||||
CREATE FUNCTION fn_opf13 (int4) RETURNS BIGINT AS 'SELECT NULL::BIGINT;' LANGUAGE SQL;
|
||||
ALTER OPERATOR FAMILY alt_opf13 USING hash ADD FUNCTION 1 fn_opf13(int4);
|
||||
ERROR: hash procedures must return integer
|
||||
ERROR: hash procedure 1 must return integer
|
||||
DROP OPERATOR FAMILY alt_opf13 USING hash;
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
ROLLBACK;
|
||||
|
@ -439,7 +439,7 @@ BEGIN TRANSACTION;
|
|||
CREATE OPERATOR FAMILY alt_opf15 USING hash;
|
||||
CREATE FUNCTION fn_opf15 (int4, int2) RETURNS BIGINT AS 'SELECT NULL::BIGINT;' LANGUAGE SQL;
|
||||
ALTER OPERATOR FAMILY alt_opf15 USING hash ADD FUNCTION 1 fn_opf15(int4, int2);
|
||||
ERROR: hash procedures must have one argument
|
||||
ERROR: hash procedure 1 must have one argument
|
||||
DROP OPERATOR FAMILY alt_opf15 USING hash;
|
||||
ERROR: current transaction is aborted, commands ignored until end of transaction block
|
||||
ROLLBACK;
|
||||
|
|
|
@ -0,0 +1,300 @@
|
|||
--
|
||||
-- Test hash functions
|
||||
--
|
||||
-- When the salt is 0, the extended hash function should produce a result
|
||||
-- whose low 32 bits match the standard hash function. When the salt is
|
||||
-- not 0, we should get a different result.
|
||||
--
|
||||
SELECT v as value, hashint2(v)::bit(32) as standard,
|
||||
hashint2extended(v, 0)::bit(32) as extended0,
|
||||
hashint2extended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES (0::int2), (1::int2), (17::int2), (42::int2)) x(v)
|
||||
WHERE hashint2(v)::bit(32) != hashint2extended(v, 0)::bit(32)
|
||||
OR hashint2(v)::bit(32) = hashint2extended(v, 1)::bit(32);
|
||||
value | standard | extended0 | extended1
|
||||
-------+----------+-----------+-----------
|
||||
(0 rows)
|
||||
|
||||
SELECT v as value, hashint4(v)::bit(32) as standard,
|
||||
hashint4extended(v, 0)::bit(32) as extended0,
|
||||
hashint4extended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES (0), (1), (17), (42), (550273), (207112489)) x(v)
|
||||
WHERE hashint4(v)::bit(32) != hashint4extended(v, 0)::bit(32)
|
||||
OR hashint4(v)::bit(32) = hashint4extended(v, 1)::bit(32);
|
||||
value | standard | extended0 | extended1
|
||||
-------+----------+-----------+-----------
|
||||
(0 rows)
|
||||
|
||||
SELECT v as value, hashint8(v)::bit(32) as standard,
|
||||
hashint8extended(v, 0)::bit(32) as extended0,
|
||||
hashint8extended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES (0), (1), (17), (42), (550273), (207112489)) x(v)
|
||||
WHERE hashint8(v)::bit(32) != hashint8extended(v, 0)::bit(32)
|
||||
OR hashint8(v)::bit(32) = hashint8extended(v, 1)::bit(32);
|
||||
value | standard | extended0 | extended1
|
||||
-------+----------+-----------+-----------
|
||||
(0 rows)
|
||||
|
||||
SELECT v as value, hashfloat4(v)::bit(32) as standard,
|
||||
hashfloat4extended(v, 0)::bit(32) as extended0,
|
||||
hashfloat4extended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES (0), (1), (17), (42), (550273), (207112489)) x(v)
|
||||
WHERE hashfloat4(v)::bit(32) != hashfloat4extended(v, 0)::bit(32)
|
||||
OR hashfloat4(v)::bit(32) = hashfloat4extended(v, 1)::bit(32);
|
||||
value | standard | extended0 | extended1
|
||||
-------+----------+-----------+-----------
|
||||
(0 rows)
|
||||
|
||||
SELECT v as value, hashfloat8(v)::bit(32) as standard,
|
||||
hashfloat8extended(v, 0)::bit(32) as extended0,
|
||||
hashfloat8extended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES (0), (1), (17), (42), (550273), (207112489)) x(v)
|
||||
WHERE hashfloat8(v)::bit(32) != hashfloat8extended(v, 0)::bit(32)
|
||||
OR hashfloat8(v)::bit(32) = hashfloat8extended(v, 1)::bit(32);
|
||||
value | standard | extended0 | extended1
|
||||
-------+----------+-----------+-----------
|
||||
(0 rows)
|
||||
|
||||
SELECT v as value, hashoid(v)::bit(32) as standard,
|
||||
hashoidextended(v, 0)::bit(32) as extended0,
|
||||
hashoidextended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES (0), (1), (17), (42), (550273), (207112489)) x(v)
|
||||
WHERE hashoid(v)::bit(32) != hashoidextended(v, 0)::bit(32)
|
||||
OR hashoid(v)::bit(32) = hashoidextended(v, 1)::bit(32);
|
||||
value | standard | extended0 | extended1
|
||||
-------+----------+-----------+-----------
|
||||
(0 rows)
|
||||
|
||||
SELECT v as value, hashchar(v)::bit(32) as standard,
|
||||
hashcharextended(v, 0)::bit(32) as extended0,
|
||||
hashcharextended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES (NULL::"char"), ('1'), ('x'), ('X'), ('p'), ('N')) x(v)
|
||||
WHERE hashchar(v)::bit(32) != hashcharextended(v, 0)::bit(32)
|
||||
OR hashchar(v)::bit(32) = hashcharextended(v, 1)::bit(32);
|
||||
value | standard | extended0 | extended1
|
||||
-------+----------+-----------+-----------
|
||||
(0 rows)
|
||||
|
||||
SELECT v as value, hashname(v)::bit(32) as standard,
|
||||
hashnameextended(v, 0)::bit(32) as extended0,
|
||||
hashnameextended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES (NULL), ('PostgreSQL'), ('eIpUEtqmY89'), ('AXKEJBTK'),
|
||||
('muop28x03'), ('yi3nm0d73')) x(v)
|
||||
WHERE hashname(v)::bit(32) != hashnameextended(v, 0)::bit(32)
|
||||
OR hashname(v)::bit(32) = hashnameextended(v, 1)::bit(32);
|
||||
value | standard | extended0 | extended1
|
||||
-------+----------+-----------+-----------
|
||||
(0 rows)
|
||||
|
||||
SELECT v as value, hashtext(v)::bit(32) as standard,
|
||||
hashtextextended(v, 0)::bit(32) as extended0,
|
||||
hashtextextended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES (NULL), ('PostgreSQL'), ('eIpUEtqmY89'), ('AXKEJBTK'),
|
||||
('muop28x03'), ('yi3nm0d73')) x(v)
|
||||
WHERE hashtext(v)::bit(32) != hashtextextended(v, 0)::bit(32)
|
||||
OR hashtext(v)::bit(32) = hashtextextended(v, 1)::bit(32);
|
||||
value | standard | extended0 | extended1
|
||||
-------+----------+-----------+-----------
|
||||
(0 rows)
|
||||
|
||||
SELECT v as value, hashoidvector(v)::bit(32) as standard,
|
||||
hashoidvectorextended(v, 0)::bit(32) as extended0,
|
||||
hashoidvectorextended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES (NULL::oidvector), ('0 1 2 3 4'), ('17 18 19 20'),
|
||||
('42 43 42 45'), ('550273 550273 570274'),
|
||||
('207112489 207112499 21512 2155 372325 1363252')) x(v)
|
||||
WHERE hashoidvector(v)::bit(32) != hashoidvectorextended(v, 0)::bit(32)
|
||||
OR hashoidvector(v)::bit(32) = hashoidvectorextended(v, 1)::bit(32);
|
||||
value | standard | extended0 | extended1
|
||||
-------+----------+-----------+-----------
|
||||
(0 rows)
|
||||
|
||||
SELECT v as value, hash_aclitem(v)::bit(32) as standard,
|
||||
hash_aclitem_extended(v, 0)::bit(32) as extended0,
|
||||
hash_aclitem_extended(v, 1)::bit(32) as extended1
|
||||
FROM (SELECT DISTINCT(relacl[1]) FROM pg_class LIMIT 10) x(v)
|
||||
WHERE hash_aclitem(v)::bit(32) != hash_aclitem_extended(v, 0)::bit(32)
|
||||
OR hash_aclitem(v)::bit(32) = hash_aclitem_extended(v, 1)::bit(32);
|
||||
value | standard | extended0 | extended1
|
||||
-------+----------+-----------+-----------
|
||||
(0 rows)
|
||||
|
||||
SELECT v as value, hashmacaddr(v)::bit(32) as standard,
|
||||
hashmacaddrextended(v, 0)::bit(32) as extended0,
|
||||
hashmacaddrextended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES (NULL::macaddr), ('08:00:2b:01:02:04'), ('08:00:2b:01:02:04'),
|
||||
('e2:7f:51:3e:70:49'), ('d6:a9:4a:78:1c:d5'),
|
||||
('ea:29:b1:5e:1f:a5')) x(v)
|
||||
WHERE hashmacaddr(v)::bit(32) != hashmacaddrextended(v, 0)::bit(32)
|
||||
OR hashmacaddr(v)::bit(32) = hashmacaddrextended(v, 1)::bit(32);
|
||||
value | standard | extended0 | extended1
|
||||
-------+----------+-----------+-----------
|
||||
(0 rows)
|
||||
|
||||
SELECT v as value, hashinet(v)::bit(32) as standard,
|
||||
hashinetextended(v, 0)::bit(32) as extended0,
|
||||
hashinetextended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES (NULL::inet), ('192.168.100.128/25'), ('192.168.100.0/8'),
|
||||
('172.168.10.126/16'), ('172.18.103.126/24'), ('192.188.13.16/32')) x(v)
|
||||
WHERE hashinet(v)::bit(32) != hashinetextended(v, 0)::bit(32)
|
||||
OR hashinet(v)::bit(32) = hashinetextended(v, 1)::bit(32);
|
||||
value | standard | extended0 | extended1
|
||||
-------+----------+-----------+-----------
|
||||
(0 rows)
|
||||
|
||||
SELECT v as value, hash_numeric(v)::bit(32) as standard,
|
||||
hash_numeric_extended(v, 0)::bit(32) as extended0,
|
||||
hash_numeric_extended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES (0), (1.149484958), (17.149484958), (42.149484958),
|
||||
(149484958.550273), (2071124898672)) x(v)
|
||||
WHERE hash_numeric(v)::bit(32) != hash_numeric_extended(v, 0)::bit(32)
|
||||
OR hash_numeric(v)::bit(32) = hash_numeric_extended(v, 1)::bit(32);
|
||||
value | standard | extended0 | extended1
|
||||
-------+----------+-----------+-----------
|
||||
(0 rows)
|
||||
|
||||
SELECT v as value, hashmacaddr8(v)::bit(32) as standard,
|
||||
hashmacaddr8extended(v, 0)::bit(32) as extended0,
|
||||
hashmacaddr8extended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES (NULL::macaddr8), ('08:00:2b:01:02:04:36:49'),
|
||||
('08:00:2b:01:02:04:f0:e8'), ('e2:7f:51:3e:70:49:16:29'),
|
||||
('d6:a9:4a:78:1c:d5:47:32'), ('ea:29:b1:5e:1f:a5')) x(v)
|
||||
WHERE hashmacaddr8(v)::bit(32) != hashmacaddr8extended(v, 0)::bit(32)
|
||||
OR hashmacaddr8(v)::bit(32) = hashmacaddr8extended(v, 1)::bit(32);
|
||||
value | standard | extended0 | extended1
|
||||
-------+----------+-----------+-----------
|
||||
(0 rows)
|
||||
|
||||
SELECT v as value, hash_array(v)::bit(32) as standard,
|
||||
hash_array_extended(v, 0)::bit(32) as extended0,
|
||||
hash_array_extended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES ('{0}'::int4[]), ('{0,1,2,3,4}'), ('{17,18,19,20}'),
|
||||
('{42,34,65,98}'), ('{550273,590027, 870273}'),
|
||||
('{207112489, 807112489}')) x(v)
|
||||
WHERE hash_array(v)::bit(32) != hash_array_extended(v, 0)::bit(32)
|
||||
OR hash_array(v)::bit(32) = hash_array_extended(v, 1)::bit(32);
|
||||
value | standard | extended0 | extended1
|
||||
-------+----------+-----------+-----------
|
||||
(0 rows)
|
||||
|
||||
SELECT v as value, hashbpchar(v)::bit(32) as standard,
|
||||
hashbpcharextended(v, 0)::bit(32) as extended0,
|
||||
hashbpcharextended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES (NULL), ('PostgreSQL'), ('eIpUEtqmY89'), ('AXKEJBTK'),
|
||||
('muop28x03'), ('yi3nm0d73')) x(v)
|
||||
WHERE hashbpchar(v)::bit(32) != hashbpcharextended(v, 0)::bit(32)
|
||||
OR hashbpchar(v)::bit(32) = hashbpcharextended(v, 1)::bit(32);
|
||||
value | standard | extended0 | extended1
|
||||
-------+----------+-----------+-----------
|
||||
(0 rows)
|
||||
|
||||
SELECT v as value, time_hash(v)::bit(32) as standard,
|
||||
time_hash_extended(v, 0)::bit(32) as extended0,
|
||||
time_hash_extended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES (NULL::time), ('11:09:59'), ('1:09:59'), ('11:59:59'),
|
||||
('7:9:59'), ('5:15:59')) x(v)
|
||||
WHERE time_hash(v)::bit(32) != time_hash_extended(v, 0)::bit(32)
|
||||
OR time_hash(v)::bit(32) = time_hash_extended(v, 1)::bit(32);
|
||||
value | standard | extended0 | extended1
|
||||
-------+----------+-----------+-----------
|
||||
(0 rows)
|
||||
|
||||
SELECT v as value, timetz_hash(v)::bit(32) as standard,
|
||||
timetz_hash_extended(v, 0)::bit(32) as extended0,
|
||||
timetz_hash_extended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES (NULL::timetz), ('00:11:52.518762-07'), ('00:11:52.51762-08'),
|
||||
('00:11:52.62-01'), ('00:11:52.62+01'), ('11:59:59+04')) x(v)
|
||||
WHERE timetz_hash(v)::bit(32) != timetz_hash_extended(v, 0)::bit(32)
|
||||
OR timetz_hash(v)::bit(32) = timetz_hash_extended(v, 1)::bit(32);
|
||||
value | standard | extended0 | extended1
|
||||
-------+----------+-----------+-----------
|
||||
(0 rows)
|
||||
|
||||
SELECT v as value, interval_hash(v)::bit(32) as standard,
|
||||
interval_hash_extended(v, 0)::bit(32) as extended0,
|
||||
interval_hash_extended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES (NULL::interval),
|
||||
('5 month 7 day 46 minutes'), ('1 year 7 day 46 minutes'),
|
||||
('1 year 7 month 20 day 46 minutes'), ('5 month'),
|
||||
('17 year 11 month 7 day 9 hours 46 minutes 5 seconds')) x(v)
|
||||
WHERE interval_hash(v)::bit(32) != interval_hash_extended(v, 0)::bit(32)
|
||||
OR interval_hash(v)::bit(32) = interval_hash_extended(v, 1)::bit(32);
|
||||
value | standard | extended0 | extended1
|
||||
-------+----------+-----------+-----------
|
||||
(0 rows)
|
||||
|
||||
SELECT v as value, timestamp_hash(v)::bit(32) as standard,
|
||||
timestamp_hash_extended(v, 0)::bit(32) as extended0,
|
||||
timestamp_hash_extended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES (NULL::timestamp), ('2017-08-22 00:09:59.518762'),
|
||||
('2015-08-20 00:11:52.51762-08'),
|
||||
('2017-05-22 00:11:52.62-01'),
|
||||
('2013-08-22 00:11:52.62+01'), ('2013-08-22 11:59:59+04')) x(v)
|
||||
WHERE timestamp_hash(v)::bit(32) != timestamp_hash_extended(v, 0)::bit(32)
|
||||
OR timestamp_hash(v)::bit(32) = timestamp_hash_extended(v, 1)::bit(32);
|
||||
value | standard | extended0 | extended1
|
||||
-------+----------+-----------+-----------
|
||||
(0 rows)
|
||||
|
||||
SELECT v as value, uuid_hash(v)::bit(32) as standard,
|
||||
uuid_hash_extended(v, 0)::bit(32) as extended0,
|
||||
uuid_hash_extended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES (NULL::uuid), ('a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11'),
|
||||
('5a9ba4ac-8d6f-11e7-bb31-be2e44b06b34'),
|
||||
('99c6705c-d939-461c-a3c9-1690ad64ed7b'),
|
||||
('7deed3ca-8d6f-11e7-bb31-be2e44b06b34'),
|
||||
('9ad46d4f-6f2a-4edd-aadb-745993928e1e')) x(v)
|
||||
WHERE uuid_hash(v)::bit(32) != uuid_hash_extended(v, 0)::bit(32)
|
||||
OR uuid_hash(v)::bit(32) = uuid_hash_extended(v, 1)::bit(32);
|
||||
value | standard | extended0 | extended1
|
||||
-------+----------+-----------+-----------
|
||||
(0 rows)
|
||||
|
||||
SELECT v as value, pg_lsn_hash(v)::bit(32) as standard,
|
||||
pg_lsn_hash_extended(v, 0)::bit(32) as extended0,
|
||||
pg_lsn_hash_extended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES (NULL::pg_lsn), ('16/B374D84'), ('30/B374D84'),
|
||||
('255/B374D84'), ('25/B379D90'), ('900/F37FD90')) x(v)
|
||||
WHERE pg_lsn_hash(v)::bit(32) != pg_lsn_hash_extended(v, 0)::bit(32)
|
||||
OR pg_lsn_hash(v)::bit(32) = pg_lsn_hash_extended(v, 1)::bit(32);
|
||||
value | standard | extended0 | extended1
|
||||
-------+----------+-----------+-----------
|
||||
(0 rows)
|
||||
|
||||
CREATE TYPE mood AS ENUM ('sad', 'ok', 'happy');
|
||||
SELECT v as value, hashenum(v)::bit(32) as standard,
|
||||
hashenumextended(v, 0)::bit(32) as extended0,
|
||||
hashenumextended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES ('sad'::mood), ('ok'), ('happy')) x(v)
|
||||
WHERE hashenum(v)::bit(32) != hashenumextended(v, 0)::bit(32)
|
||||
OR hashenum(v)::bit(32) = hashenumextended(v, 1)::bit(32);
|
||||
value | standard | extended0 | extended1
|
||||
-------+----------+-----------+-----------
|
||||
(0 rows)
|
||||
|
||||
DROP TYPE mood;
|
||||
SELECT v as value, jsonb_hash(v)::bit(32) as standard,
|
||||
jsonb_hash_extended(v, 0)::bit(32) as extended0,
|
||||
jsonb_hash_extended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES (NULL::jsonb),
|
||||
('{"a": "aaa bbb ddd ccc", "b": ["eee fff ggg"], "c": {"d": "hhh iii"}}'),
|
||||
('{"foo": [true, "bar"], "tags": {"e": 1, "f": null}}'),
|
||||
('{"g": {"h": "value"}}')) x(v)
|
||||
WHERE jsonb_hash(v)::bit(32) != jsonb_hash_extended(v, 0)::bit(32)
|
||||
OR jsonb_hash(v)::bit(32) = jsonb_hash_extended(v, 1)::bit(32);
|
||||
value | standard | extended0 | extended1
|
||||
-------+----------+-----------+-----------
|
||||
(0 rows)
|
||||
|
||||
SELECT v as value, hash_range(v)::bit(32) as standard,
|
||||
hash_range_extended(v, 0)::bit(32) as extended0,
|
||||
hash_range_extended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES (int4range(10, 20)), (int4range(23, 43)),
|
||||
(int4range(5675, 550273)),
|
||||
(int4range(550274, 1550274)), (int4range(1550275, 208112489))) x(v)
|
||||
WHERE hash_range(v)::bit(32) != hash_range_extended(v, 0)::bit(32)
|
||||
OR hash_range(v)::bit(32) = hash_range_extended(v, 1)::bit(32);
|
||||
value | standard | extended0 | extended1
|
||||
-------+----------+-----------+-----------
|
||||
(0 rows)
|
||||
|
|
@ -60,7 +60,7 @@ test: create_index create_view
|
|||
# ----------
|
||||
# Another group of parallel tests
|
||||
# ----------
|
||||
test: create_aggregate create_function_3 create_cast constraints triggers inherit create_table_like typed_table vacuum drop_if_exists updatable_views rolenames roleattributes create_am
|
||||
test: create_aggregate create_function_3 create_cast constraints triggers inherit create_table_like typed_table vacuum drop_if_exists updatable_views rolenames roleattributes create_am hash_func
|
||||
|
||||
# ----------
|
||||
# sanity_check does a vacuum, affecting the sort order of SELECT *
|
||||
|
|
|
@ -0,0 +1,222 @@
|
|||
--
|
||||
-- Test hash functions
|
||||
--
|
||||
-- When the salt is 0, the extended hash function should produce a result
|
||||
-- whose low 32 bits match the standard hash function. When the salt is
|
||||
-- not 0, we should get a different result.
|
||||
--
|
||||
|
||||
SELECT v as value, hashint2(v)::bit(32) as standard,
|
||||
hashint2extended(v, 0)::bit(32) as extended0,
|
||||
hashint2extended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES (0::int2), (1::int2), (17::int2), (42::int2)) x(v)
|
||||
WHERE hashint2(v)::bit(32) != hashint2extended(v, 0)::bit(32)
|
||||
OR hashint2(v)::bit(32) = hashint2extended(v, 1)::bit(32);
|
||||
|
||||
SELECT v as value, hashint4(v)::bit(32) as standard,
|
||||
hashint4extended(v, 0)::bit(32) as extended0,
|
||||
hashint4extended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES (0), (1), (17), (42), (550273), (207112489)) x(v)
|
||||
WHERE hashint4(v)::bit(32) != hashint4extended(v, 0)::bit(32)
|
||||
OR hashint4(v)::bit(32) = hashint4extended(v, 1)::bit(32);
|
||||
|
||||
SELECT v as value, hashint8(v)::bit(32) as standard,
|
||||
hashint8extended(v, 0)::bit(32) as extended0,
|
||||
hashint8extended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES (0), (1), (17), (42), (550273), (207112489)) x(v)
|
||||
WHERE hashint8(v)::bit(32) != hashint8extended(v, 0)::bit(32)
|
||||
OR hashint8(v)::bit(32) = hashint8extended(v, 1)::bit(32);
|
||||
|
||||
SELECT v as value, hashfloat4(v)::bit(32) as standard,
|
||||
hashfloat4extended(v, 0)::bit(32) as extended0,
|
||||
hashfloat4extended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES (0), (1), (17), (42), (550273), (207112489)) x(v)
|
||||
WHERE hashfloat4(v)::bit(32) != hashfloat4extended(v, 0)::bit(32)
|
||||
OR hashfloat4(v)::bit(32) = hashfloat4extended(v, 1)::bit(32);
|
||||
|
||||
SELECT v as value, hashfloat8(v)::bit(32) as standard,
|
||||
hashfloat8extended(v, 0)::bit(32) as extended0,
|
||||
hashfloat8extended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES (0), (1), (17), (42), (550273), (207112489)) x(v)
|
||||
WHERE hashfloat8(v)::bit(32) != hashfloat8extended(v, 0)::bit(32)
|
||||
OR hashfloat8(v)::bit(32) = hashfloat8extended(v, 1)::bit(32);
|
||||
|
||||
SELECT v as value, hashoid(v)::bit(32) as standard,
|
||||
hashoidextended(v, 0)::bit(32) as extended0,
|
||||
hashoidextended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES (0), (1), (17), (42), (550273), (207112489)) x(v)
|
||||
WHERE hashoid(v)::bit(32) != hashoidextended(v, 0)::bit(32)
|
||||
OR hashoid(v)::bit(32) = hashoidextended(v, 1)::bit(32);
|
||||
|
||||
SELECT v as value, hashchar(v)::bit(32) as standard,
|
||||
hashcharextended(v, 0)::bit(32) as extended0,
|
||||
hashcharextended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES (NULL::"char"), ('1'), ('x'), ('X'), ('p'), ('N')) x(v)
|
||||
WHERE hashchar(v)::bit(32) != hashcharextended(v, 0)::bit(32)
|
||||
OR hashchar(v)::bit(32) = hashcharextended(v, 1)::bit(32);
|
||||
|
||||
SELECT v as value, hashname(v)::bit(32) as standard,
|
||||
hashnameextended(v, 0)::bit(32) as extended0,
|
||||
hashnameextended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES (NULL), ('PostgreSQL'), ('eIpUEtqmY89'), ('AXKEJBTK'),
|
||||
('muop28x03'), ('yi3nm0d73')) x(v)
|
||||
WHERE hashname(v)::bit(32) != hashnameextended(v, 0)::bit(32)
|
||||
OR hashname(v)::bit(32) = hashnameextended(v, 1)::bit(32);
|
||||
|
||||
SELECT v as value, hashtext(v)::bit(32) as standard,
|
||||
hashtextextended(v, 0)::bit(32) as extended0,
|
||||
hashtextextended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES (NULL), ('PostgreSQL'), ('eIpUEtqmY89'), ('AXKEJBTK'),
|
||||
('muop28x03'), ('yi3nm0d73')) x(v)
|
||||
WHERE hashtext(v)::bit(32) != hashtextextended(v, 0)::bit(32)
|
||||
OR hashtext(v)::bit(32) = hashtextextended(v, 1)::bit(32);
|
||||
|
||||
SELECT v as value, hashoidvector(v)::bit(32) as standard,
|
||||
hashoidvectorextended(v, 0)::bit(32) as extended0,
|
||||
hashoidvectorextended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES (NULL::oidvector), ('0 1 2 3 4'), ('17 18 19 20'),
|
||||
('42 43 42 45'), ('550273 550273 570274'),
|
||||
('207112489 207112499 21512 2155 372325 1363252')) x(v)
|
||||
WHERE hashoidvector(v)::bit(32) != hashoidvectorextended(v, 0)::bit(32)
|
||||
OR hashoidvector(v)::bit(32) = hashoidvectorextended(v, 1)::bit(32);
|
||||
|
||||
SELECT v as value, hash_aclitem(v)::bit(32) as standard,
|
||||
hash_aclitem_extended(v, 0)::bit(32) as extended0,
|
||||
hash_aclitem_extended(v, 1)::bit(32) as extended1
|
||||
FROM (SELECT DISTINCT(relacl[1]) FROM pg_class LIMIT 10) x(v)
|
||||
WHERE hash_aclitem(v)::bit(32) != hash_aclitem_extended(v, 0)::bit(32)
|
||||
OR hash_aclitem(v)::bit(32) = hash_aclitem_extended(v, 1)::bit(32);
|
||||
|
||||
SELECT v as value, hashmacaddr(v)::bit(32) as standard,
|
||||
hashmacaddrextended(v, 0)::bit(32) as extended0,
|
||||
hashmacaddrextended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES (NULL::macaddr), ('08:00:2b:01:02:04'), ('08:00:2b:01:02:04'),
|
||||
('e2:7f:51:3e:70:49'), ('d6:a9:4a:78:1c:d5'),
|
||||
('ea:29:b1:5e:1f:a5')) x(v)
|
||||
WHERE hashmacaddr(v)::bit(32) != hashmacaddrextended(v, 0)::bit(32)
|
||||
OR hashmacaddr(v)::bit(32) = hashmacaddrextended(v, 1)::bit(32);
|
||||
|
||||
SELECT v as value, hashinet(v)::bit(32) as standard,
|
||||
hashinetextended(v, 0)::bit(32) as extended0,
|
||||
hashinetextended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES (NULL::inet), ('192.168.100.128/25'), ('192.168.100.0/8'),
|
||||
('172.168.10.126/16'), ('172.18.103.126/24'), ('192.188.13.16/32')) x(v)
|
||||
WHERE hashinet(v)::bit(32) != hashinetextended(v, 0)::bit(32)
|
||||
OR hashinet(v)::bit(32) = hashinetextended(v, 1)::bit(32);
|
||||
|
||||
SELECT v as value, hash_numeric(v)::bit(32) as standard,
|
||||
hash_numeric_extended(v, 0)::bit(32) as extended0,
|
||||
hash_numeric_extended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES (0), (1.149484958), (17.149484958), (42.149484958),
|
||||
(149484958.550273), (2071124898672)) x(v)
|
||||
WHERE hash_numeric(v)::bit(32) != hash_numeric_extended(v, 0)::bit(32)
|
||||
OR hash_numeric(v)::bit(32) = hash_numeric_extended(v, 1)::bit(32);
|
||||
|
||||
SELECT v as value, hashmacaddr8(v)::bit(32) as standard,
|
||||
hashmacaddr8extended(v, 0)::bit(32) as extended0,
|
||||
hashmacaddr8extended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES (NULL::macaddr8), ('08:00:2b:01:02:04:36:49'),
|
||||
('08:00:2b:01:02:04:f0:e8'), ('e2:7f:51:3e:70:49:16:29'),
|
||||
('d6:a9:4a:78:1c:d5:47:32'), ('ea:29:b1:5e:1f:a5')) x(v)
|
||||
WHERE hashmacaddr8(v)::bit(32) != hashmacaddr8extended(v, 0)::bit(32)
|
||||
OR hashmacaddr8(v)::bit(32) = hashmacaddr8extended(v, 1)::bit(32);
|
||||
|
||||
SELECT v as value, hash_array(v)::bit(32) as standard,
|
||||
hash_array_extended(v, 0)::bit(32) as extended0,
|
||||
hash_array_extended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES ('{0}'::int4[]), ('{0,1,2,3,4}'), ('{17,18,19,20}'),
|
||||
('{42,34,65,98}'), ('{550273,590027, 870273}'),
|
||||
('{207112489, 807112489}')) x(v)
|
||||
WHERE hash_array(v)::bit(32) != hash_array_extended(v, 0)::bit(32)
|
||||
OR hash_array(v)::bit(32) = hash_array_extended(v, 1)::bit(32);
|
||||
|
||||
SELECT v as value, hashbpchar(v)::bit(32) as standard,
|
||||
hashbpcharextended(v, 0)::bit(32) as extended0,
|
||||
hashbpcharextended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES (NULL), ('PostgreSQL'), ('eIpUEtqmY89'), ('AXKEJBTK'),
|
||||
('muop28x03'), ('yi3nm0d73')) x(v)
|
||||
WHERE hashbpchar(v)::bit(32) != hashbpcharextended(v, 0)::bit(32)
|
||||
OR hashbpchar(v)::bit(32) = hashbpcharextended(v, 1)::bit(32);
|
||||
|
||||
SELECT v as value, time_hash(v)::bit(32) as standard,
|
||||
time_hash_extended(v, 0)::bit(32) as extended0,
|
||||
time_hash_extended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES (NULL::time), ('11:09:59'), ('1:09:59'), ('11:59:59'),
|
||||
('7:9:59'), ('5:15:59')) x(v)
|
||||
WHERE time_hash(v)::bit(32) != time_hash_extended(v, 0)::bit(32)
|
||||
OR time_hash(v)::bit(32) = time_hash_extended(v, 1)::bit(32);
|
||||
|
||||
SELECT v as value, timetz_hash(v)::bit(32) as standard,
|
||||
timetz_hash_extended(v, 0)::bit(32) as extended0,
|
||||
timetz_hash_extended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES (NULL::timetz), ('00:11:52.518762-07'), ('00:11:52.51762-08'),
|
||||
('00:11:52.62-01'), ('00:11:52.62+01'), ('11:59:59+04')) x(v)
|
||||
WHERE timetz_hash(v)::bit(32) != timetz_hash_extended(v, 0)::bit(32)
|
||||
OR timetz_hash(v)::bit(32) = timetz_hash_extended(v, 1)::bit(32);
|
||||
|
||||
SELECT v as value, interval_hash(v)::bit(32) as standard,
|
||||
interval_hash_extended(v, 0)::bit(32) as extended0,
|
||||
interval_hash_extended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES (NULL::interval),
|
||||
('5 month 7 day 46 minutes'), ('1 year 7 day 46 minutes'),
|
||||
('1 year 7 month 20 day 46 minutes'), ('5 month'),
|
||||
('17 year 11 month 7 day 9 hours 46 minutes 5 seconds')) x(v)
|
||||
WHERE interval_hash(v)::bit(32) != interval_hash_extended(v, 0)::bit(32)
|
||||
OR interval_hash(v)::bit(32) = interval_hash_extended(v, 1)::bit(32);
|
||||
|
||||
SELECT v as value, timestamp_hash(v)::bit(32) as standard,
|
||||
timestamp_hash_extended(v, 0)::bit(32) as extended0,
|
||||
timestamp_hash_extended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES (NULL::timestamp), ('2017-08-22 00:09:59.518762'),
|
||||
('2015-08-20 00:11:52.51762-08'),
|
||||
('2017-05-22 00:11:52.62-01'),
|
||||
('2013-08-22 00:11:52.62+01'), ('2013-08-22 11:59:59+04')) x(v)
|
||||
WHERE timestamp_hash(v)::bit(32) != timestamp_hash_extended(v, 0)::bit(32)
|
||||
OR timestamp_hash(v)::bit(32) = timestamp_hash_extended(v, 1)::bit(32);
|
||||
|
||||
SELECT v as value, uuid_hash(v)::bit(32) as standard,
|
||||
uuid_hash_extended(v, 0)::bit(32) as extended0,
|
||||
uuid_hash_extended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES (NULL::uuid), ('a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11'),
|
||||
('5a9ba4ac-8d6f-11e7-bb31-be2e44b06b34'),
|
||||
('99c6705c-d939-461c-a3c9-1690ad64ed7b'),
|
||||
('7deed3ca-8d6f-11e7-bb31-be2e44b06b34'),
|
||||
('9ad46d4f-6f2a-4edd-aadb-745993928e1e')) x(v)
|
||||
WHERE uuid_hash(v)::bit(32) != uuid_hash_extended(v, 0)::bit(32)
|
||||
OR uuid_hash(v)::bit(32) = uuid_hash_extended(v, 1)::bit(32);
|
||||
|
||||
SELECT v as value, pg_lsn_hash(v)::bit(32) as standard,
|
||||
pg_lsn_hash_extended(v, 0)::bit(32) as extended0,
|
||||
pg_lsn_hash_extended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES (NULL::pg_lsn), ('16/B374D84'), ('30/B374D84'),
|
||||
('255/B374D84'), ('25/B379D90'), ('900/F37FD90')) x(v)
|
||||
WHERE pg_lsn_hash(v)::bit(32) != pg_lsn_hash_extended(v, 0)::bit(32)
|
||||
OR pg_lsn_hash(v)::bit(32) = pg_lsn_hash_extended(v, 1)::bit(32);
|
||||
|
||||
CREATE TYPE mood AS ENUM ('sad', 'ok', 'happy');
|
||||
SELECT v as value, hashenum(v)::bit(32) as standard,
|
||||
hashenumextended(v, 0)::bit(32) as extended0,
|
||||
hashenumextended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES ('sad'::mood), ('ok'), ('happy')) x(v)
|
||||
WHERE hashenum(v)::bit(32) != hashenumextended(v, 0)::bit(32)
|
||||
OR hashenum(v)::bit(32) = hashenumextended(v, 1)::bit(32);
|
||||
DROP TYPE mood;
|
||||
|
||||
SELECT v as value, jsonb_hash(v)::bit(32) as standard,
|
||||
jsonb_hash_extended(v, 0)::bit(32) as extended0,
|
||||
jsonb_hash_extended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES (NULL::jsonb),
|
||||
('{"a": "aaa bbb ddd ccc", "b": ["eee fff ggg"], "c": {"d": "hhh iii"}}'),
|
||||
('{"foo": [true, "bar"], "tags": {"e": 1, "f": null}}'),
|
||||
('{"g": {"h": "value"}}')) x(v)
|
||||
WHERE jsonb_hash(v)::bit(32) != jsonb_hash_extended(v, 0)::bit(32)
|
||||
OR jsonb_hash(v)::bit(32) = jsonb_hash_extended(v, 1)::bit(32);
|
||||
|
||||
SELECT v as value, hash_range(v)::bit(32) as standard,
|
||||
hash_range_extended(v, 0)::bit(32) as extended0,
|
||||
hash_range_extended(v, 1)::bit(32) as extended1
|
||||
FROM (VALUES (int4range(10, 20)), (int4range(23, 43)),
|
||||
(int4range(5675, 550273)),
|
||||
(int4range(550274, 1550274)), (int4range(1550275, 208112489))) x(v)
|
||||
WHERE hash_range(v)::bit(32) != hash_range_extended(v, 0)::bit(32)
|
||||
OR hash_range(v)::bit(32) = hash_range_extended(v, 1)::bit(32);
|
Loading…
Reference in New Issue