1996-07-09 08:22:35 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
1999-02-14 00:22:53 +01:00
|
|
|
* hashfunc.c
|
1997-09-07 07:04:48 +02:00
|
|
|
* Comparison functions for hash access method.
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
* Copyright (c) 1994, Regents of the University of California
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
2000-01-10 18:14:46 +01:00
|
|
|
* $Header: /cvsroot/pgsql/src/backend/access/hash/hashfunc.c,v 1.22 2000/01/10 17:14:28 momjian Exp $
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
* NOTES
|
1997-09-07 07:04:48 +02:00
|
|
|
* These functions are stored in pg_amproc. For each operator class
|
|
|
|
* defined on hash tables, they compute the hash value of the argument.
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
1996-10-20 08:34:30 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
#include "postgres.h"
|
|
|
|
|
1996-11-10 04:06:38 +01:00
|
|
|
#include "access/hash.h"
|
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
uint32
|
|
|
|
hashint2(int16 key)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1998-09-01 05:29:17 +02:00
|
|
|
return (uint32) ~key;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
uint32
|
|
|
|
hashint4(uint32 key)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1998-09-01 05:29:17 +02:00
|
|
|
return ~key;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
1999-03-14 06:09:05 +01:00
|
|
|
uint32
|
1999-05-26 00:43:53 +02:00
|
|
|
hashint8(int64 *key)
|
1999-03-14 06:09:05 +01:00
|
|
|
{
|
1999-05-25 18:15:34 +02:00
|
|
|
return ~((uint32) *key);
|
1999-03-14 06:09:05 +01:00
|
|
|
}
|
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/* Hash function from Chris Torek. */
|
1997-09-07 07:04:48 +02:00
|
|
|
uint32
|
|
|
|
hashfloat4(float32 keyp)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
int len;
|
|
|
|
int loop;
|
|
|
|
uint32 h;
|
|
|
|
char *kp = (char *) keyp;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
len = sizeof(float32data);
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
#define HASH4a h = (h << 5) - h + *kp++;
|
|
|
|
#define HASH4b h = (h << 5) + h + *kp++;
|
1996-07-09 08:22:35 +02:00
|
|
|
#define HASH4 HASH4b
|
|
|
|
|
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
h = 0;
|
|
|
|
if (len > 0)
|
|
|
|
{
|
|
|
|
loop = (len + 8 - 1) >> 3;
|
|
|
|
|
|
|
|
switch (len & (8 - 1))
|
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
case 0:
|
|
|
|
do
|
|
|
|
{ /* All fall throughs */
|
|
|
|
HASH4;
|
|
|
|
case 7:
|
|
|
|
HASH4;
|
|
|
|
case 6:
|
|
|
|
HASH4;
|
|
|
|
case 5:
|
|
|
|
HASH4;
|
|
|
|
case 4:
|
|
|
|
HASH4;
|
|
|
|
case 3:
|
|
|
|
HASH4;
|
|
|
|
case 2:
|
|
|
|
HASH4;
|
|
|
|
case 1:
|
|
|
|
HASH4;
|
|
|
|
} while (--loop);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
1998-09-01 05:29:17 +02:00
|
|
|
return h;
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
uint32
|
|
|
|
hashfloat8(float64 keyp)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
int len;
|
|
|
|
int loop;
|
|
|
|
uint32 h;
|
|
|
|
char *kp = (char *) keyp;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
len = sizeof(float64data);
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
#define HASH4a h = (h << 5) - h + *kp++;
|
|
|
|
#define HASH4b h = (h << 5) + h + *kp++;
|
1996-07-09 08:22:35 +02:00
|
|
|
#define HASH4 HASH4b
|
|
|
|
|
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
h = 0;
|
|
|
|
if (len > 0)
|
|
|
|
{
|
|
|
|
loop = (len + 8 - 1) >> 3;
|
|
|
|
|
|
|
|
switch (len & (8 - 1))
|
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
case 0:
|
|
|
|
do
|
|
|
|
{ /* All fall throughs */
|
|
|
|
HASH4;
|
|
|
|
case 7:
|
|
|
|
HASH4;
|
|
|
|
case 6:
|
|
|
|
HASH4;
|
|
|
|
case 5:
|
|
|
|
HASH4;
|
|
|
|
case 4:
|
|
|
|
HASH4;
|
|
|
|
case 3:
|
|
|
|
HASH4;
|
|
|
|
case 2:
|
|
|
|
HASH4;
|
|
|
|
case 1:
|
|
|
|
HASH4;
|
|
|
|
} while (--loop);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
1998-09-01 05:29:17 +02:00
|
|
|
return h;
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
uint32
|
|
|
|
hashoid(Oid key)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1998-09-01 05:29:17 +02:00
|
|
|
return (uint32) ~key;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
1998-08-19 04:04:17 +02:00
|
|
|
uint32
|
2000-01-10 17:13:23 +01:00
|
|
|
hashoidvector(Oid *key)
|
1998-08-19 04:04:17 +02:00
|
|
|
{
|
1998-09-01 06:40:42 +02:00
|
|
|
int i;
|
|
|
|
uint32 result = 0;
|
1998-08-19 04:04:17 +02:00
|
|
|
|
2000-01-10 18:14:46 +01:00
|
|
|
for (i = 0; i < INDEX_MAX_KEYS; i++)
|
1998-09-01 06:40:42 +02:00
|
|
|
result = result ^ (~(uint32) key[i]);
|
1998-08-19 04:04:17 +02:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1998-04-26 06:12:15 +02:00
|
|
|
#define PRIME1 37
|
|
|
|
#define PRIME2 1048583
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
uint32
|
|
|
|
hashchar(char key)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
int len;
|
|
|
|
uint32 h;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1998-04-07 20:14:38 +02:00
|
|
|
h = 0;
|
1998-04-26 06:12:15 +02:00
|
|
|
len = sizeof(char);
|
1997-09-07 07:04:48 +02:00
|
|
|
/* Convert char to integer */
|
|
|
|
h = h * PRIME1 ^ (key - ' ');
|
|
|
|
h %= PRIME2;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1998-09-01 05:29:17 +02:00
|
|
|
return h;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
uint32
|
1997-09-08 23:56:23 +02:00
|
|
|
hashname(NameData *n)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
uint32 h;
|
|
|
|
int len;
|
|
|
|
char *key;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1999-11-08 00:08:36 +01:00
|
|
|
key = NameStr(*n);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
h = 0;
|
|
|
|
len = NAMEDATALEN;
|
|
|
|
/* Convert string to integer */
|
|
|
|
while (len--)
|
|
|
|
h = h * PRIME1 ^ (*key++ - ' ');
|
|
|
|
h %= PRIME2;
|
|
|
|
|
1998-09-01 05:29:17 +02:00
|
|
|
return h;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* (Comment from the original db3 hashing code: )
|
|
|
|
*
|
|
|
|
* "This is INCREDIBLY ugly, but fast. We break the string up into 8 byte
|
|
|
|
* units. On the first time through the loop we get the 'leftover bytes'
|
|
|
|
* (strlen % 8). On every other iteration, we perform 8 HASHC's so we handle
|
|
|
|
* all 8 bytes. Essentially, this saves us 7 cmp & branch instructions. If
|
|
|
|
* this routine is heavily used enough, it's worth the ugly coding.
|
|
|
|
*
|
|
|
|
* "OZ's original sdbm hash"
|
|
|
|
*/
|
1997-09-07 07:04:48 +02:00
|
|
|
uint32
|
|
|
|
hashtext(struct varlena * key)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
int keylen;
|
|
|
|
char *keydata;
|
|
|
|
uint32 n;
|
|
|
|
int loop;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
keydata = VARDATA(key);
|
|
|
|
keylen = VARSIZE(key);
|
|
|
|
|
|
|
|
/* keylen includes the four bytes in which string keylength is stored */
|
|
|
|
keylen -= sizeof(VARSIZE(key));
|
|
|
|
|
|
|
|
#define HASHC n = *keydata++ + 65599 * n
|
|
|
|
|
|
|
|
n = 0;
|
|
|
|
if (keylen > 0)
|
|
|
|
{
|
|
|
|
loop = (keylen + 8 - 1) >> 3;
|
|
|
|
|
|
|
|
switch (keylen & (8 - 1))
|
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
case 0:
|
|
|
|
do
|
|
|
|
{ /* All fall throughs */
|
|
|
|
HASHC;
|
|
|
|
case 7:
|
|
|
|
HASHC;
|
|
|
|
case 6:
|
|
|
|
HASHC;
|
|
|
|
case 5:
|
|
|
|
HASHC;
|
|
|
|
case 4:
|
|
|
|
HASHC;
|
|
|
|
case 3:
|
|
|
|
HASHC;
|
|
|
|
case 2:
|
|
|
|
HASHC;
|
|
|
|
case 1:
|
|
|
|
HASHC;
|
|
|
|
} while (--loop);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
1998-09-01 05:29:17 +02:00
|
|
|
return n;
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|