commit 50f4a4efcb9ed3ae5e0378676459c6d1ce455bd2
Author: Anastasia <a.lubennikova@postgrespro.ru>
Date:   Tue Mar 21 10:11:37 2017 +0300

    complete btree_gin_gist_enum patch

diff --git a/contrib/btree_gin/Makefile b/contrib/btree_gin/Makefile
index f22e4af..589755f 100644
--- a/contrib/btree_gin/Makefile
+++ b/contrib/btree_gin/Makefile
@@ -10,7 +10,7 @@ PGFILEDESC = "btree_gin - B-tree equivalent GIN operator classes"
 REGRESS = install_btree_gin int2 int4 int8 float4 float8 money oid \
 	timestamp timestamptz time timetz date interval \
 	macaddr macaddr8 inet cidr text varchar char bytea bit varbit \
-	numeric
+	numeric enum
 
 ifdef USE_PGXS
 PG_CONFIG = pg_config
diff --git a/contrib/btree_gin/btree_gin--1.0--1.1.sql b/contrib/btree_gin/btree_gin--1.0--1.1.sql
index dd81d27..006af59 100644
--- a/contrib/btree_gin/btree_gin--1.0--1.1.sql
+++ b/contrib/btree_gin/btree_gin--1.0--1.1.sql
@@ -33,3 +33,47 @@ AS
     FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
     FUNCTION        5       gin_compare_prefix_macaddr8(macaddr8, macaddr8, int2, internal),
 STORAGE         macaddr8;
+
+
+--
+--
+--
+-- enum ops
+--
+--
+
+
+CREATE FUNCTION gin_extract_value_anyenum(anyenum, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_compare_prefix_anyenum(anyenum, anyenum, int2, internal)
+RETURNS int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_extract_query_anyenum(anyenum, internal, int2, internal, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_enum_cmp(anyenum, anyenum)
+RETURNS int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE OPERATOR CLASS enum_ops
+DEFAULT FOR TYPE anyenum USING gin
+AS
+    OPERATOR        1       <,
+    OPERATOR        2       <=,
+    OPERATOR        3       =,
+    OPERATOR        4       >=,
+    OPERATOR        5       >,
+    FUNCTION        1       gin_enum_cmp(anyenum,anyenum),
+    FUNCTION        2       gin_extract_value_anyenum(anyenum, internal),
+    FUNCTION        3       gin_extract_query_anyenum(anyenum, internal, int2, internal, internal),
+    FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
+    FUNCTION        5       gin_compare_prefix_anyenum(anyenum,anyenum,int2, internal),
+STORAGE         anyenum;
diff --git a/contrib/btree_gin/btree_gin.c b/contrib/btree_gin/btree_gin.c
index 725456e..7191fbf 100644
--- a/contrib/btree_gin/btree_gin.c
+++ b/contrib/btree_gin/btree_gin.c
@@ -25,7 +25,6 @@ typedef struct QueryInfo
 	Datum		(*typecmp) (FunctionCallInfo);
 } QueryInfo;
 
-
 /*** GIN support functions shared by all datatypes ***/
 
 static Datum
@@ -112,13 +111,14 @@ gin_btree_compare_prefix(FunctionCallInfo fcinfo)
 	int32		res,
 				cmp;
 
-	cmp = DatumGetInt32(DirectFunctionCall2Coll(
-												data->typecmp,
-												PG_GET_COLLATION(),
-								   (data->strategy == BTLessStrategyNumber ||
-								 data->strategy == BTLessEqualStrategyNumber)
-												? data->datum : a,
-												b));
+	cmp = DatumGetInt32(CallerFInfoFunctionCall2(
+							data->typecmp,
+							fcinfo->flinfo,
+							PG_GET_COLLATION(),
+							(data->strategy == BTLessStrategyNumber ||
+							 data->strategy == BTLessEqualStrategyNumber)
+							? data->datum : a,
+							b));
 
 	switch (data->strategy)
 	{
@@ -426,3 +426,54 @@ leftmostvalue_numeric(void)
 }
 
 GIN_SUPPORT(numeric, true, leftmostvalue_numeric, gin_numeric_cmp)
+
+/*
+ * Use a similar trick to that used for numeric for enums, since we don't
+ * actually know the leftmost value of any enum without knowing the concrete
+ * type, so we use a dummy leftmost value of InvalidOid.
+ *
+ * Note that we use CallerFInfoFunctionCall2 here so that enum_cmp
+ * gets a valid fn_extra to work with. Unlike most other type comparison
+ * routines it needs it, so we can't use DirectFunctionCall2.
+ */
+
+
+#define ENUM_IS_LEFTMOST(x)	((x) == InvalidOid)
+
+PG_FUNCTION_INFO_V1(gin_enum_cmp);
+
+Datum
+gin_enum_cmp(PG_FUNCTION_ARGS)
+{
+	Oid		a = PG_GETARG_OID(0);
+	Oid		b = PG_GETARG_OID(1);
+	int		res = 0;
+
+	if (ENUM_IS_LEFTMOST(a))
+	{
+		res = (ENUM_IS_LEFTMOST(b)) ? 0 : -1;
+	}
+	else if (ENUM_IS_LEFTMOST(b))
+	{
+		res = 1;
+	}
+	else
+	{
+		res = DatumGetInt32(CallerFInfoFunctionCall2(
+								enum_cmp,
+								fcinfo->flinfo,
+								PG_GET_COLLATION(),
+								ObjectIdGetDatum(a),
+								ObjectIdGetDatum(b)));
+	}
+
+	PG_RETURN_INT32(res);
+}
+
+static Datum
+leftmostvalue_enum(void)
+{
+	return ObjectIdGetDatum(InvalidOid);
+}
+
+GIN_SUPPORT(anyenum, false, leftmostvalue_enum, gin_enum_cmp)
diff --git a/contrib/btree_gin/expected/enum.out b/contrib/btree_gin/expected/enum.out
new file mode 100644
index 0000000..bad1cc0
--- /dev/null
+++ b/contrib/btree_gin/expected/enum.out
@@ -0,0 +1,63 @@
+set enable_seqscan=off;
+CREATE TYPE rainbow AS ENUM ('r','o','y','g','b','i','v');
+CREATE TABLE test_enum (
+	i rainbow
+);
+INSERT INTO test_enum VALUES ('v'),('y'),('r'),('g'),('o'),('i'),('b');
+CREATE INDEX idx_enum ON test_enum USING gin (i);
+SELECT * FROM test_enum WHERE i<'g'::rainbow ORDER BY i;
+ i 
+---
+ r
+ o
+ y
+(3 rows)
+
+SELECT * FROM test_enum WHERE i<='g'::rainbow ORDER BY i;
+ i 
+---
+ r
+ o
+ y
+ g
+(4 rows)
+
+SELECT * FROM test_enum WHERE i='g'::rainbow ORDER BY i;
+ i 
+---
+ g
+(1 row)
+
+SELECT * FROM test_enum WHERE i>='g'::rainbow ORDER BY i;
+ i 
+---
+ g
+ b
+ i
+ v
+(4 rows)
+
+SELECT * FROM test_enum WHERE i>'g'::rainbow ORDER BY i;
+ i 
+---
+ b
+ i
+ v
+(3 rows)
+
+explain (costs off) SELECT * FROM test_enum WHERE i>='g'::rainbow ORDER BY i;
+                  QUERY PLAN                   
+-----------------------------------------------
+ Sort
+   Sort Key: i
+   ->  Bitmap Heap Scan on test_enum
+         Recheck Cond: (i >= 'g'::rainbow)
+         ->  Bitmap Index Scan on idx_enum
+               Index Cond: (i >= 'g'::rainbow)
+(6 rows)
+
+-- make sure we handle the non-evenly-numbered oid case for enums
+create type e as enum ('0', '2', '3');
+alter type e add value '1' after '0';
+create table t as select (i % 4)::text::e from generate_series(0, 100000) as i;
+create index on t using gin (e);
diff --git a/contrib/btree_gist/Makefile b/contrib/btree_gist/Makefile
index c70f178..5d6ab63 100644
--- a/contrib/btree_gist/Makefile
+++ b/contrib/btree_gist/Makefile
@@ -6,7 +6,7 @@ OBJS =  btree_gist.o btree_utils_num.o btree_utils_var.o btree_int2.o \
         btree_int4.o btree_int8.o btree_float4.o btree_float8.o btree_cash.o \
         btree_oid.o btree_ts.o btree_time.o btree_date.o btree_interval.o \
         btree_macaddr.o btree_macaddr8.o btree_inet.o btree_text.o btree_bytea.o \
-        btree_bit.o btree_numeric.o btree_uuid.o $(WIN32RES)
+        btree_bit.o btree_numeric.o btree_uuid.o btree_enum.o $(WIN32RES)
 
 EXTENSION = btree_gist
 DATA = btree_gist--unpackaged--1.0.sql btree_gist--1.0--1.1.sql \
@@ -16,7 +16,7 @@ PGFILEDESC = "btree_gist - B-tree equivalent GiST operator classes"
 
 REGRESS = init int2 int4 int8 float4 float8 cash oid timestamp timestamptz \
         time timetz date interval macaddr macaddr8 inet cidr text varchar char \
-        bytea bit varbit numeric uuid not_equal
+        bytea bit varbit numeric uuid enum not_equal
 
 SHLIB_LINK += $(filter -lm, $(LIBS))
 
diff --git a/contrib/btree_gist/btree_bit.c b/contrib/btree_gist/btree_bit.c
index f34fa87..a57f45f 100644
--- a/contrib/btree_gist/btree_bit.c
+++ b/contrib/btree_gist/btree_bit.c
@@ -24,7 +24,7 @@ PG_FUNCTION_INFO_V1(gbt_bit_same);
 /* define for comparison */
 
 static bool
-gbt_bitgt(const void *a, const void *b, Oid collation)
+gbt_bitgt(const void *a, const void *b, FmgrInfo *flinfo, Oid collation)
 {
 	return DatumGetBool(DirectFunctionCall2(bitgt,
 											PointerGetDatum(a),
@@ -32,7 +32,7 @@ gbt_bitgt(const void *a, const void *b, Oid collation)
 }
 
 static bool
-gbt_bitge(const void *a, const void *b, Oid collation)
+gbt_bitge(const void *a, const void *b, FmgrInfo *flinfo, Oid collation)
 {
 	return DatumGetBool(DirectFunctionCall2(bitge,
 											PointerGetDatum(a),
@@ -40,7 +40,7 @@ gbt_bitge(const void *a, const void *b, Oid collation)
 }
 
 static bool
-gbt_biteq(const void *a, const void *b, Oid collation)
+gbt_biteq(const void *a, const void *b, FmgrInfo *flinfo, Oid collation)
 {
 	return DatumGetBool(DirectFunctionCall2(biteq,
 											PointerGetDatum(a),
@@ -48,7 +48,7 @@ gbt_biteq(const void *a, const void *b, Oid collation)
 }
 
 static bool
-gbt_bitle(const void *a, const void *b, Oid collation)
+gbt_bitle(const void *a, const void *b, FmgrInfo *flinfo, Oid collation)
 {
 	return DatumGetBool(DirectFunctionCall2(bitle,
 											PointerGetDatum(a),
@@ -56,7 +56,7 @@ gbt_bitle(const void *a, const void *b, Oid collation)
 }
 
 static bool
-gbt_bitlt(const void *a, const void *b, Oid collation)
+gbt_bitlt(const void *a, const void *b, FmgrInfo *flinfo, Oid collation)
 {
 	return DatumGetBool(DirectFunctionCall2(bitlt,
 											PointerGetDatum(a),
@@ -64,7 +64,7 @@ gbt_bitlt(const void *a, const void *b, Oid collation)
 }
 
 static int32
-gbt_bitcmp(const void *a, const void *b, Oid collation)
+gbt_bitcmp(const void *a, const void *b, FmgrInfo *flinfo, Oid collation)
 {
 	return DatumGetInt32(DirectFunctionCall2(byteacmp,
 											 PointerGetDatum(a),
@@ -92,7 +92,7 @@ gbt_bit_xfrm(bytea *leaf)
 
 
 static GBT_VARKEY *
-gbt_bit_l2n(GBT_VARKEY *leaf)
+gbt_bit_l2n(GBT_VARKEY *leaf, FmgrInfo *flinfo)
 {
 	GBT_VARKEY *out = leaf;
 	GBT_VARKEY_R r = gbt_var_key_readable(leaf);
@@ -152,13 +152,13 @@ gbt_bit_consistent(PG_FUNCTION_ARGS)
 
 	if (GIST_LEAF(entry))
 		retval = gbt_var_consistent(&r, query, strategy, PG_GET_COLLATION(),
-									TRUE, &tinfo);
+									TRUE, &tinfo, fcinfo->flinfo);
 	else
 	{
 		bytea	   *q = gbt_bit_xfrm((bytea *) query);
 
 		retval = gbt_var_consistent(&r, q, strategy, PG_GET_COLLATION(),
-									FALSE, &tinfo);
+									FALSE, &tinfo, fcinfo->flinfo);
 	}
 	PG_RETURN_BOOL(retval);
 }
@@ -172,7 +172,7 @@ gbt_bit_union(PG_FUNCTION_ARGS)
 	int32	   *size = (int *) PG_GETARG_POINTER(1);
 
 	PG_RETURN_POINTER(gbt_var_union(entryvec, size, PG_GET_COLLATION(),
-									&tinfo));
+									&tinfo, fcinfo->flinfo));
 }
 
 
@@ -183,7 +183,7 @@ gbt_bit_picksplit(PG_FUNCTION_ARGS)
 	GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
 
 	gbt_var_picksplit(entryvec, v, PG_GET_COLLATION(),
-					  &tinfo);
+					  &tinfo, fcinfo->flinfo);
 	PG_RETURN_POINTER(v);
 }
 
@@ -194,7 +194,7 @@ gbt_bit_same(PG_FUNCTION_ARGS)
 	Datum		d2 = PG_GETARG_DATUM(1);
 	bool	   *result = (bool *) PG_GETARG_POINTER(2);
 
-	*result = gbt_var_same(d1, d2, PG_GET_COLLATION(), &tinfo);
+	*result = gbt_var_same(d1, d2, PG_GET_COLLATION(), &tinfo, fcinfo->flinfo);
 	PG_RETURN_POINTER(result);
 }
 
@@ -207,5 +207,5 @@ gbt_bit_penalty(PG_FUNCTION_ARGS)
 	float	   *result = (float *) PG_GETARG_POINTER(2);
 
 	PG_RETURN_POINTER(gbt_var_penalty(result, o, n, PG_GET_COLLATION(),
-									  &tinfo));
+									  &tinfo, fcinfo->flinfo));
 }
diff --git a/contrib/btree_gist/btree_bytea.c b/contrib/btree_gist/btree_bytea.c
index df6c960..b9cd00f 100644
--- a/contrib/btree_gist/btree_bytea.c
+++ b/contrib/btree_gist/btree_bytea.c
@@ -23,7 +23,7 @@ PG_FUNCTION_INFO_V1(gbt_bytea_same);
 /* define for comparison */
 
 static bool
-gbt_byteagt(const void *a, const void *b, Oid collation)
+gbt_byteagt(const void *a, const void *b, FmgrInfo *flinfo, Oid collation)
 {
 	return DatumGetBool(DirectFunctionCall2(byteagt,
 											PointerGetDatum(a),
@@ -31,7 +31,7 @@ gbt_byteagt(const void *a, const void *b, Oid collation)
 }
 
 static bool
-gbt_byteage(const void *a, const void *b, Oid collation)
+gbt_byteage(const void *a, const void *b, FmgrInfo *flinfo, Oid collation)
 {
 	return DatumGetBool(DirectFunctionCall2(byteage,
 											PointerGetDatum(a),
@@ -39,7 +39,7 @@ gbt_byteage(const void *a, const void *b, Oid collation)
 }
 
 static bool
-gbt_byteaeq(const void *a, const void *b, Oid collation)
+gbt_byteaeq(const void *a, const void *b, FmgrInfo *flinfo, Oid collation)
 {
 	return DatumGetBool(DirectFunctionCall2(byteaeq,
 											PointerGetDatum(a),
@@ -47,7 +47,7 @@ gbt_byteaeq(const void *a, const void *b, Oid collation)
 }
 
 static bool
-gbt_byteale(const void *a, const void *b, Oid collation)
+gbt_byteale(const void *a, const void *b, FmgrInfo *flinfo, Oid collation)
 {
 	return DatumGetBool(DirectFunctionCall2(byteale,
 											PointerGetDatum(a),
@@ -55,7 +55,7 @@ gbt_byteale(const void *a, const void *b, Oid collation)
 }
 
 static bool
-gbt_bytealt(const void *a, const void *b, Oid collation)
+gbt_bytealt(const void *a, const void *b, FmgrInfo *flinfo, Oid collation)
 {
 	return DatumGetBool(DirectFunctionCall2(bytealt,
 											PointerGetDatum(a),
@@ -63,7 +63,7 @@ gbt_bytealt(const void *a, const void *b, Oid collation)
 }
 
 static int32
-gbt_byteacmp(const void *a, const void *b, Oid collation)
+gbt_byteacmp(const void *a, const void *b, FmgrInfo *flinfo, Oid collation)
 {
 	return DatumGetInt32(DirectFunctionCall2(byteacmp,
 											 PointerGetDatum(a),
@@ -118,7 +118,7 @@ gbt_bytea_consistent(PG_FUNCTION_ARGS)
 	*recheck = false;
 
 	retval = gbt_var_consistent(&r, query, strategy, PG_GET_COLLATION(),
-								GIST_LEAF(entry), &tinfo);
+								GIST_LEAF(entry), &tinfo, fcinfo->flinfo);
 	PG_RETURN_BOOL(retval);
 }
 
@@ -131,7 +131,7 @@ gbt_bytea_union(PG_FUNCTION_ARGS)
 	int32	   *size = (int *) PG_GETARG_POINTER(1);
 
 	PG_RETURN_POINTER(gbt_var_union(entryvec, size, PG_GET_COLLATION(),
-									&tinfo));
+									&tinfo, fcinfo->flinfo));
 }
 
 
@@ -142,7 +142,7 @@ gbt_bytea_picksplit(PG_FUNCTION_ARGS)
 	GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
 
 	gbt_var_picksplit(entryvec, v, PG_GET_COLLATION(),
-					  &tinfo);
+					  &tinfo, fcinfo->flinfo);
 	PG_RETURN_POINTER(v);
 }
 
@@ -153,7 +153,7 @@ gbt_bytea_same(PG_FUNCTION_ARGS)
 	Datum		d2 = PG_GETARG_DATUM(1);
 	bool	   *result = (bool *) PG_GETARG_POINTER(2);
 
-	*result = gbt_var_same(d1, d2, PG_GET_COLLATION(), &tinfo);
+	*result = gbt_var_same(d1, d2, PG_GET_COLLATION(), &tinfo, fcinfo->flinfo);
 	PG_RETURN_POINTER(result);
 }
 
@@ -166,5 +166,5 @@ gbt_bytea_penalty(PG_FUNCTION_ARGS)
 	float	   *result = (float *) PG_GETARG_POINTER(2);
 
 	PG_RETURN_POINTER(gbt_var_penalty(result, o, n, PG_GET_COLLATION(),
-									  &tinfo));
+									  &tinfo, fcinfo->flinfo));
 }
diff --git a/contrib/btree_gist/btree_cash.c b/contrib/btree_gist/btree_cash.c
index aa14735..ca0c86b 100644
--- a/contrib/btree_gist/btree_cash.c
+++ b/contrib/btree_gist/btree_cash.c
@@ -26,33 +26,33 @@ PG_FUNCTION_INFO_V1(gbt_cash_penalty);
 PG_FUNCTION_INFO_V1(gbt_cash_same);
 
 static bool
-gbt_cashgt(const void *a, const void *b)
+gbt_cashgt(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return (*((const Cash *) a) > *((const Cash *) b));
 }
 static bool
-gbt_cashge(const void *a, const void *b)
+gbt_cashge(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return (*((const Cash *) a) >= *((const Cash *) b));
 }
 static bool
-gbt_casheq(const void *a, const void *b)
+gbt_casheq(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return (*((const Cash *) a) == *((const Cash *) b));
 }
 static bool
-gbt_cashle(const void *a, const void *b)
+gbt_cashle(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return (*((const Cash *) a) <= *((const Cash *) b));
 }
 static bool
-gbt_cashlt(const void *a, const void *b)
+gbt_cashlt(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return (*((const Cash *) a) < *((const Cash *) b));
 }
 
 static int
-gbt_cashkey_cmp(const void *a, const void *b)
+gbt_cashkey_cmp(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	cashKEY    *ia = (cashKEY *) (((const Nsrt *) a)->t);
 	cashKEY    *ib = (cashKEY *) (((const Nsrt *) b)->t);
@@ -69,7 +69,7 @@ gbt_cashkey_cmp(const void *a, const void *b)
 }
 
 static float8
-gbt_cash_dist(const void *a, const void *b)
+gbt_cash_dist(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return GET_FLOAT_DISTANCE(Cash, a, b);
 }
@@ -151,7 +151,7 @@ gbt_cash_consistent(PG_FUNCTION_ARGS)
 	key.upper = (GBT_NUMKEY *) &kkk->upper;
 
 	PG_RETURN_BOOL(
-				   gbt_num_consistent(&key, (void *) &query, &strategy, GIST_LEAF(entry), &tinfo)
+				   gbt_num_consistent(&key, (void *) &query, &strategy, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)
 		);
 }
 
@@ -170,7 +170,7 @@ gbt_cash_distance(PG_FUNCTION_ARGS)
 	key.upper = (GBT_NUMKEY *) &kkk->upper;
 
 	PG_RETURN_FLOAT8(
-			gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo)
+			gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)
 		);
 }
 
@@ -182,7 +182,7 @@ gbt_cash_union(PG_FUNCTION_ARGS)
 	void	   *out = palloc(sizeof(cashKEY));
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(cashKEY);
-	PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo));
+	PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo, fcinfo->flinfo));
 }
 
 
@@ -205,7 +205,7 @@ gbt_cash_picksplit(PG_FUNCTION_ARGS)
 	PG_RETURN_POINTER(gbt_num_picksplit(
 									(GistEntryVector *) PG_GETARG_POINTER(0),
 									  (GIST_SPLITVEC *) PG_GETARG_POINTER(1),
-										&tinfo
+										&tinfo, fcinfo->flinfo
 										));
 }
 
@@ -216,6 +216,6 @@ gbt_cash_same(PG_FUNCTION_ARGS)
 	cashKEY    *b2 = (cashKEY *) PG_GETARG_POINTER(1);
 	bool	   *result = (bool *) PG_GETARG_POINTER(2);
 
-	*result = gbt_num_same((void *) b1, (void *) b2, &tinfo);
+	*result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
 	PG_RETURN_POINTER(result);
 }
diff --git a/contrib/btree_gist/btree_date.c b/contrib/btree_gist/btree_date.c
index 56031d4..c9daf34 100644
--- a/contrib/btree_gist/btree_date.c
+++ b/contrib/btree_gist/btree_date.c
@@ -27,7 +27,7 @@ PG_FUNCTION_INFO_V1(gbt_date_penalty);
 PG_FUNCTION_INFO_V1(gbt_date_same);
 
 static bool
-gbt_dategt(const void *a, const void *b)
+gbt_dategt(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return DatumGetBool(
 						DirectFunctionCall2(date_gt, DateADTGetDatum(*((const DateADT *) a)), DateADTGetDatum(*((const DateADT *) b)))
@@ -35,7 +35,7 @@ gbt_dategt(const void *a, const void *b)
 }
 
 static bool
-gbt_datege(const void *a, const void *b)
+gbt_datege(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return DatumGetBool(
 						DirectFunctionCall2(date_ge, DateADTGetDatum(*((const DateADT *) a)), DateADTGetDatum(*((const DateADT *) b)))
@@ -43,7 +43,7 @@ gbt_datege(const void *a, const void *b)
 }
 
 static bool
-gbt_dateeq(const void *a, const void *b)
+gbt_dateeq(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return DatumGetBool(
 						DirectFunctionCall2(date_eq, DateADTGetDatum(*((const DateADT *) a)), DateADTGetDatum(*((const DateADT *) b)))
@@ -51,7 +51,7 @@ gbt_dateeq(const void *a, const void *b)
 }
 
 static bool
-gbt_datele(const void *a, const void *b)
+gbt_datele(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return DatumGetBool(
 						DirectFunctionCall2(date_le, DateADTGetDatum(*((const DateADT *) a)), DateADTGetDatum(*((const DateADT *) b)))
@@ -59,7 +59,7 @@ gbt_datele(const void *a, const void *b)
 }
 
 static bool
-gbt_datelt(const void *a, const void *b)
+gbt_datelt(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return DatumGetBool(
 						DirectFunctionCall2(date_lt, DateADTGetDatum(*((const DateADT *) a)), DateADTGetDatum(*((const DateADT *) b)))
@@ -69,7 +69,7 @@ gbt_datelt(const void *a, const void *b)
 
 
 static int
-gbt_datekey_cmp(const void *a, const void *b)
+gbt_datekey_cmp(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	dateKEY    *ia = (dateKEY *) (((const Nsrt *) a)->t);
 	dateKEY    *ib = (dateKEY *) (((const Nsrt *) b)->t);
@@ -83,7 +83,7 @@ gbt_datekey_cmp(const void *a, const void *b)
 }
 
 static float8
-gdb_date_dist(const void *a, const void *b)
+gdb_date_dist(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	/* we assume the difference can't overflow */
 	Datum		diff = DirectFunctionCall2(date_mi,
@@ -163,7 +163,7 @@ gbt_date_consistent(PG_FUNCTION_ARGS)
 	key.upper = (GBT_NUMKEY *) &kkk->upper;
 
 	PG_RETURN_BOOL(
-				   gbt_num_consistent(&key, (void *) &query, &strategy, GIST_LEAF(entry), &tinfo)
+				   gbt_num_consistent(&key, (void *) &query, &strategy, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)
 		);
 }
 
@@ -182,7 +182,7 @@ gbt_date_distance(PG_FUNCTION_ARGS)
 	key.upper = (GBT_NUMKEY *) &kkk->upper;
 
 	PG_RETURN_FLOAT8(
-			gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo)
+			gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)
 		);
 }
 
@@ -194,7 +194,7 @@ gbt_date_union(PG_FUNCTION_ARGS)
 	void	   *out = palloc(sizeof(dateKEY));
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(dateKEY);
-	PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo));
+	PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo, fcinfo->flinfo));
 }
 
 
@@ -244,7 +244,7 @@ gbt_date_picksplit(PG_FUNCTION_ARGS)
 	PG_RETURN_POINTER(gbt_num_picksplit(
 									(GistEntryVector *) PG_GETARG_POINTER(0),
 									  (GIST_SPLITVEC *) PG_GETARG_POINTER(1),
-										&tinfo
+										&tinfo, fcinfo->flinfo
 										));
 }
 
@@ -255,6 +255,6 @@ gbt_date_same(PG_FUNCTION_ARGS)
 	dateKEY    *b2 = (dateKEY *) PG_GETARG_POINTER(1);
 	bool	   *result = (bool *) PG_GETARG_POINTER(2);
 
-	*result = gbt_num_same((void *) b1, (void *) b2, &tinfo);
+	*result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
 	PG_RETURN_POINTER(result);
 }
diff --git a/contrib/btree_gist/btree_enum.c b/contrib/btree_gist/btree_enum.c
new file mode 100644
index 0000000..5e46e78
--- /dev/null
+++ b/contrib/btree_gist/btree_enum.c
@@ -0,0 +1,187 @@
+/*
+ * contrib/btree_gist/btree_enum.c
+ */
+#include "postgres.h"
+#include "fmgr.h"
+#include "utils/builtins.h"
+
+#include "btree_gist.h"
+#include "btree_utils_num.h"
+
+/* enums are really Oids, so we just use the same structure */
+
+typedef struct
+{
+	Oid			lower;
+	Oid			upper;
+} oidKEY;
+
+/*
+** enum ops
+*/
+PG_FUNCTION_INFO_V1(gbt_enum_compress);
+PG_FUNCTION_INFO_V1(gbt_enum_fetch);
+PG_FUNCTION_INFO_V1(gbt_enum_union);
+PG_FUNCTION_INFO_V1(gbt_enum_picksplit);
+PG_FUNCTION_INFO_V1(gbt_enum_consistent);
+PG_FUNCTION_INFO_V1(gbt_enum_penalty);
+PG_FUNCTION_INFO_V1(gbt_enum_same);
+
+
+static bool
+gbt_enumgt(const void *a, const void *b, FmgrInfo *flinfo)
+{
+	return DatumGetBool(
+		CallerFInfoFunctionCall2(enum_gt, flinfo, InvalidOid, ObjectIdGetDatum(*((const Oid *) a)), ObjectIdGetDatum(*((const Oid *) b)))
+		);
+}
+static bool
+gbt_enumge(const void *a, const void *b, FmgrInfo *flinfo)
+{
+	return DatumGetBool(
+		CallerFInfoFunctionCall2(enum_ge, flinfo, InvalidOid, ObjectIdGetDatum(*((const Oid *) a)), ObjectIdGetDatum(*((const Oid *) b)))
+		);
+}
+static bool
+gbt_enumeq(const void *a, const void *b, FmgrInfo *flinfo)
+{
+	return (*((const Oid *) a) == *((const Oid *) b));
+}
+static bool
+gbt_enumle(const void *a, const void *b, FmgrInfo *flinfo)
+{
+	return DatumGetBool(
+						CallerFInfoFunctionCall2(enum_le, flinfo, InvalidOid, ObjectIdGetDatum(*((const Oid *) a)), ObjectIdGetDatum(*((const Oid *) b)))
+		);
+}
+static bool
+gbt_enumlt(const void *a, const void *b, FmgrInfo *flinfo)
+{
+	return DatumGetBool(
+						CallerFInfoFunctionCall2(enum_lt, flinfo, InvalidOid, ObjectIdGetDatum(*((const Oid *) a)), ObjectIdGetDatum(*((const Oid *) b)))
+		);
+}
+
+static int
+gbt_enumkey_cmp(const void *a, const void *b, FmgrInfo *flinfo)
+{
+	oidKEY	   *ia = (oidKEY *) (((const Nsrt *) a)->t);
+	oidKEY	   *ib = (oidKEY *) (((const Nsrt *) b)->t);
+
+	if (ia->lower == ib->lower)
+	{
+		if (ia->upper == ib->upper)
+			return 0;
+
+		return DatumGetInt32(
+			CallerFInfoFunctionCall2(enum_cmp, flinfo, InvalidOid, ObjectIdGetDatum(ia->upper), ObjectIdGetDatum(ib->upper))
+			);
+	}
+
+	return DatumGetInt32(
+		CallerFInfoFunctionCall2(enum_cmp, flinfo, InvalidOid, ObjectIdGetDatum(ia->lower), ObjectIdGetDatum(ib->lower))
+		);
+}
+
+static const gbtree_ninfo tinfo =
+{
+	gbt_t_enum,
+	sizeof(Oid),
+	8,							/* sizeof(gbtreekey8) */
+	gbt_enumgt,
+	gbt_enumge,
+	gbt_enumeq,
+	gbt_enumle,
+	gbt_enumlt,
+	gbt_enumkey_cmp,
+	NULL /* no KNN support at least for now */
+};
+
+
+/**************************************************
+ * Enum ops
+ **************************************************/
+
+
+Datum
+gbt_enum_compress(PG_FUNCTION_ARGS)
+{
+	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+
+	PG_RETURN_POINTER(gbt_num_compress(entry, &tinfo));
+}
+
+Datum
+gbt_enum_fetch(PG_FUNCTION_ARGS)
+{
+	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+
+	PG_RETURN_POINTER(gbt_num_fetch(entry, &tinfo));
+}
+
+Datum
+gbt_enum_consistent(PG_FUNCTION_ARGS)
+{
+	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+	Oid			query = PG_GETARG_OID(1);
+	StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
+
+	/* Oid		subtype = PG_GETARG_OID(3); */
+	bool	   *recheck = (bool *) PG_GETARG_POINTER(4);
+	oidKEY	   *kkk = (oidKEY *) DatumGetPointer(entry->key);
+	GBT_NUMKEY_R key;
+
+	/* All cases served by this function are exact */
+	*recheck = false;
+
+	key.lower = (GBT_NUMKEY *) &kkk->lower;
+	key.upper = (GBT_NUMKEY *) &kkk->upper;
+
+	PG_RETURN_BOOL(
+				   gbt_num_consistent(&key, (void *) &query, &strategy, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)
+		);
+}
+
+Datum
+gbt_enum_union(PG_FUNCTION_ARGS)
+{
+	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
+	void	   *out = palloc(sizeof(oidKEY));
+
+	*(int *) PG_GETARG_POINTER(1) = sizeof(oidKEY);
+	PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo, fcinfo->flinfo));
+}
+
+
+Datum
+gbt_enum_penalty(PG_FUNCTION_ARGS)
+{
+	oidKEY	   *origentry = (oidKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
+	oidKEY	   *newentry = (oidKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
+	float	   *result = (float *) PG_GETARG_POINTER(2);
+
+	penalty_num(result, origentry->lower, origentry->upper, newentry->lower, newentry->upper);
+
+	PG_RETURN_POINTER(result);
+}
+
+Datum
+gbt_enum_picksplit(PG_FUNCTION_ARGS)
+{
+	PG_RETURN_POINTER(gbt_num_picksplit(
+									(GistEntryVector *) PG_GETARG_POINTER(0),
+									  (GIST_SPLITVEC *) PG_GETARG_POINTER(1),
+										&tinfo, fcinfo->flinfo
+										));
+}
+
+Datum
+gbt_enum_same(PG_FUNCTION_ARGS)
+{
+	oidKEY	   *b1 = (oidKEY *) PG_GETARG_POINTER(0);
+	oidKEY	   *b2 = (oidKEY *) PG_GETARG_POINTER(1);
+	bool	   *result = (bool *) PG_GETARG_POINTER(2);
+
+	*result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
+	PG_RETURN_POINTER(result);
+}
diff --git a/contrib/btree_gist/btree_float4.c b/contrib/btree_gist/btree_float4.c
index 13dc4a5..46b3edb 100644
--- a/contrib/btree_gist/btree_float4.c
+++ b/contrib/btree_gist/btree_float4.c
@@ -25,33 +25,33 @@ PG_FUNCTION_INFO_V1(gbt_float4_penalty);
 PG_FUNCTION_INFO_V1(gbt_float4_same);
 
 static bool
-gbt_float4gt(const void *a, const void *b)
+gbt_float4gt(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return (*((const float4 *) a) > *((const float4 *) b));
 }
 static bool
-gbt_float4ge(const void *a, const void *b)
+gbt_float4ge(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return (*((const float4 *) a) >= *((const float4 *) b));
 }
 static bool
-gbt_float4eq(const void *a, const void *b)
+gbt_float4eq(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return (*((const float4 *) a) == *((const float4 *) b));
 }
 static bool
-gbt_float4le(const void *a, const void *b)
+gbt_float4le(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return (*((const float4 *) a) <= *((const float4 *) b));
 }
 static bool
-gbt_float4lt(const void *a, const void *b)
+gbt_float4lt(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return (*((const float4 *) a) < *((const float4 *) b));
 }
 
 static int
-gbt_float4key_cmp(const void *a, const void *b)
+gbt_float4key_cmp(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	float4KEY  *ia = (float4KEY *) (((const Nsrt *) a)->t);
 	float4KEY  *ib = (float4KEY *) (((const Nsrt *) b)->t);
@@ -68,7 +68,7 @@ gbt_float4key_cmp(const void *a, const void *b)
 }
 
 static float8
-gbt_float4_dist(const void *a, const void *b)
+gbt_float4_dist(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return GET_FLOAT_DISTANCE(float4, a, b);
 }
@@ -144,7 +144,7 @@ gbt_float4_consistent(PG_FUNCTION_ARGS)
 	key.upper = (GBT_NUMKEY *) &kkk->upper;
 
 	PG_RETURN_BOOL(
-				   gbt_num_consistent(&key, (void *) &query, &strategy, GIST_LEAF(entry), &tinfo)
+				   gbt_num_consistent(&key, (void *) &query, &strategy, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)
 		);
 }
 
@@ -163,7 +163,7 @@ gbt_float4_distance(PG_FUNCTION_ARGS)
 	key.upper = (GBT_NUMKEY *) &kkk->upper;
 
 	PG_RETURN_FLOAT8(
-			gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo)
+			gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)
 		);
 }
 
@@ -175,7 +175,7 @@ gbt_float4_union(PG_FUNCTION_ARGS)
 	void	   *out = palloc(sizeof(float4KEY));
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(float4KEY);
-	PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo));
+	PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo, fcinfo->flinfo));
 }
 
 
@@ -198,7 +198,7 @@ gbt_float4_picksplit(PG_FUNCTION_ARGS)
 	PG_RETURN_POINTER(gbt_num_picksplit(
 									(GistEntryVector *) PG_GETARG_POINTER(0),
 									  (GIST_SPLITVEC *) PG_GETARG_POINTER(1),
-										&tinfo
+										&tinfo, fcinfo->flinfo
 										));
 }
 
@@ -209,6 +209,6 @@ gbt_float4_same(PG_FUNCTION_ARGS)
 	float4KEY  *b2 = (float4KEY *) PG_GETARG_POINTER(1);
 	bool	   *result = (bool *) PG_GETARG_POINTER(2);
 
-	*result = gbt_num_same((void *) b1, (void *) b2, &tinfo);
+	*result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
 	PG_RETURN_POINTER(result);
 }
diff --git a/contrib/btree_gist/btree_float8.c b/contrib/btree_gist/btree_float8.c
index c3a2415..7d65307 100644
--- a/contrib/btree_gist/btree_float8.c
+++ b/contrib/btree_gist/btree_float8.c
@@ -26,33 +26,33 @@ PG_FUNCTION_INFO_V1(gbt_float8_same);
 
 
 static bool
-gbt_float8gt(const void *a, const void *b)
+gbt_float8gt(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return (*((const float8 *) a) > *((const float8 *) b));
 }
 static bool
-gbt_float8ge(const void *a, const void *b)
+gbt_float8ge(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return (*((const float8 *) a) >= *((const float8 *) b));
 }
 static bool
-gbt_float8eq(const void *a, const void *b)
+gbt_float8eq(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return (*((const float8 *) a) == *((const float8 *) b));
 }
 static bool
-gbt_float8le(const void *a, const void *b)
+gbt_float8le(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return (*((const float8 *) a) <= *((const float8 *) b));
 }
 static bool
-gbt_float8lt(const void *a, const void *b)
+gbt_float8lt(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return (*((const float8 *) a) < *((const float8 *) b));
 }
 
 static int
-gbt_float8key_cmp(const void *a, const void *b)
+gbt_float8key_cmp(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	float8KEY  *ia = (float8KEY *) (((const Nsrt *) a)->t);
 	float8KEY  *ib = (float8KEY *) (((const Nsrt *) b)->t);
@@ -69,7 +69,7 @@ gbt_float8key_cmp(const void *a, const void *b)
 }
 
 static float8
-gbt_float8_dist(const void *a, const void *b)
+gbt_float8_dist(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	float8		arg1 = *(const float8 *) a;
 	float8		arg2 = *(const float8 *) b;
@@ -151,7 +151,7 @@ gbt_float8_consistent(PG_FUNCTION_ARGS)
 	key.upper = (GBT_NUMKEY *) &kkk->upper;
 
 	PG_RETURN_BOOL(
-				   gbt_num_consistent(&key, (void *) &query, &strategy, GIST_LEAF(entry), &tinfo)
+				   gbt_num_consistent(&key, (void *) &query, &strategy, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)
 		);
 }
 
@@ -170,7 +170,7 @@ gbt_float8_distance(PG_FUNCTION_ARGS)
 	key.upper = (GBT_NUMKEY *) &kkk->upper;
 
 	PG_RETURN_FLOAT8(
-			gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo)
+			gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)
 		);
 }
 
@@ -182,7 +182,7 @@ gbt_float8_union(PG_FUNCTION_ARGS)
 	void	   *out = palloc(sizeof(float8KEY));
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(float8KEY);
-	PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo));
+	PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo, fcinfo->flinfo));
 }
 
 
@@ -205,7 +205,7 @@ gbt_float8_picksplit(PG_FUNCTION_ARGS)
 	PG_RETURN_POINTER(gbt_num_picksplit(
 									(GistEntryVector *) PG_GETARG_POINTER(0),
 									  (GIST_SPLITVEC *) PG_GETARG_POINTER(1),
-										&tinfo
+										&tinfo, fcinfo->flinfo
 										));
 }
 
@@ -216,6 +216,6 @@ gbt_float8_same(PG_FUNCTION_ARGS)
 	float8KEY  *b2 = (float8KEY *) PG_GETARG_POINTER(1);
 	bool	   *result = (bool *) PG_GETARG_POINTER(2);
 
-	*result = gbt_num_same((void *) b1, (void *) b2, &tinfo);
+	*result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
 	PG_RETURN_POINTER(result);
 }
diff --git a/contrib/btree_gist/btree_gist--1.3--1.4.sql b/contrib/btree_gist/btree_gist--1.3--1.4.sql
index f77f6c8..e8dabe1 100644
--- a/contrib/btree_gist/btree_gist--1.3--1.4.sql
+++ b/contrib/btree_gist/btree_gist--1.3--1.4.sql
@@ -62,3 +62,69 @@ AS
 ALTER OPERATOR FAMILY gist_macaddr8_ops USING gist ADD
 	OPERATOR	6	<> (macaddr8, macaddr8) ,
 	FUNCTION	9 (macaddr8, macaddr8) gbt_macad8_fetch (internal);
+
+
+--
+--
+--
+-- enum ops
+--
+--
+--
+-- define the GiST support methods
+CREATE FUNCTION gbt_enum_consistent(internal,anyenum,int2,oid,internal)
+RETURNS bool
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gbt_enum_compress(internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gbt_enum_fetch(internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gbt_enum_penalty(internal,internal,internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gbt_enum_picksplit(internal, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gbt_enum_union(internal, internal)
+RETURNS gbtreekey8
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+CREATE FUNCTION gbt_enum_same(gbtreekey8, gbtreekey8, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C IMMUTABLE STRICT;
+
+-- Create the operator class
+CREATE OPERATOR CLASS gist_enum_ops
+DEFAULT FOR TYPE anyenum USING gist
+AS
+	OPERATOR	1	<  ,
+	OPERATOR	2	<= ,
+	OPERATOR	3	=  ,
+	OPERATOR	4	>= ,
+	OPERATOR	5	>  ,
+	FUNCTION	1	gbt_enum_consistent (internal, anyenum, int2, oid, internal),
+	FUNCTION	2	gbt_enum_union (internal, internal),
+	FUNCTION	3	gbt_enum_compress (internal),
+	FUNCTION	4	gbt_decompress (internal),
+	FUNCTION	5	gbt_enum_penalty (internal, internal, internal),
+	FUNCTION	6	gbt_enum_picksplit (internal, internal),
+	FUNCTION	7	gbt_enum_same (gbtreekey8, gbtreekey8, internal),
+	STORAGE		gbtreekey8;
+
+ALTER OPERATOR FAMILY gist_enum_ops USING gist ADD
+	OPERATOR	6	<> (anyenum, anyenum) ,
+	FUNCTION	9 (anyenum, anyenum) gbt_enum_fetch (internal) ;
diff --git a/contrib/btree_gist/btree_gist.h b/contrib/btree_gist/btree_gist.h
index f759299..011285a 100644
--- a/contrib/btree_gist/btree_gist.h
+++ b/contrib/btree_gist/btree_gist.h
@@ -33,7 +33,8 @@ enum gbtree_type
 	gbt_t_bytea,
 	gbt_t_bit,
 	gbt_t_inet,
-	gbt_t_uuid
+	gbt_t_uuid,
+	gbt_t_enum
 };
 
 #endif
diff --git a/contrib/btree_gist/btree_inet.c b/contrib/btree_gist/btree_inet.c
index 8227861..7c95ee6 100644
--- a/contrib/btree_gist/btree_inet.c
+++ b/contrib/btree_gist/btree_inet.c
@@ -27,33 +27,33 @@ PG_FUNCTION_INFO_V1(gbt_inet_same);
 
 
 static bool
-gbt_inetgt(const void *a, const void *b)
+gbt_inetgt(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return (*((const double *) a) > *((const double *) b));
 }
 static bool
-gbt_inetge(const void *a, const void *b)
+gbt_inetge(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return (*((const double *) a) >= *((const double *) b));
 }
 static bool
-gbt_ineteq(const void *a, const void *b)
+gbt_ineteq(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return (*((const double *) a) == *((const double *) b));
 }
 static bool
-gbt_inetle(const void *a, const void *b)
+gbt_inetle(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return (*((const double *) a) <= *((const double *) b));
 }
 static bool
-gbt_inetlt(const void *a, const void *b)
+gbt_inetlt(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return (*((const double *) a) < *((const double *) b));
 }
 
 static int
-gbt_inetkey_cmp(const void *a, const void *b)
+gbt_inetkey_cmp(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	inetKEY    *ia = (inetKEY *) (((const Nsrt *) a)->t);
 	inetKEY    *ib = (inetKEY *) (((const Nsrt *) b)->t);
@@ -133,7 +133,7 @@ gbt_inet_consistent(PG_FUNCTION_ARGS)
 	key.upper = (GBT_NUMKEY *) &kkk->upper;
 
 	PG_RETURN_BOOL(gbt_num_consistent(&key, (void *) &query,
-									  &strategy, GIST_LEAF(entry), &tinfo));
+									  &strategy, GIST_LEAF(entry), &tinfo, fcinfo->flinfo));
 }
 
 
@@ -144,7 +144,7 @@ gbt_inet_union(PG_FUNCTION_ARGS)
 	void	   *out = palloc(sizeof(inetKEY));
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(inetKEY);
-	PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo));
+	PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo, fcinfo->flinfo));
 }
 
 
@@ -167,7 +167,7 @@ gbt_inet_picksplit(PG_FUNCTION_ARGS)
 	PG_RETURN_POINTER(gbt_num_picksplit(
 									(GistEntryVector *) PG_GETARG_POINTER(0),
 									  (GIST_SPLITVEC *) PG_GETARG_POINTER(1),
-										&tinfo
+										&tinfo, fcinfo->flinfo
 										));
 }
 
@@ -178,6 +178,6 @@ gbt_inet_same(PG_FUNCTION_ARGS)
 	inetKEY    *b2 = (inetKEY *) PG_GETARG_POINTER(1);
 	bool	   *result = (bool *) PG_GETARG_POINTER(2);
 
-	*result = gbt_num_same((void *) b1, (void *) b2, &tinfo);
+	*result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
 	PG_RETURN_POINTER(result);
 }
diff --git a/contrib/btree_gist/btree_int2.c b/contrib/btree_gist/btree_int2.c
index 54dc1cc..3dae5e7 100644
--- a/contrib/btree_gist/btree_int2.c
+++ b/contrib/btree_gist/btree_int2.c
@@ -25,33 +25,33 @@ PG_FUNCTION_INFO_V1(gbt_int2_penalty);
 PG_FUNCTION_INFO_V1(gbt_int2_same);
 
 static bool
-gbt_int2gt(const void *a, const void *b)
+gbt_int2gt(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return (*((const int16 *) a) > *((const int16 *) b));
 }
 static bool
-gbt_int2ge(const void *a, const void *b)
+gbt_int2ge(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return (*((const int16 *) a) >= *((const int16 *) b));
 }
 static bool
-gbt_int2eq(const void *a, const void *b)
+gbt_int2eq(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return (*((const int16 *) a) == *((const int16 *) b));
 }
 static bool
-gbt_int2le(const void *a, const void *b)
+gbt_int2le(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return (*((const int16 *) a) <= *((const int16 *) b));
 }
 static bool
-gbt_int2lt(const void *a, const void *b)
+gbt_int2lt(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return (*((const int16 *) a) < *((const int16 *) b));
 }
 
 static int
-gbt_int2key_cmp(const void *a, const void *b)
+gbt_int2key_cmp(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	int16KEY   *ia = (int16KEY *) (((const Nsrt *) a)->t);
 	int16KEY   *ib = (int16KEY *) (((const Nsrt *) b)->t);
@@ -68,7 +68,7 @@ gbt_int2key_cmp(const void *a, const void *b)
 }
 
 static float8
-gbt_int2_dist(const void *a, const void *b)
+gbt_int2_dist(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return GET_FLOAT_DISTANCE(int16, a, b);
 }
@@ -151,7 +151,7 @@ gbt_int2_consistent(PG_FUNCTION_ARGS)
 	key.upper = (GBT_NUMKEY *) &kkk->upper;
 
 	PG_RETURN_BOOL(
-				   gbt_num_consistent(&key, (void *) &query, &strategy, GIST_LEAF(entry), &tinfo)
+				   gbt_num_consistent(&key, (void *) &query, &strategy, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)
 		);
 }
 
@@ -170,7 +170,7 @@ gbt_int2_distance(PG_FUNCTION_ARGS)
 	key.upper = (GBT_NUMKEY *) &kkk->upper;
 
 	PG_RETURN_FLOAT8(
-			gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo)
+			gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)
 		);
 }
 
@@ -182,7 +182,7 @@ gbt_int2_union(PG_FUNCTION_ARGS)
 	void	   *out = palloc(sizeof(int16KEY));
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(int16KEY);
-	PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo));
+	PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo, fcinfo->flinfo));
 }
 
 
@@ -204,7 +204,7 @@ gbt_int2_picksplit(PG_FUNCTION_ARGS)
 	PG_RETURN_POINTER(gbt_num_picksplit(
 									(GistEntryVector *) PG_GETARG_POINTER(0),
 									  (GIST_SPLITVEC *) PG_GETARG_POINTER(1),
-										&tinfo
+										&tinfo, fcinfo->flinfo
 										));
 }
 
@@ -215,6 +215,6 @@ gbt_int2_same(PG_FUNCTION_ARGS)
 	int16KEY   *b2 = (int16KEY *) PG_GETARG_POINTER(1);
 	bool	   *result = (bool *) PG_GETARG_POINTER(2);
 
-	*result = gbt_num_same((void *) b1, (void *) b2, &tinfo);
+	*result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
 	PG_RETURN_POINTER(result);
 }
diff --git a/contrib/btree_gist/btree_int4.c b/contrib/btree_gist/btree_int4.c
index ddbcf52..213bfa3 100644
--- a/contrib/btree_gist/btree_int4.c
+++ b/contrib/btree_gist/btree_int4.c
@@ -26,33 +26,33 @@ PG_FUNCTION_INFO_V1(gbt_int4_same);
 
 
 static bool
-gbt_int4gt(const void *a, const void *b)
+gbt_int4gt(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return (*((const int32 *) a) > *((const int32 *) b));
 }
 static bool
-gbt_int4ge(const void *a, const void *b)
+gbt_int4ge(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return (*((const int32 *) a) >= *((const int32 *) b));
 }
 static bool
-gbt_int4eq(const void *a, const void *b)
+gbt_int4eq(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return (*((const int32 *) a) == *((const int32 *) b));
 }
 static bool
-gbt_int4le(const void *a, const void *b)
+gbt_int4le(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return (*((const int32 *) a) <= *((const int32 *) b));
 }
 static bool
-gbt_int4lt(const void *a, const void *b)
+gbt_int4lt(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return (*((const int32 *) a) < *((const int32 *) b));
 }
 
 static int
-gbt_int4key_cmp(const void *a, const void *b)
+gbt_int4key_cmp(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	int32KEY   *ia = (int32KEY *) (((const Nsrt *) a)->t);
 	int32KEY   *ib = (int32KEY *) (((const Nsrt *) b)->t);
@@ -69,7 +69,7 @@ gbt_int4key_cmp(const void *a, const void *b)
 }
 
 static float8
-gbt_int4_dist(const void *a, const void *b)
+gbt_int4_dist(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return GET_FLOAT_DISTANCE(int32, a, b);
 }
@@ -152,7 +152,7 @@ gbt_int4_consistent(PG_FUNCTION_ARGS)
 	key.upper = (GBT_NUMKEY *) &kkk->upper;
 
 	PG_RETURN_BOOL(
-				   gbt_num_consistent(&key, (void *) &query, &strategy, GIST_LEAF(entry), &tinfo)
+				   gbt_num_consistent(&key, (void *) &query, &strategy, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)
 		);
 }
 
@@ -171,7 +171,7 @@ gbt_int4_distance(PG_FUNCTION_ARGS)
 	key.upper = (GBT_NUMKEY *) &kkk->upper;
 
 	PG_RETURN_FLOAT8(
-			gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo)
+			gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)
 		);
 }
 
@@ -183,7 +183,7 @@ gbt_int4_union(PG_FUNCTION_ARGS)
 	void	   *out = palloc(sizeof(int32KEY));
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(int32KEY);
-	PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo));
+	PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo, fcinfo->flinfo));
 }
 
 
@@ -205,7 +205,7 @@ gbt_int4_picksplit(PG_FUNCTION_ARGS)
 	PG_RETURN_POINTER(gbt_num_picksplit(
 									(GistEntryVector *) PG_GETARG_POINTER(0),
 									  (GIST_SPLITVEC *) PG_GETARG_POINTER(1),
-										&tinfo
+										&tinfo, fcinfo->flinfo
 										));
 }
 
@@ -216,6 +216,6 @@ gbt_int4_same(PG_FUNCTION_ARGS)
 	int32KEY   *b2 = (int32KEY *) PG_GETARG_POINTER(1);
 	bool	   *result = (bool *) PG_GETARG_POINTER(2);
 
-	*result = gbt_num_same((void *) b1, (void *) b2, &tinfo);
+	*result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
 	PG_RETURN_POINTER(result);
 }
diff --git a/contrib/btree_gist/btree_int8.c b/contrib/btree_gist/btree_int8.c
index 44bf69a..62b079b 100644
--- a/contrib/btree_gist/btree_int8.c
+++ b/contrib/btree_gist/btree_int8.c
@@ -26,33 +26,33 @@ PG_FUNCTION_INFO_V1(gbt_int8_same);
 
 
 static bool
-gbt_int8gt(const void *a, const void *b)
+gbt_int8gt(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return (*((const int64 *) a) > *((const int64 *) b));
 }
 static bool
-gbt_int8ge(const void *a, const void *b)
+gbt_int8ge(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return (*((const int64 *) a) >= *((const int64 *) b));
 }
 static bool
-gbt_int8eq(const void *a, const void *b)
+gbt_int8eq(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return (*((const int64 *) a) == *((const int64 *) b));
 }
 static bool
-gbt_int8le(const void *a, const void *b)
+gbt_int8le(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return (*((const int64 *) a) <= *((const int64 *) b));
 }
 static bool
-gbt_int8lt(const void *a, const void *b)
+gbt_int8lt(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return (*((const int64 *) a) < *((const int64 *) b));
 }
 
 static int
-gbt_int8key_cmp(const void *a, const void *b)
+gbt_int8key_cmp(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	int64KEY   *ia = (int64KEY *) (((const Nsrt *) a)->t);
 	int64KEY   *ib = (int64KEY *) (((const Nsrt *) b)->t);
@@ -69,7 +69,7 @@ gbt_int8key_cmp(const void *a, const void *b)
 }
 
 static float8
-gbt_int8_dist(const void *a, const void *b)
+gbt_int8_dist(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return GET_FLOAT_DISTANCE(int64, a, b);
 }
@@ -152,7 +152,7 @@ gbt_int8_consistent(PG_FUNCTION_ARGS)
 	key.upper = (GBT_NUMKEY *) &kkk->upper;
 
 	PG_RETURN_BOOL(
-				   gbt_num_consistent(&key, (void *) &query, &strategy, GIST_LEAF(entry), &tinfo)
+				   gbt_num_consistent(&key, (void *) &query, &strategy, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)
 		);
 }
 
@@ -171,7 +171,7 @@ gbt_int8_distance(PG_FUNCTION_ARGS)
 	key.upper = (GBT_NUMKEY *) &kkk->upper;
 
 	PG_RETURN_FLOAT8(
-			gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo)
+			gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)
 		);
 }
 
@@ -183,7 +183,7 @@ gbt_int8_union(PG_FUNCTION_ARGS)
 	void	   *out = palloc(sizeof(int64KEY));
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(int64KEY);
-	PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo));
+	PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo, fcinfo->flinfo));
 }
 
 
@@ -205,7 +205,7 @@ gbt_int8_picksplit(PG_FUNCTION_ARGS)
 	PG_RETURN_POINTER(gbt_num_picksplit(
 									(GistEntryVector *) PG_GETARG_POINTER(0),
 									  (GIST_SPLITVEC *) PG_GETARG_POINTER(1),
-										&tinfo
+										&tinfo, fcinfo->flinfo
 										));
 }
 
@@ -216,6 +216,6 @@ gbt_int8_same(PG_FUNCTION_ARGS)
 	int64KEY   *b2 = (int64KEY *) PG_GETARG_POINTER(1);
 	bool	   *result = (bool *) PG_GETARG_POINTER(2);
 
-	*result = gbt_num_same((void *) b1, (void *) b2, &tinfo);
+	*result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
 	PG_RETURN_POINTER(result);
 }
diff --git a/contrib/btree_gist/btree_interval.c b/contrib/btree_gist/btree_interval.c
index e5cd0a2..f41f471 100644
--- a/contrib/btree_gist/btree_interval.c
+++ b/contrib/btree_gist/btree_interval.c
@@ -30,37 +30,37 @@ PG_FUNCTION_INFO_V1(gbt_intv_same);
 
 
 static bool
-gbt_intvgt(const void *a, const void *b)
+gbt_intvgt(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return DatumGetBool(DirectFunctionCall2(interval_gt, IntervalPGetDatum(a), IntervalPGetDatum(b)));
 }
 
 static bool
-gbt_intvge(const void *a, const void *b)
+gbt_intvge(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return DatumGetBool(DirectFunctionCall2(interval_ge, IntervalPGetDatum(a), IntervalPGetDatum(b)));
 }
 
 static bool
-gbt_intveq(const void *a, const void *b)
+gbt_intveq(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return DatumGetBool(DirectFunctionCall2(interval_eq, IntervalPGetDatum(a), IntervalPGetDatum(b)));
 }
 
 static bool
-gbt_intvle(const void *a, const void *b)
+gbt_intvle(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return DatumGetBool(DirectFunctionCall2(interval_le, IntervalPGetDatum(a), IntervalPGetDatum(b)));
 }
 
 static bool
-gbt_intvlt(const void *a, const void *b)
+gbt_intvlt(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return DatumGetBool(DirectFunctionCall2(interval_lt, IntervalPGetDatum(a), IntervalPGetDatum(b)));
 }
 
 static int
-gbt_intvkey_cmp(const void *a, const void *b)
+gbt_intvkey_cmp(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	intvKEY    *ia = (intvKEY *) (((const Nsrt *) a)->t);
 	intvKEY    *ib = (intvKEY *) (((const Nsrt *) b)->t);
@@ -81,7 +81,7 @@ intr2num(const Interval *i)
 }
 
 static float8
-gbt_intv_dist(const void *a, const void *b)
+gbt_intv_dist(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return (float8) Abs(intr2num((const Interval *) a) - intr2num((const Interval *) b));
 }
@@ -226,7 +226,7 @@ gbt_intv_consistent(PG_FUNCTION_ARGS)
 	key.upper = (GBT_NUMKEY *) &kkk->upper;
 
 	PG_RETURN_BOOL(
-				   gbt_num_consistent(&key, (void *) query, &strategy, GIST_LEAF(entry), &tinfo)
+				   gbt_num_consistent(&key, (void *) query, &strategy, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)
 		);
 }
 
@@ -245,7 +245,7 @@ gbt_intv_distance(PG_FUNCTION_ARGS)
 	key.upper = (GBT_NUMKEY *) &kkk->upper;
 
 	PG_RETURN_FLOAT8(
-			 gbt_num_distance(&key, (void *) query, GIST_LEAF(entry), &tinfo)
+			 gbt_num_distance(&key, (void *) query, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)
 		);
 }
 
@@ -257,7 +257,7 @@ gbt_intv_union(PG_FUNCTION_ARGS)
 	void	   *out = palloc(sizeof(intvKEY));
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(intvKEY);
-	PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo));
+	PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo, fcinfo->flinfo));
 }
 
 
@@ -287,7 +287,7 @@ gbt_intv_picksplit(PG_FUNCTION_ARGS)
 	PG_RETURN_POINTER(gbt_num_picksplit(
 									(GistEntryVector *) PG_GETARG_POINTER(0),
 									  (GIST_SPLITVEC *) PG_GETARG_POINTER(1),
-										&tinfo
+										&tinfo, fcinfo->flinfo
 										));
 }
 
@@ -298,6 +298,6 @@ gbt_intv_same(PG_FUNCTION_ARGS)
 	intvKEY    *b2 = (intvKEY *) PG_GETARG_POINTER(1);
 	bool	   *result = (bool *) PG_GETARG_POINTER(2);
 
-	*result = gbt_num_same((void *) b1, (void *) b2, &tinfo);
+	*result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
 	PG_RETURN_POINTER(result);
 }
diff --git a/contrib/btree_gist/btree_macaddr.c b/contrib/btree_gist/btree_macaddr.c
index 87d96c0..d530b4e 100644
--- a/contrib/btree_gist/btree_macaddr.c
+++ b/contrib/btree_gist/btree_macaddr.c
@@ -28,37 +28,37 @@ PG_FUNCTION_INFO_V1(gbt_macad_same);
 
 
 static bool
-gbt_macadgt(const void *a, const void *b)
+gbt_macadgt(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return DatumGetBool(DirectFunctionCall2(macaddr_gt, PointerGetDatum(a), PointerGetDatum(b)));
 }
 static bool
-gbt_macadge(const void *a, const void *b)
+gbt_macadge(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return DatumGetBool(DirectFunctionCall2(macaddr_ge, PointerGetDatum(a), PointerGetDatum(b)));
 }
 
 static bool
-gbt_macadeq(const void *a, const void *b)
+gbt_macadeq(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return DatumGetBool(DirectFunctionCall2(macaddr_eq, PointerGetDatum(a), PointerGetDatum(b)));
 }
 
 static bool
-gbt_macadle(const void *a, const void *b)
+gbt_macadle(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return DatumGetBool(DirectFunctionCall2(macaddr_le, PointerGetDatum(a), PointerGetDatum(b)));
 }
 
 static bool
-gbt_macadlt(const void *a, const void *b)
+gbt_macadlt(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return DatumGetBool(DirectFunctionCall2(macaddr_lt, PointerGetDatum(a), PointerGetDatum(b)));
 }
 
 
 static int
-gbt_macadkey_cmp(const void *a, const void *b)
+gbt_macadkey_cmp(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	macKEY	   *ia = (macKEY *) (((const Nsrt *) a)->t);
 	macKEY	   *ib = (macKEY *) (((const Nsrt *) b)->t);
@@ -142,7 +142,7 @@ gbt_macad_consistent(PG_FUNCTION_ARGS)
 	key.upper = (GBT_NUMKEY *) &kkk->upper;
 
 	PG_RETURN_BOOL(
-				   gbt_num_consistent(&key, (void *) query, &strategy, GIST_LEAF(entry), &tinfo)
+				   gbt_num_consistent(&key, (void *) query, &strategy, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)
 		);
 }
 
@@ -154,7 +154,7 @@ gbt_macad_union(PG_FUNCTION_ARGS)
 	void	   *out = palloc0(sizeof(macKEY));
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(macKEY);
-	PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo));
+	PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo, fcinfo->flinfo));
 }
 
 
@@ -184,7 +184,7 @@ gbt_macad_picksplit(PG_FUNCTION_ARGS)
 	PG_RETURN_POINTER(gbt_num_picksplit(
 									(GistEntryVector *) PG_GETARG_POINTER(0),
 									  (GIST_SPLITVEC *) PG_GETARG_POINTER(1),
-										&tinfo
+										&tinfo, fcinfo->flinfo
 										));
 }
 
@@ -195,6 +195,6 @@ gbt_macad_same(PG_FUNCTION_ARGS)
 	macKEY	   *b2 = (macKEY *) PG_GETARG_POINTER(1);
 	bool	   *result = (bool *) PG_GETARG_POINTER(2);
 
-	*result = gbt_num_same((void *) b1, (void *) b2, &tinfo);
+	*result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
 	PG_RETURN_POINTER(result);
 }
diff --git a/contrib/btree_gist/btree_macaddr8.c b/contrib/btree_gist/btree_macaddr8.c
index 13238ef..96afbcd 100644
--- a/contrib/btree_gist/btree_macaddr8.c
+++ b/contrib/btree_gist/btree_macaddr8.c
@@ -28,37 +28,37 @@ PG_FUNCTION_INFO_V1(gbt_macad8_same);
 
 
 static bool
-gbt_macad8gt(const void *a, const void *b)
+gbt_macad8gt(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return DatumGetBool(DirectFunctionCall2(macaddr8_gt, PointerGetDatum(a), PointerGetDatum(b)));
 }
 static bool
-gbt_macad8ge(const void *a, const void *b)
+gbt_macad8ge(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return DatumGetBool(DirectFunctionCall2(macaddr8_ge, PointerGetDatum(a), PointerGetDatum(b)));
 }
 
 static bool
-gbt_macad8eq(const void *a, const void *b)
+gbt_macad8eq(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return DatumGetBool(DirectFunctionCall2(macaddr8_eq, PointerGetDatum(a), PointerGetDatum(b)));
 }
 
 static bool
-gbt_macad8le(const void *a, const void *b)
+gbt_macad8le(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return DatumGetBool(DirectFunctionCall2(macaddr8_le, PointerGetDatum(a), PointerGetDatum(b)));
 }
 
 static bool
-gbt_macad8lt(const void *a, const void *b)
+gbt_macad8lt(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return DatumGetBool(DirectFunctionCall2(macaddr8_lt, PointerGetDatum(a), PointerGetDatum(b)));
 }
 
 
 static int
-gbt_macad8key_cmp(const void *a, const void *b)
+gbt_macad8key_cmp(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	mac8KEY    *ia = (mac8KEY *) (((const Nsrt *) a)->t);
 	mac8KEY    *ib = (mac8KEY *) (((const Nsrt *) b)->t);
@@ -142,7 +142,7 @@ gbt_macad8_consistent(PG_FUNCTION_ARGS)
 	key.upper = (GBT_NUMKEY *) &kkk->upper;
 
 	PG_RETURN_BOOL(
-				   gbt_num_consistent(&key, (void *) query, &strategy, GIST_LEAF(entry), &tinfo)
+				   gbt_num_consistent(&key, (void *) query, &strategy, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)
 		);
 }
 
@@ -154,7 +154,7 @@ gbt_macad8_union(PG_FUNCTION_ARGS)
 	void	   *out = palloc0(sizeof(mac8KEY));
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(mac8KEY);
-	PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo));
+	PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo, fcinfo->flinfo));
 }
 
 
@@ -184,7 +184,7 @@ gbt_macad8_picksplit(PG_FUNCTION_ARGS)
 	PG_RETURN_POINTER(gbt_num_picksplit(
 									(GistEntryVector *) PG_GETARG_POINTER(0),
 									  (GIST_SPLITVEC *) PG_GETARG_POINTER(1),
-										&tinfo
+										&tinfo, fcinfo->flinfo
 										));
 }
 
@@ -195,6 +195,6 @@ gbt_macad8_same(PG_FUNCTION_ARGS)
 	mac8KEY    *b2 = (mac8KEY *) PG_GETARG_POINTER(1);
 	bool	   *result = (bool *) PG_GETARG_POINTER(2);
 
-	*result = gbt_num_same((void *) b1, (void *) b2, &tinfo);
+	*result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
 	PG_RETURN_POINTER(result);
 }
diff --git a/contrib/btree_gist/btree_numeric.c b/contrib/btree_gist/btree_numeric.c
index 47b0020..62e8f9d 100644
--- a/contrib/btree_gist/btree_numeric.c
+++ b/contrib/btree_gist/btree_numeric.c
@@ -27,7 +27,7 @@ PG_FUNCTION_INFO_V1(gbt_numeric_same);
 /* define for comparison */
 
 static bool
-gbt_numeric_gt(const void *a, const void *b, Oid collation)
+gbt_numeric_gt(const void *a, const void *b, FmgrInfo *flinfo, Oid collation)
 {
 	return DatumGetBool(DirectFunctionCall2(numeric_gt,
 											PointerGetDatum(a),
@@ -35,7 +35,7 @@ gbt_numeric_gt(const void *a, const void *b, Oid collation)
 }
 
 static bool
-gbt_numeric_ge(const void *a, const void *b, Oid collation)
+gbt_numeric_ge(const void *a, const void *b, FmgrInfo *flinfo, Oid collation)
 {
 	return DatumGetBool(DirectFunctionCall2(numeric_ge,
 											PointerGetDatum(a),
@@ -43,7 +43,7 @@ gbt_numeric_ge(const void *a, const void *b, Oid collation)
 }
 
 static bool
-gbt_numeric_eq(const void *a, const void *b, Oid collation)
+gbt_numeric_eq(const void *a, const void *b, FmgrInfo *flinfo, Oid collation)
 {
 	return DatumGetBool(DirectFunctionCall2(numeric_eq,
 											PointerGetDatum(a),
@@ -51,7 +51,7 @@ gbt_numeric_eq(const void *a, const void *b, Oid collation)
 }
 
 static bool
-gbt_numeric_le(const void *a, const void *b, Oid collation)
+gbt_numeric_le(const void *a, const void *b, FmgrInfo *flinfo, Oid collation)
 {
 	return DatumGetBool(DirectFunctionCall2(numeric_le,
 											PointerGetDatum(a),
@@ -59,7 +59,7 @@ gbt_numeric_le(const void *a, const void *b, Oid collation)
 }
 
 static bool
-gbt_numeric_lt(const void *a, const void *b, Oid collation)
+gbt_numeric_lt(const void *a, const void *b, FmgrInfo *flinfo, Oid collation)
 {
 	return DatumGetBool(DirectFunctionCall2(numeric_lt,
 											PointerGetDatum(a),
@@ -67,7 +67,7 @@ gbt_numeric_lt(const void *a, const void *b, Oid collation)
 }
 
 static int32
-gbt_numeric_cmp(const void *a, const void *b, Oid collation)
+gbt_numeric_cmp(const void *a, const void *b, FmgrInfo *flinfo, Oid collation)
 {
 	return DatumGetInt32(DirectFunctionCall2(numeric_cmp,
 											 PointerGetDatum(a),
@@ -122,7 +122,7 @@ gbt_numeric_consistent(PG_FUNCTION_ARGS)
 	*recheck = false;
 
 	retval = gbt_var_consistent(&r, query, strategy, PG_GET_COLLATION(),
-								GIST_LEAF(entry), &tinfo);
+								GIST_LEAF(entry), &tinfo, fcinfo->flinfo);
 	PG_RETURN_BOOL(retval);
 }
 
@@ -135,7 +135,7 @@ gbt_numeric_union(PG_FUNCTION_ARGS)
 	int32	   *size = (int *) PG_GETARG_POINTER(1);
 
 	PG_RETURN_POINTER(gbt_var_union(entryvec, size, PG_GET_COLLATION(),
-									&tinfo));
+									&tinfo, fcinfo->flinfo));
 }
 
 
@@ -146,7 +146,7 @@ gbt_numeric_same(PG_FUNCTION_ARGS)
 	Datum		d2 = PG_GETARG_DATUM(1);
 	bool	   *result = (bool *) PG_GETARG_POINTER(2);
 
-	*result = gbt_var_same(d1, d2, PG_GET_COLLATION(), &tinfo);
+	*result = gbt_var_same(d1, d2, PG_GET_COLLATION(), &tinfo, fcinfo->flinfo);
 	PG_RETURN_POINTER(result);
 }
 
@@ -171,7 +171,7 @@ gbt_numeric_penalty(PG_FUNCTION_ARGS)
 
 	rk = gbt_var_key_readable(org);
 	uni = PointerGetDatum(gbt_var_key_copy(&rk));
-	gbt_var_bin_union(&uni, newe, PG_GET_COLLATION(), &tinfo);
+	gbt_var_bin_union(&uni, newe, PG_GET_COLLATION(), &tinfo, fcinfo->flinfo);
 	ok = gbt_var_key_readable(org);
 	uk = gbt_var_key_readable((GBT_VARKEY *) DatumGetPointer(uni));
 
@@ -233,6 +233,6 @@ gbt_numeric_picksplit(PG_FUNCTION_ARGS)
 	GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
 
 	gbt_var_picksplit(entryvec, v, PG_GET_COLLATION(),
-					  &tinfo);
+					  &tinfo, fcinfo->flinfo);
 	PG_RETURN_POINTER(v);
 }
diff --git a/contrib/btree_gist/btree_oid.c b/contrib/btree_gist/btree_oid.c
index ac61a76..e588faa 100644
--- a/contrib/btree_gist/btree_oid.c
+++ b/contrib/btree_gist/btree_oid.c
@@ -26,33 +26,33 @@ PG_FUNCTION_INFO_V1(gbt_oid_same);
 
 
 static bool
-gbt_oidgt(const void *a, const void *b)
+gbt_oidgt(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return (*((const Oid *) a) > *((const Oid *) b));
 }
 static bool
-gbt_oidge(const void *a, const void *b)
+gbt_oidge(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return (*((const Oid *) a) >= *((const Oid *) b));
 }
 static bool
-gbt_oideq(const void *a, const void *b)
+gbt_oideq(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return (*((const Oid *) a) == *((const Oid *) b));
 }
 static bool
-gbt_oidle(const void *a, const void *b)
+gbt_oidle(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return (*((const Oid *) a) <= *((const Oid *) b));
 }
 static bool
-gbt_oidlt(const void *a, const void *b)
+gbt_oidlt(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return (*((const Oid *) a) < *((const Oid *) b));
 }
 
 static int
-gbt_oidkey_cmp(const void *a, const void *b)
+gbt_oidkey_cmp(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	oidKEY	   *ia = (oidKEY *) (((const Nsrt *) a)->t);
 	oidKEY	   *ib = (oidKEY *) (((const Nsrt *) b)->t);
@@ -69,7 +69,7 @@ gbt_oidkey_cmp(const void *a, const void *b)
 }
 
 static float8
-gbt_oid_dist(const void *a, const void *b)
+gbt_oid_dist(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	Oid			aa = *(const Oid *) a;
 	Oid			bb = *(const Oid *) b;
@@ -152,7 +152,7 @@ gbt_oid_consistent(PG_FUNCTION_ARGS)
 	key.upper = (GBT_NUMKEY *) &kkk->upper;
 
 	PG_RETURN_BOOL(
-				   gbt_num_consistent(&key, (void *) &query, &strategy, GIST_LEAF(entry), &tinfo)
+				   gbt_num_consistent(&key, (void *) &query, &strategy, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)
 		);
 }
 
@@ -171,7 +171,7 @@ gbt_oid_distance(PG_FUNCTION_ARGS)
 	key.upper = (GBT_NUMKEY *) &kkk->upper;
 
 	PG_RETURN_FLOAT8(
-			gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo)
+			gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)
 		);
 }
 
@@ -183,7 +183,7 @@ gbt_oid_union(PG_FUNCTION_ARGS)
 	void	   *out = palloc(sizeof(oidKEY));
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(oidKEY);
-	PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo));
+	PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo, fcinfo->flinfo));
 }
 
 
@@ -205,7 +205,7 @@ gbt_oid_picksplit(PG_FUNCTION_ARGS)
 	PG_RETURN_POINTER(gbt_num_picksplit(
 									(GistEntryVector *) PG_GETARG_POINTER(0),
 									  (GIST_SPLITVEC *) PG_GETARG_POINTER(1),
-										&tinfo
+										&tinfo, fcinfo->flinfo
 										));
 }
 
@@ -216,6 +216,6 @@ gbt_oid_same(PG_FUNCTION_ARGS)
 	oidKEY	   *b2 = (oidKEY *) PG_GETARG_POINTER(1);
 	bool	   *result = (bool *) PG_GETARG_POINTER(2);
 
-	*result = gbt_num_same((void *) b1, (void *) b2, &tinfo);
+	*result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
 	PG_RETURN_POINTER(result);
 }
diff --git a/contrib/btree_gist/btree_text.c b/contrib/btree_gist/btree_text.c
index 2e00cb6..51fc310 100644
--- a/contrib/btree_gist/btree_text.c
+++ b/contrib/btree_gist/btree_text.c
@@ -23,7 +23,7 @@ PG_FUNCTION_INFO_V1(gbt_text_same);
 /* define for comparison */
 
 static bool
-gbt_textgt(const void *a, const void *b, Oid collation)
+gbt_textgt(const void *a, const void *b, FmgrInfo *flinfo, Oid collation)
 {
 	return DatumGetBool(DirectFunctionCall2Coll(text_gt,
 												collation,
@@ -32,7 +32,7 @@ gbt_textgt(const void *a, const void *b, Oid collation)
 }
 
 static bool
-gbt_textge(const void *a, const void *b, Oid collation)
+gbt_textge(const void *a, const void *b, FmgrInfo *flinfo, Oid collation)
 {
 	return DatumGetBool(DirectFunctionCall2Coll(text_ge,
 												collation,
@@ -41,7 +41,7 @@ gbt_textge(const void *a, const void *b, Oid collation)
 }
 
 static bool
-gbt_texteq(const void *a, const void *b, Oid collation)
+gbt_texteq(const void *a, const void *b, FmgrInfo *flinfo, Oid collation)
 {
 	return DatumGetBool(DirectFunctionCall2Coll(texteq,
 												collation,
@@ -50,7 +50,7 @@ gbt_texteq(const void *a, const void *b, Oid collation)
 }
 
 static bool
-gbt_textle(const void *a, const void *b, Oid collation)
+gbt_textle(const void *a, const void *b, FmgrInfo *flinfo, Oid collation)
 {
 	return DatumGetBool(DirectFunctionCall2Coll(text_le,
 												collation,
@@ -59,7 +59,7 @@ gbt_textle(const void *a, const void *b, Oid collation)
 }
 
 static bool
-gbt_textlt(const void *a, const void *b, Oid collation)
+gbt_textlt(const void *a, const void *b, FmgrInfo *flinfo, Oid collation)
 {
 	return DatumGetBool(DirectFunctionCall2Coll(text_lt,
 												collation,
@@ -68,7 +68,7 @@ gbt_textlt(const void *a, const void *b, Oid collation)
 }
 
 static int32
-gbt_textcmp(const void *a, const void *b, Oid collation)
+gbt_textcmp(const void *a, const void *b, FmgrInfo *flinfo, Oid collation)
 {
 	return DatumGetInt32(DirectFunctionCall2Coll(bttextcmp,
 												 collation,
@@ -161,7 +161,7 @@ gbt_text_consistent(PG_FUNCTION_ARGS)
 	}
 
 	retval = gbt_var_consistent(&r, query, strategy, PG_GET_COLLATION(),
-								GIST_LEAF(entry), &tinfo);
+								GIST_LEAF(entry), &tinfo, fcinfo->flinfo);
 
 	PG_RETURN_BOOL(retval);
 }
@@ -190,7 +190,7 @@ gbt_bpchar_consistent(PG_FUNCTION_ARGS)
 	}
 
 	retval = gbt_var_consistent(&r, trim, strategy, PG_GET_COLLATION(),
-								GIST_LEAF(entry), &tinfo);
+								GIST_LEAF(entry), &tinfo, fcinfo->flinfo);
 	PG_RETURN_BOOL(retval);
 }
 
@@ -202,7 +202,7 @@ gbt_text_union(PG_FUNCTION_ARGS)
 	int32	   *size = (int *) PG_GETARG_POINTER(1);
 
 	PG_RETURN_POINTER(gbt_var_union(entryvec, size, PG_GET_COLLATION(),
-									&tinfo));
+									&tinfo, fcinfo->flinfo));
 }
 
 
@@ -213,7 +213,7 @@ gbt_text_picksplit(PG_FUNCTION_ARGS)
 	GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
 
 	gbt_var_picksplit(entryvec, v, PG_GET_COLLATION(),
-					  &tinfo);
+					  &tinfo, fcinfo->flinfo);
 	PG_RETURN_POINTER(v);
 }
 
@@ -224,7 +224,7 @@ gbt_text_same(PG_FUNCTION_ARGS)
 	Datum		d2 = PG_GETARG_DATUM(1);
 	bool	   *result = (bool *) PG_GETARG_POINTER(2);
 
-	*result = gbt_var_same(d1, d2, PG_GET_COLLATION(), &tinfo);
+	*result = gbt_var_same(d1, d2, PG_GET_COLLATION(), &tinfo, fcinfo->flinfo);
 	PG_RETURN_POINTER(result);
 }
 
@@ -237,5 +237,5 @@ gbt_text_penalty(PG_FUNCTION_ARGS)
 	float	   *result = (float *) PG_GETARG_POINTER(2);
 
 	PG_RETURN_POINTER(gbt_var_penalty(result, o, n, PG_GET_COLLATION(),
-									  &tinfo));
+									  &tinfo, fcinfo->flinfo));
 }
diff --git a/contrib/btree_gist/btree_time.c b/contrib/btree_gist/btree_time.c
index 959b282..a4a1ad5 100644
--- a/contrib/btree_gist/btree_time.c
+++ b/contrib/btree_gist/btree_time.c
@@ -38,7 +38,7 @@ PG_FUNCTION_INFO_V1(gbt_time_same);
 
 
 static bool
-gbt_timegt(const void *a, const void *b)
+gbt_timegt(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	const TimeADT *aa = (const TimeADT *) a;
 	const TimeADT *bb = (const TimeADT *) b;
@@ -49,7 +49,7 @@ gbt_timegt(const void *a, const void *b)
 }
 
 static bool
-gbt_timege(const void *a, const void *b)
+gbt_timege(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	const TimeADT *aa = (const TimeADT *) a;
 	const TimeADT *bb = (const TimeADT *) b;
@@ -60,7 +60,7 @@ gbt_timege(const void *a, const void *b)
 }
 
 static bool
-gbt_timeeq(const void *a, const void *b)
+gbt_timeeq(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	const TimeADT *aa = (const TimeADT *) a;
 	const TimeADT *bb = (const TimeADT *) b;
@@ -71,7 +71,7 @@ gbt_timeeq(const void *a, const void *b)
 }
 
 static bool
-gbt_timele(const void *a, const void *b)
+gbt_timele(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	const TimeADT *aa = (const TimeADT *) a;
 	const TimeADT *bb = (const TimeADT *) b;
@@ -82,7 +82,7 @@ gbt_timele(const void *a, const void *b)
 }
 
 static bool
-gbt_timelt(const void *a, const void *b)
+gbt_timelt(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	const TimeADT *aa = (const TimeADT *) a;
 	const TimeADT *bb = (const TimeADT *) b;
@@ -95,7 +95,7 @@ gbt_timelt(const void *a, const void *b)
 
 
 static int
-gbt_timekey_cmp(const void *a, const void *b)
+gbt_timekey_cmp(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	timeKEY    *ia = (timeKEY *) (((const Nsrt *) a)->t);
 	timeKEY    *ib = (timeKEY *) (((const Nsrt *) b)->t);
@@ -109,7 +109,7 @@ gbt_timekey_cmp(const void *a, const void *b)
 }
 
 static float8
-gbt_time_dist(const void *a, const void *b)
+gbt_time_dist(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	const TimeADT *aa = (const TimeADT *) a;
 	const TimeADT *bb = (const TimeADT *) b;
@@ -217,7 +217,7 @@ gbt_time_consistent(PG_FUNCTION_ARGS)
 	key.upper = (GBT_NUMKEY *) &kkk->upper;
 
 	PG_RETURN_BOOL(
-				   gbt_num_consistent(&key, (void *) &query, &strategy, GIST_LEAF(entry), &tinfo)
+				   gbt_num_consistent(&key, (void *) &query, &strategy, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)
 		);
 }
 
@@ -235,7 +235,7 @@ gbt_time_distance(PG_FUNCTION_ARGS)
 	key.upper = (GBT_NUMKEY *) &kkk->upper;
 
 	PG_RETURN_FLOAT8(
-			gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo)
+			gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)
 		);
 }
 
@@ -261,7 +261,7 @@ gbt_timetz_consistent(PG_FUNCTION_ARGS)
 	key.upper = (GBT_NUMKEY *) &kkk->upper;
 
 	PG_RETURN_BOOL(
-				   gbt_num_consistent(&key, (void *) &qqq, &strategy, GIST_LEAF(entry), &tinfo)
+				   gbt_num_consistent(&key, (void *) &qqq, &strategy, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)
 		);
 }
 
@@ -273,7 +273,7 @@ gbt_time_union(PG_FUNCTION_ARGS)
 	void	   *out = palloc(sizeof(timeKEY));
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(timeKEY);
-	PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo));
+	PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo, fcinfo->flinfo));
 }
 
 
@@ -326,7 +326,7 @@ gbt_time_picksplit(PG_FUNCTION_ARGS)
 	PG_RETURN_POINTER(gbt_num_picksplit(
 									(GistEntryVector *) PG_GETARG_POINTER(0),
 									  (GIST_SPLITVEC *) PG_GETARG_POINTER(1),
-										&tinfo
+										&tinfo, fcinfo->flinfo
 										));
 }
 
@@ -337,6 +337,6 @@ gbt_time_same(PG_FUNCTION_ARGS)
 	timeKEY    *b2 = (timeKEY *) PG_GETARG_POINTER(1);
 	bool	   *result = (bool *) PG_GETARG_POINTER(2);
 
-	*result = gbt_num_same((void *) b1, (void *) b2, &tinfo);
+	*result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
 	PG_RETURN_POINTER(result);
 }
diff --git a/contrib/btree_gist/btree_ts.c b/contrib/btree_gist/btree_ts.c
index 97408f5..13bc394 100644
--- a/contrib/btree_gist/btree_ts.c
+++ b/contrib/btree_gist/btree_ts.c
@@ -40,7 +40,7 @@ PG_FUNCTION_INFO_V1(gbt_ts_same);
 
 
 static bool
-gbt_tsgt(const void *a, const void *b)
+gbt_tsgt(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	const Timestamp *aa = (const Timestamp *) a;
 	const Timestamp *bb = (const Timestamp *) b;
@@ -51,7 +51,7 @@ gbt_tsgt(const void *a, const void *b)
 }
 
 static bool
-gbt_tsge(const void *a, const void *b)
+gbt_tsge(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	const Timestamp *aa = (const Timestamp *) a;
 	const Timestamp *bb = (const Timestamp *) b;
@@ -62,7 +62,7 @@ gbt_tsge(const void *a, const void *b)
 }
 
 static bool
-gbt_tseq(const void *a, const void *b)
+gbt_tseq(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	const Timestamp *aa = (const Timestamp *) a;
 	const Timestamp *bb = (const Timestamp *) b;
@@ -73,7 +73,7 @@ gbt_tseq(const void *a, const void *b)
 }
 
 static bool
-gbt_tsle(const void *a, const void *b)
+gbt_tsle(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	const Timestamp *aa = (const Timestamp *) a;
 	const Timestamp *bb = (const Timestamp *) b;
@@ -84,7 +84,7 @@ gbt_tsle(const void *a, const void *b)
 }
 
 static bool
-gbt_tslt(const void *a, const void *b)
+gbt_tslt(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	const Timestamp *aa = (const Timestamp *) a;
 	const Timestamp *bb = (const Timestamp *) b;
@@ -96,7 +96,7 @@ gbt_tslt(const void *a, const void *b)
 
 
 static int
-gbt_tskey_cmp(const void *a, const void *b)
+gbt_tskey_cmp(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	tsKEY	   *ia = (tsKEY *) (((const Nsrt *) a)->t);
 	tsKEY	   *ib = (tsKEY *) (((const Nsrt *) b)->t);
@@ -110,7 +110,7 @@ gbt_tskey_cmp(const void *a, const void *b)
 }
 
 static float8
-gbt_ts_dist(const void *a, const void *b)
+gbt_ts_dist(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	const Timestamp *aa = (const Timestamp *) a;
 	const Timestamp *bb = (const Timestamp *) b;
@@ -265,7 +265,7 @@ gbt_ts_consistent(PG_FUNCTION_ARGS)
 	key.upper = (GBT_NUMKEY *) &kkk->upper;
 
 	PG_RETURN_BOOL(
-				   gbt_num_consistent(&key, (void *) &query, &strategy, GIST_LEAF(entry), &tinfo)
+				   gbt_num_consistent(&key, (void *) &query, &strategy, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)
 		);
 }
 
@@ -283,7 +283,7 @@ gbt_ts_distance(PG_FUNCTION_ARGS)
 	key.upper = (GBT_NUMKEY *) &kkk->upper;
 
 	PG_RETURN_FLOAT8(
-			gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo)
+			gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)
 		);
 }
 
@@ -308,7 +308,7 @@ gbt_tstz_consistent(PG_FUNCTION_ARGS)
 	qqq = tstz_to_ts_gmt(query);
 
 	PG_RETURN_BOOL(
-				   gbt_num_consistent(&key, (void *) &qqq, &strategy, GIST_LEAF(entry), &tinfo)
+				   gbt_num_consistent(&key, (void *) &qqq, &strategy, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)
 		);
 }
 
@@ -328,7 +328,7 @@ gbt_tstz_distance(PG_FUNCTION_ARGS)
 	qqq = tstz_to_ts_gmt(query);
 
 	PG_RETURN_FLOAT8(
-			  gbt_num_distance(&key, (void *) &qqq, GIST_LEAF(entry), &tinfo)
+			  gbt_num_distance(&key, (void *) &qqq, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)
 		);
 }
 
@@ -340,7 +340,7 @@ gbt_ts_union(PG_FUNCTION_ARGS)
 	void	   *out = palloc(sizeof(tsKEY));
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(tsKEY);
-	PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo));
+	PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo, fcinfo->flinfo));
 }
 
 
@@ -389,7 +389,7 @@ gbt_ts_picksplit(PG_FUNCTION_ARGS)
 	PG_RETURN_POINTER(gbt_num_picksplit(
 									(GistEntryVector *) PG_GETARG_POINTER(0),
 									  (GIST_SPLITVEC *) PG_GETARG_POINTER(1),
-										&tinfo
+										&tinfo, fcinfo->flinfo
 										));
 }
 
@@ -400,6 +400,6 @@ gbt_ts_same(PG_FUNCTION_ARGS)
 	tsKEY	   *b2 = (tsKEY *) PG_GETARG_POINTER(1);
 	bool	   *result = (bool *) PG_GETARG_POINTER(2);
 
-	*result = gbt_num_same((void *) b1, (void *) b2, &tinfo);
+	*result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
 	PG_RETURN_POINTER(result);
 }
diff --git a/contrib/btree_gist/btree_utils_num.c b/contrib/btree_gist/btree_utils_num.c
index 99cb41f..d4fee91 100644
--- a/contrib/btree_gist/btree_utils_num.c
+++ b/contrib/btree_gist/btree_utils_num.c
@@ -48,6 +48,7 @@ gbt_num_compress(GISTENTRY *entry, const gbtree_ninfo *tinfo)
 				leaf = &v.i8;
 				break;
 			case gbt_t_oid:
+			case gbt_t_enum:
 				v.i4 = DatumGetObjectId(entry->key);
 				leaf = &v.i4;
 				break;
@@ -122,6 +123,7 @@ gbt_num_fetch(GISTENTRY *entry, const gbtree_ninfo *tinfo)
 			datum = Int64GetDatum(*(int64 *) entry->key);
 			break;
 		case gbt_t_oid:
+		case gbt_t_enum:
 			datum = ObjectIdGetDatum(*(Oid *) entry->key);
 			break;
 		case gbt_t_float4:
@@ -159,7 +161,7 @@ gbt_num_fetch(GISTENTRY *entry, const gbtree_ninfo *tinfo)
 */
 
 void *
-gbt_num_union(GBT_NUMKEY *out, const GistEntryVector *entryvec, const gbtree_ninfo *tinfo)
+gbt_num_union(GBT_NUMKEY *out, const GistEntryVector *entryvec, const gbtree_ninfo *tinfo, FmgrInfo *flinfo)
 {
 	int			i,
 				numranges;
@@ -181,9 +183,9 @@ gbt_num_union(GBT_NUMKEY *out, const GistEntryVector *entryvec, const gbtree_nin
 		cur = (GBT_NUMKEY *) DatumGetPointer((entryvec->vector[i].key));
 		c.lower = &cur[0];
 		c.upper = &cur[tinfo->size];
-		if ((*tinfo->f_gt) (o.lower, c.lower))	/* out->lower > cur->lower */
+		if ((*tinfo->f_gt) (o.lower, c.lower, flinfo))	/* out->lower > cur->lower */
 			memcpy((void *) o.lower, (void *) c.lower, tinfo->size);
-		if ((*tinfo->f_lt) (o.upper, c.upper))	/* out->upper < cur->upper */
+		if ((*tinfo->f_lt) (o.upper, c.upper, flinfo))	/* out->upper < cur->upper */
 			memcpy((void *) o.upper, (void *) c.upper, tinfo->size);
 	}
 
@@ -197,7 +199,7 @@ gbt_num_union(GBT_NUMKEY *out, const GistEntryVector *entryvec, const gbtree_nin
 */
 
 bool
-gbt_num_same(const GBT_NUMKEY *a, const GBT_NUMKEY *b, const gbtree_ninfo *tinfo)
+gbt_num_same(const GBT_NUMKEY *a, const GBT_NUMKEY *b, const gbtree_ninfo *tinfo, FmgrInfo *flinfo)
 {
 	GBT_NUMKEY_R b1,
 				b2;
@@ -207,13 +209,13 @@ gbt_num_same(const GBT_NUMKEY *a, const GBT_NUMKEY *b, const gbtree_ninfo *tinfo
 	b2.lower = &(((GBT_NUMKEY *) b)[0]);
 	b2.upper = &(((GBT_NUMKEY *) b)[tinfo->size]);
 
-	return ((*tinfo->f_eq) (b1.lower, b2.lower) &&
-			(*tinfo->f_eq) (b1.upper, b2.upper));
+	return ((*tinfo->f_eq) (b1.lower, b2.lower, flinfo) &&
+			(*tinfo->f_eq) (b1.upper, b2.upper, flinfo));
 }
 
 
 void
-gbt_num_bin_union(Datum *u, GBT_NUMKEY *e, const gbtree_ninfo *tinfo)
+gbt_num_bin_union(Datum *u, GBT_NUMKEY *e, const gbtree_ninfo *tinfo, FmgrInfo *flinfo)
 {
 	GBT_NUMKEY_R rd;
 
@@ -232,9 +234,9 @@ gbt_num_bin_union(Datum *u, GBT_NUMKEY *e, const gbtree_ninfo *tinfo)
 
 		ur.lower = &(((GBT_NUMKEY *) DatumGetPointer(*u))[0]);
 		ur.upper = &(((GBT_NUMKEY *) DatumGetPointer(*u))[tinfo->size]);
-		if ((*tinfo->f_gt) ((void *) ur.lower, (void *) rd.lower))
+		if ((*tinfo->f_gt) ((void *) ur.lower, (void *) rd.lower, flinfo))
 			memcpy((void *) ur.lower, (void *) rd.lower, tinfo->size);
-		if ((*tinfo->f_lt) ((void *) ur.upper, (void *) rd.upper))
+		if ((*tinfo->f_lt) ((void *) ur.upper, (void *) rd.upper, flinfo))
 			memcpy((void *) ur.upper, (void *) rd.upper, tinfo->size);
 	}
 }
@@ -252,39 +254,40 @@ gbt_num_consistent(const GBT_NUMKEY_R *key,
 				   const void *query,
 				   const StrategyNumber *strategy,
 				   bool is_leaf,
-				   const gbtree_ninfo *tinfo)
+				   const gbtree_ninfo *tinfo,
+				   FmgrInfo *flinfo)
 {
 	bool		retval;
 
 	switch (*strategy)
 	{
 		case BTLessEqualStrategyNumber:
-			retval = (*tinfo->f_ge) (query, key->lower);
+			retval = (*tinfo->f_ge) (query, key->lower, flinfo);
 			break;
 		case BTLessStrategyNumber:
 			if (is_leaf)
-				retval = (*tinfo->f_gt) (query, key->lower);
+				retval = (*tinfo->f_gt) (query, key->lower, flinfo);
 			else
-				retval = (*tinfo->f_ge) (query, key->lower);
+				retval = (*tinfo->f_ge) (query, key->lower, flinfo);
 			break;
 		case BTEqualStrategyNumber:
 			if (is_leaf)
-				retval = (*tinfo->f_eq) (query, key->lower);
+				retval = (*tinfo->f_eq) (query, key->lower, flinfo);
 			else
-				retval = ((*tinfo->f_le) (key->lower, query) && (*tinfo->f_le) (query, key->upper)) ? true : false;
+				retval = ((*tinfo->f_le) (key->lower, query, flinfo) && (*tinfo->f_le) (query, key->upper, flinfo)) ? true : false;
 			break;
 		case BTGreaterStrategyNumber:
 			if (is_leaf)
-				retval = (*tinfo->f_lt) (query, key->upper);
+				retval = (*tinfo->f_lt) (query, key->upper, flinfo);
 			else
-				retval = (*tinfo->f_le) (query, key->upper);
+				retval = (*tinfo->f_le) (query, key->upper, flinfo);
 			break;
 		case BTGreaterEqualStrategyNumber:
-			retval = (*tinfo->f_le) (query, key->upper);
+			retval = (*tinfo->f_le) (query, key->upper, flinfo);
 			break;
 		case BtreeGistNotEqualStrategyNumber:
-			retval = (!((*tinfo->f_eq) (query, key->lower) &&
-						(*tinfo->f_eq) (query, key->upper))) ? true : false;
+			retval = (!((*tinfo->f_eq) (query, key->lower, flinfo) &&
+						(*tinfo->f_eq) (query, key->upper, flinfo))) ? true : false;
 			break;
 		default:
 			retval = false;
@@ -302,17 +305,18 @@ float8
 gbt_num_distance(const GBT_NUMKEY_R *key,
 				 const void *query,
 				 bool is_leaf,
-				 const gbtree_ninfo *tinfo)
+				 const gbtree_ninfo *tinfo,
+				 FmgrInfo *flinfo)
 {
 	float8		retval;
 
 	if (tinfo->f_dist == NULL)
 		elog(ERROR, "KNN search is not supported for btree_gist type %d",
 			 (int) tinfo->t);
-	if (tinfo->f_le(query, key->lower))
-		retval = tinfo->f_dist(query, key->lower);
-	else if (tinfo->f_ge(query, key->upper))
-		retval = tinfo->f_dist(query, key->upper);
+	if (tinfo->f_le(query, key->lower, flinfo))
+		retval = tinfo->f_dist(query, key->lower, flinfo);
+	else if (tinfo->f_ge(query, key->upper, flinfo))
+		retval = tinfo->f_dist(query, key->upper, flinfo);
 	else
 		retval = 0.0;
 
@@ -322,7 +326,7 @@ gbt_num_distance(const GBT_NUMKEY_R *key,
 
 GIST_SPLITVEC *
 gbt_num_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v,
-				  const gbtree_ninfo *tinfo)
+				  const gbtree_ninfo *tinfo, FmgrInfo *flinfo)
 {
 	OffsetNumber i,
 				maxoff = entryvec->n - 1;
@@ -345,7 +349,7 @@ gbt_num_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v,
 		arr[i].t = (GBT_NUMKEY *) DatumGetPointer((entryvec->vector[i].key));
 		arr[i].i = i;
 	}
-	qsort((void *) &arr[FirstOffsetNumber], maxoff - FirstOffsetNumber + 1, sizeof(Nsrt), tinfo->f_cmp);
+	qsort_arg((void *) &arr[FirstOffsetNumber], maxoff - FirstOffsetNumber + 1, sizeof(Nsrt), (qsort_arg_comparator) tinfo->f_cmp, (void *) flinfo);
 
 	/* We do simply create two parts */
 
@@ -353,13 +357,13 @@ gbt_num_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v,
 	{
 		if (i <= (maxoff - FirstOffsetNumber + 1) / 2)
 		{
-			gbt_num_bin_union(&v->spl_ldatum, arr[i].t, tinfo);
+			gbt_num_bin_union(&v->spl_ldatum, arr[i].t, tinfo, flinfo);
 			v->spl_left[v->spl_nleft] = arr[i].i;
 			v->spl_nleft++;
 		}
 		else
 		{
-			gbt_num_bin_union(&v->spl_rdatum, arr[i].t, tinfo);
+			gbt_num_bin_union(&v->spl_rdatum, arr[i].t, tinfo, flinfo);
 			v->spl_right[v->spl_nright] = arr[i].i;
 			v->spl_nright++;
 		}
diff --git a/contrib/btree_gist/btree_utils_num.h b/contrib/btree_gist/btree_utils_num.h
index 67d4968..17561fa 100644
--- a/contrib/btree_gist/btree_utils_num.h
+++ b/contrib/btree_gist/btree_utils_num.h
@@ -42,13 +42,13 @@ typedef struct
 
 	/* Methods */
 
-	bool		(*f_gt) (const void *, const void *);	/* greater than */
-	bool		(*f_ge) (const void *, const void *);	/* greater or equal */
-	bool		(*f_eq) (const void *, const void *);	/* equal */
-	bool		(*f_le) (const void *, const void *);	/* less or equal */
-	bool		(*f_lt) (const void *, const void *);	/* less than */
-	int			(*f_cmp) (const void *, const void *);	/* key compare function */
-	float8		(*f_dist) (const void *, const void *); /* key distance function */
+	bool		(*f_gt) (const void *, const void *, FmgrInfo *);	/* greater than */
+	bool		(*f_ge) (const void *, const void *, FmgrInfo *);	/* greater or equal */
+	bool		(*f_eq) (const void *, const void *, FmgrInfo *);	/* equal */
+	bool		(*f_le) (const void *, const void *, FmgrInfo *);	/* less or equal */
+	bool		(*f_lt) (const void *, const void *, FmgrInfo *);	/* less than */
+	int			(*f_cmp) (const void *, const void *, FmgrInfo *);	/* key compare function */
+	float8		(*f_dist) (const void *, const void *, FmgrInfo *); /* key distance function */
 } gbtree_ninfo;
 
 
@@ -113,25 +113,25 @@ extern Interval *abs_interval(Interval *a);
 
 extern bool gbt_num_consistent(const GBT_NUMKEY_R *key, const void *query,
 				   const StrategyNumber *strategy, bool is_leaf,
-				   const gbtree_ninfo *tinfo);
+				   const gbtree_ninfo *tinfo, FmgrInfo *flinfo);
 
 extern float8 gbt_num_distance(const GBT_NUMKEY_R *key, const void *query,
-				 bool is_leaf, const gbtree_ninfo *tinfo);
+				 bool is_leaf, const gbtree_ninfo *tinfo, FmgrInfo *flinfo);
 
 extern GIST_SPLITVEC *gbt_num_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v,
-				  const gbtree_ninfo *tinfo);
+				  const gbtree_ninfo *tinfo, FmgrInfo *flinfo);
 
 extern GISTENTRY *gbt_num_compress(GISTENTRY *entry, const gbtree_ninfo *tinfo);
 
 extern GISTENTRY *gbt_num_fetch(GISTENTRY *entry, const gbtree_ninfo *tinfo);
 
 extern void *gbt_num_union(GBT_NUMKEY *out, const GistEntryVector *entryvec,
-			  const gbtree_ninfo *tinfo);
+			  const gbtree_ninfo *tinfo, FmgrInfo *flinfo);
 
 extern bool gbt_num_same(const GBT_NUMKEY *a, const GBT_NUMKEY *b,
-			 const gbtree_ninfo *tinfo);
+			 const gbtree_ninfo *tinfo, FmgrInfo *flinfo);
 
 extern void gbt_num_bin_union(Datum *u, GBT_NUMKEY *e,
-				  const gbtree_ninfo *tinfo);
+				  const gbtree_ninfo *tinfo, FmgrInfo *flinfo);
 
 #endif
diff --git a/contrib/btree_gist/btree_utils_var.c b/contrib/btree_gist/btree_utils_var.c
index 70b3794..16de893 100644
--- a/contrib/btree_gist/btree_utils_var.c
+++ b/contrib/btree_gist/btree_utils_var.c
@@ -25,6 +25,7 @@ typedef struct
 {
 	const gbtree_vinfo *tinfo;
 	Oid			collation;
+	FmgrInfo *flinfo;
 } gbt_vsrt_arg;
 
 
@@ -103,12 +104,12 @@ gbt_var_key_copy(const GBT_VARKEY_R *u)
 
 
 static GBT_VARKEY *
-gbt_var_leaf2node(GBT_VARKEY *leaf, const gbtree_vinfo *tinfo)
+gbt_var_leaf2node(GBT_VARKEY *leaf, const gbtree_vinfo *tinfo, FmgrInfo *flinfo)
 {
 	GBT_VARKEY *out = leaf;
 
 	if (tinfo->f_l2n)
-		out = (*tinfo->f_l2n) (leaf);
+		out = (*tinfo->f_l2n) (leaf, flinfo);
 
 	return out;
 }
@@ -232,7 +233,7 @@ gbt_var_node_truncate(const GBT_VARKEY *node, int32 cpf_length, const gbtree_vin
 
 void
 gbt_var_bin_union(Datum *u, GBT_VARKEY *e, Oid collation,
-				  const gbtree_vinfo *tinfo)
+				  const gbtree_vinfo *tinfo, FmgrInfo *flinfo)
 {
 	GBT_VARKEY_R eo = gbt_var_key_readable(e);
 	GBT_VARKEY_R nr;
@@ -241,7 +242,7 @@ gbt_var_bin_union(Datum *u, GBT_VARKEY *e, Oid collation,
 	{
 		GBT_VARKEY *tmp;
 
-		tmp = gbt_var_leaf2node(e, tinfo);
+		tmp = gbt_var_leaf2node(e, tinfo, flinfo);
 		if (tmp != e)
 			eo = gbt_var_key_readable(tmp);
 	}
@@ -254,13 +255,13 @@ gbt_var_bin_union(Datum *u, GBT_VARKEY *e, Oid collation,
 		nr.lower = ro.lower;
 		nr.upper = ro.upper;
 
-		if ((*tinfo->f_cmp) (ro.lower, eo.lower, collation) > 0)
+		if ((*tinfo->f_cmp) (ro.lower, eo.lower, flinfo, collation) > 0)
 		{
 			nr.lower = eo.lower;
 			update = true;
 		}
 
-		if ((*tinfo->f_cmp) (ro.upper, eo.upper, collation) < 0)
+		if ((*tinfo->f_cmp) (ro.upper, eo.upper, flinfo, collation) < 0)
 		{
 			nr.upper = eo.upper;
 			update = true;
@@ -321,7 +322,7 @@ gbt_var_fetch(PG_FUNCTION_ARGS)
 
 GBT_VARKEY *
 gbt_var_union(const GistEntryVector *entryvec, int32 *size, Oid collation,
-			  const gbtree_vinfo *tinfo)
+			  const gbtree_vinfo *tinfo, FmgrInfo *flinfo)
 {
 	int			i = 0,
 				numranges = entryvec->n;
@@ -338,7 +339,7 @@ gbt_var_union(const GistEntryVector *entryvec, int32 *size, Oid collation,
 	for (i = 1; i < numranges; i++)
 	{
 		cur = (GBT_VARKEY *) DatumGetPointer(entryvec->vector[i].key);
-		gbt_var_bin_union(&out, cur, collation, tinfo);
+		gbt_var_bin_union(&out, cur, collation, tinfo, flinfo);
 	}
 
 
@@ -360,7 +361,7 @@ gbt_var_union(const GistEntryVector *entryvec, int32 *size, Oid collation,
 
 bool
 gbt_var_same(Datum d1, Datum d2, Oid collation,
-			 const gbtree_vinfo *tinfo)
+			 const gbtree_vinfo *tinfo, FmgrInfo *flinfo)
 {
 	GBT_VARKEY *t1 = (GBT_VARKEY *) DatumGetPointer(d1);
 	GBT_VARKEY *t2 = (GBT_VARKEY *) DatumGetPointer(d2);
@@ -370,14 +371,14 @@ gbt_var_same(Datum d1, Datum d2, Oid collation,
 	r1 = gbt_var_key_readable(t1);
 	r2 = gbt_var_key_readable(t2);
 
-	return ((*tinfo->f_cmp) (r1.lower, r2.lower, collation) == 0 &&
-			(*tinfo->f_cmp) (r1.upper, r2.upper, collation) == 0);
+	return ((*tinfo->f_cmp) (r1.lower, r2.lower, flinfo, collation) == 0 &&
+			(*tinfo->f_cmp) (r1.upper, r2.upper, flinfo, collation) == 0);
 }
 
 
 float *
 gbt_var_penalty(float *res, const GISTENTRY *o, const GISTENTRY *n,
-				Oid collation, const gbtree_vinfo *tinfo)
+				Oid collation, const gbtree_vinfo *tinfo, FmgrInfo *flinfo)
 {
 	GBT_VARKEY *orge = (GBT_VARKEY *) DatumGetPointer(o->key);
 	GBT_VARKEY *newe = (GBT_VARKEY *) DatumGetPointer(n->key);
@@ -391,7 +392,7 @@ gbt_var_penalty(float *res, const GISTENTRY *o, const GISTENTRY *n,
 	{
 		GBT_VARKEY *tmp;
 
-		tmp = gbt_var_leaf2node(newe, tinfo);
+		tmp = gbt_var_leaf2node(newe, tinfo, flinfo);
 		if (tmp != newe)
 			nk = gbt_var_key_readable(tmp);
 	}
@@ -399,9 +400,9 @@ gbt_var_penalty(float *res, const GISTENTRY *o, const GISTENTRY *n,
 
 	if ((VARSIZE(ok.lower) - VARHDRSZ) == 0 && (VARSIZE(ok.upper) - VARHDRSZ) == 0)
 		*res = 0.0;
-	else if (!(((*tinfo->f_cmp) (nk.lower, ok.lower, collation) >= 0 ||
+	else if (!(((*tinfo->f_cmp) (nk.lower, ok.lower, flinfo, collation) >= 0 ||
 				gbt_bytea_pf_match(ok.lower, nk.lower, tinfo)) &&
-			   ((*tinfo->f_cmp) (nk.upper, ok.upper, collation) <= 0 ||
+			   ((*tinfo->f_cmp) (nk.upper, ok.upper, flinfo, collation) <= 0 ||
 				gbt_bytea_pf_match(ok.upper, nk.upper, tinfo))))
 	{
 		Datum		d = PointerGetDatum(0);
@@ -409,9 +410,9 @@ gbt_var_penalty(float *res, const GISTENTRY *o, const GISTENTRY *n,
 		int32		ol,
 					ul;
 
-		gbt_var_bin_union(&d, orge, collation, tinfo);
+		gbt_var_bin_union(&d, orge, collation, tinfo, flinfo);
 		ol = gbt_var_node_cp_len((GBT_VARKEY *) DatumGetPointer(d), tinfo);
-		gbt_var_bin_union(&d, newe, collation, tinfo);
+		gbt_var_bin_union(&d, newe, collation, tinfo, flinfo);
 		ul = gbt_var_node_cp_len((GBT_VARKEY *) DatumGetPointer(d), tinfo);
 
 		if (ul < ol)
@@ -448,16 +449,16 @@ gbt_vsrt_cmp(const void *a, const void *b, void *arg)
 	const gbt_vsrt_arg *varg = (const gbt_vsrt_arg *) arg;
 	int			res;
 
-	res = (*varg->tinfo->f_cmp) (ar.lower, br.lower, varg->collation);
+	res = (*varg->tinfo->f_cmp) (ar.lower, br.lower, varg->flinfo, varg->collation);
 	if (res == 0)
-		return (*varg->tinfo->f_cmp) (ar.upper, br.upper, varg->collation);
+		return (*varg->tinfo->f_cmp) (ar.upper, br.upper, varg->flinfo, varg->collation);
 
 	return res;
 }
 
 GIST_SPLITVEC *
 gbt_var_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v,
-				  Oid collation, const gbtree_vinfo *tinfo)
+				  Oid collation, const gbtree_vinfo *tinfo, FmgrInfo *flinfo)
 {
 	OffsetNumber i,
 				maxoff = entryvec->n - 1;
@@ -489,7 +490,7 @@ gbt_var_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v,
 		ro = gbt_var_key_readable((GBT_VARKEY *) cur);
 		if (ro.lower == ro.upper)		/* leaf */
 		{
-			sv[svcntr] = gbt_var_leaf2node((GBT_VARKEY *) cur, tinfo);
+			sv[svcntr] = gbt_var_leaf2node((GBT_VARKEY *) cur, tinfo, flinfo);
 			arr[i].t = sv[svcntr];
 			if (sv[svcntr] != (GBT_VARKEY *) cur)
 				svcntr++;
@@ -502,6 +503,7 @@ gbt_var_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v,
 	/* sort */
 	varg.tinfo = tinfo;
 	varg.collation = collation;
+	varg.flinfo = flinfo;
 	qsort_arg((void *) &arr[FirstOffsetNumber],
 			  maxoff - FirstOffsetNumber + 1,
 			  sizeof(Vsrt),
@@ -514,13 +516,13 @@ gbt_var_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v,
 	{
 		if (i <= (maxoff - FirstOffsetNumber + 1) / 2)
 		{
-			gbt_var_bin_union(&v->spl_ldatum, arr[i].t, collation, tinfo);
+			gbt_var_bin_union(&v->spl_ldatum, arr[i].t, collation, tinfo, flinfo);
 			v->spl_left[v->spl_nleft] = arr[i].i;
 			v->spl_nleft++;
 		}
 		else
 		{
-			gbt_var_bin_union(&v->spl_rdatum, arr[i].t, collation, tinfo);
+			gbt_var_bin_union(&v->spl_rdatum, arr[i].t, collation, tinfo, flinfo);
 			v->spl_right[v->spl_nright] = arr[i].i;
 			v->spl_nright++;
 		}
@@ -556,7 +558,8 @@ gbt_var_consistent(GBT_VARKEY_R *key,
 				   StrategyNumber strategy,
 				   Oid collation,
 				   bool is_leaf,
-				   const gbtree_vinfo *tinfo)
+				   const gbtree_vinfo *tinfo,
+				   FmgrInfo *flinfo)
 {
 	bool		retval = FALSE;
 
@@ -564,44 +567,44 @@ gbt_var_consistent(GBT_VARKEY_R *key,
 	{
 		case BTLessEqualStrategyNumber:
 			if (is_leaf)
-				retval = (*tinfo->f_ge) (query, key->lower, collation);
+				retval = (*tinfo->f_ge) (query, key->lower, flinfo, collation);
 			else
-				retval = (*tinfo->f_cmp) (query, key->lower, collation) >= 0
+				retval = (*tinfo->f_cmp) (query, key->lower, flinfo, collation) >= 0
 					|| gbt_var_node_pf_match(key, query, tinfo);
 			break;
 		case BTLessStrategyNumber:
 			if (is_leaf)
-				retval = (*tinfo->f_gt) (query, key->lower, collation);
+				retval = (*tinfo->f_gt) (query, key->lower, flinfo, collation);
 			else
-				retval = (*tinfo->f_cmp) (query, key->lower, collation) >= 0
+				retval = (*tinfo->f_cmp) (query, key->lower, flinfo, collation) >= 0
 					|| gbt_var_node_pf_match(key, query, tinfo);
 			break;
 		case BTEqualStrategyNumber:
 			if (is_leaf)
-				retval = (*tinfo->f_eq) (query, key->lower, collation);
+				retval = (*tinfo->f_eq) (query, key->lower, flinfo, collation);
 			else
 				retval =
-					((*tinfo->f_cmp) (key->lower, query, collation) <= 0 &&
-					 (*tinfo->f_cmp) (query, key->upper, collation) <= 0) ||
+					((*tinfo->f_cmp) (key->lower, query, flinfo, collation) <= 0 &&
+					 (*tinfo->f_cmp) (query, key->upper, flinfo, collation) <= 0) ||
 					gbt_var_node_pf_match(key, query, tinfo);
 			break;
 		case BTGreaterStrategyNumber:
 			if (is_leaf)
-				retval = (*tinfo->f_lt) (query, key->upper, collation);
+				retval = (*tinfo->f_lt) (query, key->upper, flinfo, collation);
 			else
-				retval = (*tinfo->f_cmp) (query, key->upper, collation) <= 0
+				retval = (*tinfo->f_cmp) (query, key->upper, flinfo, collation) <= 0
 					|| gbt_var_node_pf_match(key, query, tinfo);
 			break;
 		case BTGreaterEqualStrategyNumber:
 			if (is_leaf)
-				retval = (*tinfo->f_le) (query, key->upper, collation);
+				retval = (*tinfo->f_le) (query, key->upper, flinfo, collation);
 			else
-				retval = (*tinfo->f_cmp) (query, key->upper, collation) <= 0
+				retval = (*tinfo->f_cmp) (query, key->upper, flinfo, collation) <= 0
 					|| gbt_var_node_pf_match(key, query, tinfo);
 			break;
 		case BtreeGistNotEqualStrategyNumber:
-			retval = !((*tinfo->f_eq) (query, key->lower, collation) &&
-					   (*tinfo->f_eq) (query, key->upper, collation));
+			retval = !((*tinfo->f_eq) (query, key->lower, flinfo, collation) &&
+					   (*tinfo->f_eq) (query, key->upper, flinfo, collation));
 			break;
 		default:
 			retval = FALSE;
diff --git a/contrib/btree_gist/btree_utils_var.h b/contrib/btree_gist/btree_utils_var.h
index 9a7c4d1..7c9ffaf 100644
--- a/contrib/btree_gist/btree_utils_var.h
+++ b/contrib/btree_gist/btree_utils_var.h
@@ -34,13 +34,13 @@ typedef struct
 
 	/* Methods */
 
-	bool		(*f_gt) (const void *, const void *, Oid);		/* greater than */
-	bool		(*f_ge) (const void *, const void *, Oid);		/* greater equal */
-	bool		(*f_eq) (const void *, const void *, Oid);		/* equal */
-	bool		(*f_le) (const void *, const void *, Oid);		/* less equal */
-	bool		(*f_lt) (const void *, const void *, Oid);		/* less than */
-	int32		(*f_cmp) (const void *, const void *, Oid);		/* compare */
-	GBT_VARKEY *(*f_l2n) (GBT_VARKEY *);		/* convert leaf to node */
+	bool		(*f_gt) (const void *, const void *, FmgrInfo *flinfo, Oid);		/* greater than */
+	bool		(*f_ge) (const void *, const void *, FmgrInfo *flinfo, Oid);		/* greater equal */
+	bool		(*f_eq) (const void *, const void *, FmgrInfo *flinfo, Oid);		/* equal */
+	bool		(*f_le) (const void *, const void *, FmgrInfo *flinfo, Oid);		/* less equal */
+	bool		(*f_lt) (const void *, const void *, FmgrInfo *flinfo, Oid);		/* less than */
+	int32		(*f_cmp) (const void *, const void *, FmgrInfo *flinfo, Oid);		/* compare */
+	GBT_VARKEY *(*f_l2n) (GBT_VARKEY *, FmgrInfo *flinfo);		/* convert leaf to node */
 } gbtree_vinfo;
 
 
@@ -52,22 +52,22 @@ extern GBT_VARKEY *gbt_var_key_copy(const GBT_VARKEY_R *u);
 extern GISTENTRY *gbt_var_compress(GISTENTRY *entry, const gbtree_vinfo *tinfo);
 
 extern GBT_VARKEY *gbt_var_union(const GistEntryVector *entryvec, int32 *size,
-			  Oid collation, const gbtree_vinfo *tinfo);
+			  Oid collation, const gbtree_vinfo *tinfo, FmgrInfo *flinfo);
 
 extern bool gbt_var_same(Datum d1, Datum d2, Oid collation,
-			 const gbtree_vinfo *tinfo);
+			 const gbtree_vinfo *tinfo, FmgrInfo *flinfo);
 
 extern float *gbt_var_penalty(float *res, const GISTENTRY *o, const GISTENTRY *n,
-				Oid collation, const gbtree_vinfo *tinfo);
+				Oid collation, const gbtree_vinfo *tinfo, FmgrInfo *flinfo);
 
 extern bool gbt_var_consistent(GBT_VARKEY_R *key, const void *query,
 				   StrategyNumber strategy, Oid collation, bool is_leaf,
-				   const gbtree_vinfo *tinfo);
+				   const gbtree_vinfo *tinfo, FmgrInfo *flinfo);
 
 extern GIST_SPLITVEC *gbt_var_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v,
-				  Oid collation, const gbtree_vinfo *tinfo);
+				  Oid collation, const gbtree_vinfo *tinfo, FmgrInfo *flinfo);
 
 extern void gbt_var_bin_union(Datum *u, GBT_VARKEY *e, Oid collation,
-				  const gbtree_vinfo *tinfo);
+				  const gbtree_vinfo *tinfo, FmgrInfo *flinfo);
 
 #endif
diff --git a/contrib/btree_gist/btree_uuid.c b/contrib/btree_gist/btree_uuid.c
index 44cef64..5ed8092 100644
--- a/contrib/btree_gist/btree_uuid.c
+++ b/contrib/btree_gist/btree_uuid.c
@@ -34,37 +34,37 @@ uuid_internal_cmp(const pg_uuid_t *arg1, const pg_uuid_t *arg2)
 }
 
 static bool
-gbt_uuidgt(const void *a, const void *b)
+gbt_uuidgt(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return uuid_internal_cmp((const pg_uuid_t *) a, (const pg_uuid_t *) b) > 0;
 }
 
 static bool
-gbt_uuidge(const void *a, const void *b)
+gbt_uuidge(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return uuid_internal_cmp((const pg_uuid_t *) a, (const pg_uuid_t *) b) >= 0;
 }
 
 static bool
-gbt_uuideq(const void *a, const void *b)
+gbt_uuideq(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return uuid_internal_cmp((const pg_uuid_t *) a, (const pg_uuid_t *) b) == 0;
 }
 
 static bool
-gbt_uuidle(const void *a, const void *b)
+gbt_uuidle(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return uuid_internal_cmp((const pg_uuid_t *) a, (const pg_uuid_t *) b) <= 0;
 }
 
 static bool
-gbt_uuidlt(const void *a, const void *b)
+gbt_uuidlt(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	return uuid_internal_cmp((const pg_uuid_t *) a, (const pg_uuid_t *) b) < 0;
 }
 
 static int
-gbt_uuidkey_cmp(const void *a, const void *b)
+gbt_uuidkey_cmp(const void *a, const void *b, FmgrInfo *flinfo)
 {
 	uuidKEY    *ia = (uuidKEY *) (((const Nsrt *) a)->t);
 	uuidKEY    *ib = (uuidKEY *) (((const Nsrt *) b)->t);
@@ -150,7 +150,7 @@ gbt_uuid_consistent(PG_FUNCTION_ARGS)
 
 	PG_RETURN_BOOL(
 				   gbt_num_consistent(&key, (void *) query, &strategy,
-									  GIST_LEAF(entry), &tinfo)
+									  GIST_LEAF(entry), &tinfo, fcinfo->flinfo)
 		);
 }
 
@@ -161,7 +161,7 @@ gbt_uuid_union(PG_FUNCTION_ARGS)
 	void	   *out = palloc(sizeof(uuidKEY));
 
 	*(int *) PG_GETARG_POINTER(1) = sizeof(uuidKEY);
-	PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo));
+	PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo, fcinfo->flinfo));
 }
 
 /*
@@ -222,7 +222,7 @@ gbt_uuid_picksplit(PG_FUNCTION_ARGS)
 	PG_RETURN_POINTER(gbt_num_picksplit(
 									(GistEntryVector *) PG_GETARG_POINTER(0),
 									  (GIST_SPLITVEC *) PG_GETARG_POINTER(1),
-										&tinfo
+										&tinfo, fcinfo->flinfo
 										));
 }
 
@@ -233,6 +233,6 @@ gbt_uuid_same(PG_FUNCTION_ARGS)
 	uuidKEY    *b2 = (uuidKEY *) PG_GETARG_POINTER(1);
 	bool	   *result = (bool *) PG_GETARG_POINTER(2);
 
-	*result = gbt_num_same((void *) b1, (void *) b2, &tinfo);
+	*result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
 	PG_RETURN_POINTER(result);
 }
diff --git a/contrib/btree_gist/data/enum.data b/contrib/btree_gist/data/enum.data
new file mode 100644
index 0000000..d03bfce
--- /dev/null
+++ b/contrib/btree_gist/data/enum.data
@@ -0,0 +1,595 @@
+r
+v
+i
+b
+r
+\N
+y
+v
+g
+o
+y
+b
+o
+o
+o
+o
+v
+r
+i
+o
+b
+r
+g
+b
+i
+o
+r
+r
+r
+\N
+o
+b
+v
+y
+o
+\N
+i
+o
+o
+g
+g
+b
+y
+v
+g
+g
+\N
+v
+g
+i
+i
+\N
+v
+y
+i
+r
+\N
+r
+\N
+g
+\N
+g
+\N
+v
+g
+y
+v
+r
+v
+r
+v
+y
+i
+i
+v
+y
+v
+i
+b
+i
+i
+r
+r
+\N
+\N
+y
+r
+g
+i
+y
+i
+i
+r
+g
+y
+\N
+i
+o
+r
+y
+y
+g
+o
+o
+g
+y
+r
+g
+v
+r
+i
+r
+i
+r
+y
+v
+b
+i
+o
+r
+\N
+o
+i
+v
+o
+b
+\N
+b
+g
+y
+o
+v
+b
+i
+v
+v
+o
+y
+i
+i
+i
+g
+b
+b
+g
+r
+i
+y
+o
+\N
+r
+\N
+i
+i
+g
+v
+o
+y
+y
+o
+i
+b
+r
+y
+y
+o
+g
+g
+g
+\N
+y
+o
+v
+g
+y
+g
+v
+\N
+i
+o
+v
+b
+b
+\N
+y
+v
+\N
+v
+\N
+i
+\N
+r
+b
+r
+o
+r
+b
+o
+g
+i
+r
+b
+g
+g
+y
+b
+b
+g
+y
+g
+v
+v
+b
+\N
+i
+v
+y
+b
+b
+o
+g
+b
+v
+g
+g
+b
+\N
+y
+r
+r
+b
+\N
+r
+g
+i
+o
+v
+\N
+o
+r
+b
+o
+b
+i
+\N
+\N
+y
+b
+y
+\N
+i
+i
+i
+o
+y
+o
+i
+b
+o
+g
+r
+\N
+b
+y
+\N
+g
+b
+y
+y
+o
+o
+b
+g
+i
+i
+v
+b
+o
+o
+v
+i
+g
+i
+o
+r
+o
+i
+i
+r
+b
+g
+o
+o
+y
+v
+g
+g
+g
+r
+o
+i
+i
+g
+\N
+o
+v
+b
+b
+v
+i
+g
+y
+i
+i
+g
+r
+y
+i
+b
+\N
+g
+y
+o
+\N
+i
+i
+b
+v
+o
+b
+v
+r
+g
+o
+v
+v
+y
+r
+v
+g
+\N
+v
+v
+b
+y
+o
+g
+i
+o
+b
+r
+y
+r
+v
+b
+b
+\N
+i
+v
+y
+r
+b
+i
+y
+g
+\N
+g
+r
+y
+y
+g
+b
+o
+v
+r
+i
+g
+r
+b
+b
+b
+\N
+y
+y
+y
+i
+o
+r
+g
+g
+i
+y
+g
+y
+v
+o
+o
+g
+\N
+b
+v
+o
+y
+r
+\N
+o
+i
+g
+\N
+i
+i
+i
+o
+b
+\N
+\N
+b
+\N
+v
+v
+r
+\N
+o
+b
+r
+o
+b
+o
+r
+y
+\N
+r
+i
+b
+b
+y
+v
+r
+g
+r
+r
+\N
+g
+\N
+v
+v
+y
+r
+o
+r
+o
+i
+o
+\N
+r
+\N
+i
+v
+b
+v
+\N
+b
+r
+v
+o
+\N
+i
+r
+b
+g
+o
+\N
+o
+g
+r
+v
+y
+g
+v
+r
+b
+r
+v
+o
+g
+i
+i
+g
+i
+y
+b
+i
+y
+r
+y
+o
+r
+b
+y
+y
+b
+y
+g
+b
+\N
+r
+g
+b
+o
+y
+o
+g
+r
+g
+b
+\N
+v
+v
+v
+g
+b
+y
+v
+o
+v
+g
+o
+g
+i
+b
+v
+i
+r
+r
+i
+b
+i
+b
+o
+\N
+\N
+y
+r
+g
+v
+o
+y
+\N
+g
+v
+o
+b
+v
+v
+\N
+r
+v
+y
+g
+b
+o
+v
+b
+v
+b
+r
+r
+i
+r
+v
+y
+v
+y
+o
+v
+g
+i
+r
+o
+o
+i
+y
+r
+\N
+y
+r
+b
+y
+y
+\N
+b
+\N
+\N
+i
+v
diff --git a/contrib/btree_gist/expected/enum.out b/contrib/btree_gist/expected/enum.out
new file mode 100644
index 0000000..c4b769d
--- /dev/null
+++ b/contrib/btree_gist/expected/enum.out
@@ -0,0 +1,91 @@
+-- enum check
+create type rainbow as enum ('r','o','y','g','b','i','v');
+CREATE TABLE enumtmp (a rainbow);
+\copy enumtmp from 'data/enum.data'
+SET enable_seqscan=on;
+select a, count(*) from enumtmp group by a order by 1;
+ a | count 
+---+-------
+ r |    76
+ o |    78
+ y |    73
+ g |    75
+ b |    77
+ i |    78
+ v |    75
+   |    63
+(8 rows)
+
+SELECT count(*) FROM enumtmp WHERE a <  'g'::rainbow;
+ count 
+-------
+   227
+(1 row)
+
+SELECT count(*) FROM enumtmp WHERE a <= 'g'::rainbow;
+ count 
+-------
+   302
+(1 row)
+
+SELECT count(*) FROM enumtmp WHERE a  = 'g'::rainbow;
+ count 
+-------
+    75
+(1 row)
+
+SELECT count(*) FROM enumtmp WHERE a >= 'g'::rainbow;
+ count 
+-------
+   305
+(1 row)
+
+SELECT count(*) FROM enumtmp WHERE a >  'g'::rainbow;
+ count 
+-------
+   230
+(1 row)
+
+CREATE INDEX enumidx ON enumtmp USING gist ( a );
+SET enable_seqscan=off;
+SELECT count(*) FROM enumtmp WHERE a <  'g'::rainbow;
+ count 
+-------
+   227
+(1 row)
+
+SELECT count(*) FROM enumtmp WHERE a <= 'g'::rainbow;
+ count 
+-------
+   302
+(1 row)
+
+SELECT count(*) FROM enumtmp WHERE a  = 'g'::rainbow;
+ count 
+-------
+    75
+(1 row)
+
+SELECT count(*) FROM enumtmp WHERE a >= 'g'::rainbow;
+ count 
+-------
+   305
+(1 row)
+
+SELECT count(*) FROM enumtmp WHERE a >  'g'::rainbow;
+ count 
+-------
+   230
+(1 row)
+
+EXPLAIN (COSTS OFF)
+SELECT count(*) FROM enumtmp WHERE a >= 'g'::rainbow;
+                  QUERY PLAN                   
+-----------------------------------------------
+ Aggregate
+   ->  Bitmap Heap Scan on enumtmp
+         Recheck Cond: (a >= 'g'::rainbow)
+         ->  Bitmap Index Scan on enumidx
+               Index Cond: (a >= 'g'::rainbow)
+(5 rows)
+
diff --git a/contrib/btree_gist/sql/enum.sql b/contrib/btree_gist/sql/enum.sql
new file mode 100644
index 0000000..476211e
--- /dev/null
+++ b/contrib/btree_gist/sql/enum.sql
@@ -0,0 +1,38 @@
+-- enum check
+
+create type rainbow as enum ('r','o','y','g','b','i','v');
+
+CREATE TABLE enumtmp (a rainbow);
+
+\copy enumtmp from 'data/enum.data'
+
+SET enable_seqscan=on;
+
+select a, count(*) from enumtmp group by a order by 1;
+
+SELECT count(*) FROM enumtmp WHERE a <  'g'::rainbow;
+
+SELECT count(*) FROM enumtmp WHERE a <= 'g'::rainbow;
+
+SELECT count(*) FROM enumtmp WHERE a  = 'g'::rainbow;
+
+SELECT count(*) FROM enumtmp WHERE a >= 'g'::rainbow;
+
+SELECT count(*) FROM enumtmp WHERE a >  'g'::rainbow;
+
+CREATE INDEX enumidx ON enumtmp USING gist ( a );
+
+SET enable_seqscan=off;
+
+SELECT count(*) FROM enumtmp WHERE a <  'g'::rainbow;
+
+SELECT count(*) FROM enumtmp WHERE a <= 'g'::rainbow;
+
+SELECT count(*) FROM enumtmp WHERE a  = 'g'::rainbow;
+
+SELECT count(*) FROM enumtmp WHERE a >= 'g'::rainbow;
+
+SELECT count(*) FROM enumtmp WHERE a >  'g'::rainbow;
+
+EXPLAIN (COSTS OFF)
+SELECT count(*) FROM enumtmp WHERE a >= 'g'::rainbow;
diff --git a/doc/src/sgml/btree-gin.sgml b/doc/src/sgml/btree-gin.sgml
index 0de8eb5..375e7ec 100644
--- a/doc/src/sgml/btree-gin.sgml
+++ b/doc/src/sgml/btree-gin.sgml
@@ -17,7 +17,7 @@
   <type>oid</>, <type>money</>, <type>"char"</>,
   <type>varchar</>, <type>text</>, <type>bytea</>, <type>bit</>,
   <type>varbit</>, <type>macaddr</>, <type>macaddr8</>, <type>inet</>,
-  and <type>cidr</>.
+  <type>cidr</>, and all <type>enum</> types.
  </para>
 
  <para>
diff --git a/doc/src/sgml/btree-gist.sgml b/doc/src/sgml/btree-gist.sgml
index cfdd5be..c05f527 100644
--- a/doc/src/sgml/btree-gist.sgml
+++ b/doc/src/sgml/btree-gist.sgml
@@ -17,7 +17,8 @@
   <type>oid</>, <type>money</>, <type>char</>,
   <type>varchar</>, <type>text</>, <type>bytea</>, <type>bit</>,
   <type>varbit</>, <type>macaddr</>, <type>macaddr8</>, <type>inet</>,
-  <type>cidr</> and <type>uuid</>.
+  <type>cidr</>, <type>uuid</> and all <type>enum</> types.
+
  </para>
 
  <para>
diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c
index 8c00da6..9fb6952 100644
--- a/src/backend/utils/fmgr/fmgr.c
+++ b/src/backend/utils/fmgr/fmgr.c
@@ -1276,6 +1276,56 @@ DirectFunctionCall9Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2,
 	return result;
 }
 
+/*
+ * These functions work like the DirectFunctionCall functions except that
+ * they use the flinfo parameter to initialise the fcinfo for the call.
+ * It's recommended that the callee only use the fn_extra and fn_mcxt
+ * fields, as other fields will typically describe the calling function
+ * not the callee.  Conversely, the calling function should not have
+ * used fn_extra, unless its use is known to be compatible with the callee's.
+ */
+
+Datum
+CallerFInfoFunctionCall1(PGFunction func, FmgrInfo *flinfo, Oid collation, Datum arg1)
+{
+	FunctionCallInfoData fcinfo;
+	Datum		result;
+
+	InitFunctionCallInfoData(fcinfo, flinfo, 1, collation, NULL, NULL);
+
+	fcinfo.arg[0] = arg1;
+	fcinfo.argnull[0] = false;
+
+	result = (*func) (&fcinfo);
+
+	/* Check for null result, since caller is clearly not expecting one */
+	if (fcinfo.isnull)
+		elog(ERROR, "function %p returned NULL", (void *) func);
+
+	return result;
+}
+
+Datum
+CallerFInfoFunctionCall2(PGFunction func, FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
+{
+	FunctionCallInfoData fcinfo;
+	Datum		result;
+
+	InitFunctionCallInfoData(fcinfo, flinfo, 2, collation, NULL, NULL);
+
+	fcinfo.arg[0] = arg1;
+	fcinfo.arg[1] = arg2;
+	fcinfo.argnull[0] = false;
+	fcinfo.argnull[1] = false;
+
+	result = (*func) (&fcinfo);
+
+	/* Check for null result, since caller is clearly not expecting one */
+	if (fcinfo.isnull)
+		elog(ERROR, "function %p returned NULL", (void *) func);
+
+	return result;
+}
 
 /*
  * These are for invocation of a previously-looked-up function with a
diff --git a/src/include/fmgr.h b/src/include/fmgr.h
index 4d400d2..d0b3edb 100644
--- a/src/include/fmgr.h
+++ b/src/include/fmgr.h
@@ -482,6 +482,18 @@ extern Datum DirectFunctionCall9Coll(PGFunction func, Oid collation,
 						Datum arg3, Datum arg4, Datum arg5,
 						Datum arg6, Datum arg7, Datum arg8,
 						Datum arg9);
+/*
+ * These functions work like the DirectFunctionCall functions except that
+ * they use the flinfo parameter to initialise the fcinfo for the call.
+ * It's recommended that the callee only use the fn_extra and fn_mcxt
+ * fields, as other fields will typically describe the calling function
+ * not the callee.  Conversely, the calling function should not have
+ * used fn_extra, unless its use is known to be compatible with the callee's.
+ */
+extern Datum CallerFInfoFunctionCall1(PGFunction func, FmgrInfo *flinfo,
+						 Oid collation, Datum arg1);
+extern Datum CallerFInfoFunctionCall2(PGFunction func, FmgrInfo *flinfo,
+						 Oid collation, Datum arg1, Datum arg2);
 
 /* These are for invocation of a previously-looked-up function with a
  * directly-computed parameter list.  Note that neither arguments nor result
