#include "postgres.h"#include "access/hash.h"
Go to the source code of this file.
Defines | |
| #define | UINT32_ALIGN_MASK (sizeof(uint32) - 1) |
| #define | rot(x, k) (((x)<<(k)) | ((x)>>(32-(k)))) |
| #define | mix(a, b, c) |
| #define | final(a, b, c) |
Functions | |
| Datum | hashchar (PG_FUNCTION_ARGS) |
| Datum | hashint2 (PG_FUNCTION_ARGS) |
| Datum | hashint4 (PG_FUNCTION_ARGS) |
| Datum | hashint8 (PG_FUNCTION_ARGS) |
| Datum | hashoid (PG_FUNCTION_ARGS) |
| Datum | hashenum (PG_FUNCTION_ARGS) |
| Datum | hashfloat4 (PG_FUNCTION_ARGS) |
| Datum | hashfloat8 (PG_FUNCTION_ARGS) |
| Datum | hashoidvector (PG_FUNCTION_ARGS) |
| Datum | hashint2vector (PG_FUNCTION_ARGS) |
| Datum | hashname (PG_FUNCTION_ARGS) |
| Datum | hashtext (PG_FUNCTION_ARGS) |
| Datum | hashvarlena (PG_FUNCTION_ARGS) |
| Datum | hash_any (register const unsigned char *k, register int keylen) |
| Datum | hash_uint32 (uint32 k) |
| #define final | ( | a, | ||
| b, | ||||
| c | ||||
| ) |
| #define mix | ( | a, | ||
| b, | ||||
| c | ||||
| ) |
{ \
a -= c; a ^= rot(c, 4); c += b; \
b -= a; b ^= rot(a, 6); a += c; \
c -= b; c ^= rot(b, 8); b += a; \
a -= c; a ^= rot(c,16); c += b; \
b -= a; b ^= rot(a,19); a += c; \
c -= b; c ^= rot(b, 4); b += a; \
}
Definition at line 244 of file hashfunc.c.
Referenced by hash_any(), pgp_cfb_decrypt(), and pgp_cfb_encrypt().
| #define rot | ( | x, | ||
| k | ||||
| ) | (((x)<<(k)) | ((x)>>(32-(k)))) |
Definition at line 210 of file hashfunc.c.
| #define UINT32_ALIGN_MASK (sizeof(uint32) - 1) |
Definition at line 207 of file hashfunc.c.
Referenced by hash_any().
| Datum hash_any | ( | register const unsigned char * | k, | |
| register int | keylen | |||
| ) |
Definition at line 305 of file hashfunc.c.
References mix, UINT32_ALIGN_MASK, and UInt32GetDatum.
Referenced by AppendJumble(), bms_hash_value(), citext_hash(), hash_numeric(), hashbpchar(), hashfloat4(), hashfloat8(), hashinet(), hashint2vector(), hashmacaddr(), hashname(), hashoidvector(), hashtext(), hashvarlena(), hstore_hash(), lexeme_hash(), pgss_hash_string(), pgss_post_parse_analyze(), sepgsql_avc_hash(), string_hash(), tag_hash(), and uuid_hash().
{
register uint32 a,
b,
c,
len;
/* Set up the internal state */
len = keylen;
a = b = c = 0x9e3779b9 + len + 3923095;
/* If the source pointer is word-aligned, we use word-wide fetches */
if (((intptr_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 */
return UInt32GetDatum(c);
}
Definition at line 510 of file hashfunc.c.
References UInt32GetDatum.
Referenced by hash_range(), hashchar(), hashenum(), hashint2(), hashint4(), hashint8(), hashoid(), oid_hash(), pgss_hash_fn(), and timetz_hash().
{
register uint32 a,
b,
c;
a = b = c = 0x9e3779b9 + (uint32) sizeof(uint32) + 3923095;
a += k;
final(a, b, c);
/* report the result */
return UInt32GetDatum(c);
}
| Datum hashchar | ( | PG_FUNCTION_ARGS | ) |
Definition at line 34 of file hashfunc.c.
References hash_uint32(), and PG_GETARG_CHAR.
{
return hash_uint32((int32) PG_GETARG_CHAR(0));
}
| Datum hashenum | ( | PG_FUNCTION_ARGS | ) |
Definition at line 78 of file hashfunc.c.
References hash_uint32(), and PG_GETARG_OID.
{
return hash_uint32((uint32) PG_GETARG_OID(0));
}
| Datum hashfloat4 | ( | PG_FUNCTION_ARGS | ) |
Definition at line 84 of file hashfunc.c.
References hash_any(), PG_GETARG_FLOAT4, and PG_RETURN_UINT32.
{
float4 key = PG_GETARG_FLOAT4(0);
float8 key8;
/*
* On IEEE-float machines, minus zero and zero have different bit patterns
* but should compare as equal. We must ensure that they have the same
* hash value, which is most reliably done this way:
*/
if (key == (float4) 0)
PG_RETURN_UINT32(0);
/*
* To support cross-type hashing of float8 and float4, we want to return
* the same hash value hashfloat8 would produce for an equal float8 value.
* So, widen the value to float8 and hash that. (We must do this rather
* than have hashfloat8 try to narrow its value to float4; that could fail
* on overflow.)
*/
key8 = key;
return hash_any((unsigned char *) &key8, sizeof(key8));
}
| Datum hashfloat8 | ( | PG_FUNCTION_ARGS | ) |
Definition at line 110 of file hashfunc.c.
References hash_any(), PG_GETARG_FLOAT8, and PG_RETURN_UINT32.
Referenced by interval_hash(), time_hash(), timestamp_hash(), and timetz_hash().
{
float8 key = PG_GETARG_FLOAT8(0);
/*
* On IEEE-float machines, minus zero and zero have different bit patterns
* but should compare as equal. We must ensure that they have the same
* hash value, which is most reliably done this way:
*/
if (key == (float8) 0)
PG_RETURN_UINT32(0);
return hash_any((unsigned char *) &key, sizeof(key));
}
| Datum hashint2 | ( | PG_FUNCTION_ARGS | ) |
Definition at line 40 of file hashfunc.c.
References hash_uint32(), and PG_GETARG_INT16.
{
return hash_uint32((int32) PG_GETARG_INT16(0));
}
| Datum hashint2vector | ( | PG_FUNCTION_ARGS | ) |
Definition at line 134 of file hashfunc.c.
References int2vector::dim1, hash_any(), PG_GETARG_POINTER, and int2vector::values.
{
int2vector *key = (int2vector *) PG_GETARG_POINTER(0);
return hash_any((unsigned char *) key->values, key->dim1 * sizeof(int16));
}
| Datum hashint4 | ( | PG_FUNCTION_ARGS | ) |
Definition at line 46 of file hashfunc.c.
References hash_uint32(), and PG_GETARG_INT32.
{
return hash_uint32(PG_GETARG_INT32(0));
}
| Datum hashint8 | ( | PG_FUNCTION_ARGS | ) |
Definition at line 52 of file hashfunc.c.
References hash_uint32(), PG_GETARG_INT64, and val.
Referenced by interval_hash(), time_hash(), timestamp_hash(), and timetz_hash().
{
/*
* The idea here is to produce a hash value compatible with the values
* produced by hashint4 and hashint2 for logically equal inputs; this is
* necessary to support cross-type hash joins across these input types.
* Since all three types are signed, we can xor the high half of the int8
* value if the sign is positive, or the complement of the high half when
* the sign is negative.
*/
int64 val = PG_GETARG_INT64(0);
uint32 lohalf = (uint32) val;
uint32 hihalf = (uint32) (val >> 32);
lohalf ^= (val >= 0) ? hihalf : ~hihalf;
return hash_uint32(lohalf);
}
| Datum hashname | ( | PG_FUNCTION_ARGS | ) |
Definition at line 142 of file hashfunc.c.
References Assert, hash_any(), NAMEDATALEN, NameStr, and PG_GETARG_NAME.
{
char *key = NameStr(*PG_GETARG_NAME(0));
int keylen = strlen(key);
Assert(keylen < NAMEDATALEN); /* else it's not truncated correctly */
return hash_any((unsigned char *) key, keylen);
}
| Datum hashoid | ( | PG_FUNCTION_ARGS | ) |
Definition at line 72 of file hashfunc.c.
References hash_uint32(), and PG_GETARG_OID.
{
return hash_uint32((uint32) PG_GETARG_OID(0));
}
| Datum hashoidvector | ( | PG_FUNCTION_ARGS | ) |
Definition at line 126 of file hashfunc.c.
References oidvector::dim1, hash_any(), PG_GETARG_POINTER, and oidvector::values.
| Datum hashtext | ( | PG_FUNCTION_ARGS | ) |
Definition at line 153 of file hashfunc.c.
References hash_any(), PG_FREE_IF_COPY, PG_GETARG_TEXT_PP, VARDATA_ANY, and VARSIZE_ANY_EXHDR.
{
text *key = PG_GETARG_TEXT_PP(0);
Datum result;
/*
* Note: this is currently identical in behavior to hashvarlena, but keep
* it as a separate function in case we someday want to do something
* different in non-C locales. (See also hashbpchar, if so.)
*/
result = hash_any((unsigned char *) VARDATA_ANY(key),
VARSIZE_ANY_EXHDR(key));
/* Avoid leaking memory for toasted inputs */
PG_FREE_IF_COPY(key, 0);
return result;
}
| Datum hashvarlena | ( | PG_FUNCTION_ARGS | ) |
Definition at line 177 of file hashfunc.c.
References hash_any(), PG_FREE_IF_COPY, PG_GETARG_VARLENA_PP, VARDATA_ANY, and VARSIZE_ANY_EXHDR.
{
struct varlena *key = PG_GETARG_VARLENA_PP(0);
Datum result;
result = hash_any((unsigned char *) VARDATA_ANY(key),
VARSIZE_ANY_EXHDR(key));
/* Avoid leaking memory for toasted inputs */
PG_FREE_IF_COPY(key, 0);
return result;
}
1.7.1