Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -73,5 +73,5 @@ tgz:
pg_version?=16
codename?=jammy
regress:
docker build . --tag pg_hash:1.0 --build-arg POSTGRES_VERSION=$(pg_version) --build-arg codename=$(codename) && docker run pg_hash:1.0 | tee logs.out
docker build . --tag spqrhash_regress:1.0 --build-arg POSTGRES_VERSION=$(pg_version) --build-arg codename=$(codename) && docker run spqrhash_regress:1.0 | tee logs.out

21 changes: 5 additions & 16 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,15 @@ You need PostgreSQL developent environment. Then simply::
Functions
---------

hash64_string
spqrhash_murmur3
~~~~~~~~~~~~~

::
spqrhash_murmur3(text) RETURNS int8
spqrhash_murmur3(bytea) RETURNS int8
spqrhash_murmur3(int8) RETURNS int8

hash64_string(data text, algo text, [, iv1 int8 [, iv2 int8]]) returns int8
hash64_string(data byte, algo text, [, iv1 int8 [, iv2 int8]]) returns int8

Uses same algorithms as `hash_string()` but returns 64-bit result.

hash_int8
~~~~~~~~~

::

hash_int8(val int8) returns int8

Hash 64-bit integer.


Murmur3 hash algorithm

Hashing algorithms
-------------------------
Expand Down
25 changes: 6 additions & 19 deletions sql/spqrhash--1.0.sql
Original file line number Diff line number Diff line change
@@ -1,22 +1,9 @@

CREATE OR REPLACE FUNCTION hash64_string(text, text) RETURNS int8
AS '$libdir/spqrhash', 'pg_hash64_string' LANGUAGE C IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION spqrhash_murmur3(int8) RETURNS int8
AS '$libdir/spqrhash', 'spqr_hash_murmur3_int64' LANGUAGE C IMMUTABLE STRICT;

CREATE OR REPLACE FUNCTION hash64_string(bytea, text) RETURNS int8
AS '$libdir/spqrhash', 'pg_hash64_string' LANGUAGE C IMMUTABLE STRICT;

CREATE OR REPLACE FUNCTION hash64_string(text, text, int8) RETURNS int8
AS '$libdir/spqrhash', 'pg_hash64_string' LANGUAGE C IMMUTABLE STRICT;

CREATE OR REPLACE FUNCTION hash64_string(bytea, text, int8) RETURNS int8
AS '$libdir/spqrhash', 'pg_hash64_string' LANGUAGE C IMMUTABLE STRICT;

CREATE OR REPLACE FUNCTION hash64_string(text, text, int8, int8) RETURNS int8
AS '$libdir/spqrhash', 'pg_hash64_string' LANGUAGE C IMMUTABLE STRICT;

CREATE OR REPLACE FUNCTION hash64_string(bytea, text, int8, int8) RETURNS int8
AS '$libdir/spqrhash', 'pg_hash64_string' LANGUAGE C IMMUTABLE STRICT;

CREATE OR REPLACE FUNCTION hash_int8(int8, text) RETURNS int8
AS '$libdir/spqrhash', 'pg_hash_int64' LANGUAGE C IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION spqrhash_murmur3(text) RETURNS int8
AS '$libdir/spqrhash', 'spqr_hash_murmur3_str' LANGUAGE C IMMUTABLE STRICT;

CREATE OR REPLACE FUNCTION spqrhash_murmur3(bytea) RETURNS int8
AS '$libdir/spqrhash', 'spqr_hash_murmur3_str' LANGUAGE C IMMUTABLE STRICT;
11 changes: 3 additions & 8 deletions sql/spqrhash--unpackaged--1.0.sql
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@

ALTER EXTENSION spqrhash ADD FUNCTION hash64_string(text, text);
ALTER EXTENSION spqrhash ADD FUNCTION hash64_string(bytea, text);
ALTER EXTENSION spqrhash ADD FUNCTION hash64_string(text, text, int8);
ALTER EXTENSION spqrhash ADD FUNCTION hash64_string(bytea, text, int8);
ALTER EXTENSION spqrhash ADD FUNCTION hash64_string(text, text, int8, int8);
ALTER EXTENSION spqrhash ADD FUNCTION hash64_string(bytea, text, int8, int8);
ALTER EXTENSION spqrhash ADD FUNCTION hash_int8(int8, text);

ALTER EXTENSION spqrhash ADD FUNCTION spqrhash_murmur3(int8);
ALTER EXTENSION spqrhash ADD FUNCTION spqrhash_murmur3(text);
ALTER EXTENSION spqrhash ADD FUNCTION spqrhash_murmur3(bytea);
24 changes: 6 additions & 18 deletions sql/spqrhash.sql
Original file line number Diff line number Diff line change
@@ -1,21 +1,9 @@
CREATE OR REPLACE FUNCTION hash64_string(text, text) RETURNS int8
AS '$libdir/spqrhash', 'pg_hash64_string' LANGUAGE C IMMUTABLE STRICT;

CREATE OR REPLACE FUNCTION hash64_string(bytea, text) RETURNS int8
AS '$libdir/spqrhash', 'pg_hash64_string' LANGUAGE C IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION spqrhash_murmur3(int8) RETURNS int8
AS '$libdir/spqrhash', 'spqr_hash_murmur3_int64' LANGUAGE C IMMUTABLE STRICT;

CREATE OR REPLACE FUNCTION hash64_string(text, text, int8) RETURNS int8
AS '$libdir/spqrhash', 'pg_hash64_string' LANGUAGE C IMMUTABLE STRICT;

CREATE OR REPLACE FUNCTION hash64_string(bytea, text, int8) RETURNS int8
AS '$libdir/spqrhash', 'pg_hash64_string' LANGUAGE C IMMUTABLE STRICT;

CREATE OR REPLACE FUNCTION hash64_string(text, text, int8, int8) RETURNS int8
AS '$libdir/spqrhash', 'pg_hash64_string' LANGUAGE C IMMUTABLE STRICT;

CREATE OR REPLACE FUNCTION hash64_string(bytea, text, int8, int8) RETURNS int8
AS '$libdir/spqrhash', 'pg_hash64_string' LANGUAGE C IMMUTABLE STRICT;

CREATE OR REPLACE FUNCTION hash_int8(int8, text) RETURNS int8
AS '$libdir/spqrhash', 'pg_hash_int64' LANGUAGE C IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION spqrhash_murmur3(text) RETURNS int8
AS '$libdir/spqrhash', 'spqr_hash_murmur3_str' LANGUAGE C IMMUTABLE STRICT;

CREATE OR REPLACE FUNCTION spqrhash_murmur3(bytea) RETURNS int8
AS '$libdir/spqrhash', 'spqr_hash_murmur3_str' LANGUAGE C IMMUTABLE STRICT;
10 changes: 3 additions & 7 deletions sql/uninstall_spqrhash.sql
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@

DROP FUNCTION hash64_string(text, text);
DROP FUNCTION hash64_string(bytea, text);
DROP FUNCTION hash64_string(text, text, int8);
DROP FUNCTION hash64_string(bytea, text, int8);
DROP FUNCTION hash64_string(text, text, int8, int8);
DROP FUNCTION hash64_string(bytea, text, int8, int8);
DROP FUNCTION hash_int8(int8, text);
DROP FUNCTION spqrhash_murmur3(int8);
DROP FUNCTION spqrhash_murmur3(text);
DROP FUNCTION spqrhash_murmur3(bytea);

132 changes: 7 additions & 125 deletions src/spqrhash.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,110 +7,18 @@

PG_MODULE_MAGIC;

PG_FUNCTION_INFO_V1(pg_hash_string);
PG_FUNCTION_INFO_V1(pg_hash64_string);
PG_FUNCTION_INFO_V1(pg_hash128_string);
PG_FUNCTION_INFO_V1(pg_hash_int32);
PG_FUNCTION_INFO_V1(pg_hash_int32from64);
PG_FUNCTION_INFO_V1(pg_hash_int64);

/*
* Algorithm data
*/

#define HASHNAMELEN 12

struct StrHashDesc {
int namelen;
const char name[HASHNAMELEN];
hlib_str_hash_fn hash;
uint64_t initval;
};

struct Int64HashDesc {
int namelen;
const char name[HASHNAMELEN];
hlib_int64_hash_fn hash;
};

static const struct StrHashDesc string_hash_list[] = {
{ 7, "murmur3", hlib_murmur3, 0 },
{ 0 },
};

static const struct Int64HashDesc int64_hash_list[] = {
{ 7, "murmur3", hlib_murmur3_int64 },
{ 0 },
};

/*
* Lookup functions.
*/

static const struct StrHashDesc *
find_string_hash(const char *name, unsigned nlen)
{
const struct StrHashDesc *desc;
char buf[HASHNAMELEN];

if (nlen >= HASHNAMELEN)
return NULL;
memset(buf, 0, sizeof(buf));
memcpy(buf, name, nlen);

for (desc = string_hash_list; desc->namelen; desc++) {
if (desc->namelen != nlen)
continue;
if (name[0] != desc->name[0])
continue;
if (memcmp(desc->name, name, nlen) == 0)
return desc;
}
return NULL;
}

static const struct Int64HashDesc *
find_int64_hash(const char *name, unsigned nlen)
{
const struct Int64HashDesc *desc;
char buf[HASHNAMELEN];

if (nlen >= HASHNAMELEN)
return NULL;
memset(buf, 0, sizeof(buf));
memcpy(buf, name, nlen);

for (desc = int64_hash_list; desc->namelen; desc++) {
if (desc->namelen == nlen && !memcmp(desc->name, name, nlen))
return desc;
}
return NULL;
}

/*
* Utility functions.
*/

static void
err_nohash(text *hashname)
{
const char *name;
name = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(hashname)));
elog(ERROR, "hash '%s' not found", name);
}
PG_FUNCTION_INFO_V1(spqr_hash_murmur3_str);
PG_FUNCTION_INFO_V1(spqr_hash_murmur3_int64);

/*
* Public functions
*/

/* hash64_string(bytea, text [, int8 [, int8]]) returns int8 */
Datum
pg_hash64_string(PG_FUNCTION_ARGS)
spqr_hash_murmur3_str(PG_FUNCTION_ARGS)
{
struct varlena *data;
text *hashname = PG_GETARG_TEXT_PP(1);
uint64_t io[MAX_IO_VALUES];
const struct StrHashDesc *desc;

memset(io, 0, sizeof(io));

Expand All @@ -121,45 +29,19 @@ pg_hash64_string(PG_FUNCTION_ARGS)
data = PG_GETARG_VARLENA_P(0);
#endif

/* load hash */
desc = find_string_hash(VARDATA_ANY(hashname), VARSIZE_ANY_EXHDR(hashname));
if (desc == NULL)
err_nohash(hashname);

/* decide initvals */
if (PG_NARGS() >= 4)
io[1] = PG_GETARG_INT64(3);
if (PG_NARGS() >= 3)
io[0] = PG_GETARG_INT64(2);
else
io[0] = desc->initval;

/* do hash */
desc->hash(VARDATA_ANY(data), VARSIZE_ANY_EXHDR(data), io);
hlib_murmur3(VARDATA_ANY(data), VARSIZE_ANY_EXHDR(data), io);

PG_FREE_IF_COPY(data, 0);
PG_FREE_IF_COPY(hashname, 1);

PG_RETURN_INT64(io[0]);
}

/*
* Integer hashing
*/

/* hash_int8(int8, text) returns int8 */
Datum
pg_hash_int64(PG_FUNCTION_ARGS)
spqr_hash_murmur3_int64(PG_FUNCTION_ARGS)
{
int64 data = PG_GETARG_INT64(0);
text *hashname = PG_GETARG_TEXT_PP(1);
const struct Int64HashDesc *desc;

desc = find_int64_hash(VARDATA_ANY(hashname), VARSIZE_ANY_EXHDR(hashname));
if (desc == NULL)
err_nohash(hashname);
PG_FREE_IF_COPY(hashname, 1);

PG_RETURN_INT64(desc->hash((uint64_t)(data)));
PG_RETURN_INT64(hlib_murmur3_int64((uint64_t)(data)));
}


8 changes: 2 additions & 6 deletions src/spqrhash.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,14 @@
/* how many values in io array will be used, max */
#define MAX_IO_VALUES 2

/* hash function signatures */
typedef void (*hlib_str_hash_fn)(const void *data, size_t len, uint64_t *io);
typedef uint64_t (*hlib_int64_hash_fn)(uint64_t data);

/* string hashes */
void hlib_murmur3(const void *data, size_t len, uint64_t *io);

/* integer hashes */
uint64_t hlib_murmur3_int64(uint64_t data);

Datum pg_hash64_string(PG_FUNCTION_ARGS);
Datum pg_hash_int64(PG_FUNCTION_ARGS);
Datum spqr_hash_murmur3_str(PG_FUNCTION_ARGS);
Datum spqr_hash_murmur3_int64(PG_FUNCTION_ARGS);

#endif

Loading