From 48c41fa97480756b70ad095fe8d59199df9b12c7 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Fri, 23 Nov 2018 13:24:45 -0500 Subject: [PATCH] Add a 64-bit hash function for type citext. Amul Sul, reviewed by Hironobu Suzuki Discussion: https://postgr.es/m/CAAJ_b947JjnNr9Cp45iNjSqKf6PA5mCTmKsRwPjows93YwQrmw@mail.gmail.com --- contrib/citext/Makefile | 4 +++- contrib/citext/citext--1.5--1.6.sql | 12 ++++++++++++ contrib/citext/citext.c | 20 ++++++++++++++++++++ contrib/citext/citext.control | 2 +- contrib/citext/expected/citext.out | 12 ++++++++++++ contrib/citext/expected/citext_1.out | 12 ++++++++++++ contrib/citext/sql/citext.sql | 9 +++++++++ 7 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 contrib/citext/citext--1.5--1.6.sql diff --git a/contrib/citext/Makefile b/contrib/citext/Makefile index e32a7de946..e37dcf9b58 100644 --- a/contrib/citext/Makefile +++ b/contrib/citext/Makefile @@ -3,7 +3,9 @@ MODULES = citext EXTENSION = citext -DATA = citext--1.4.sql citext--1.4--1.5.sql \ +DATA = citext--1.4.sql \ + citext--1.5--1.6.sql \ + citext--1.4--1.5.sql \ citext--1.3--1.4.sql \ citext--1.2--1.3.sql citext--1.1--1.2.sql \ citext--1.0--1.1.sql citext--unpackaged--1.0.sql diff --git a/contrib/citext/citext--1.5--1.6.sql b/contrib/citext/citext--1.5--1.6.sql new file mode 100644 index 0000000000..32268983ae --- /dev/null +++ b/contrib/citext/citext--1.5--1.6.sql @@ -0,0 +1,12 @@ +/* contrib/citext/citext--1.5--1.6.sql */ + +-- complain if script is sourced in psql, rather than via ALTER EXTENSION +\echo Use "ALTER EXTENSION citext UPDATE TO '1.6'" to load this file. \quit + +CREATE FUNCTION citext_hash_extended(citext, int8) +RETURNS int8 +AS 'MODULE_PATHNAME' +LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE; + +ALTER OPERATOR FAMILY citext_ops USING hash ADD + FUNCTION 2 citext_hash_extended(citext, int8); diff --git a/contrib/citext/citext.c b/contrib/citext/citext.c index 2c0e48e2bc..24ceeb11fc 100644 --- a/contrib/citext/citext.c +++ b/contrib/citext/citext.c @@ -153,6 +153,26 @@ citext_hash(PG_FUNCTION_ARGS) PG_RETURN_DATUM(result); } +PG_FUNCTION_INFO_V1(citext_hash_extended); + +Datum +citext_hash_extended(PG_FUNCTION_ARGS) +{ + text *txt = PG_GETARG_TEXT_PP(0); + uint64 seed = PG_GETARG_INT64(1); + char *str; + Datum result; + + str = str_tolower(VARDATA_ANY(txt), VARSIZE_ANY_EXHDR(txt), DEFAULT_COLLATION_OID); + result = hash_any_extended((unsigned char *) str, strlen(str), seed); + pfree(str); + + /* Avoid leaking memory for toasted inputs */ + PG_FREE_IF_COPY(txt, 0); + + PG_RETURN_DATUM(result); +} + /* * ================== * OPERATOR FUNCTIONS diff --git a/contrib/citext/citext.control b/contrib/citext/citext.control index 4cd6e09331..a872a3f012 100644 --- a/contrib/citext/citext.control +++ b/contrib/citext/citext.control @@ -1,5 +1,5 @@ # citext extension comment = 'data type for case-insensitive character strings' -default_version = '1.5' +default_version = '1.6' module_pathname = '$libdir/citext' relocatable = true diff --git a/contrib/citext/expected/citext.out b/contrib/citext/expected/citext.out index 99365c57b0..20890db859 100644 --- a/contrib/citext/expected/citext.out +++ b/contrib/citext/expected/citext.out @@ -222,6 +222,18 @@ SELECT citext_cmp('B'::citext, 'a'::citext) > 0 AS true; t (1 row) +-- Check the citext_hash() and citext_hash_extended() function explicitly. +SELECT v as value, citext_hash(v)::bit(32) as standard, + citext_hash_extended(v, 0)::bit(32) as extended0, + citext_hash_extended(v, 1)::bit(32) as extended1 +FROM (VALUES (NULL::citext), ('PostgreSQL'), ('eIpUEtqmY89'), ('AXKEJBTK'), + ('muop28x03'), ('yi3nm0d73')) x(v) +WHERE citext_hash(v)::bit(32) != citext_hash_extended(v, 0)::bit(32) + OR citext_hash(v)::bit(32) = citext_hash_extended(v, 1)::bit(32); + value | standard | extended0 | extended1 +-------+----------+-----------+----------- +(0 rows) + -- Do some tests using a table and index. CREATE TEMP TABLE try ( name citext PRIMARY KEY diff --git a/contrib/citext/expected/citext_1.out b/contrib/citext/expected/citext_1.out index 8aac72e226..755baad8e2 100644 --- a/contrib/citext/expected/citext_1.out +++ b/contrib/citext/expected/citext_1.out @@ -222,6 +222,18 @@ SELECT citext_cmp('B'::citext, 'a'::citext) > 0 AS true; t (1 row) +-- Check the citext_hash() and citext_hash_extended() function explicitly. +SELECT v as value, citext_hash(v)::bit(32) as standard, + citext_hash_extended(v, 0)::bit(32) as extended0, + citext_hash_extended(v, 1)::bit(32) as extended1 +FROM (VALUES (NULL::citext), ('PostgreSQL'), ('eIpUEtqmY89'), ('AXKEJBTK'), + ('muop28x03'), ('yi3nm0d73')) x(v) +WHERE citext_hash(v)::bit(32) != citext_hash_extended(v, 0)::bit(32) + OR citext_hash(v)::bit(32) = citext_hash_extended(v, 1)::bit(32); + value | standard | extended0 | extended1 +-------+----------+-----------+----------- +(0 rows) + -- Do some tests using a table and index. CREATE TEMP TABLE try ( name citext PRIMARY KEY diff --git a/contrib/citext/sql/citext.sql b/contrib/citext/sql/citext.sql index 2732be436d..0cc909eb52 100644 --- a/contrib/citext/sql/citext.sql +++ b/contrib/citext/sql/citext.sql @@ -89,6 +89,15 @@ SELECT citext_cmp('aardvark'::citext, 'aardVark'::citext) AS zero; SELECT citext_cmp('AARDVARK'::citext, 'AARDVARK'::citext) AS zero; SELECT citext_cmp('B'::citext, 'a'::citext) > 0 AS true; +-- Check the citext_hash() and citext_hash_extended() function explicitly. +SELECT v as value, citext_hash(v)::bit(32) as standard, + citext_hash_extended(v, 0)::bit(32) as extended0, + citext_hash_extended(v, 1)::bit(32) as extended1 +FROM (VALUES (NULL::citext), ('PostgreSQL'), ('eIpUEtqmY89'), ('AXKEJBTK'), + ('muop28x03'), ('yi3nm0d73')) x(v) +WHERE citext_hash(v)::bit(32) != citext_hash_extended(v, 0)::bit(32) + OR citext_hash(v)::bit(32) = citext_hash_extended(v, 1)::bit(32); + -- Do some tests using a table and index. CREATE TEMP TABLE try ( -- 2.40.0