#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; }