From cd806424137c74fe3993cb119e23b522f44e68f7 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Sat, 29 Aug 2015 16:17:13 -0400 Subject: [PATCH] Add hash operator class MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The uri = uri operator was marked as HASHES, but no hash function or hash operator class was defined. Hash joins would therefore fail. Bug report and original patch by Grégoire HUBERT (@chanmix51). closes #3 --- Makefile | 3 ++- test/expected/test.out | 11 +++++++++++ test/sql/test.sql | 9 +++++++++ uri--0--1.sql | 10 ++++++++++ uri.c | 19 +++++++++++++++++++ uri.control | 2 +- uri.sql | 11 +++++++++++ 7 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 uri--0--1.sql diff --git a/Makefile b/Makefile index e1926f9..e8cffe6 100644 --- a/Makefile +++ b/Makefile @@ -1,11 +1,12 @@ PG_CONFIG = pg_config PKG_CONFIG = pkg-config -extension_version = 0 +extension_version = 1 EXTENSION = uri MODULE_big = uri OBJS = uri.o +DATA = uri--0--1.sql DATA_built = uri--$(extension_version).sql ifeq (no,$(shell $(PKG_CONFIG) liburiparser || echo no)) diff --git a/test/expected/test.out b/test/expected/test.out index b9fb392..bffb978 100644 --- a/test/expected/test.out +++ b/test/expected/test.out @@ -289,3 +289,14 @@ SELECT DISTINCT b FROM test ORDER BY b; ssh://username@review.openstack.org:29418/openstack/nova.git (17 rows) +CREATE TABLE test2 (x text, y uri); +INSERT INTO test2 VALUES ('foo', 'http://www.postgresql.org/'); +-- check hashing (issue petere/pguri#3) +SET enable_nestloop = off; +SET enable_mergejoin = off; +SELECT * FROM test JOIN test2 ON b = y AND a = 1; + a | b | x | y +---+----------------------------+-----+---------------------------- + 1 | http://www.postgresql.org/ | foo | http://www.postgresql.org/ +(1 row) + diff --git a/test/sql/test.sql b/test/sql/test.sql index abe6e23..7c3ceb8 100644 --- a/test/sql/test.sql +++ b/test/sql/test.sql @@ -48,3 +48,12 @@ SELECT b AS uri, \x off SELECT DISTINCT b FROM test ORDER BY b; + + +CREATE TABLE test2 (x text, y uri); +INSERT INTO test2 VALUES ('foo', 'http://www.postgresql.org/'); + +-- check hashing (issue petere/pguri#3) +SET enable_nestloop = off; +SET enable_mergejoin = off; +SELECT * FROM test JOIN test2 ON b = y AND a = 1; diff --git a/uri--0--1.sql b/uri--0--1.sql new file mode 100644 index 0000000..c862c9c --- /dev/null +++ b/uri--0--1.sql @@ -0,0 +1,10 @@ +CREATE FUNCTION uri_hash(uri) RETURNS integer + IMMUTABLE + STRICT + LANGUAGE C + AS '$libdir/uri'; + +CREATE OPERATOR CLASS uri_ops_hash + DEFAULT FOR TYPE uri USING hash AS + OPERATOR 1 =, + FUNCTION 1 uri_hash(uri); diff --git a/uri.c b/uri.c index 3fad2e1..85ca239 100644 --- a/uri.c +++ b/uri.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -16,9 +17,11 @@ typedef struct varlena uritype; #define DatumGetUriP(X) ((uritype *) PG_DETOAST_DATUM(X)) +#define DatumGetUriPP(X) ((uritype *) PG_DETOAST_DATUM_PACKED(X)) #define UriPGetDatum(X) PointerGetDatum(X) #define PG_GETARG_URI_P(n) DatumGetUriP(PG_GETARG_DATUM(n)) +#define PG_GETARG_URI_PP(n) DatumGetUriPP(PG_GETARG_DATUM(n)) #define PG_RETURN_URI_P(x) PG_RETURN_POINTER(x) @@ -436,3 +439,19 @@ uri_cmp(PG_FUNCTION_ARGS) PG_RETURN_INT32(_uri_cmp(arg1, arg2)); } + +PG_FUNCTION_INFO_V1(uri_hash); +Datum +uri_hash(PG_FUNCTION_ARGS) +{ + uritype *key = PG_GETARG_URI_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; +} diff --git a/uri.control b/uri.control index e07dc2a..6c78246 100644 --- a/uri.control +++ b/uri.control @@ -1,4 +1,4 @@ comment = 'uri type' -default_version = 0 +default_version = 1 module_pathname = '$libdir/uri' relocatable = true diff --git a/uri.sql b/uri.sql index edf5261..7f68cb1 100644 --- a/uri.sql +++ b/uri.sql @@ -130,6 +130,12 @@ CREATE FUNCTION uri_cmp(uri, uri) RETURNS integer LANGUAGE C AS '$libdir/uri'; +CREATE FUNCTION uri_hash(uri) RETURNS integer + IMMUTABLE + STRICT + LANGUAGE C + AS '$libdir/uri'; + CREATE OPERATOR < ( LEFTARG = uri, RIGHTARG = uri, @@ -200,3 +206,8 @@ CREATE OPERATOR CLASS uri_ops OPERATOR 4 >= , OPERATOR 5 > , FUNCTION 1 uri_cmp(uri, uri); + +CREATE OPERATOR CLASS uri_ops_hash + DEFAULT FOR TYPE uri USING hash AS + OPERATOR 1 =, + FUNCTION 1 uri_hash(uri);