btree_gin and ranges

Started by Teodor Sigaevabout 11 years ago12 messages
#1Teodor Sigaev
teodor@sigaev.ru
1 attachment(s)

Suggested patch adds GIN support contains operator for ranges over scalar column.

It allows more effective GIN scan. Currently, queries like
SELECT * FROM test_int4 WHERE i <= 1 and i >= 1
will be excuted by GIN with two scans: one is from mines infinity to 1 and
another is from -1 to plus infinity. That's because GIN is "generalized" and it
doesn't know a semantics of operation.

With patch it's possible to rewrite query with ranges
SELECT * FROM test_int4 WHERE i <@ '[-1, 1]'::int4range
and GIN index will support this query with single scan from -1 to 1.

Patch provides index support only for existing range types: int4, int8, numeric,
date and timestamp with and without time zone.

--
Teodor Sigaev E-mail: teodor@sigaev.ru
WWW: http://www.sigaev.ru/

Attachments:

btree_gin_range-1.patch.gzapplication/x-gzip; name=btree_gin_range-1.patch.gzDownload
#2Marti Raudsepp
marti@juffo.org
In reply to: Teodor Sigaev (#1)
Re: btree_gin and ranges

Hi

On Wed, Oct 22, 2014 at 1:55 PM, Teodor Sigaev <teodor@sigaev.ru> wrote:

With patch it's possible to rewrite query with ranges
SELECT * FROM test_int4 WHERE i <@ '[-1, 1]'::int4range
and GIN index will support this query with single scan from -1 to 1.

Shouldn't this be implemented in a more generic manner? An ordinary
btree index could very well support <@ queries too, but your patch
only adds this capability to btree-gin.

The documentation describes btree-gin as providing "GIN operator
classes that implement B-tree equivalent behavior", but now the
behavior diverges.

Regards,
Marti

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#3Teodor Sigaev
teodor@sigaev.ru
In reply to: Marti Raudsepp (#2)
Re: btree_gin and ranges

Shouldn't this be implemented in a more generic manner? An ordinary

Unfortunately I don't see a way for that. GIN is generalized - and it doesn't
know semantic. Actually, we could fix first five strategy numbers for BTree's
strategies, and then we could teach GIN core to use BTRee semantic, but what
about with already existed operator classes?

The documentation describes btree-gin as providing "GIN operator
classes that implement B-tree equivalent behavior", but now the
behavior diverges.

Anyway GIN couldn't be used for ORDER BY clause.

--
Teodor Sigaev E-mail: teodor@sigaev.ru
WWW: http://www.sigaev.ru/

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#4Heikki Linnakangas
hlinnakangas@vmware.com
In reply to: Teodor Sigaev (#3)
Re: btree_gin and ranges

On 10/22/2014 03:01 PM, Teodor Sigaev wrote:

Anyway GIN couldn't be used for ORDER BY clause.

which would also be nice to fix...

- Heikki

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#5Heikki Linnakangas
hlinnakangas@vmware.com
In reply to: Teodor Sigaev (#3)
Re: btree_gin and ranges

On 10/22/2014 03:01 PM, Teodor Sigaev wrote:

Anyway GIN couldn't be used for ORDER BY clause.

which would also be nice to fix...

- Heikki

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#6Teodor Sigaev
teodor@sigaev.ru
In reply to: Heikki Linnakangas (#5)
Re: btree_gin and ranges

which would also be nice to fix..

Of course, agree. With rbtree usage instead of tidbitmap hash and semantic
knowledge about operators in GIN...

--
Teodor Sigaev E-mail: teodor@sigaev.ru
WWW: http://www.sigaev.ru/

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#7Heikki Linnakangas
hlinnakangas@vmware.com
In reply to: Teodor Sigaev (#1)
1 attachment(s)
Re: btree_gin and ranges

On 10/22/2014 01:55 PM, Teodor Sigaev wrote:

Suggested patch adds GIN support contains operator for ranges over scalar column.

It allows more effective GIN scan. Currently, queries like
SELECT * FROM test_int4 WHERE i <= 1 and i >= 1
will be excuted by GIN with two scans: one is from mines infinity to 1 and
another is from -1 to plus infinity. That's because GIN is "generalized" and it
doesn't know a semantics of operation.

With patch it's possible to rewrite query with ranges
SELECT * FROM test_int4 WHERE i <@ '[-1, 1]'::int4range
and GIN index will support this query with single scan from -1 to 1.

Patch provides index support only for existing range types: int4, int8, numeric,
date and timestamp with and without time zone.

I started to look at this, but very quickly got carried away into
refactoring away the macros. Defining long functions as macros makes
debugging quite difficult, and it's not nice to read or edit the source
code either.

I propose the attached refactoring (it doesn't include your range-patch
yet, just refactoring the existing code). It turns the bulk of the
macros into static functions. GIN_SUPPORT macro still defines the
datatype-specific functions, but they are now very thin wrappers that
just call the corresponding generic static functions.

It's annoying that we need the concept of a leftmost value, for the <
and <= queries. Without that, we could have the support functions look
up the required datatype information from the type cache, based on the
datatype of the passed argument. Then you could easily use the btree_gin
support functions also for user-defined datatypes. But that needs bigger
changes, and this is a step in the right direction anyway.

- Heikki

Attachments:

0001-Turn-much-of-the-btree_gin-macros-into-real-function.patchtext/x-diff; name=0001-Turn-much-of-the-btree_gin-macros-into-real-function.patchDownload
>From fc96b3842e0695f8b4e39fc870ad0c3d628db834 Mon Sep 17 00:00:00 2001
From: Heikki Linnakangas <heikki.linnakangas@iki.fi>
Date: Wed, 17 Dec 2014 19:57:39 +0200
Subject: [PATCH] Turn much of the btree_gin macros into real functions.

This makes the functions much nicer to read and edit, and also makes
debugging easier.

diff --git a/contrib/btree_gin/btree_gin.c b/contrib/btree_gin/btree_gin.c
index 87d23e0..80521fb 100644
--- a/contrib/btree_gin/btree_gin.c
+++ b/contrib/btree_gin/btree_gin.c
@@ -17,34 +17,30 @@
 
 PG_MODULE_MAGIC;
 
-typedef struct TypeInfo
-{
-	bool		is_varlena;
-	Datum		(*leftmostvalue) (void);
-	Datum		(*typecmp) (FunctionCallInfo);
-} TypeInfo;
-
 typedef struct QueryInfo
 {
 	StrategyNumber strategy;
 	Datum		datum;
+	bool		is_varlena;
+	Datum		(*typecmp) (FunctionCallInfo);
 } QueryInfo;
 
-#define  GIN_EXTRACT_VALUE(type)											\
-PG_FUNCTION_INFO_V1(gin_extract_value_##type);								\
-Datum																		\
-gin_extract_value_##type(PG_FUNCTION_ARGS)									\
-{																			\
-	Datum		datum = PG_GETARG_DATUM(0);									\
-	int32	   *nentries = (int32 *) PG_GETARG_POINTER(1);					\
-	Datum	   *entries = (Datum *) palloc(sizeof(Datum));					\
-																			\
-	if ( TypeInfo_##type.is_varlena )										\
-		datum = PointerGetDatum(PG_DETOAST_DATUM(datum));					\
-	entries[0] = datum;														\
-	*nentries = 1;															\
-																			\
-	PG_RETURN_POINTER(entries);												\
+
+/*** GIN support functions shared by all datatypes ***/
+
+static Datum
+gin_btree_extract_value(FunctionCallInfo fcinfo, bool is_varlena)
+{
+	Datum		datum = PG_GETARG_DATUM(0);
+	int32	   *nentries = (int32 *) PG_GETARG_POINTER(1);
+	Datum	   *entries = (Datum *) palloc(sizeof(Datum));
+
+	if (is_varlena)
+		datum = PointerGetDatum(PG_DETOAST_DATUM(datum));
+	entries[0] = datum;
+	*nentries = 1;
+
+	PG_RETURN_POINTER(entries);
 }
 
 /*
@@ -55,49 +51,51 @@ gin_extract_value_##type(PG_FUNCTION_ARGS)									\
  * key, and work forward until the supplied query datum (which must be
  * sent along inside the QueryInfo structure).
  */
+static Datum
+gin_btree_extract_query(FunctionCallInfo fcinfo,
+						bool is_varlena,
+						Datum (*leftmostvalue) (void),
+						Datum (*typecmp) (FunctionCallInfo))
+{
+	Datum		datum = PG_GETARG_DATUM(0);
+	int32	   *nentries = (int32 *) PG_GETARG_POINTER(1);
+	StrategyNumber strategy = PG_GETARG_UINT16(2);
+	bool	  **partialmatch = (bool **) PG_GETARG_POINTER(3);
+	Pointer   **extra_data = (Pointer **) PG_GETARG_POINTER(4);
+	Datum	   *entries = (Datum *) palloc(sizeof(Datum));
+	QueryInfo  *data = (QueryInfo *) palloc(sizeof(QueryInfo));
+	bool	   *ptr_partialmatch;
+
+	*nentries = 1;
+	ptr_partialmatch = *partialmatch = (bool *) palloc(sizeof(bool));
+	*ptr_partialmatch = false;
+	if (is_varlena)
+		datum = PointerGetDatum(PG_DETOAST_DATUM(datum));
+	data->strategy = strategy;
+	data->datum = datum;
+	data->is_varlena = is_varlena;
+	data->typecmp = typecmp;
+	*extra_data = (Pointer *) palloc(sizeof(Pointer));
+	**extra_data = (Pointer) data;
+
+	switch (strategy)
+	{
+		case BTLessStrategyNumber:
+		case BTLessEqualStrategyNumber:
+			entries[0] = leftmostvalue();
+			*ptr_partialmatch = true;
+			break;
+		case BTGreaterEqualStrategyNumber:
+		case BTGreaterStrategyNumber:
+			*ptr_partialmatch = true;
+		case BTEqualStrategyNumber:
+			entries[0] = datum;
+			break;
+		default:
+			elog(ERROR, "unrecognized strategy number: %d", strategy);
+	}
 
-#define GIN_EXTRACT_QUERY(type)												\
-PG_FUNCTION_INFO_V1(gin_extract_query_##type);								\
-Datum																		\
-gin_extract_query_##type(PG_FUNCTION_ARGS)									\
-{																			\
-	Datum		datum = PG_GETARG_DATUM(0);									\
-	int32	   *nentries = (int32 *) PG_GETARG_POINTER(1);					\
-	StrategyNumber strategy = PG_GETARG_UINT16(2);							\
-	bool	  **partialmatch = (bool **) PG_GETARG_POINTER(3);				\
-	Pointer   **extra_data = (Pointer **) PG_GETARG_POINTER(4);				\
-	Datum	   *entries = (Datum *) palloc(sizeof(Datum));					\
-	QueryInfo  *data = (QueryInfo *) palloc(sizeof(QueryInfo));				\
-	bool	   *ptr_partialmatch;											\
-																			\
-	*nentries = 1;															\
-	ptr_partialmatch = *partialmatch = (bool *) palloc(sizeof(bool));		\
-	*ptr_partialmatch = false;												\
-	if ( TypeInfo_##type.is_varlena )										\
-		datum = PointerGetDatum(PG_DETOAST_DATUM(datum));					\
-	data->strategy = strategy;												\
-	data->datum = datum;													\
-	*extra_data = (Pointer *) palloc(sizeof(Pointer));						\
-	**extra_data = (Pointer) data;											\
-																			\
-	switch (strategy)														\
-	{																		\
-		case BTLessStrategyNumber:											\
-		case BTLessEqualStrategyNumber:										\
-			entries[0] = TypeInfo_##type.leftmostvalue();					\
-			*ptr_partialmatch = true;										\
-			break;															\
-		case BTGreaterEqualStrategyNumber:									\
-		case BTGreaterStrategyNumber:										\
-			*ptr_partialmatch = true;										\
-		case BTEqualStrategyNumber:											\
-			entries[0] = datum;												\
-			break;															\
-		default:															\
-			elog(ERROR, "unrecognized strategy number: %d", strategy);		\
-	}																		\
-																			\
-	PG_RETURN_POINTER(entries);												\
+	PG_RETURN_POINTER(entries);
 }
 
 /*
@@ -105,78 +103,70 @@ gin_extract_query_##type(PG_FUNCTION_ARGS)									\
  * strategy it is a left-most value.  So, use original datum from QueryInfo
  * to decide to stop scanning or not.  Datum b is always from index.
  */
-#define GIN_COMPARE_PREFIX(type)											\
-PG_FUNCTION_INFO_V1(gin_compare_prefix_##type);								\
-Datum																		\
-gin_compare_prefix_##type(PG_FUNCTION_ARGS)									\
-{																			\
-	Datum		a = PG_GETARG_DATUM(0);										\
-	Datum		b = PG_GETARG_DATUM(1);										\
-	QueryInfo  *data = (QueryInfo *) PG_GETARG_POINTER(3);					\
-	int32		res,														\
-				cmp;														\
-																			\
-	cmp = DatumGetInt32(DirectFunctionCall2Coll(							\
-				TypeInfo_##type.typecmp,									\
-				PG_GET_COLLATION(),											\
-				(data->strategy == BTLessStrategyNumber ||					\
-				 data->strategy == BTLessEqualStrategyNumber)				\
-				 ? data->datum : a,											\
-				b));														\
-																			\
-	switch (data->strategy)													\
-	{																		\
-		case BTLessStrategyNumber:											\
-			/* If original datum > indexed one then return match */			\
-			if (cmp > 0)													\
-				res = 0;													\
-			else															\
-				res = 1;													\
-			break;															\
-		case BTLessEqualStrategyNumber:										\
-			/* The same except equality */									\
-			if (cmp >= 0)													\
-				res = 0;													\
-			else															\
-				res = 1;													\
-			break;															\
-		case BTEqualStrategyNumber:											\
-			if (cmp != 0)													\
-				res = 1;													\
-			else															\
-				res = 0;													\
-			break;															\
-		case BTGreaterEqualStrategyNumber:									\
-			/* If original datum <= indexed one then return match */		\
-			if (cmp <= 0)													\
-				res = 0;													\
-			else															\
-				res = 1;													\
-			break;															\
-		case BTGreaterStrategyNumber:										\
-			/* If original datum <= indexed one then return match */		\
-			/* If original datum == indexed one then continue scan */		\
-			if (cmp < 0)													\
-				res = 0;													\
-			else if (cmp == 0)												\
-				res = -1;													\
-			else															\
-				res = 1;													\
-			break;															\
-		default:															\
-			elog(ERROR, "unrecognized strategy number: %d",					\
-				 data->strategy);											\
-			res = 0;														\
-	}																		\
-																			\
-	PG_RETURN_INT32(res);													\
-}
-
-#define GIN_SUPPORT(type)			\
-	GIN_EXTRACT_VALUE(type)			\
-	GIN_EXTRACT_QUERY(type)			\
-	GIN_COMPARE_PREFIX(type)
+static Datum
+gin_btree_compare_prefix(FunctionCallInfo fcinfo)
+{
+	Datum		a = PG_GETARG_DATUM(0);
+	Datum		b = PG_GETARG_DATUM(1);
+	QueryInfo  *data = (QueryInfo *) PG_GETARG_POINTER(3);
+	int32		res,
+				cmp;
+
+	cmp = DatumGetInt32(DirectFunctionCall2Coll(
+				data->typecmp,
+				PG_GET_COLLATION(),
+				(data->strategy == BTLessStrategyNumber ||
+				 data->strategy == BTLessEqualStrategyNumber)
+				 ? data->datum : a,
+				b));
+
+	switch (data->strategy)
+	{
+		case BTLessStrategyNumber:
+			/* If original datum > indexed one then return match */
+			if (cmp > 0)
+				res = 0;
+			else
+				res = 1;
+			break;
+		case BTLessEqualStrategyNumber:
+			/* The same except equality */
+			if (cmp >= 0)
+				res = 0;
+			else
+				res = 1;
+			break;
+		case BTEqualStrategyNumber:
+			if (cmp != 0)
+				res = 1;
+			else
+				res = 0;
+			break;
+		case BTGreaterEqualStrategyNumber:
+			/* If original datum <= indexed one then return match */
+			if (cmp <= 0)
+				res = 0;
+			else
+				res = 1;
+			break;
+		case BTGreaterStrategyNumber:
+			/* If original datum <= indexed one then return match */
+			/* If original datum == indexed one then continue scan */
+			if (cmp < 0)
+				res = 0;
+			else if (cmp == 0)
+				res = -1;
+			else
+				res = 1;
+			break;
+		default:
+			elog(ERROR, "unrecognized strategy number: %d",
+				 data->strategy);
+			res = 0;
+	}
 
+	PG_RETURN_INT32(res);
+}
 
 PG_FUNCTION_INFO_V1(gin_btree_consistent);
 Datum
@@ -188,23 +178,45 @@ gin_btree_consistent(PG_FUNCTION_ARGS)
 	PG_RETURN_BOOL(true);
 }
 
+/*** GIN_SUPPORT macro defines the datatype specific functions ***/
+
+#define GIN_SUPPORT(type, is_varlena, leftmostvalue, typecmp)				\
+PG_FUNCTION_INFO_V1(gin_extract_value_##type);								\
+Datum																		\
+gin_extract_value_##type(PG_FUNCTION_ARGS)									\
+{																			\
+	return gin_btree_extract_value(fcinfo, is_varlena);						\
+}																			\
+PG_FUNCTION_INFO_V1(gin_extract_query_##type);								\
+Datum																		\
+gin_extract_query_##type(PG_FUNCTION_ARGS)									\
+{																			\
+	return gin_btree_extract_query(fcinfo,									\
+								   is_varlena, leftmostvalue, typecmp);		\
+}																			\
+PG_FUNCTION_INFO_V1(gin_compare_prefix_##type);								\
+Datum																		\
+gin_compare_prefix_##type(PG_FUNCTION_ARGS)									\
+{																			\
+	return gin_btree_compare_prefix(fcinfo);								\
+}
+
+
+/*** Datatype specifications ***/
+
 static Datum
 leftmostvalue_int2(void)
 {
 	return Int16GetDatum(SHRT_MIN);
 }
-static TypeInfo TypeInfo_int2 = {false, leftmostvalue_int2, btint2cmp};
-
-GIN_SUPPORT(int2)
+GIN_SUPPORT(int2, false, leftmostvalue_int2, btint2cmp)
 
 static Datum
 leftmostvalue_int4(void)
 {
 	return Int32GetDatum(INT_MIN);
 }
-static TypeInfo TypeInfo_int4 = {false, leftmostvalue_int4, btint4cmp};
-
-GIN_SUPPORT(int4)
+GIN_SUPPORT(int4, false, leftmostvalue_int4, btint4cmp)
 
 static Datum
 leftmostvalue_int8(void)
@@ -214,27 +226,21 @@ leftmostvalue_int8(void)
 	 */
 	return Int64GetDatum(SEQ_MINVALUE);
 }
-static TypeInfo TypeInfo_int8 = {false, leftmostvalue_int8, btint8cmp};
-
-GIN_SUPPORT(int8)
+GIN_SUPPORT(int8, false, leftmostvalue_int8, btint8cmp)
 
 static Datum
 leftmostvalue_float4(void)
 {
 	return Float4GetDatum(-get_float4_infinity());
 }
-static TypeInfo TypeInfo_float4 = {false, leftmostvalue_float4, btfloat4cmp};
-
-GIN_SUPPORT(float4)
+GIN_SUPPORT(float4, false, leftmostvalue_float4, btfloat4cmp)
 
 static Datum
 leftmostvalue_float8(void)
 {
 	return Float8GetDatum(-get_float8_infinity());
 }
-static TypeInfo TypeInfo_float8 = {false, leftmostvalue_float8, btfloat8cmp};
-
-GIN_SUPPORT(float8)
+GIN_SUPPORT(float8, false, leftmostvalue_float8, btfloat8cmp)
 
 static Datum
 leftmostvalue_money(void)
@@ -244,40 +250,30 @@ leftmostvalue_money(void)
 	 */
 	return Int64GetDatum(SEQ_MINVALUE);
 }
-static TypeInfo TypeInfo_money = {false, leftmostvalue_money, cash_cmp};
-
-GIN_SUPPORT(money)
+GIN_SUPPORT(money, false, leftmostvalue_money, cash_cmp)
 
 static Datum
 leftmostvalue_oid(void)
 {
 	return ObjectIdGetDatum(0);
 }
-static TypeInfo TypeInfo_oid = {false, leftmostvalue_oid, btoidcmp};
-
-GIN_SUPPORT(oid)
+GIN_SUPPORT(oid, false, leftmostvalue_oid, btoidcmp)
 
 static Datum
 leftmostvalue_timestamp(void)
 {
 	return TimestampGetDatum(DT_NOBEGIN);
 }
-static TypeInfo TypeInfo_timestamp = {false, leftmostvalue_timestamp, timestamp_cmp};
-
-GIN_SUPPORT(timestamp)
-
-static TypeInfo TypeInfo_timestamptz = {false, leftmostvalue_timestamp, timestamp_cmp};
+GIN_SUPPORT(timestamp, false, leftmostvalue_timestamp, timestamp_cmp)
 
-GIN_SUPPORT(timestamptz)
+GIN_SUPPORT(timestamptz, false, leftmostvalue_timestamp, timestamp_cmp)
 
 static Datum
 leftmostvalue_time(void)
 {
 	return TimeADTGetDatum(0);
 }
-static TypeInfo TypeInfo_time = {false, leftmostvalue_time, time_cmp};
-
-GIN_SUPPORT(time)
+GIN_SUPPORT(time, false, leftmostvalue_time, time_cmp)
 
 static Datum
 leftmostvalue_timetz(void)
@@ -289,18 +285,14 @@ leftmostvalue_timetz(void)
 
 	return TimeTzADTPGetDatum(v);
 }
-static TypeInfo TypeInfo_timetz = {false, leftmostvalue_timetz, timetz_cmp};
-
-GIN_SUPPORT(timetz)
+GIN_SUPPORT(timetz, false, leftmostvalue_timetz, timetz_cmp)
 
 static Datum
 leftmostvalue_date(void)
 {
 	return DateADTGetDatum(DATEVAL_NOBEGIN);
 }
-static TypeInfo TypeInfo_date = {false, leftmostvalue_date, date_cmp};
-
-GIN_SUPPORT(date)
+GIN_SUPPORT(date, false, leftmostvalue_date, date_cmp)
 
 static Datum
 leftmostvalue_interval(void)
@@ -312,9 +304,7 @@ leftmostvalue_interval(void)
 	v->month = 0;
 	return IntervalPGetDatum(v);
 }
-static TypeInfo TypeInfo_interval = {false, leftmostvalue_interval, interval_cmp};
-
-GIN_SUPPORT(interval)
+GIN_SUPPORT(interval, false, leftmostvalue_interval, interval_cmp)
 
 static Datum
 leftmostvalue_macaddr(void)
@@ -323,9 +313,7 @@ leftmostvalue_macaddr(void)
 
 	return MacaddrPGetDatum(v);
 }
-static TypeInfo TypeInfo_macaddr = {false, leftmostvalue_macaddr, macaddr_cmp};
-
-GIN_SUPPORT(macaddr)
+GIN_SUPPORT(macaddr, false, leftmostvalue_macaddr, macaddr_cmp)
 
 static Datum
 leftmostvalue_inet(void)
@@ -335,35 +323,25 @@ leftmostvalue_inet(void)
 							   ObjectIdGetDatum(0),
 							   Int32GetDatum(-1));
 }
-static TypeInfo TypeInfo_inet = {true, leftmostvalue_inet, network_cmp};
+GIN_SUPPORT(inet, true, leftmostvalue_inet, network_cmp)
 
-GIN_SUPPORT(inet)
-
-static TypeInfo TypeInfo_cidr = {true, leftmostvalue_inet, network_cmp};
-
-GIN_SUPPORT(cidr)
+GIN_SUPPORT(cidr, true, leftmostvalue_inet, network_cmp)
 
 static Datum
 leftmostvalue_text(void)
 {
 	return PointerGetDatum(cstring_to_text_with_len("", 0));
 }
-static TypeInfo TypeInfo_text = {true, leftmostvalue_text, bttextcmp};
-
-GIN_SUPPORT(text)
+GIN_SUPPORT(text, true, leftmostvalue_text, bttextcmp)
 
 static Datum
 leftmostvalue_char(void)
 {
 	return CharGetDatum(SCHAR_MIN);
 }
-static TypeInfo TypeInfo_char = {false, leftmostvalue_char, btcharcmp};
-
-GIN_SUPPORT(char)
-
-static TypeInfo TypeInfo_bytea = {true, leftmostvalue_text, byteacmp};
+GIN_SUPPORT(char, false, leftmostvalue_char, btcharcmp)
 
-GIN_SUPPORT(bytea)
+GIN_SUPPORT(bytea, true, leftmostvalue_text, byteacmp)
 
 static Datum
 leftmostvalue_bit(void)
@@ -373,9 +351,7 @@ leftmostvalue_bit(void)
 							   ObjectIdGetDatum(0),
 							   Int32GetDatum(-1));
 }
-static TypeInfo TypeInfo_bit = {true, leftmostvalue_bit, bitcmp};
-
-GIN_SUPPORT(bit)
+GIN_SUPPORT(bit, true, leftmostvalue_bit, bitcmp)
 
 static Datum
 leftmostvalue_varbit(void)
@@ -385,9 +361,7 @@ leftmostvalue_varbit(void)
 							   ObjectIdGetDatum(0),
 							   Int32GetDatum(-1));
 }
-static TypeInfo TypeInfo_varbit = {true, leftmostvalue_varbit, bitcmp};
-
-GIN_SUPPORT(varbit)
+GIN_SUPPORT(varbit, true, leftmostvalue_varbit, bitcmp)
 
 /*
  * Numeric type hasn't a real left-most value, so we use PointerGetDatum(NULL)
@@ -431,7 +405,4 @@ leftmostvalue_numeric(void)
 {
 	return PointerGetDatum(NULL);
 }
-
-static TypeInfo TypeInfo_numeric = {true, leftmostvalue_numeric, gin_numeric_cmp};
-
-GIN_SUPPORT(numeric)
+GIN_SUPPORT(numeric, true, leftmostvalue_numeric, gin_numeric_cmp)
-- 
2.1.3

#8Michael Paquier
michael.paquier@gmail.com
In reply to: Heikki Linnakangas (#7)
Re: btree_gin and ranges

On Thu, Dec 18, 2014 at 4:13 AM, Heikki Linnakangas
<hlinnakangas@vmware.com> wrote:

On 10/22/2014 01:55 PM, Teodor Sigaev wrote:

Suggested patch adds GIN support contains operator for ranges over scalar
column.

It allows more effective GIN scan. Currently, queries like
SELECT * FROM test_int4 WHERE i <= 1 and i >= 1
will be excuted by GIN with two scans: one is from mines infinity to 1 and
another is from -1 to plus infinity. That's because GIN is "generalized"
and it
doesn't know a semantics of operation.

With patch it's possible to rewrite query with ranges
SELECT * FROM test_int4 WHERE i <@ '[-1, 1]'::int4range
and GIN index will support this query with single scan from -1 to 1.

Patch provides index support only for existing range types: int4, int8,
numeric,
date and timestamp with and without time zone.

I started to look at this, but very quickly got carried away into
refactoring away the macros. Defining long functions as macros makes
debugging quite difficult, and it's not nice to read or edit the source code
either.

I propose the attached refactoring (it doesn't include your range-patch yet,
just refactoring the existing code). It turns the bulk of the macros into
static functions. GIN_SUPPORT macro still defines the datatype-specific
functions, but they are now very thin wrappers that just call the
corresponding generic static functions.

It's annoying that we need the concept of a leftmost value, for the < and <=
queries. Without that, we could have the support functions look up the
required datatype information from the type cache, based on the datatype of
the passed argument. Then you could easily use the btree_gin support
functions also for user-defined datatypes. But that needs bigger changes,
and this is a step in the right direction anyway.

I just had a look at the refactoring patch and ISTM that this is a
good step forward in terms of readability. Teodor, I am noticing that
your patch cannot apply once the refactoring is done. Could you rebase
your patch once the refactoring is pushed?s
--
Michael

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#9Heikki Linnakangas
hlinnakangas@vmware.com
In reply to: Michael Paquier (#8)
1 attachment(s)
Re: btree_gin and ranges

On 12/22/2014 03:15 AM, Michael Paquier wrote:

On Thu, Dec 18, 2014 at 4:13 AM, Heikki Linnakangas
<hlinnakangas@vmware.com> wrote:

On 10/22/2014 01:55 PM, Teodor Sigaev wrote:

Suggested patch adds GIN support contains operator for ranges over scalar
column.

It allows more effective GIN scan. Currently, queries like
SELECT * FROM test_int4 WHERE i <= 1 and i >= 1
will be excuted by GIN with two scans: one is from mines infinity to 1 and
another is from -1 to plus infinity. That's because GIN is "generalized"
and it
doesn't know a semantics of operation.

With patch it's possible to rewrite query with ranges
SELECT * FROM test_int4 WHERE i <@ '[-1, 1]'::int4range
and GIN index will support this query with single scan from -1 to 1.

Patch provides index support only for existing range types: int4, int8,
numeric,
date and timestamp with and without time zone.

I started to look at this, but very quickly got carried away into
refactoring away the macros. Defining long functions as macros makes
debugging quite difficult, and it's not nice to read or edit the source code
either.

I propose the attached refactoring (it doesn't include your range-patch yet,
just refactoring the existing code). It turns the bulk of the macros into
static functions. GIN_SUPPORT macro still defines the datatype-specific
functions, but they are now very thin wrappers that just call the
corresponding generic static functions.

It's annoying that we need the concept of a leftmost value, for the < and <=
queries. Without that, we could have the support functions look up the
required datatype information from the type cache, based on the datatype of
the passed argument. Then you could easily use the btree_gin support
functions also for user-defined datatypes. But that needs bigger changes,
and this is a step in the right direction anyway.

I just had a look at the refactoring patch and ISTM that this is a
good step forward in terms of readability. Teodor, I am noticing that
your patch cannot apply once the refactoring is done. Could you rebase
your patch once the refactoring is pushed?s

I've pushed the refactoring patch. Here's a version of Teodor's patch,
rebased over the pushed patch.

Teodor's patch could use some more comments. The
STOP_SCAN/MATCH_SCAN/CONT_SCAN macros are a good idea, but they probably
should go into src/include/access/gin.h so that they can be used in all
compare_partial implementations.

- Heikki

Attachments:

btree_gin_range-2.patchtext/x-diff; name=btree_gin_range-2.patchDownload
commit 51217bac66009f876d44ee547c25523a1b0eaeb3
Author: Heikki Linnakangas <heikki.linnakangas@iki.fi>
Date:   Mon Dec 22 17:38:40 2014 +0200

    Rebase Teodor's btree_gin_range-1.patch over my refactorings.

diff --git a/contrib/btree_gin/Makefile b/contrib/btree_gin/Makefile
index 0492091..b85c390 100644
--- a/contrib/btree_gin/Makefile
+++ b/contrib/btree_gin/Makefile
@@ -4,7 +4,7 @@ MODULE_big = btree_gin
 OBJS = btree_gin.o $(WIN32RES)
 
 EXTENSION = btree_gin
-DATA = btree_gin--1.0.sql btree_gin--unpackaged--1.0.sql
+DATA = btree_gin--1.1.sql btree_gin--1.0--1.1.sql btree_gin--unpackaged--1.0.sql
 PGFILEDESC = "btree_gin - B-tree equivalent GIN operator classes"
 
 REGRESS = install_btree_gin int2 int4 int8 float4 float8 money oid \
diff --git a/contrib/btree_gin/btree_gin--1.0--1.1.sql b/contrib/btree_gin/btree_gin--1.0--1.1.sql
new file mode 100644
index 0000000..a7f0e54
--- /dev/null
+++ b/contrib/btree_gin/btree_gin--1.0--1.1.sql
@@ -0,0 +1,7 @@
+ALTER OPERATOR FAMILY int4_ops USING gin ADD OPERATOR 8 <@(anyelement, anyrange);
+ALTER OPERATOR FAMILY int8_ops USING gin ADD OPERATOR 8 <@(anyelement, anyrange);
+ALTER OPERATOR FAMILY timestamp_ops USING gin ADD OPERATOR 8 <@(anyelement, anyrange);
+ALTER OPERATOR FAMILY timestamptz_ops USING gin ADD OPERATOR 8 <@(anyelement, anyrange);
+ALTER OPERATOR FAMILY date_ops USING gin ADD OPERATOR 8 <@(anyelement, anyrange);
+ALTER OPERATOR FAMILY numeric_ops USING gin ADD OPERATOR 8 <@(anyelement, anyrange);
+
diff --git a/contrib/btree_gin/btree_gin--1.0.sql b/contrib/btree_gin/btree_gin--1.0.sql
deleted file mode 100644
index cf867ef..0000000
--- a/contrib/btree_gin/btree_gin--1.0.sql
+++ /dev/null
@@ -1,689 +0,0 @@
-/* contrib/btree_gin/btree_gin--1.0.sql */
-
--- complain if script is sourced in psql, rather than via CREATE EXTENSION
-\echo Use "CREATE EXTENSION btree_gin" to load this file. \quit
-
-CREATE FUNCTION gin_btree_consistent(internal, int2, anyelement, int4, internal, internal)
-RETURNS bool
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION gin_extract_value_int2(int2, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION gin_compare_prefix_int2(int2, int2, int2, internal)
-RETURNS int4
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION gin_extract_query_int2(int2, internal, int2, internal, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE OPERATOR CLASS int2_ops
-DEFAULT FOR TYPE int2 USING gin
-AS
-    OPERATOR        1       <,
-    OPERATOR        2       <=,
-    OPERATOR        3       =,
-    OPERATOR        4       >=,
-    OPERATOR        5       >,
-    FUNCTION        1       btint2cmp(int2,int2),
-    FUNCTION        2       gin_extract_value_int2(int2, internal),
-    FUNCTION        3       gin_extract_query_int2(int2, internal, int2, internal, internal),
-    FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
-    FUNCTION        5       gin_compare_prefix_int2(int2,int2,int2, internal),
-STORAGE         int2;
-
-CREATE FUNCTION gin_extract_value_int4(int4, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION gin_compare_prefix_int4(int4, int4, int2, internal)
-RETURNS int4
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION gin_extract_query_int4(int4, internal, int2, internal, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE OPERATOR CLASS int4_ops
-DEFAULT FOR TYPE int4 USING gin
-AS
-    OPERATOR        1       <,
-    OPERATOR        2       <=,
-    OPERATOR        3       =,
-    OPERATOR        4       >=,
-    OPERATOR        5       >,
-    FUNCTION        1       btint4cmp(int4,int4),
-    FUNCTION        2       gin_extract_value_int4(int4, internal),
-    FUNCTION        3       gin_extract_query_int4(int4, internal, int2, internal, internal),
-    FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
-    FUNCTION        5       gin_compare_prefix_int4(int4,int4,int2, internal),
-STORAGE         int4;
-
-CREATE FUNCTION gin_extract_value_int8(int8, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION gin_compare_prefix_int8(int8, int8, int2, internal)
-RETURNS int4
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION gin_extract_query_int8(int8, internal, int2, internal, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE OPERATOR CLASS int8_ops
-DEFAULT FOR TYPE int8 USING gin
-AS
-    OPERATOR        1       <,
-    OPERATOR        2       <=,
-    OPERATOR        3       =,
-    OPERATOR        4       >=,
-    OPERATOR        5       >,
-    FUNCTION        1       btint8cmp(int8,int8),
-    FUNCTION        2       gin_extract_value_int8(int8, internal),
-    FUNCTION        3       gin_extract_query_int8(int8, internal, int2, internal, internal),
-    FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
-    FUNCTION        5       gin_compare_prefix_int8(int8,int8,int2, internal),
-STORAGE         int8;
-
-CREATE FUNCTION gin_extract_value_float4(float4, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION gin_compare_prefix_float4(float4, float4, int2, internal)
-RETURNS int4
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION gin_extract_query_float4(float4, internal, int2, internal, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE OPERATOR CLASS float4_ops
-DEFAULT FOR TYPE float4 USING gin
-AS
-    OPERATOR        1       <,
-    OPERATOR        2       <=,
-    OPERATOR        3       =,
-    OPERATOR        4       >=,
-    OPERATOR        5       >,
-    FUNCTION        1       btfloat4cmp(float4,float4),
-    FUNCTION        2       gin_extract_value_float4(float4, internal),
-    FUNCTION        3       gin_extract_query_float4(float4, internal, int2, internal, internal),
-    FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
-    FUNCTION        5       gin_compare_prefix_float4(float4,float4,int2, internal),
-STORAGE         float4;
-
-CREATE FUNCTION gin_extract_value_float8(float8, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION gin_compare_prefix_float8(float8, float8, int2, internal)
-RETURNS int4
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION gin_extract_query_float8(float8, internal, int2, internal, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE OPERATOR CLASS float8_ops
-DEFAULT FOR TYPE float8 USING gin
-AS
-    OPERATOR        1       <,
-    OPERATOR        2       <=,
-    OPERATOR        3       =,
-    OPERATOR        4       >=,
-    OPERATOR        5       >,
-    FUNCTION        1       btfloat8cmp(float8,float8),
-    FUNCTION        2       gin_extract_value_float8(float8, internal),
-    FUNCTION        3       gin_extract_query_float8(float8, internal, int2, internal, internal),
-    FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
-    FUNCTION        5       gin_compare_prefix_float8(float8,float8,int2, internal),
-STORAGE         float8;
-
-CREATE FUNCTION gin_extract_value_money(money, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION gin_compare_prefix_money(money, money, int2, internal)
-RETURNS int4
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION gin_extract_query_money(money, internal, int2, internal, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE OPERATOR CLASS money_ops
-DEFAULT FOR TYPE money USING gin
-AS
-    OPERATOR        1       <,
-    OPERATOR        2       <=,
-    OPERATOR        3       =,
-    OPERATOR        4       >=,
-    OPERATOR        5       >,
-    FUNCTION        1       cash_cmp(money,money),
-    FUNCTION        2       gin_extract_value_money(money, internal),
-    FUNCTION        3       gin_extract_query_money(money, internal, int2, internal, internal),
-    FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
-    FUNCTION        5       gin_compare_prefix_money(money,money,int2, internal),
-STORAGE         money;
-
-CREATE FUNCTION gin_extract_value_oid(oid, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION gin_compare_prefix_oid(oid, oid, int2, internal)
-RETURNS int4
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION gin_extract_query_oid(oid, internal, int2, internal, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE OPERATOR CLASS oid_ops
-DEFAULT FOR TYPE oid USING gin
-AS
-    OPERATOR        1       <,
-    OPERATOR        2       <=,
-    OPERATOR        3       =,
-    OPERATOR        4       >=,
-    OPERATOR        5       >,
-    FUNCTION        1       btoidcmp(oid,oid),
-    FUNCTION        2       gin_extract_value_oid(oid, internal),
-    FUNCTION        3       gin_extract_query_oid(oid, internal, int2, internal, internal),
-    FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
-    FUNCTION        5       gin_compare_prefix_oid(oid,oid,int2, internal),
-STORAGE         oid;
-
-CREATE FUNCTION gin_extract_value_timestamp(timestamp, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION gin_compare_prefix_timestamp(timestamp, timestamp, int2, internal)
-RETURNS int4
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION gin_extract_query_timestamp(timestamp, internal, int2, internal, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE OPERATOR CLASS timestamp_ops
-DEFAULT FOR TYPE timestamp USING gin
-AS
-    OPERATOR        1       <,
-    OPERATOR        2       <=,
-    OPERATOR        3       =,
-    OPERATOR        4       >=,
-    OPERATOR        5       >,
-    FUNCTION        1       timestamp_cmp(timestamp,timestamp),
-    FUNCTION        2       gin_extract_value_timestamp(timestamp, internal),
-    FUNCTION        3       gin_extract_query_timestamp(timestamp, internal, int2, internal, internal),
-    FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
-    FUNCTION        5       gin_compare_prefix_timestamp(timestamp,timestamp,int2, internal),
-STORAGE         timestamp;
-
-CREATE FUNCTION gin_extract_value_timestamptz(timestamptz, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION gin_compare_prefix_timestamptz(timestamptz, timestamptz, int2, internal)
-RETURNS int4
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION gin_extract_query_timestamptz(timestamptz, internal, int2, internal, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE OPERATOR CLASS timestamptz_ops
-DEFAULT FOR TYPE timestamptz USING gin
-AS
-    OPERATOR        1       <,
-    OPERATOR        2       <=,
-    OPERATOR        3       =,
-    OPERATOR        4       >=,
-    OPERATOR        5       >,
-    FUNCTION        1       timestamptz_cmp(timestamptz,timestamptz),
-    FUNCTION        2       gin_extract_value_timestamptz(timestamptz, internal),
-    FUNCTION        3       gin_extract_query_timestamptz(timestamptz, internal, int2, internal, internal),
-    FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
-    FUNCTION        5       gin_compare_prefix_timestamptz(timestamptz,timestamptz,int2, internal),
-STORAGE         timestamptz;
-
-CREATE FUNCTION gin_extract_value_time(time, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION gin_compare_prefix_time(time, time, int2, internal)
-RETURNS int4
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION gin_extract_query_time(time, internal, int2, internal, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE OPERATOR CLASS time_ops
-DEFAULT FOR TYPE time USING gin
-AS
-    OPERATOR        1       <,
-    OPERATOR        2       <=,
-    OPERATOR        3       =,
-    OPERATOR        4       >=,
-    OPERATOR        5       >,
-    FUNCTION        1       time_cmp(time,time),
-    FUNCTION        2       gin_extract_value_time(time, internal),
-    FUNCTION        3       gin_extract_query_time(time, internal, int2, internal, internal),
-    FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
-    FUNCTION        5       gin_compare_prefix_time(time,time,int2, internal),
-STORAGE         time;
-
-CREATE FUNCTION gin_extract_value_timetz(timetz, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION gin_compare_prefix_timetz(timetz, timetz, int2, internal)
-RETURNS int4
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION gin_extract_query_timetz(timetz, internal, int2, internal, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE OPERATOR CLASS timetz_ops
-DEFAULT FOR TYPE timetz USING gin
-AS
-    OPERATOR        1       <,
-    OPERATOR        2       <=,
-    OPERATOR        3       =,
-    OPERATOR        4       >=,
-    OPERATOR        5       >,
-    FUNCTION        1       timetz_cmp(timetz,timetz),
-    FUNCTION        2       gin_extract_value_timetz(timetz, internal),
-    FUNCTION        3       gin_extract_query_timetz(timetz, internal, int2, internal, internal),
-    FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
-    FUNCTION        5       gin_compare_prefix_timetz(timetz,timetz,int2, internal),
-STORAGE         timetz;
-
-CREATE FUNCTION gin_extract_value_date(date, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION gin_compare_prefix_date(date, date, int2, internal)
-RETURNS int4
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION gin_extract_query_date(date, internal, int2, internal, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE OPERATOR CLASS date_ops
-DEFAULT FOR TYPE date USING gin
-AS
-    OPERATOR        1       <,
-    OPERATOR        2       <=,
-    OPERATOR        3       =,
-    OPERATOR        4       >=,
-    OPERATOR        5       >,
-    FUNCTION        1       date_cmp(date,date),
-    FUNCTION        2       gin_extract_value_date(date, internal),
-    FUNCTION        3       gin_extract_query_date(date, internal, int2, internal, internal),
-    FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
-    FUNCTION        5       gin_compare_prefix_date(date,date,int2, internal),
-STORAGE         date;
-
-CREATE FUNCTION gin_extract_value_interval(interval, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION gin_compare_prefix_interval(interval, interval, int2, internal)
-RETURNS int4
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION gin_extract_query_interval(interval, internal, int2, internal, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE OPERATOR CLASS interval_ops
-DEFAULT FOR TYPE interval USING gin
-AS
-    OPERATOR        1       <,
-    OPERATOR        2       <=,
-    OPERATOR        3       =,
-    OPERATOR        4       >=,
-    OPERATOR        5       >,
-    FUNCTION        1       interval_cmp(interval,interval),
-    FUNCTION        2       gin_extract_value_interval(interval, internal),
-    FUNCTION        3       gin_extract_query_interval(interval, internal, int2, internal, internal),
-    FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
-    FUNCTION        5       gin_compare_prefix_interval(interval,interval,int2, internal),
-STORAGE         interval;
-
-CREATE FUNCTION gin_extract_value_macaddr(macaddr, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION gin_compare_prefix_macaddr(macaddr, macaddr, int2, internal)
-RETURNS int4
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION gin_extract_query_macaddr(macaddr, internal, int2, internal, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE OPERATOR CLASS macaddr_ops
-DEFAULT FOR TYPE macaddr USING gin
-AS
-    OPERATOR        1       <,
-    OPERATOR        2       <=,
-    OPERATOR        3       =,
-    OPERATOR        4       >=,
-    OPERATOR        5       >,
-    FUNCTION        1       macaddr_cmp(macaddr,macaddr),
-    FUNCTION        2       gin_extract_value_macaddr(macaddr, internal),
-    FUNCTION        3       gin_extract_query_macaddr(macaddr, internal, int2, internal, internal),
-    FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
-    FUNCTION        5       gin_compare_prefix_macaddr(macaddr,macaddr,int2, internal),
-STORAGE         macaddr;
-
-CREATE FUNCTION gin_extract_value_inet(inet, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION gin_compare_prefix_inet(inet, inet, int2, internal)
-RETURNS int4
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION gin_extract_query_inet(inet, internal, int2, internal, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE OPERATOR CLASS inet_ops
-DEFAULT FOR TYPE inet USING gin
-AS
-    OPERATOR        1       <,
-    OPERATOR        2       <=,
-    OPERATOR        3       =,
-    OPERATOR        4       >=,
-    OPERATOR        5       >,
-    FUNCTION        1       network_cmp(inet,inet),
-    FUNCTION        2       gin_extract_value_inet(inet, internal),
-    FUNCTION        3       gin_extract_query_inet(inet, internal, int2, internal, internal),
-    FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
-    FUNCTION        5       gin_compare_prefix_inet(inet,inet,int2, internal),
-STORAGE         inet;
-
-CREATE FUNCTION gin_extract_value_cidr(cidr, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION gin_compare_prefix_cidr(cidr, cidr, int2, internal)
-RETURNS int4
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION gin_extract_query_cidr(cidr, internal, int2, internal, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE OPERATOR CLASS cidr_ops
-DEFAULT FOR TYPE cidr USING gin
-AS
-    OPERATOR        1       <(inet,inet),
-    OPERATOR        2       <=(inet,inet),
-    OPERATOR        3       =(inet,inet),
-    OPERATOR        4       >=(inet,inet),
-    OPERATOR        5       >(inet,inet),
-    FUNCTION        1       network_cmp(inet,inet),
-    FUNCTION        2       gin_extract_value_cidr(cidr, internal),
-    FUNCTION        3       gin_extract_query_cidr(cidr, internal, int2, internal, internal),
-    FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
-    FUNCTION        5       gin_compare_prefix_cidr(cidr,cidr,int2, internal),
-STORAGE         cidr;
-
-CREATE FUNCTION gin_extract_value_text(text, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION gin_compare_prefix_text(text, text, int2, internal)
-RETURNS int4
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION gin_extract_query_text(text, internal, int2, internal, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE OPERATOR CLASS text_ops
-DEFAULT FOR TYPE text USING gin
-AS
-    OPERATOR        1       <,
-    OPERATOR        2       <=,
-    OPERATOR        3       =,
-    OPERATOR        4       >=,
-    OPERATOR        5       >,
-    FUNCTION        1       bttextcmp(text,text),
-    FUNCTION        2       gin_extract_value_text(text, internal),
-    FUNCTION        3       gin_extract_query_text(text, internal, int2, internal, internal),
-    FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
-    FUNCTION        5       gin_compare_prefix_text(text,text,int2, internal),
-STORAGE         text;
-
-CREATE OPERATOR CLASS varchar_ops
-DEFAULT FOR TYPE varchar USING gin
-AS
-    OPERATOR        1       <(text,text),
-    OPERATOR        2       <=(text,text),
-    OPERATOR        3       =(text,text),
-    OPERATOR        4       >=(text,text),
-    OPERATOR        5       >(text,text),
-    FUNCTION        1       bttextcmp(text,text),
-    FUNCTION        2       gin_extract_value_text(text, internal),
-    FUNCTION        3       gin_extract_query_text(text, internal, int2, internal, internal),
-    FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
-    FUNCTION        5       gin_compare_prefix_text(text,text,int2, internal),
-STORAGE         varchar;
-
-CREATE FUNCTION gin_extract_value_char("char", internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION gin_compare_prefix_char("char", "char", int2, internal)
-RETURNS int4
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION gin_extract_query_char("char", internal, int2, internal, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE OPERATOR CLASS char_ops
-DEFAULT FOR TYPE "char" USING gin
-AS
-    OPERATOR        1       <,
-    OPERATOR        2       <=,
-    OPERATOR        3       =,
-    OPERATOR        4       >=,
-    OPERATOR        5       >,
-    FUNCTION        1       btcharcmp("char","char"),
-    FUNCTION        2       gin_extract_value_char("char", internal),
-    FUNCTION        3       gin_extract_query_char("char", internal, int2, internal, internal),
-    FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
-    FUNCTION        5       gin_compare_prefix_char("char","char",int2, internal),
-STORAGE         "char";
-
-CREATE FUNCTION gin_extract_value_bytea(bytea, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION gin_compare_prefix_bytea(bytea, bytea, int2, internal)
-RETURNS int4
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION gin_extract_query_bytea(bytea, internal, int2, internal, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE OPERATOR CLASS bytea_ops
-DEFAULT FOR TYPE bytea USING gin
-AS
-    OPERATOR        1       <,
-    OPERATOR        2       <=,
-    OPERATOR        3       =,
-    OPERATOR        4       >=,
-    OPERATOR        5       >,
-    FUNCTION        1       byteacmp(bytea,bytea),
-    FUNCTION        2       gin_extract_value_bytea(bytea, internal),
-    FUNCTION        3       gin_extract_query_bytea(bytea, internal, int2, internal, internal),
-    FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
-    FUNCTION        5       gin_compare_prefix_bytea(bytea,bytea,int2, internal),
-STORAGE         bytea;
-
-CREATE FUNCTION gin_extract_value_bit(bit, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION gin_compare_prefix_bit(bit, bit, int2, internal)
-RETURNS int4
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION gin_extract_query_bit(bit, internal, int2, internal, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE OPERATOR CLASS bit_ops
-DEFAULT FOR TYPE bit USING gin
-AS
-    OPERATOR        1       <,
-    OPERATOR        2       <=,
-    OPERATOR        3       =,
-    OPERATOR        4       >=,
-    OPERATOR        5       >,
-    FUNCTION        1       bitcmp(bit,bit),
-    FUNCTION        2       gin_extract_value_bit(bit, internal),
-    FUNCTION        3       gin_extract_query_bit(bit, internal, int2, internal, internal),
-    FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
-    FUNCTION        5       gin_compare_prefix_bit(bit,bit,int2, internal),
-STORAGE         bit;
-
-CREATE FUNCTION gin_extract_value_varbit(varbit, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION gin_compare_prefix_varbit(varbit, varbit, int2, internal)
-RETURNS int4
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION gin_extract_query_varbit(varbit, internal, int2, internal, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE OPERATOR CLASS varbit_ops
-DEFAULT FOR TYPE varbit USING gin
-AS
-    OPERATOR        1       <,
-    OPERATOR        2       <=,
-    OPERATOR        3       =,
-    OPERATOR        4       >=,
-    OPERATOR        5       >,
-    FUNCTION        1       varbitcmp(varbit,varbit),
-    FUNCTION        2       gin_extract_value_varbit(varbit, internal),
-    FUNCTION        3       gin_extract_query_varbit(varbit, internal, int2, internal, internal),
-    FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
-    FUNCTION        5       gin_compare_prefix_varbit(varbit,varbit,int2, internal),
-STORAGE         varbit;
-
-CREATE FUNCTION gin_extract_value_numeric(numeric, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION gin_compare_prefix_numeric(numeric, numeric, int2, internal)
-RETURNS int4
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION gin_extract_query_numeric(numeric, internal, int2, internal, internal)
-RETURNS internal
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE FUNCTION gin_numeric_cmp(numeric, numeric)
-RETURNS int4
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE OPERATOR CLASS numeric_ops
-DEFAULT FOR TYPE numeric USING gin
-AS
-    OPERATOR        1       <,
-    OPERATOR        2       <=,
-    OPERATOR        3       =,
-    OPERATOR        4       >=,
-    OPERATOR        5       >,
-    FUNCTION        1       gin_numeric_cmp(numeric,numeric),
-    FUNCTION        2       gin_extract_value_numeric(numeric, internal),
-    FUNCTION        3       gin_extract_query_numeric(numeric, internal, int2, internal, internal),
-    FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
-    FUNCTION        5       gin_compare_prefix_numeric(numeric,numeric,int2, internal),
-STORAGE         numeric;
diff --git a/contrib/btree_gin/btree_gin--1.1.sql b/contrib/btree_gin/btree_gin--1.1.sql
new file mode 100644
index 0000000..c5980a1
--- /dev/null
+++ b/contrib/btree_gin/btree_gin--1.1.sql
@@ -0,0 +1,695 @@
+/* contrib/btree_gin/btree_gin--1.1.sql */
+
+-- complain if script is sourced in psql, rather than via CREATE EXTENSION
+\echo Use "CREATE EXTENSION btree_gin" to load this file. \quit
+
+CREATE FUNCTION gin_btree_consistent(internal, int2, anyelement, int4, internal, internal)
+RETURNS bool
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_extract_value_int2(int2, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_compare_prefix_int2(int2, int2, int2, internal)
+RETURNS int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_extract_query_int2(int2, internal, int2, internal, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE OPERATOR CLASS int2_ops
+DEFAULT FOR TYPE int2 USING gin
+AS
+    OPERATOR        1       <,
+    OPERATOR        2       <=,
+    OPERATOR        3       =,
+    OPERATOR        4       >=,
+    OPERATOR        5       >,
+    FUNCTION        1       btint2cmp(int2,int2),
+    FUNCTION        2       gin_extract_value_int2(int2, internal),
+    FUNCTION        3       gin_extract_query_int2(int2, internal, int2, internal, internal),
+    FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
+    FUNCTION        5       gin_compare_prefix_int2(int2,int2,int2, internal),
+STORAGE         int2;
+
+CREATE FUNCTION gin_extract_value_int4(int4, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_compare_prefix_int4(int4, int4, int2, internal)
+RETURNS int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_extract_query_int4(int4, internal, int2, internal, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE OPERATOR CLASS int4_ops
+DEFAULT FOR TYPE int4 USING gin
+AS
+    OPERATOR        1       <,
+    OPERATOR        2       <=,
+    OPERATOR        3       =,
+    OPERATOR        4       >=,
+    OPERATOR        5       >,
+	OPERATOR		8		<@(anyelement, anyrange),
+    FUNCTION        1       btint4cmp(int4,int4),
+    FUNCTION        2       gin_extract_value_int4(int4, internal),
+    FUNCTION        3       gin_extract_query_int4(int4, internal, int2, internal, internal),
+    FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
+    FUNCTION        5       gin_compare_prefix_int4(int4,int4,int2, internal),
+STORAGE         int4;
+
+CREATE FUNCTION gin_extract_value_int8(int8, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_compare_prefix_int8(int8, int8, int2, internal)
+RETURNS int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_extract_query_int8(int8, internal, int2, internal, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE OPERATOR CLASS int8_ops
+DEFAULT FOR TYPE int8 USING gin
+AS
+    OPERATOR        1       <,
+    OPERATOR        2       <=,
+    OPERATOR        3       =,
+    OPERATOR        4       >=,
+    OPERATOR        5       >,
+	OPERATOR		8		<@(anyelement, anyrange),
+    FUNCTION        1       btint8cmp(int8,int8),
+    FUNCTION        2       gin_extract_value_int8(int8, internal),
+    FUNCTION        3       gin_extract_query_int8(int8, internal, int2, internal, internal),
+    FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
+    FUNCTION        5       gin_compare_prefix_int8(int8,int8,int2, internal),
+STORAGE         int8;
+
+CREATE FUNCTION gin_extract_value_float4(float4, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_compare_prefix_float4(float4, float4, int2, internal)
+RETURNS int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_extract_query_float4(float4, internal, int2, internal, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE OPERATOR CLASS float4_ops
+DEFAULT FOR TYPE float4 USING gin
+AS
+    OPERATOR        1       <,
+    OPERATOR        2       <=,
+    OPERATOR        3       =,
+    OPERATOR        4       >=,
+    OPERATOR        5       >,
+    FUNCTION        1       btfloat4cmp(float4,float4),
+    FUNCTION        2       gin_extract_value_float4(float4, internal),
+    FUNCTION        3       gin_extract_query_float4(float4, internal, int2, internal, internal),
+    FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
+    FUNCTION        5       gin_compare_prefix_float4(float4,float4,int2, internal),
+STORAGE         float4;
+
+CREATE FUNCTION gin_extract_value_float8(float8, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_compare_prefix_float8(float8, float8, int2, internal)
+RETURNS int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_extract_query_float8(float8, internal, int2, internal, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE OPERATOR CLASS float8_ops
+DEFAULT FOR TYPE float8 USING gin
+AS
+    OPERATOR        1       <,
+    OPERATOR        2       <=,
+    OPERATOR        3       =,
+    OPERATOR        4       >=,
+    OPERATOR        5       >,
+    FUNCTION        1       btfloat8cmp(float8,float8),
+    FUNCTION        2       gin_extract_value_float8(float8, internal),
+    FUNCTION        3       gin_extract_query_float8(float8, internal, int2, internal, internal),
+    FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
+    FUNCTION        5       gin_compare_prefix_float8(float8,float8,int2, internal),
+STORAGE         float8;
+
+CREATE FUNCTION gin_extract_value_money(money, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_compare_prefix_money(money, money, int2, internal)
+RETURNS int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_extract_query_money(money, internal, int2, internal, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE OPERATOR CLASS money_ops
+DEFAULT FOR TYPE money USING gin
+AS
+    OPERATOR        1       <,
+    OPERATOR        2       <=,
+    OPERATOR        3       =,
+    OPERATOR        4       >=,
+    OPERATOR        5       >,
+    FUNCTION        1       cash_cmp(money,money),
+    FUNCTION        2       gin_extract_value_money(money, internal),
+    FUNCTION        3       gin_extract_query_money(money, internal, int2, internal, internal),
+    FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
+    FUNCTION        5       gin_compare_prefix_money(money,money,int2, internal),
+STORAGE         money;
+
+CREATE FUNCTION gin_extract_value_oid(oid, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_compare_prefix_oid(oid, oid, int2, internal)
+RETURNS int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_extract_query_oid(oid, internal, int2, internal, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE OPERATOR CLASS oid_ops
+DEFAULT FOR TYPE oid USING gin
+AS
+    OPERATOR        1       <,
+    OPERATOR        2       <=,
+    OPERATOR        3       =,
+    OPERATOR        4       >=,
+    OPERATOR        5       >,
+    FUNCTION        1       btoidcmp(oid,oid),
+    FUNCTION        2       gin_extract_value_oid(oid, internal),
+    FUNCTION        3       gin_extract_query_oid(oid, internal, int2, internal, internal),
+    FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
+    FUNCTION        5       gin_compare_prefix_oid(oid,oid,int2, internal),
+STORAGE         oid;
+
+CREATE FUNCTION gin_extract_value_timestamp(timestamp, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_compare_prefix_timestamp(timestamp, timestamp, int2, internal)
+RETURNS int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_extract_query_timestamp(timestamp, internal, int2, internal, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE OPERATOR CLASS timestamp_ops
+DEFAULT FOR TYPE timestamp USING gin
+AS
+    OPERATOR        1       <,
+    OPERATOR        2       <=,
+    OPERATOR        3       =,
+    OPERATOR        4       >=,
+    OPERATOR        5       >,
+	OPERATOR		8		<@(anyelement, anyrange),
+    FUNCTION        1       timestamp_cmp(timestamp,timestamp),
+    FUNCTION        2       gin_extract_value_timestamp(timestamp, internal),
+    FUNCTION        3       gin_extract_query_timestamp(timestamp, internal, int2, internal, internal),
+    FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
+    FUNCTION        5       gin_compare_prefix_timestamp(timestamp,timestamp,int2, internal),
+STORAGE         timestamp;
+
+CREATE FUNCTION gin_extract_value_timestamptz(timestamptz, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_compare_prefix_timestamptz(timestamptz, timestamptz, int2, internal)
+RETURNS int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_extract_query_timestamptz(timestamptz, internal, int2, internal, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE OPERATOR CLASS timestamptz_ops
+DEFAULT FOR TYPE timestamptz USING gin
+AS
+    OPERATOR        1       <,
+    OPERATOR        2       <=,
+    OPERATOR        3       =,
+    OPERATOR        4       >=,
+    OPERATOR        5       >,
+	OPERATOR		8		<@(anyelement, anyrange),
+    FUNCTION        1       timestamptz_cmp(timestamptz,timestamptz),
+    FUNCTION        2       gin_extract_value_timestamptz(timestamptz, internal),
+    FUNCTION        3       gin_extract_query_timestamptz(timestamptz, internal, int2, internal, internal),
+    FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
+    FUNCTION        5       gin_compare_prefix_timestamptz(timestamptz,timestamptz,int2, internal),
+STORAGE         timestamptz;
+
+CREATE FUNCTION gin_extract_value_time(time, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_compare_prefix_time(time, time, int2, internal)
+RETURNS int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_extract_query_time(time, internal, int2, internal, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE OPERATOR CLASS time_ops
+DEFAULT FOR TYPE time USING gin
+AS
+    OPERATOR        1       <,
+    OPERATOR        2       <=,
+    OPERATOR        3       =,
+    OPERATOR        4       >=,
+    OPERATOR        5       >,
+    FUNCTION        1       time_cmp(time,time),
+    FUNCTION        2       gin_extract_value_time(time, internal),
+    FUNCTION        3       gin_extract_query_time(time, internal, int2, internal, internal),
+    FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
+    FUNCTION        5       gin_compare_prefix_time(time,time,int2, internal),
+STORAGE         time;
+
+CREATE FUNCTION gin_extract_value_timetz(timetz, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_compare_prefix_timetz(timetz, timetz, int2, internal)
+RETURNS int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_extract_query_timetz(timetz, internal, int2, internal, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE OPERATOR CLASS timetz_ops
+DEFAULT FOR TYPE timetz USING gin
+AS
+    OPERATOR        1       <,
+    OPERATOR        2       <=,
+    OPERATOR        3       =,
+    OPERATOR        4       >=,
+    OPERATOR        5       >,
+    FUNCTION        1       timetz_cmp(timetz,timetz),
+    FUNCTION        2       gin_extract_value_timetz(timetz, internal),
+    FUNCTION        3       gin_extract_query_timetz(timetz, internal, int2, internal, internal),
+    FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
+    FUNCTION        5       gin_compare_prefix_timetz(timetz,timetz,int2, internal),
+STORAGE         timetz;
+
+CREATE FUNCTION gin_extract_value_date(date, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_compare_prefix_date(date, date, int2, internal)
+RETURNS int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_extract_query_date(date, internal, int2, internal, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE OPERATOR CLASS date_ops
+DEFAULT FOR TYPE date USING gin
+AS
+    OPERATOR        1       <,
+    OPERATOR        2       <=,
+    OPERATOR        3       =,
+    OPERATOR        4       >=,
+    OPERATOR        5       >,
+	OPERATOR		8		<@(anyelement, anyrange),
+    FUNCTION        1       date_cmp(date,date),
+    FUNCTION        2       gin_extract_value_date(date, internal),
+    FUNCTION        3       gin_extract_query_date(date, internal, int2, internal, internal),
+    FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
+    FUNCTION        5       gin_compare_prefix_date(date,date,int2, internal),
+STORAGE         date;
+
+CREATE FUNCTION gin_extract_value_interval(interval, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_compare_prefix_interval(interval, interval, int2, internal)
+RETURNS int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_extract_query_interval(interval, internal, int2, internal, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE OPERATOR CLASS interval_ops
+DEFAULT FOR TYPE interval USING gin
+AS
+    OPERATOR        1       <,
+    OPERATOR        2       <=,
+    OPERATOR        3       =,
+    OPERATOR        4       >=,
+    OPERATOR        5       >,
+    FUNCTION        1       interval_cmp(interval,interval),
+    FUNCTION        2       gin_extract_value_interval(interval, internal),
+    FUNCTION        3       gin_extract_query_interval(interval, internal, int2, internal, internal),
+    FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
+    FUNCTION        5       gin_compare_prefix_interval(interval,interval,int2, internal),
+STORAGE         interval;
+
+CREATE FUNCTION gin_extract_value_macaddr(macaddr, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_compare_prefix_macaddr(macaddr, macaddr, int2, internal)
+RETURNS int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_extract_query_macaddr(macaddr, internal, int2, internal, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE OPERATOR CLASS macaddr_ops
+DEFAULT FOR TYPE macaddr USING gin
+AS
+    OPERATOR        1       <,
+    OPERATOR        2       <=,
+    OPERATOR        3       =,
+    OPERATOR        4       >=,
+    OPERATOR        5       >,
+    FUNCTION        1       macaddr_cmp(macaddr,macaddr),
+    FUNCTION        2       gin_extract_value_macaddr(macaddr, internal),
+    FUNCTION        3       gin_extract_query_macaddr(macaddr, internal, int2, internal, internal),
+    FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
+    FUNCTION        5       gin_compare_prefix_macaddr(macaddr,macaddr,int2, internal),
+STORAGE         macaddr;
+
+CREATE FUNCTION gin_extract_value_inet(inet, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_compare_prefix_inet(inet, inet, int2, internal)
+RETURNS int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_extract_query_inet(inet, internal, int2, internal, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE OPERATOR CLASS inet_ops
+DEFAULT FOR TYPE inet USING gin
+AS
+    OPERATOR        1       <,
+    OPERATOR        2       <=,
+    OPERATOR        3       =,
+    OPERATOR        4       >=,
+    OPERATOR        5       >,
+    FUNCTION        1       network_cmp(inet,inet),
+    FUNCTION        2       gin_extract_value_inet(inet, internal),
+    FUNCTION        3       gin_extract_query_inet(inet, internal, int2, internal, internal),
+    FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
+    FUNCTION        5       gin_compare_prefix_inet(inet,inet,int2, internal),
+STORAGE         inet;
+
+CREATE FUNCTION gin_extract_value_cidr(cidr, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_compare_prefix_cidr(cidr, cidr, int2, internal)
+RETURNS int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_extract_query_cidr(cidr, internal, int2, internal, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE OPERATOR CLASS cidr_ops
+DEFAULT FOR TYPE cidr USING gin
+AS
+    OPERATOR        1       <(inet,inet),
+    OPERATOR        2       <=(inet,inet),
+    OPERATOR        3       =(inet,inet),
+    OPERATOR        4       >=(inet,inet),
+    OPERATOR        5       >(inet,inet),
+    FUNCTION        1       network_cmp(inet,inet),
+    FUNCTION        2       gin_extract_value_cidr(cidr, internal),
+    FUNCTION        3       gin_extract_query_cidr(cidr, internal, int2, internal, internal),
+    FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
+    FUNCTION        5       gin_compare_prefix_cidr(cidr,cidr,int2, internal),
+STORAGE         cidr;
+
+CREATE FUNCTION gin_extract_value_text(text, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_compare_prefix_text(text, text, int2, internal)
+RETURNS int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_extract_query_text(text, internal, int2, internal, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE OPERATOR CLASS text_ops
+DEFAULT FOR TYPE text USING gin
+AS
+    OPERATOR        1       <,
+    OPERATOR        2       <=,
+    OPERATOR        3       =,
+    OPERATOR        4       >=,
+    OPERATOR        5       >,
+    FUNCTION        1       bttextcmp(text,text),
+    FUNCTION        2       gin_extract_value_text(text, internal),
+    FUNCTION        3       gin_extract_query_text(text, internal, int2, internal, internal),
+    FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
+    FUNCTION        5       gin_compare_prefix_text(text,text,int2, internal),
+STORAGE         text;
+
+CREATE OPERATOR CLASS varchar_ops
+DEFAULT FOR TYPE varchar USING gin
+AS
+    OPERATOR        1       <(text,text),
+    OPERATOR        2       <=(text,text),
+    OPERATOR        3       =(text,text),
+    OPERATOR        4       >=(text,text),
+    OPERATOR        5       >(text,text),
+    FUNCTION        1       bttextcmp(text,text),
+    FUNCTION        2       gin_extract_value_text(text, internal),
+    FUNCTION        3       gin_extract_query_text(text, internal, int2, internal, internal),
+    FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
+    FUNCTION        5       gin_compare_prefix_text(text,text,int2, internal),
+STORAGE         varchar;
+
+CREATE FUNCTION gin_extract_value_char("char", internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_compare_prefix_char("char", "char", int2, internal)
+RETURNS int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_extract_query_char("char", internal, int2, internal, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE OPERATOR CLASS char_ops
+DEFAULT FOR TYPE "char" USING gin
+AS
+    OPERATOR        1       <,
+    OPERATOR        2       <=,
+    OPERATOR        3       =,
+    OPERATOR        4       >=,
+    OPERATOR        5       >,
+    FUNCTION        1       btcharcmp("char","char"),
+    FUNCTION        2       gin_extract_value_char("char", internal),
+    FUNCTION        3       gin_extract_query_char("char", internal, int2, internal, internal),
+    FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
+    FUNCTION        5       gin_compare_prefix_char("char","char",int2, internal),
+STORAGE         "char";
+
+CREATE FUNCTION gin_extract_value_bytea(bytea, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_compare_prefix_bytea(bytea, bytea, int2, internal)
+RETURNS int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_extract_query_bytea(bytea, internal, int2, internal, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE OPERATOR CLASS bytea_ops
+DEFAULT FOR TYPE bytea USING gin
+AS
+    OPERATOR        1       <,
+    OPERATOR        2       <=,
+    OPERATOR        3       =,
+    OPERATOR        4       >=,
+    OPERATOR        5       >,
+    FUNCTION        1       byteacmp(bytea,bytea),
+    FUNCTION        2       gin_extract_value_bytea(bytea, internal),
+    FUNCTION        3       gin_extract_query_bytea(bytea, internal, int2, internal, internal),
+    FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
+    FUNCTION        5       gin_compare_prefix_bytea(bytea,bytea,int2, internal),
+STORAGE         bytea;
+
+CREATE FUNCTION gin_extract_value_bit(bit, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_compare_prefix_bit(bit, bit, int2, internal)
+RETURNS int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_extract_query_bit(bit, internal, int2, internal, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE OPERATOR CLASS bit_ops
+DEFAULT FOR TYPE bit USING gin
+AS
+    OPERATOR        1       <,
+    OPERATOR        2       <=,
+    OPERATOR        3       =,
+    OPERATOR        4       >=,
+    OPERATOR        5       >,
+    FUNCTION        1       bitcmp(bit,bit),
+    FUNCTION        2       gin_extract_value_bit(bit, internal),
+    FUNCTION        3       gin_extract_query_bit(bit, internal, int2, internal, internal),
+    FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
+    FUNCTION        5       gin_compare_prefix_bit(bit,bit,int2, internal),
+STORAGE         bit;
+
+CREATE FUNCTION gin_extract_value_varbit(varbit, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_compare_prefix_varbit(varbit, varbit, int2, internal)
+RETURNS int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_extract_query_varbit(varbit, internal, int2, internal, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE OPERATOR CLASS varbit_ops
+DEFAULT FOR TYPE varbit USING gin
+AS
+    OPERATOR        1       <,
+    OPERATOR        2       <=,
+    OPERATOR        3       =,
+    OPERATOR        4       >=,
+    OPERATOR        5       >,
+    FUNCTION        1       varbitcmp(varbit,varbit),
+    FUNCTION        2       gin_extract_value_varbit(varbit, internal),
+    FUNCTION        3       gin_extract_query_varbit(varbit, internal, int2, internal, internal),
+    FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
+    FUNCTION        5       gin_compare_prefix_varbit(varbit,varbit,int2, internal),
+STORAGE         varbit;
+
+CREATE FUNCTION gin_extract_value_numeric(numeric, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_compare_prefix_numeric(numeric, numeric, int2, internal)
+RETURNS int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_extract_query_numeric(numeric, internal, int2, internal, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE FUNCTION gin_numeric_cmp(numeric, numeric)
+RETURNS int4
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT IMMUTABLE;
+
+CREATE OPERATOR CLASS numeric_ops
+DEFAULT FOR TYPE numeric USING gin
+AS
+    OPERATOR        1       <,
+    OPERATOR        2       <=,
+    OPERATOR        3       =,
+    OPERATOR        4       >=,
+    OPERATOR        5       >,
+	OPERATOR		8		<@(anyelement, anyrange),
+    FUNCTION        1       gin_numeric_cmp(numeric,numeric),
+    FUNCTION        2       gin_extract_value_numeric(numeric, internal),
+    FUNCTION        3       gin_extract_query_numeric(numeric, internal, int2, internal, internal),
+    FUNCTION        4       gin_btree_consistent(internal, int2, anyelement, int4, internal, internal),
+    FUNCTION        5       gin_compare_prefix_numeric(numeric,numeric,int2, internal),
+STORAGE         numeric;
diff --git a/contrib/btree_gin/btree_gin.c b/contrib/btree_gin/btree_gin.c
index 80521fb..95ce9a6 100644
--- a/contrib/btree_gin/btree_gin.c
+++ b/contrib/btree_gin/btree_gin.c
@@ -5,6 +5,8 @@
 
 #include <limits.h>
 
+#include "access/gin.h"
+#include "access/gist.h"
 #include "access/skey.h"
 #include "utils/builtins.h"
 #include "utils/bytea.h"
@@ -12,6 +14,7 @@
 #include "utils/date.h"
 #include "utils/inet.h"
 #include "utils/numeric.h"
+#include "utils/rangetypes.h"
 #include "utils/timestamp.h"
 #include "utils/varbit.h"
 
@@ -21,6 +24,8 @@ typedef struct QueryInfo
 {
 	StrategyNumber strategy;
 	Datum		datum;
+	RangeBound	lower;
+	RangeBound	upper;
 	bool		is_varlena;
 	Datum		(*typecmp) (FunctionCallInfo);
 } QueryInfo;
@@ -28,6 +33,23 @@ typedef struct QueryInfo
 
 /*** GIN support functions shared by all datatypes ***/
 
+static void
+get_bounds(Datum r, QueryInfo *data)
+{
+	RangeType	*range = DatumGetRangeType(r);
+	TypeCacheEntry *typcache;
+	bool		empty;
+
+	typcache = lookup_type_cache(RangeTypeGetOid(range), TYPECACHE_RANGE_INFO);
+	if (typcache->rngelemtype == NULL)
+		elog(ERROR, "type %u is not a range type", RangeTypeGetOid(range));
+
+	range_deserialize(typcache, range, &data->lower, &data->upper, &empty);
+
+	if (empty)
+		data->lower.infinite = data->upper.infinite = true;
+}
+
 static Datum
 gin_btree_extract_value(FunctionCallInfo fcinfo, bool is_varlena)
 {
@@ -62,15 +84,19 @@ gin_btree_extract_query(FunctionCallInfo fcinfo,
 	StrategyNumber strategy = PG_GETARG_UINT16(2);
 	bool	  **partialmatch = (bool **) PG_GETARG_POINTER(3);
 	Pointer   **extra_data = (Pointer **) PG_GETARG_POINTER(4);
+	int32	   *searchMode = (int32 *) PG_GETARG_POINTER(6);
 	Datum	   *entries = (Datum *) palloc(sizeof(Datum));
 	QueryInfo  *data = (QueryInfo *) palloc(sizeof(QueryInfo));
 	bool	   *ptr_partialmatch;
 
+	if (strategy == RTContainedByStrategyNumber /* range type */ ||
+		is_varlena)
+		datum = PointerGetDatum(PG_DETOAST_DATUM(datum));
+
 	*nentries = 1;
 	ptr_partialmatch = *partialmatch = (bool *) palloc(sizeof(bool));
 	*ptr_partialmatch = false;
-	if (is_varlena)
-		datum = PointerGetDatum(PG_DETOAST_DATUM(datum));
+	*searchMode = GIN_SEARCH_MODE_DEFAULT;
 	data->strategy = strategy;
 	data->datum = datum;
 	data->is_varlena = is_varlena;
@@ -78,7 +104,37 @@ gin_btree_extract_query(FunctionCallInfo fcinfo,
 	*extra_data = (Pointer *) palloc(sizeof(Pointer));
 	**extra_data = (Pointer) data;
 
-	switch (strategy)
+	if (strategy == RTContainedByStrategyNumber)
+	{
+		get_bounds(datum, data);
+
+		if (data->lower.infinite && data->upper.infinite)
+		{
+			*nentries = 0;
+			*searchMode = GIN_SEARCH_MODE_ALL;
+			PG_RETURN_POINTER(entries);
+		}
+		else if (data->lower.infinite)
+		{
+			data->strategy = data->upper.inclusive ?
+					BTLessEqualStrategyNumber : BTLessStrategyNumber;
+			data->datum = data->upper.val;
+		}
+		else if (data->upper.infinite)
+		{
+			data->strategy = data->lower.inclusive ?
+					BTGreaterEqualStrategyNumber : BTGreaterStrategyNumber;
+			data->datum = data->lower.val;
+		}
+		else
+		{
+			*ptr_partialmatch = true;
+			entries[0] = data->lower.val;
+			PG_RETURN_POINTER(entries);
+		}
+	}
+
+	switch (data->strategy)
 	{
 		case BTLessStrategyNumber:
 		case BTLessEqualStrategyNumber:
@@ -89,7 +145,7 @@ gin_btree_extract_query(FunctionCallInfo fcinfo,
 		case BTGreaterStrategyNumber:
 			*ptr_partialmatch = true;
 		case BTEqualStrategyNumber:
-			entries[0] = datum;
+			entries[0] = data->datum;
 			break;
 		default:
 			elog(ERROR, "unrecognized strategy number: %d", strategy);
@@ -98,6 +154,10 @@ gin_btree_extract_query(FunctionCallInfo fcinfo,
 	PG_RETURN_POINTER(entries);
 }
 
+#define STOP_SCAN	(1)
+#define	MATCH_SCAN	(0)
+#define CONT_SCAN	(-1)
+
 /*
  * Datum a is a value from extract_query method and for BTLess*
  * strategy it is a left-most value.  So, use original datum from QueryInfo
@@ -112,6 +172,36 @@ gin_btree_compare_prefix(FunctionCallInfo fcinfo)
 	int32		res,
 				cmp;
 
+	if (data->strategy == RTContainedByStrategyNumber)
+	{
+		cmp = DatumGetInt32(DirectFunctionCall2Coll(
+					data->typecmp,
+					PG_GET_COLLATION(), a, b));
+
+		if (cmp < 0)
+		{
+			cmp = DatumGetInt32(DirectFunctionCall2Coll(
+						data->typecmp,
+						PG_GET_COLLATION(), data->upper.val, b));
+			if (cmp < 0)
+				res = STOP_SCAN;
+			else if (cmp == 0)
+				res = (data->upper.inclusive) ? MATCH_SCAN : STOP_SCAN;
+			else
+				res = MATCH_SCAN;
+		}
+		else if (cmp == 0)
+		{
+			res = (data->lower.inclusive) ? MATCH_SCAN : CONT_SCAN;
+		}
+		else
+		{
+			res = STOP_SCAN;
+		}
+
+		PG_RETURN_INT32(res);
+	}
+
 	cmp = DatumGetInt32(DirectFunctionCall2Coll(
 				data->typecmp,
 				PG_GET_COLLATION(),
@@ -125,44 +215,44 @@ gin_btree_compare_prefix(FunctionCallInfo fcinfo)
 		case BTLessStrategyNumber:
 			/* If original datum > indexed one then return match */
 			if (cmp > 0)
-				res = 0;
+				res = MATCH_SCAN;
 			else
-				res = 1;
+				res = STOP_SCAN;
 			break;
 		case BTLessEqualStrategyNumber:
 			/* The same except equality */
 			if (cmp >= 0)
-				res = 0;
+				res = MATCH_SCAN;
 			else
-				res = 1;
+				res = STOP_SCAN;
 			break;
 		case BTEqualStrategyNumber:
 			if (cmp != 0)
-				res = 1;
+				res = STOP_SCAN;
 			else
-				res = 0;
+				res = MATCH_SCAN;
 			break;
 		case BTGreaterEqualStrategyNumber:
 			/* If original datum <= indexed one then return match */
 			if (cmp <= 0)
-				res = 0;
+				res = MATCH_SCAN;
 			else
-				res = 1;
+				res = STOP_SCAN;
 			break;
 		case BTGreaterStrategyNumber:
 			/* If original datum <= indexed one then return match */
 			/* If original datum == indexed one then continue scan */
 			if (cmp < 0)
-				res = 0;
+				res = MATCH_SCAN;
 			else if (cmp == 0)
-				res = -1;
+				res = CONT_SCAN;
 			else
-				res = 1;
+				res = STOP_SCAN;
 			break;
 		default:
 			elog(ERROR, "unrecognized strategy number: %d",
 				 data->strategy);
-			res = 0;
+			res = MATCH_SCAN;
 	}
 
 	PG_RETURN_INT32(res);
diff --git a/contrib/btree_gin/btree_gin.control b/contrib/btree_gin/btree_gin.control
index 3b2cb2d..d96436e 100644
--- a/contrib/btree_gin/btree_gin.control
+++ b/contrib/btree_gin/btree_gin.control
@@ -1,5 +1,5 @@
 # btree_gin extension
 comment = 'support for indexing common datatypes in GIN'
-default_version = '1.0'
+default_version = '1.1'
 module_pathname = '$libdir/btree_gin'
 relocatable = true
diff --git a/contrib/btree_gin/expected/date.out b/contrib/btree_gin/expected/date.out
index 40dfa30..162759f 100644
--- a/contrib/btree_gin/expected/date.out
+++ b/contrib/btree_gin/expected/date.out
@@ -49,3 +49,73 @@ SELECT * FROM test_date WHERE i>'2004-10-26'::date ORDER BY i;
  10-28-2004
 (2 rows)
 
+SELECT * FROM test_date WHERE i <@ '[2004-10-24, 2004-10-27]'::daterange ORDER BY i;
+     i      
+------------
+ 10-24-2004
+ 10-25-2004
+ 10-26-2004
+ 10-27-2004
+(4 rows)
+
+SELECT * FROM test_date WHERE i <@ '(2004-10-24, 2004-10-27]'::daterange ORDER BY i;
+     i      
+------------
+ 10-25-2004
+ 10-26-2004
+ 10-27-2004
+(3 rows)
+
+SELECT * FROM test_date WHERE i <@ '[2004-10-24, 2004-10-27)'::daterange ORDER BY i;
+     i      
+------------
+ 10-24-2004
+ 10-25-2004
+ 10-26-2004
+(3 rows)
+
+SELECT * FROM test_date WHERE i <@ '(2004-10-24, 2004-10-27)'::daterange ORDER BY i;
+     i      
+------------
+ 10-25-2004
+ 10-26-2004
+(2 rows)
+
+SELECT * FROM test_date WHERE i <@ daterange('2004-10-24', '2004-10-27') ORDER BY i;
+     i      
+------------
+ 10-24-2004
+ 10-25-2004
+ 10-26-2004
+(3 rows)
+
+SELECT * FROM test_date WHERE i <@ daterange(NULL, '2004-10-27') ORDER BY i;
+     i      
+------------
+ 10-23-2004
+ 10-24-2004
+ 10-25-2004
+ 10-26-2004
+(4 rows)
+
+SELECT * FROM test_date WHERE i <@ daterange('2004-10-24', NULL) ORDER BY i;
+     i      
+------------
+ 10-24-2004
+ 10-25-2004
+ 10-26-2004
+ 10-27-2004
+ 10-28-2004
+(5 rows)
+
+SELECT * FROM test_date WHERE i <@ daterange(NULL, NULL) ORDER BY i;
+     i      
+------------
+ 10-23-2004
+ 10-24-2004
+ 10-25-2004
+ 10-26-2004
+ 10-27-2004
+ 10-28-2004
+(6 rows)
+
diff --git a/contrib/btree_gin/expected/int4.out b/contrib/btree_gin/expected/int4.out
index 0f0122c..923a56c 100644
--- a/contrib/btree_gin/expected/int4.out
+++ b/contrib/btree_gin/expected/int4.out
@@ -42,3 +42,67 @@ SELECT * FROM test_int4 WHERE i>1::int4 ORDER BY i;
  3
 (2 rows)
 
+SELECT * FROM test_int4 WHERE i <@ '[-1, 1]'::int4range ORDER BY i;
+ i  
+----
+ -1
+  0
+  1
+(3 rows)
+
+SELECT * FROM test_int4 WHERE i <@ '(-1, 1]'::int4range ORDER BY i;
+ i 
+---
+ 0
+ 1
+(2 rows)
+
+SELECT * FROM test_int4 WHERE i <@ '[-1, 1)'::int4range ORDER BY i;
+ i  
+----
+ -1
+  0
+(2 rows)
+
+SELECT * FROM test_int4 WHERE i <@ '(-1, 1)'::int4range ORDER BY i;
+ i 
+---
+ 0
+(1 row)
+
+SELECT * FROM test_int4 WHERE i <@ int4range(-1, 1) ORDER BY i;
+ i  
+----
+ -1
+  0
+(2 rows)
+
+SELECT * FROM test_int4 WHERE i <@ int4range(NULL, 1) ORDER BY i;
+ i  
+----
+ -2
+ -1
+  0
+(3 rows)
+
+SELECT * FROM test_int4 WHERE i <@ int4range(-1, NULL) ORDER BY i;
+ i  
+----
+ -1
+  0
+  1
+  2
+  3
+(5 rows)
+
+SELECT * FROM test_int4 WHERE i <@ int4range(NULL, NULL) ORDER BY i;
+ i  
+----
+ -2
+ -1
+  0
+  1
+  2
+  3
+(6 rows)
+
diff --git a/contrib/btree_gin/expected/int8.out b/contrib/btree_gin/expected/int8.out
index 307e19e..c7067eb 100644
--- a/contrib/btree_gin/expected/int8.out
+++ b/contrib/btree_gin/expected/int8.out
@@ -42,3 +42,67 @@ SELECT * FROM test_int8 WHERE i>1::int8 ORDER BY i;
  3
 (2 rows)
 
+SELECT * FROM test_int8 WHERE i <@ '[-1, 1]'::int8range ORDER BY i;
+ i  
+----
+ -1
+  0
+  1
+(3 rows)
+
+SELECT * FROM test_int8 WHERE i <@ '(-1, 1]'::int8range ORDER BY i;
+ i 
+---
+ 0
+ 1
+(2 rows)
+
+SELECT * FROM test_int8 WHERE i <@ '[-1, 1)'::int8range ORDER BY i;
+ i  
+----
+ -1
+  0
+(2 rows)
+
+SELECT * FROM test_int8 WHERE i <@ '(-1, 1)'::int8range ORDER BY i;
+ i 
+---
+ 0
+(1 row)
+
+SELECT * FROM test_int8 WHERE i <@ int8range(-1, 1) ORDER BY i;
+ i  
+----
+ -1
+  0
+(2 rows)
+
+SELECT * FROM test_int8 WHERE i <@ int8range(NULL, 1) ORDER BY i;
+ i  
+----
+ -2
+ -1
+  0
+(3 rows)
+
+SELECT * FROM test_int8 WHERE i <@ int8range(-1, NULL) ORDER BY i;
+ i  
+----
+ -1
+  0
+  1
+  2
+  3
+(5 rows)
+
+SELECT * FROM test_int8 WHERE i <@ int8range(NULL, NULL) ORDER BY i;
+ i  
+----
+ -2
+ -1
+  0
+  1
+  2
+  3
+(6 rows)
+
diff --git a/contrib/btree_gin/expected/numeric.out b/contrib/btree_gin/expected/numeric.out
index f10a672..461f9d1 100644
--- a/contrib/btree_gin/expected/numeric.out
+++ b/contrib/btree_gin/expected/numeric.out
@@ -42,3 +42,67 @@ SELECT * FROM test_numeric WHERE i>'1'::numeric ORDER BY i;
  3
 (2 rows)
 
+SELECT * FROM test_numeric WHERE i <@ '[-1, 1]'::numrange ORDER BY i;
+ i  
+----
+ -1
+  0
+  1
+(3 rows)
+
+SELECT * FROM test_numeric WHERE i <@ '(-1, 1]'::numrange ORDER BY i;
+ i 
+---
+ 0
+ 1
+(2 rows)
+
+SELECT * FROM test_numeric WHERE i <@ '[-1, 1)'::numrange ORDER BY i;
+ i  
+----
+ -1
+  0
+(2 rows)
+
+SELECT * FROM test_numeric WHERE i <@ '(-1, 1)'::numrange ORDER BY i;
+ i 
+---
+ 0
+(1 row)
+
+SELECT * FROM test_numeric WHERE i <@ numrange(-1, 1) ORDER BY i;
+ i  
+----
+ -1
+  0
+(2 rows)
+
+SELECT * FROM test_numeric WHERE i <@ numrange(NULL, 1) ORDER BY i;
+ i  
+----
+ -2
+ -1
+  0
+(3 rows)
+
+SELECT * FROM test_numeric WHERE i <@ numrange(-1, NULL) ORDER BY i;
+ i  
+----
+ -1
+  0
+  1
+  2
+  3
+(5 rows)
+
+SELECT * FROM test_numeric WHERE i <@ numrange(NULL, NULL) ORDER BY i;
+ i  
+----
+ -2
+ -1
+  0
+  1
+  2
+  3
+(6 rows)
+
diff --git a/contrib/btree_gin/expected/timestamp.out b/contrib/btree_gin/expected/timestamp.out
index a236cdc..1feb7e9 100644
--- a/contrib/btree_gin/expected/timestamp.out
+++ b/contrib/btree_gin/expected/timestamp.out
@@ -49,3 +49,73 @@ SELECT * FROM test_timestamp WHERE i>'2004-10-26 08:55:08'::timestamp ORDER BY i
  Tue Oct 26 10:55:08 2004
 (2 rows)
 
+SELECT * FROM test_timestamp WHERE i <@ '[2004-10-26 04:55:08, 2004-10-26 09:55:08]'::tsrange ORDER BY i;
+            i             
+--------------------------
+ Tue Oct 26 04:55:08 2004
+ Tue Oct 26 05:55:08 2004
+ Tue Oct 26 08:55:08 2004
+ Tue Oct 26 09:55:08 2004
+(4 rows)
+
+SELECT * FROM test_timestamp WHERE i <@ '(2004-10-26 04:55:08, 2004-10-26 09:55:08]'::tsrange ORDER BY i;
+            i             
+--------------------------
+ Tue Oct 26 05:55:08 2004
+ Tue Oct 26 08:55:08 2004
+ Tue Oct 26 09:55:08 2004
+(3 rows)
+
+SELECT * FROM test_timestamp WHERE i <@ '[2004-10-26 04:55:08, 2004-10-26 09:55:08)'::tsrange ORDER BY i;
+            i             
+--------------------------
+ Tue Oct 26 04:55:08 2004
+ Tue Oct 26 05:55:08 2004
+ Tue Oct 26 08:55:08 2004
+(3 rows)
+
+SELECT * FROM test_timestamp WHERE i <@ '(2004-10-26 04:55:08, 2004-10-26 09:55:08)'::tsrange ORDER BY i;
+            i             
+--------------------------
+ Tue Oct 26 05:55:08 2004
+ Tue Oct 26 08:55:08 2004
+(2 rows)
+
+SELECT * FROM test_timestamp WHERE i <@ tsrange('2004-10-26 04:55:08', '2004-10-26 09:55:08') ORDER BY i;
+            i             
+--------------------------
+ Tue Oct 26 04:55:08 2004
+ Tue Oct 26 05:55:08 2004
+ Tue Oct 26 08:55:08 2004
+(3 rows)
+
+SELECT * FROM test_timestamp WHERE i <@ tsrange(NULL, '2004-10-26 09:55:08') ORDER BY i;
+            i             
+--------------------------
+ Tue Oct 26 03:55:08 2004
+ Tue Oct 26 04:55:08 2004
+ Tue Oct 26 05:55:08 2004
+ Tue Oct 26 08:55:08 2004
+(4 rows)
+
+SELECT * FROM test_timestamp WHERE i <@ tsrange('2004-10-26 04:55:08', NULL) ORDER BY i;
+            i             
+--------------------------
+ Tue Oct 26 04:55:08 2004
+ Tue Oct 26 05:55:08 2004
+ Tue Oct 26 08:55:08 2004
+ Tue Oct 26 09:55:08 2004
+ Tue Oct 26 10:55:08 2004
+(5 rows)
+
+SELECT * FROM test_timestamp WHERE i <@ tsrange(NULL, NULL) ORDER BY i;
+            i             
+--------------------------
+ Tue Oct 26 03:55:08 2004
+ Tue Oct 26 04:55:08 2004
+ Tue Oct 26 05:55:08 2004
+ Tue Oct 26 08:55:08 2004
+ Tue Oct 26 09:55:08 2004
+ Tue Oct 26 10:55:08 2004
+(6 rows)
+
diff --git a/contrib/btree_gin/expected/timestamptz.out b/contrib/btree_gin/expected/timestamptz.out
index d53963d..de2087b 100644
--- a/contrib/btree_gin/expected/timestamptz.out
+++ b/contrib/btree_gin/expected/timestamptz.out
@@ -49,3 +49,73 @@ SELECT * FROM test_timestamptz WHERE i>'2004-10-26 08:55:08'::timestamptz ORDER
  Tue Oct 26 10:55:08 2004 PDT
 (2 rows)
 
+SELECT * FROM test_timestamptz WHERE i <@ '[2004-10-26 04:55:08, 2004-10-26 09:55:08]'::tstzrange ORDER BY i;
+              i               
+------------------------------
+ Tue Oct 26 04:55:08 2004 PDT
+ Tue Oct 26 05:55:08 2004 PDT
+ Tue Oct 26 08:55:08 2004 PDT
+ Tue Oct 26 09:55:08 2004 PDT
+(4 rows)
+
+SELECT * FROM test_timestamptz WHERE i <@ '(2004-10-26 04:55:08, 2004-10-26 09:55:08]'::tstzrange ORDER BY i;
+              i               
+------------------------------
+ Tue Oct 26 05:55:08 2004 PDT
+ Tue Oct 26 08:55:08 2004 PDT
+ Tue Oct 26 09:55:08 2004 PDT
+(3 rows)
+
+SELECT * FROM test_timestamptz WHERE i <@ '[2004-10-26 04:55:08, 2004-10-26 09:55:08)'::tstzrange ORDER BY i;
+              i               
+------------------------------
+ Tue Oct 26 04:55:08 2004 PDT
+ Tue Oct 26 05:55:08 2004 PDT
+ Tue Oct 26 08:55:08 2004 PDT
+(3 rows)
+
+SELECT * FROM test_timestamptz WHERE i <@ '(2004-10-26 04:55:08, 2004-10-26 09:55:08)'::tstzrange ORDER BY i;
+              i               
+------------------------------
+ Tue Oct 26 05:55:08 2004 PDT
+ Tue Oct 26 08:55:08 2004 PDT
+(2 rows)
+
+SELECT * FROM test_timestamptz WHERE i <@ tstzrange('2004-10-26 04:55:08', '2004-10-26 09:55:08') ORDER BY i;
+              i               
+------------------------------
+ Tue Oct 26 04:55:08 2004 PDT
+ Tue Oct 26 05:55:08 2004 PDT
+ Tue Oct 26 08:55:08 2004 PDT
+(3 rows)
+
+SELECT * FROM test_timestamptz WHERE i <@ tstzrange(NULL, '2004-10-26 09:55:08') ORDER BY i;
+              i               
+------------------------------
+ Tue Oct 26 03:55:08 2004 PDT
+ Tue Oct 26 04:55:08 2004 PDT
+ Tue Oct 26 05:55:08 2004 PDT
+ Tue Oct 26 08:55:08 2004 PDT
+(4 rows)
+
+SELECT * FROM test_timestamptz WHERE i <@ tstzrange('2004-10-26 04:55:08', NULL) ORDER BY i;
+              i               
+------------------------------
+ Tue Oct 26 04:55:08 2004 PDT
+ Tue Oct 26 05:55:08 2004 PDT
+ Tue Oct 26 08:55:08 2004 PDT
+ Tue Oct 26 09:55:08 2004 PDT
+ Tue Oct 26 10:55:08 2004 PDT
+(5 rows)
+
+SELECT * FROM test_timestamptz WHERE i <@ tstzrange(NULL, NULL) ORDER BY i;
+              i               
+------------------------------
+ Tue Oct 26 03:55:08 2004 PDT
+ Tue Oct 26 04:55:08 2004 PDT
+ Tue Oct 26 05:55:08 2004 PDT
+ Tue Oct 26 08:55:08 2004 PDT
+ Tue Oct 26 09:55:08 2004 PDT
+ Tue Oct 26 10:55:08 2004 PDT
+(6 rows)
+
diff --git a/contrib/btree_gin/sql/date.sql b/contrib/btree_gin/sql/date.sql
index 35086f6..79f329a 100644
--- a/contrib/btree_gin/sql/date.sql
+++ b/contrib/btree_gin/sql/date.sql
@@ -20,3 +20,14 @@ SELECT * FROM test_date WHERE i<='2004-10-26'::date ORDER BY i;
 SELECT * FROM test_date WHERE i='2004-10-26'::date ORDER BY i;
 SELECT * FROM test_date WHERE i>='2004-10-26'::date ORDER BY i;
 SELECT * FROM test_date WHERE i>'2004-10-26'::date ORDER BY i;
+
+SELECT * FROM test_date WHERE i <@ '[2004-10-24, 2004-10-27]'::daterange ORDER BY i;
+SELECT * FROM test_date WHERE i <@ '(2004-10-24, 2004-10-27]'::daterange ORDER BY i;
+SELECT * FROM test_date WHERE i <@ '[2004-10-24, 2004-10-27)'::daterange ORDER BY i;
+SELECT * FROM test_date WHERE i <@ '(2004-10-24, 2004-10-27)'::daterange ORDER BY i;
+
+SELECT * FROM test_date WHERE i <@ daterange('2004-10-24', '2004-10-27') ORDER BY i;
+SELECT * FROM test_date WHERE i <@ daterange(NULL, '2004-10-27') ORDER BY i;
+SELECT * FROM test_date WHERE i <@ daterange('2004-10-24', NULL) ORDER BY i;
+SELECT * FROM test_date WHERE i <@ daterange(NULL, NULL) ORDER BY i;
+
diff --git a/contrib/btree_gin/sql/int4.sql b/contrib/btree_gin/sql/int4.sql
index 6499c29..af96aa5 100644
--- a/contrib/btree_gin/sql/int4.sql
+++ b/contrib/btree_gin/sql/int4.sql
@@ -13,3 +13,14 @@ SELECT * FROM test_int4 WHERE i<=1::int4 ORDER BY i;
 SELECT * FROM test_int4 WHERE i=1::int4 ORDER BY i;
 SELECT * FROM test_int4 WHERE i>=1::int4 ORDER BY i;
 SELECT * FROM test_int4 WHERE i>1::int4 ORDER BY i;
+
+SELECT * FROM test_int4 WHERE i <@ '[-1, 1]'::int4range ORDER BY i;
+SELECT * FROM test_int4 WHERE i <@ '(-1, 1]'::int4range ORDER BY i;
+SELECT * FROM test_int4 WHERE i <@ '[-1, 1)'::int4range ORDER BY i;
+SELECT * FROM test_int4 WHERE i <@ '(-1, 1)'::int4range ORDER BY i;
+
+SELECT * FROM test_int4 WHERE i <@ int4range(-1, 1) ORDER BY i;
+SELECT * FROM test_int4 WHERE i <@ int4range(NULL, 1) ORDER BY i;
+SELECT * FROM test_int4 WHERE i <@ int4range(-1, NULL) ORDER BY i;
+SELECT * FROM test_int4 WHERE i <@ int4range(NULL, NULL) ORDER BY i;
+
diff --git a/contrib/btree_gin/sql/int8.sql b/contrib/btree_gin/sql/int8.sql
index 4d9c287..0e3cf5f 100644
--- a/contrib/btree_gin/sql/int8.sql
+++ b/contrib/btree_gin/sql/int8.sql
@@ -13,3 +13,14 @@ SELECT * FROM test_int8 WHERE i<=1::int8 ORDER BY i;
 SELECT * FROM test_int8 WHERE i=1::int8 ORDER BY i;
 SELECT * FROM test_int8 WHERE i>=1::int8 ORDER BY i;
 SELECT * FROM test_int8 WHERE i>1::int8 ORDER BY i;
+
+SELECT * FROM test_int8 WHERE i <@ '[-1, 1]'::int8range ORDER BY i;
+SELECT * FROM test_int8 WHERE i <@ '(-1, 1]'::int8range ORDER BY i;
+SELECT * FROM test_int8 WHERE i <@ '[-1, 1)'::int8range ORDER BY i;
+SELECT * FROM test_int8 WHERE i <@ '(-1, 1)'::int8range ORDER BY i;
+
+SELECT * FROM test_int8 WHERE i <@ int8range(-1, 1) ORDER BY i;
+SELECT * FROM test_int8 WHERE i <@ int8range(NULL, 1) ORDER BY i;
+SELECT * FROM test_int8 WHERE i <@ int8range(-1, NULL) ORDER BY i;
+SELECT * FROM test_int8 WHERE i <@ int8range(NULL, NULL) ORDER BY i;
+
diff --git a/contrib/btree_gin/sql/numeric.sql b/contrib/btree_gin/sql/numeric.sql
index dbaaa2c..6289ccf 100644
--- a/contrib/btree_gin/sql/numeric.sql
+++ b/contrib/btree_gin/sql/numeric.sql
@@ -13,3 +13,14 @@ SELECT * FROM test_numeric WHERE i<='1'::numeric ORDER BY i;
 SELECT * FROM test_numeric WHERE i='1'::numeric ORDER BY i;
 SELECT * FROM test_numeric WHERE i>='1'::numeric ORDER BY i;
 SELECT * FROM test_numeric WHERE i>'1'::numeric ORDER BY i;
+
+SELECT * FROM test_numeric WHERE i <@ '[-1, 1]'::numrange ORDER BY i;
+SELECT * FROM test_numeric WHERE i <@ '(-1, 1]'::numrange ORDER BY i;
+SELECT * FROM test_numeric WHERE i <@ '[-1, 1)'::numrange ORDER BY i;
+SELECT * FROM test_numeric WHERE i <@ '(-1, 1)'::numrange ORDER BY i;
+
+SELECT * FROM test_numeric WHERE i <@ numrange(-1, 1) ORDER BY i;
+SELECT * FROM test_numeric WHERE i <@ numrange(NULL, 1) ORDER BY i;
+SELECT * FROM test_numeric WHERE i <@ numrange(-1, NULL) ORDER BY i;
+SELECT * FROM test_numeric WHERE i <@ numrange(NULL, NULL) ORDER BY i;
+
diff --git a/contrib/btree_gin/sql/timestamp.sql b/contrib/btree_gin/sql/timestamp.sql
index 56727e8..8876257 100644
--- a/contrib/btree_gin/sql/timestamp.sql
+++ b/contrib/btree_gin/sql/timestamp.sql
@@ -20,3 +20,14 @@ SELECT * FROM test_timestamp WHERE i<='2004-10-26 08:55:08'::timestamp ORDER BY
 SELECT * FROM test_timestamp WHERE i='2004-10-26 08:55:08'::timestamp ORDER BY i;
 SELECT * FROM test_timestamp WHERE i>='2004-10-26 08:55:08'::timestamp ORDER BY i;
 SELECT * FROM test_timestamp WHERE i>'2004-10-26 08:55:08'::timestamp ORDER BY i;
+
+SELECT * FROM test_timestamp WHERE i <@ '[2004-10-26 04:55:08, 2004-10-26 09:55:08]'::tsrange ORDER BY i;
+SELECT * FROM test_timestamp WHERE i <@ '(2004-10-26 04:55:08, 2004-10-26 09:55:08]'::tsrange ORDER BY i;
+SELECT * FROM test_timestamp WHERE i <@ '[2004-10-26 04:55:08, 2004-10-26 09:55:08)'::tsrange ORDER BY i;
+SELECT * FROM test_timestamp WHERE i <@ '(2004-10-26 04:55:08, 2004-10-26 09:55:08)'::tsrange ORDER BY i;
+
+SELECT * FROM test_timestamp WHERE i <@ tsrange('2004-10-26 04:55:08', '2004-10-26 09:55:08') ORDER BY i;
+SELECT * FROM test_timestamp WHERE i <@ tsrange(NULL, '2004-10-26 09:55:08') ORDER BY i;
+SELECT * FROM test_timestamp WHERE i <@ tsrange('2004-10-26 04:55:08', NULL) ORDER BY i;
+SELECT * FROM test_timestamp WHERE i <@ tsrange(NULL, NULL) ORDER BY i;
+
diff --git a/contrib/btree_gin/sql/timestamptz.sql b/contrib/btree_gin/sql/timestamptz.sql
index e6cfdb1..7058e4a 100644
--- a/contrib/btree_gin/sql/timestamptz.sql
+++ b/contrib/btree_gin/sql/timestamptz.sql
@@ -20,3 +20,14 @@ SELECT * FROM test_timestamptz WHERE i<='2004-10-26 08:55:08'::timestamptz ORDER
 SELECT * FROM test_timestamptz WHERE i='2004-10-26 08:55:08'::timestamptz ORDER BY i;
 SELECT * FROM test_timestamptz WHERE i>='2004-10-26 08:55:08'::timestamptz ORDER BY i;
 SELECT * FROM test_timestamptz WHERE i>'2004-10-26 08:55:08'::timestamptz ORDER BY i;
+
+SELECT * FROM test_timestamptz WHERE i <@ '[2004-10-26 04:55:08, 2004-10-26 09:55:08]'::tstzrange ORDER BY i;
+SELECT * FROM test_timestamptz WHERE i <@ '(2004-10-26 04:55:08, 2004-10-26 09:55:08]'::tstzrange ORDER BY i;
+SELECT * FROM test_timestamptz WHERE i <@ '[2004-10-26 04:55:08, 2004-10-26 09:55:08)'::tstzrange ORDER BY i;
+SELECT * FROM test_timestamptz WHERE i <@ '(2004-10-26 04:55:08, 2004-10-26 09:55:08)'::tstzrange ORDER BY i;
+
+SELECT * FROM test_timestamptz WHERE i <@ tstzrange('2004-10-26 04:55:08', '2004-10-26 09:55:08') ORDER BY i;
+SELECT * FROM test_timestamptz WHERE i <@ tstzrange(NULL, '2004-10-26 09:55:08') ORDER BY i;
+SELECT * FROM test_timestamptz WHERE i <@ tstzrange('2004-10-26 04:55:08', NULL) ORDER BY i;
+SELECT * FROM test_timestamptz WHERE i <@ tstzrange(NULL, NULL) ORDER BY i;
+
diff --git a/doc/src/sgml/btree-gin.sgml b/doc/src/sgml/btree-gin.sgml
index 42b9e97..92b1573 100644
--- a/doc/src/sgml/btree-gin.sgml
+++ b/doc/src/sgml/btree-gin.sgml
@@ -11,12 +11,19 @@
   <filename>btree_gin</> provides sample GIN operator classes that
   implement B-tree equivalent behavior for the data types
   <type>int2</>, <type>int4</>, <type>int8</>, <type>float4</>,
-  <type>float8</>, <type>timestamp with time zone</>,
+  <type>float8</>, <type>numeric</>, <type>timestamp with time zone</>,
   <type>timestamp without time zone</>, <type>time with time zone</>,
   <type>time without time zone</>, <type>date</>, <type>interval</>,
   <type>oid</>, <type>money</>, <type>"char"</>,
   <type>varchar</>, <type>text</>, <type>bytea</>, <type>bit</>,
-  <type>varbit</>, <type>macaddr</>, <type>inet</>, and <type>cidr</>.
+  <type>varbit</>, <type>macaddr</>, <type>inet</> and <type>cidr</>.
+ </para>
+
+ <para>
+  <filename>btree_gin</> also provides GIN index support for
+  &lt;@ <type>range</> operations for types <type>int4</>, <type>int8</>,
+  <type>numeric</>, <type>timestamp with time zone</>,
+  <type>timestamp without time zone</> and <type>date</>.
  </para>
 
  <para>
@@ -47,7 +54,7 @@ SELECT * FROM test WHERE a &lt; 10;
   <title>Authors</title>
 
   <para>
-   Teodor Sigaev (<email>teodor@stack.net</email>) and
+   Teodor Sigaev (<email>teodor@sigaev.ru</email>) and
    Oleg Bartunov (<email>oleg@sai.msu.su</email>).  See
    <ulink url="http://www.sai.msu.su/~megera/oddmuse/index.cgi/Gin"></ulink>
    for additional information.
#10Teodor Sigaev
teodor@sigaev.ru
In reply to: Heikki Linnakangas (#9)
2 attachment(s)
Re: btree_gin and ranges

Teodor's patch could use some more comments. The STOP_SCAN/MATCH_SCAN/CONT_SCAN
macros are a good idea, but they probably should go into
src/include/access/gin.h so that they can be used in all compare_partial
implementations.

STOP_SCAN/MATCH_SCAN/CONT_SCAN macros are moved to gin's header, and comments
are improved.

Split patch to two: gin and module

--
Teodor Sigaev E-mail: teodor@sigaev.ru
WWW: http://www.sigaev.ru/

Attachments:

gin_macros.patch.gzapplication/x-gzip; name=gin_macros.patch.gzDownload
btree_gin_range-3.patch.gzapplication/x-gzip; name=btree_gin_range-3.patch.gzDownload
�i9�T��{s�H����O���;�a��$�q���;�����E	���`����;����j=Q�e������sN���A:�f�|N����I�U_��6=�������������%��������I��o���Zm*w�V�N�z��.V������r9���&�v�G�x�o��]
'S�39%N�"�y����35��U�����
oKER$���o/o�}
�����L����k������QQ�(���).��Z6�-�v�������W����s���S�T��*~ ��Z��,��$��D��b�Q�jEW�P���TFch���,�#mi6����L�]���E&��>]�����h��V�j�_�����y�F��m���%�#���TEjT�r����:xQ�zrLiu|R�2�T��q��	�d���I�Y�kC�3�&y���qO
b�+K�MS��h8]�+V���N�V��
�����:�Y�AO0���
&�Dqx�w��cl
��N+me�H0��X* Nz�(�'��P������������p|7��%S]_��[r�W���������Q�z5���\�9��.�������������H>��i(�9�]�	�$Yr��m����8�A'�p����c�0�]���Oa���K�|���9���^��qT~�]��(����"�����a���~��O������7��SA�������B�����$������h�%A[�d�,���I't��t��x�*�����	�����������82<��DF��"�-FF�����h��3!c��� #��72��5�!��2�-���r��"_d�bd���#CF��3!c��� #��72d����!'D���X�^��F@�0y�C`�b�"@��q`��B��y�^��D���q��-�)~e�K<X��i�"[c�����Z6M�7ZD�	�Nz�h�����g�RD�
-��b��"�m�-I�v�^b������$��Z#G�0IH���QTeu?A�X3���a���Q���$^U�c<EX������y���!tl� Gl�h�-��B���h{�M��M�M��4s�������x@@��x0��2�$�]^��/U���P� q���)?,��j��)q���L�HM�����	S�}�#�nZ*�?$����'([�|�je������@9��HS�y�Z	�Fvbep�?�jy��`��#���y��������F:<�8�a��4A?����>��4q��)��!�o���#L^�1I����c1��D/|�����w&����='��I�����L1�������#��"G�� �`�aq�)�a��Cz���qjz���=&��;�3�%O�����7y�C$���Y{��[�qr��-�8��U�y�5��L��B������O��8�
y��g���I�^U�������
1����#�K������`�����2K��S�_3$�}=}RL��c���_�q�k&�w(�D����\�|b�
C��PS�P���
}��/<���C�f��3�.i�`��*��a
5BC��Lx�1��F�!r�
"�����B�#������.U��:�����Y�R�&���1k\E�!�5X-��!�(�!�C�����4D���@�� (:�ej�N�N���8r�;@��`���*����j��M1�{E����t;��\G���u�0��g�����������?���1i�
U�Wx|�[���#J.Aw�9������<���B~�9�^2���n�>�N�{��*�%�%V��(�>�T��1/��Dp%��$����$LJX���UB�X3���1���1���#^U�c<EX���L	~s�=�-C.�� Olh���Pr`���7�<�f�����E���gHp5�7�����
vm�����a�`��$9�E|����a�����`�����Sc$�S�1L����D�A��e�~���J�5/�l���'����|���%a���f��YX��/=,���m�;5���,5��x�C.����9^�M�'�������T����i6��Z�7���6M���!�a#P�2��tI�S��#�H�K[�������A3W��38]vN�RT��V'��������%d�d��>J���X�L�������B���%��(M��a=Xg�.�%@h'�Z��.��Uf(���|z���9;Zjm~��I�l���634�^gtNV��VM�?��.�s�H�]$�[Xf&��t�~�R+��o���b�
���)�#����^�
�;5����x���(�����|A���/������a�TMM_�+��S�z����T�Q�V��lE�R$'�����?+�D7L2������L�����0Shq��5��tmV,�<L���JbR��D��u�X����z*��#������S$%��=W�{:�5�D�*~�2�^�������]�-t���q��N�9��F��f�Ta������d;�pry���
���d�X=3�6
;$������
����gi8��*�+�����0�RO���p	J����dFW���B�A��+V/���z�|����>13��Pr�3J�iU��sm��h!Os�ip4���������o���G2W�?����C\w.��A��6+�)��J�����1����W���br1F����q�+5K��"�����`��T�����<>.y~������b-?�l_!������`S�$�u�r���j��������,��$�a��.|lHqw�E��u��$�*��O��u�����Zq����-����J���4&^K������5�)��a�R��wO�)99�8?9>!��:�����8k�)aa0]$�����fp;����>J3[Ep�����I���4��t�����
�l�i���I���	�����`t��������(��8=n��_�B{|����])�Im��W^O�G�5��J��q���@�����6�U�A}�ZX}�������V���pr�Grlm=Hb/�+�;�]M_/f�7�@U3���g�
��5�Y�N����1{��%V8n�1A`}I�>'Vekx���=]����Q�e���[�Te�f3���B1�������PV�
�V%�?��t���i@N��^_PbE�l�)U�����~��k��[n�7��HG\]Y�`-X_5����j(�am�0�H)��K��,v+�%g��w�+�g�_��"@���*��~������_�	d\ ��������Hl^�Trk�
�]����(�s����=&��?�����o�
KT�6+��!�y��&��:�JV�������a.�y���kZ�
B�� �P��4_�[�����$�E���AU���;sC��56��BO���>����`?h7����g�
m
]1������qB��wD�'!����,)X���"���@:80G��3��-a��3���p�P�Uc�UD�xvP����"��`RL�����b!��n������V,89����	��`����{K��d>|�P��)lJ�|���7�&���k��60����R(�K������1l,�0P�wpx�M�}2X&����P��������0d�`��b[\��	�fpv��_�f���+�*�P������lv�5#b��A�%�E��+�|��
A`ub���"��kcI,�������dU�)�Q�`����������6n��J���E�%�w�>��e��n>m�~���B�m���*v��P�jlH%�n"\��i:_y���#��g)��4�1^C��k���I2Y$�JO����,|�U��X�#�H�
����H�?������`���r�����6�isV����v���N�'��^�zvyb@8����S��h&�P
b���.���<���A�������04��|'�e����Q�Z�8*�}�^�����K+�u�Mg��*�p��.���q�B����3����6C��Q�OK�>�+�z���6{��<nZ6�M�fM��v��"e8��������|!����Gb���������hH���f���6��f���kVt3z?�w� �3�"����DjC��*a��1y�39���y�B��������;\��m���n�r��e�#K�C��������6���Lbi�'��NH�YK;5kZ!�|���r5S���-���>��S�����\!�F���ky�I i�#2'������%SY�<��Y�Mi�����Iw"L�����Z|'����fS���������w"�������v�&����nO�aug'j�~�>���V������#�&�����0�h����j����F�B�KJ0
���X`	�)�U'�0R�a<�H
�>i�N�|�(�a-��A����M�_�0t����:�Xq����;q�D��=�i�{�������w{t��8rb����#�#g!�,&��m��b��JM�0uJi�I;��`�4���E�>qC��8���8���4q���X�x*r��u��k�j�nc��5s��U,z�����N`v�|7����i)�,"(�*��F��GKG"�J��*eH�(1�B��;����6�����U|i*�)��\�U�dR���:��`�9��h?1������_=�uA���!I]~������>����Y�5��$P�Q�*�D�
7\����V�+Ip�o�D�+�%��y?�����G{d���{�:�"Y\���\o	7��������y�k���52��x�w�r%�7�P%���Q���������F���l���cu[b��b�������}��������(����&;����zFg�H�Y�y$7�����n����K~m+�]�X�7H��?�sP��LD0G>�'�����t����+�������fb�
)�����I�0[�po�f��]��Y���'u��vI���$
��;�l+h<�p��-�|�Z�zn�J�0�=1A��9Kt����Ah����f/�Y�4i�@u�uae������[�������y�V����f_�H}]��P_%���x���N�^��4.�0����?{v1�����W��l����&pW�|�M��n��vr�����jE������m��j�_�)�~WQ:I��t��K*o!^�(��71��ih�XL�L����
k�*�+"�l+�i[�@�J~����&������s%\�r�"�=��=�5,�j�:m��N�#���Y�r�E,��de��E���Y�Va�R�REdkm%�k+I][I��Bn�2���R���$���#�Z��:�����(���m�}UM����D�fo�d:��q�0�)����=���q��%qZ������?������Am%�i;�K�JFJ7Y'
�Z�n���r�&��n��K?Q��L������@tQ���0y�5�����>Su���a��&�`N����h��2Fv������T�4$#�U�3�v��l���z��L����{JDQ^7%G����$u��'�1q�I���3�U�)��������/|S������-�����;�����[t��I�8-��
#11Bruce Momjian
bruce@momjian.us
In reply to: Teodor Sigaev (#10)
Re: btree_gin and ranges

On Fri, Dec 26, 2014 at 01:33:26PM +0300, Teodor Sigaev wrote:

Teodor's patch could use some more comments. The STOP_SCAN/MATCH_SCAN/CONT_SCAN
macros are a good idea, but they probably should go into
src/include/access/gin.h so that they can be used in all compare_partial
implementations.

STOP_SCAN/MATCH_SCAN/CONT_SCAN macros are moved to gin's header, and
comments are improved.

Split patch to two: gin and module

Where are we on this patch?

--
Bruce Momjian <bruce@momjian.us> http://momjian.us
EnterpriseDB http://enterprisedb.com

+ Everyone has their own god. +

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

#12Alvaro Herrera
alvherre@2ndquadrant.com
In reply to: Teodor Sigaev (#10)
Re: btree_gin and ranges

Teodor Sigaev wrote:

Teodor's patch could use some more comments. The STOP_SCAN/MATCH_SCAN/CONT_SCAN
macros are a good idea, but they probably should go into
src/include/access/gin.h so that they can be used in all compare_partial
implementations.

STOP_SCAN/MATCH_SCAN/CONT_SCAN macros are moved to gin's header, and
comments are improved.

Split patch to two: gin and module

Here you forgot to "git add" the two .sql files for the extension. They
are present in the patch Heikki posted upthread but not here.

--
�lvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers