From 7e3a5330e1059b57e489b802abcc62676fd19ccc Mon Sep 17 00:00:00 2001
From: Amul Sul <sulamul@gmail.com>
Date: Fri, 8 Sep 2017 12:29:02 +0530
Subject: [PATCH 2/2] citext - add extended hash function

---
 contrib/citext/citext--1.4--1.5.sql        |  8 ++++++++
 contrib/citext/citext--1.5.sql             |  8 +++++++-
 contrib/citext/citext--unpackaged--1.0.sql |  1 +
 contrib/citext/citext.c                    | 20 ++++++++++++++++++++
 contrib/citext/expected/citext.out         | 12 ++++++++++++
 contrib/citext/expected/citext_1.out       | 12 ++++++++++++
 contrib/citext/sql/citext.sql              |  9 +++++++++
 7 files changed, 69 insertions(+), 1 deletion(-)

diff --git a/contrib/citext/citext--1.4--1.5.sql b/contrib/citext/citext--1.4--1.5.sql
index d69f7b1..a06c42d 100644
--- a/contrib/citext/citext--1.4--1.5.sql
+++ b/contrib/citext/citext--1.4--1.5.sql
@@ -2,3 +2,11 @@
 
 -- complain if script is sourced in psql, rather than via ALTER EXTENSION
 \echo Use "ALTER EXTENSION citext UPDATE TO '1.5'" 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--1.5.sql b/contrib/citext/citext--1.5.sql
index ce984e3..4d7ec4d 100644
--- a/contrib/citext/citext--1.5.sql
+++ b/contrib/citext/citext--1.5.sql
@@ -203,6 +203,11 @@ RETURNS int4
 AS 'MODULE_PATHNAME'
 LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
 
+CREATE FUNCTION citext_hash_extended(citext, int8)
+RETURNS int8
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE PARALLEL SAFE;
+
 --
 -- The btree indexing operator class.
 --
@@ -223,7 +228,8 @@ DEFAULT FOR TYPE CITEXT USING btree AS
 CREATE OPERATOR CLASS citext_ops
 DEFAULT FOR TYPE citext USING hash AS
     OPERATOR    1   =  (citext, citext),
-    FUNCTION    1   citext_hash(citext);
+    FUNCTION    1   citext_hash(citext),
+    FUNCTION    2   citext_hash_extended(citext, int8);
 
 --
 -- Aggregates.
diff --git a/contrib/citext/citext--unpackaged--1.0.sql b/contrib/citext/citext--unpackaged--1.0.sql
index ef6d6b0..9b1161b 100644
--- a/contrib/citext/citext--unpackaged--1.0.sql
+++ b/contrib/citext/citext--unpackaged--1.0.sql
@@ -33,6 +33,7 @@ ALTER EXTENSION citext ADD operator <(citext,citext);
 ALTER EXTENSION citext ADD operator <=(citext,citext);
 ALTER EXTENSION citext ADD function citext_cmp(citext,citext);
 ALTER EXTENSION citext ADD function citext_hash(citext);
+ALTER EXTENSION citext ADD function citext_hash_extended(citext,int8);
 ALTER EXTENSION citext ADD operator family citext_ops using btree;
 ALTER EXTENSION citext ADD operator class citext_ops using btree;
 ALTER EXTENSION citext ADD operator family citext_ops using hash;
diff --git a/contrib/citext/citext.c b/contrib/citext/citext.c
index 0ba4782..a959446 100644
--- a/contrib/citext/citext.c
+++ b/contrib/citext/citext.c
@@ -100,6 +100,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/expected/citext.out b/contrib/citext/expected/citext.out
index 9cc94f4..8f03fc9 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 d1fb1e1..b46be4d 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 f70f9eb..e97bb7e 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.6.2

