diff --git a/contrib/intarray/Makefile b/contrib/intarray/Makefile
index b3830a2dde022a9e27cd05cd0cd7f991fa7b435a..2b9a62409cd8f4760a15739aa47d4b2d79287852 100644
--- a/contrib/intarray/Makefile
+++ b/contrib/intarray/Makefile
@@ -1,7 +1,7 @@
-# $PostgreSQL: pgsql/contrib/intarray/Makefile,v 1.13 2006/02/27 12:54:39 petere Exp $
+# $PostgreSQL: pgsql/contrib/intarray/Makefile,v 1.14 2006/05/03 16:31:07 teodor Exp $
 
 MODULE_big = _int
-OBJS = _int_bool.o _int_gist.o _int_op.o _int_tool.o _intbig_gist.o 
+OBJS = _int_bool.o _int_gist.o _int_op.o _int_tool.o _intbig_gist.o _int_gin.o 
 DATA_built = _int.sql
 DATA = uninstall__int.sql
 DOCS = README.intarray
diff --git a/contrib/intarray/_int.h b/contrib/intarray/_int.h
index af67435309e4184373d67779219186ed033a6f5c..6218cbcd20dbe33c7a44d16df13ef1ff2693c422 100644
--- a/contrib/intarray/_int.h
+++ b/contrib/intarray/_int.h
@@ -151,10 +151,17 @@ typedef struct
 #define COMPUTESIZE(size)	( HDRSIZEQT + size * sizeof(ITEM) )
 #define GETQUERY(x)  (ITEM*)( (char*)(x)+HDRSIZEQT )
 
+#define END     0
+#define ERR     1
+#define VAL     2
+#define OPR     3
+#define OPEN    4
+#define CLOSE   5
+
 bool		signconsistent(QUERYTYPE * query, BITVEC sign, bool calcnot);
 bool		execconsistent(QUERYTYPE * query, ArrayType *array, bool calcnot);
-
-
+bool 		ginconsistent(QUERYTYPE * query, bool *check);
+int4 		shorterquery(ITEM * q, int4 len);
 
 int			compASC(const void *a, const void *b);
 
diff --git a/contrib/intarray/_int.sql.in b/contrib/intarray/_int.sql.in
index b9d33a7a43af44aacf75c0b5539e10f23674db43..31fae745415f083a6dca42df7bc8f89d460d55f6 100644
--- a/contrib/intarray/_int.sql.in
+++ b/contrib/intarray/_int.sql.in
@@ -6,6 +6,8 @@
 -- opclasses get created.
 SET search_path = public;
 
+BEGIN;
+
 -- Query type
 CREATE FUNCTION bqarr_in(cstring)
 RETURNS query_int
@@ -431,3 +433,35 @@ AS
 	FUNCTION	6	g_intbig_picksplit (internal, internal),
 	FUNCTION	7	g_intbig_same (internal, internal, internal),
 	STORAGE		intbig_gkey;
+
+--GIN
+--mark built-in gin's _int4_ops as non default
+update pg_opclass set opcdefault = 'f' where 
+	pg_opclass.opcamid = (select pg_am.oid from pg_am where amname='gin') and
+	opcname = '_int4_ops';
+
+CREATE FUNCTION ginint4_queryextract(internal, internal, int2)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C;
+
+CREATE FUNCTION ginint4_consistent(internal, int2, internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C;
+
+CREATE OPERATOR CLASS gin__int_ops
+DEFAULT FOR TYPE _int4 USING gin
+AS
+	OPERATOR	3	&&,
+	OPERATOR	6	= (anyarray, anyarray)	RECHECK,
+	OPERATOR	7	@,
+	OPERATOR	8	~	RECHECK,
+	OPERATOR	20	@@ (_int4, query_int),
+	FUNCTION	1	btint4cmp (int4, int4),
+	FUNCTION	2	ginarrayextract (anyarray, internal),
+	FUNCTION	3	ginint4_queryextract (internal, internal, int2),
+	FUNCTION	4	ginint4_consistent (internal, int2, internal),
+	STORAGE		int4;
+
+COMMIT;
diff --git a/contrib/intarray/_int_bool.c b/contrib/intarray/_int_bool.c
index 8e0b913c0137e458fbd76fe6d13dfa237e08130d..230c412a0486ac55fa06462cfab92323c6428094 100644
--- a/contrib/intarray/_int_bool.c
+++ b/contrib/intarray/_int_bool.c
@@ -232,7 +232,7 @@ typedef struct
  * is there value 'val' in array or not ?
  */
 static bool
-checkcondition_arr(void *checkval, int4 val)
+checkcondition_arr(void *checkval, ITEM *item)
 {
 	int4	   *StopLow = ((CHKVAL *) checkval)->arrb;
 	int4	   *StopHigh = ((CHKVAL *) checkval)->arre;
@@ -243,9 +243,9 @@ checkcondition_arr(void *checkval, int4 val)
 	while (StopLow < StopHigh)
 	{
 		StopMiddle = StopLow + (StopHigh - StopLow) / 2;
-		if (*StopMiddle == val)
+		if (*StopMiddle == item->val)
 			return (true);
-		else if (*StopMiddle < val)
+		else if (*StopMiddle < item->val)
 			StopLow = StopMiddle + 1;
 		else
 			StopHigh = StopMiddle;
@@ -254,20 +254,20 @@ checkcondition_arr(void *checkval, int4 val)
 }
 
 static bool
-checkcondition_bit(void *checkval, int4 val)
+checkcondition_bit(void *checkval, ITEM *item)
 {
-	return GETBIT(checkval, HASHVAL(val));
+	return GETBIT(checkval, HASHVAL(item->val));
 }
 
 /*
  * check for boolean condition
  */
 static bool
-execute(ITEM * curitem, void *checkval, bool calcnot, bool (*chkcond) (void *checkval, int4 val))
+execute(ITEM * curitem, void *checkval, bool calcnot, bool (*chkcond) (void *checkval, ITEM *item))
 {
 
 	if (curitem->type == VAL)
-		return (*chkcond) (checkval, curitem->val);
+		return (*chkcond) (checkval, curitem);
 	else if (curitem->val == (int4) '!')
 	{
 		return (calcnot) ?
@@ -319,6 +319,40 @@ execconsistent(QUERYTYPE * query, ArrayType *array, bool calcnot)
 		);
 }
 
+typedef struct {
+	ITEM	*first;
+	bool	*mapped_check;
+} GinChkVal;
+
+static bool
+checkcondition_gin(void *checkval, ITEM *item) {
+	GinChkVal   *gcv = (GinChkVal*)checkval;
+
+	return gcv->mapped_check[ item - gcv->first ];
+}
+
+bool
+ginconsistent(QUERYTYPE * query, bool *check) {
+	GinChkVal   gcv;
+	ITEM    *items = GETQUERY(query);
+	int i, j=0;
+
+	if ( query->size < 0 )
+		return FALSE;
+
+	gcv.first = items;
+	gcv.mapped_check = (bool*)palloc( sizeof(bool)*query->size );
+	for(i=0; i<query->size; i++)
+		if ( items[i].type == VAL ) 
+			gcv.mapped_check[ i ] = check[ j++ ];
+
+	return execute( 
+		GETQUERY(query) + query->size - 1,
+		(void *) &gcv, true,
+		checkcondition_gin
+	);
+}
+
 /*
  * boolean operations
  */
@@ -588,7 +622,7 @@ countdroptree(ITEM * q, int4 pos)
  * result of all '!' will be = 'true', so
  * we can modify query tree for clearing
  */
-static int4
+int4
 shorterquery(ITEM * q, int4 len)
 {
 	int4		index,
diff --git a/contrib/intarray/_int_gin.c b/contrib/intarray/_int_gin.c
new file mode 100644
index 0000000000000000000000000000000000000000..dfbb6e2ff1d04040d5788aa321f86a5c28bae849
--- /dev/null
+++ b/contrib/intarray/_int_gin.c
@@ -0,0 +1,100 @@
+#include "_int.h"
+
+PG_FUNCTION_INFO_V1(ginint4_queryextract);
+Datum ginint4_queryextract(PG_FUNCTION_ARGS);
+
+Datum
+ginint4_queryextract(PG_FUNCTION_ARGS) {
+	uint32  *nentries = (uint32*)PG_GETARG_POINTER(1);
+	StrategyNumber  strategy = PG_GETARG_UINT16(2);
+	Datum	*res = NULL;
+	
+	*nentries = 0;
+
+	if ( strategy == BooleanSearchStrategy ) {
+		QUERYTYPE   *query = (QUERYTYPE*)PG_DETOAST_DATUM_COPY(PG_GETARG_POINTER(0));
+		ITEM		*items = GETQUERY(query);
+		int i;
+
+		if (query->size == 0)
+			PG_RETURN_POINTER(NULL);
+
+		if ( shorterquery(items, query->size) == 0 )
+			elog(ERROR,"Query requires full scan, GIN doesn't support it");
+
+		pfree( query );
+
+		query = (QUERYTYPE*)PG_DETOAST_DATUM(PG_GETARG_POINTER(0));
+		items = GETQUERY(query);
+
+		res = (Datum*)palloc(sizeof(Datum) * query->size);
+		*nentries = 0;
+
+		for(i=0;i<query->size;i++)
+			if ( items[i].type == VAL ) { 
+				res[*nentries] = Int32GetDatum( items[i].val );
+				(*nentries)++;
+			}
+	} else {
+		ArrayType   *query = PG_GETARG_ARRAYTYPE_P(0);
+		int4 *arr;
+		uint32 i;
+
+		CHECKARRVALID(query);
+		*nentries=ARRNELEMS(query);
+		if ( *nentries > 0 ) {
+			res = (Datum*)palloc(sizeof(Datum) * (*nentries));
+
+			arr=ARRPTR(query);
+			for(i=0;i<*nentries;i++) 
+				res[i] = Int32GetDatum( arr[i] );
+		}
+	}
+
+	PG_RETURN_POINTER( res );
+}
+
+PG_FUNCTION_INFO_V1(ginint4_consistent);
+Datum ginint4_consistent(PG_FUNCTION_ARGS);
+
+Datum
+ginint4_consistent(PG_FUNCTION_ARGS) {
+    bool    *check = (bool*)PG_GETARG_POINTER(0);
+    StrategyNumber  strategy = PG_GETARG_UINT16(1);
+    int res=FALSE;
+
+    /* we can do not check array carefully, it's done by previous ginarrayextract call */
+
+    switch( strategy ) {
+        case RTOverlapStrategyNumber:
+        case RTContainedByStrategyNumber:
+            /* at least one element in check[] is true, so result = true */
+
+            res = TRUE;
+            break;
+        case RTSameStrategyNumber:
+        case RTContainsStrategyNumber:
+            res = TRUE;
+			do {
+    			ArrayType   *query = PG_GETARG_ARRAYTYPE_P(2);
+				int i, nentries=ARRNELEMS(query);
+
+            	for(i=0;i<nentries;i++)
+            	    if ( !check[i] ) {
+            	        res = FALSE;
+            	        break;
+            	    }
+			} while(0);
+            break;
+		 case BooleanSearchStrategy:
+			do {
+				QUERYTYPE	*query = (QUERYTYPE*)PG_DETOAST_DATUM(PG_GETARG_POINTER(2));
+				res = ginconsistent( query, check ); 
+			} while(0);
+			break;
+        default:
+            elog(ERROR, "ginint4_consistent: unknown strategy number: %d", strategy);
+    }
+
+    PG_RETURN_BOOL(res);
+}
diff --git a/contrib/intarray/expected/_int.out b/contrib/intarray/expected/_int.out
index 85c8d8bb1425e1115d1e3d7c607306eaba9d7f70..e45ed3cfa83a9ff40d74a086e9dce15b00df23ad 100644
--- a/contrib/intarray/expected/_int.out
+++ b/contrib/intarray/expected/_int.out
@@ -3,12 +3,12 @@
 -- does not depend on contents of _int.sql.
 --
 \set ECHO none
-psql:_int.sql:13: NOTICE:  type "query_int" is not yet defined
+psql:_int.sql:15: NOTICE:  type "query_int" is not yet defined
 DETAIL:  Creating a shell type definition.
-psql:_int.sql:18: NOTICE:  argument type query_int is only a shell
-psql:_int.sql:368: NOTICE:  type "intbig_gkey" is not yet defined
+psql:_int.sql:20: NOTICE:  argument type query_int is only a shell
+psql:_int.sql:370: NOTICE:  type "intbig_gkey" is not yet defined
 DETAIL:  Creating a shell type definition.
-psql:_int.sql:373: NOTICE:  argument type intbig_gkey is only a shell
+psql:_int.sql:375: NOTICE:  argument type intbig_gkey is only a shell
 SELECT intset(1234);
  intset 
 --------
@@ -519,3 +519,53 @@ SELECT count(*) from test__int WHERE a @@ '(20&23)|(50&68)';
     21
 (1 row)
 
+DROP INDEX text_idx;
+CREATE INDEX text_idx on test__int using gin ( a );
+SELECT count(*) from test__int WHERE a && '{23,50}';
+ count 
+-------
+   403
+(1 row)
+
+SELECT count(*) from test__int WHERE a @@ '23|50';
+ count 
+-------
+   403
+(1 row)
+
+SELECT count(*) from test__int WHERE a @ '{23,50}';
+ count 
+-------
+    12
+(1 row)
+
+SELECT count(*) from test__int WHERE a @@ '23&50';
+ count 
+-------
+    12
+(1 row)
+
+SELECT count(*) from test__int WHERE a @ '{20,23}';
+ count 
+-------
+    12
+(1 row)
+
+SELECT count(*) from test__int WHERE a @@ '50&68';
+ count 
+-------
+     9
+(1 row)
+
+SELECT count(*) from test__int WHERE a @ '{20,23}' or a @ '{50,68}';
+ count 
+-------
+    21
+(1 row)
+
+SELECT count(*) from test__int WHERE a @@ '(20&23)|(50&68)';
+ count 
+-------
+    21
+(1 row)
+
diff --git a/contrib/intarray/sql/_int.sql b/contrib/intarray/sql/_int.sql
index 5c0d00c67abc9776ba8b02b73150998ca61b1dd6..e04b88e7512b6a6e2103852936332fd9336e9045 100644
--- a/contrib/intarray/sql/_int.sql
+++ b/contrib/intarray/sql/_int.sql
@@ -107,3 +107,15 @@ SELECT count(*) from test__int WHERE a @ '{20,23}';
 SELECT count(*) from test__int WHERE a @@ '50&68';
 SELECT count(*) from test__int WHERE a @ '{20,23}' or a @ '{50,68}';
 SELECT count(*) from test__int WHERE a @@ '(20&23)|(50&68)';
+
+DROP INDEX text_idx;
+CREATE INDEX text_idx on test__int using gin ( a );
+
+SELECT count(*) from test__int WHERE a && '{23,50}';
+SELECT count(*) from test__int WHERE a @@ '23|50';
+SELECT count(*) from test__int WHERE a @ '{23,50}';
+SELECT count(*) from test__int WHERE a @@ '23&50';
+SELECT count(*) from test__int WHERE a @ '{20,23}';
+SELECT count(*) from test__int WHERE a @@ '50&68';
+SELECT count(*) from test__int WHERE a @ '{20,23}' or a @ '{50,68}';
+SELECT count(*) from test__int WHERE a @@ '(20&23)|(50&68)';
diff --git a/contrib/intarray/uninstall__int.sql b/contrib/intarray/uninstall__int.sql
index 43fd854c7ae109efae0abd747b74801d5d8a2f4f..49522b7c6c7ba55f41c8ee0fb9be0883d3dcc2b2 100644
--- a/contrib/intarray/uninstall__int.sql
+++ b/contrib/intarray/uninstall__int.sql
@@ -113,3 +113,8 @@ DROP FUNCTION boolop(_int4, query_int);
 DROP FUNCTION querytree(query_int);
 
 DROP TYPE query_int CASCADE;
+
+update pg_opclass set opcdefault = 't' where
+    pg_opclass.opcamid = (select pg_am.oid from pg_am where amname='gin') and
+	opcname = '_int4_ops';
+