Update contrib intarray to Jan 25 version.
authorBruce Momjian <[email protected]>
Sat, 17 Mar 2001 21:59:42 +0000 (21:59 +0000)
committerBruce Momjian <[email protected]>
Sat, 17 Mar 2001 21:59:42 +0000 (21:59 +0000)
contrib/intarray/Makefile
contrib/intarray/README.intarray
contrib/intarray/_int.c
contrib/intarray/_int.sql.in
contrib/intarray/bench/create_test.pl
contrib/intarray/expected/_int.out
contrib/intarray/sql/_int.sql

index b4d125b0f9827c535f51cdabfece2f793ea86fd0..3d450778250cd55a2c965b3f15d08c95136139c9 100644 (file)
@@ -1,5 +1,3 @@
-# $Header: /cvsroot/pgsql/contrib/intarray/Makefile,v 1.3 2001/02/20 19:20:27 petere Exp $
-
 subdir = contrib/intarray
 top_builddir = ../..
 include $(top_builddir)/src/Makefile.global
@@ -12,7 +10,7 @@ NAME= _int
 SO_MAJOR_VERSION= 1
 SO_MINOR_VERSION= 0
 
-override CPPFLAGS := -I$(srcdir) $(CPPFLAGS) -DPGSQL71
+override CPPFLAGS += -I$(srcdir) -DPGSQL71
 
 OBJS= _int.o
 
@@ -23,31 +21,46 @@ include $(top_srcdir)/src/Makefile.shlib
 
 
 $(NAME).sql: $(NAME).sql.in
-       sed 's,MODULE_PATHNAME,$(libdir)/$(shlib),g' $< >$@
+       sed -e 's:MODULE_PATHNAME:$(libdir)/$(shlib):g' < $< > $@
 
 .PHONY: submake
 submake:
        $(MAKE) -C $(top_builddir)/src/test/regress pg_regress
 
+# against installed postmaster
 installcheck: submake
        $(top_builddir)/src/test/regress/pg_regress _int
 
+# in-tree test doesn't work yet (no way to install my shared library)
+#check: all submake
+#      $(top_builddir)/src/test/regress/pg_regress --temp-install \
+#        --top-builddir=$(top_builddir) _int
 check:
-       @echo "'$(MAKE) check' is not supported."
-       @echo "Do '$(MAKE) install', then '$(MAKE) installcheck' instead."
+       @echo "'make check' is not supported."
+       @echo "Do 'make install', then 'make installcheck' instead."
 
 install: all installdirs install-lib
-       $(INSTALL_DATA) $(srcdir)/README.intarray $(docdir)/contrib
+       #$(INSTALL_DATA) $(srcdir)/README.$(NAME)  $(docdir)/contrib
        $(INSTALL_DATA) $(NAME).sql $(datadir)/contrib
 
 installdirs:
        $(mkinstalldirs) $(docdir)/contrib $(datadir)/contrib $(libdir)
 
 uninstall: uninstall-lib
-       rm -f $(docdir)/contrib/README.intarray $(datadir)/contrib/$(NAME).sql
+       rm -f $(docdir)/contrib/README.$(NAME) $(datadir)/contrib/$(NAME).sql
 
 clean distclean maintainer-clean: clean-lib
-       rm -f $(OBJS) $(NAME).sql
+       rm -f *.so y.tab.c y.tab.h $(OBJS) $(NAME).sql
 # things created by various check targets
-       rm -rf results
-       rm -f regression.diffs regression.out
+       rm -rf results tmp_check log
+       rm -f regression.diffs regression.out regress.out run_check.out
+ifeq ($(PORTNAME), win)
+       rm -f regress.def
+endif
+
+depend dep:
+       $(CC) -MM $(CFLAGS) *.c >depend
+
+ifeq (depend,$(wildcard depend))
+include depend
+endif
index 2829a74855a57464b378dc9799f00d99bda89595..dc7cc9a88d24572cfd46d4573648978d9f41a857 100644 (file)
@@ -1,7 +1,11 @@
 This is an implementation of RD-tree data structure using GiST interface
 of PostgreSQL. It has built-in lossy compression - must be declared
-in index creation - with (islossy). Current implementation has index support 
-for one-dimensional array of int4's.
+in index creation - with (islossy). Current implementation provides index 
+support for one-dimensional array of int4's - gist__int_ops, suitable for
+small and medium size of arrays (used on default), and gist__intbig_ops for 
+indexing large arrays (we use superimposed signature with length of 4096 
+bits to represent sets). 
+
 All work was done by Teodor Sigaev ([email protected]) and Oleg Bartunov
 ([email protected]). See http://www.sai.msu.su/~megera/postgres/gist
 for additional information.
@@ -25,7 +29,7 @@ EXAMPLE USAGE:
   -- create indices
 CREATE unique index message_key on message ( mid );
 CREATE unique index message_section_map_key2 on message_section_map (sid, mid );
-CREATE INDEX message_rdtree_idx on message using gist ( sections ) with ( islossy );
+CREATE INDEX message_rdtree_idx on message using gist ( sections gist__int_ops) with ( islossy );
 
   -- select some messages with section in 1 OR 2 - OVERLAP operator
   select message.mid from message where message.sections && '{1,2}';  
index a34b36942b232a265cadb80b1738d5a4781cd679..1e28cec6e2b092ff0b3650ee17ea459d5426d43b 100644 (file)
@@ -4,11 +4,11 @@
   format for these routines is dictated by Postgres architecture.
 ******************************************************************************/
 
-#include "postgres.h"
-
+#include <stdio.h>
 #include <float.h>
 #include <string.h>
 
+#include "postgres.h"
 #include "access/gist.h"
 #include "access/itup.h"
 #include "access/rtree.h"
@@ -32,6 +32,7 @@
 #endif
 
 #define NDIM 1
+
 #define ARRISNULL(x) ( (x) ? ( ( ARR_NDIM(x) == NDIM ) ? ( ( ARRSIZE( x ) ) ? 0 : 1 ) : 1  ) : 1 )
 #define SORT(x) if ( ARRSIZE( x ) > 1 ) isort( (void*)ARRPTR( x ), ARRSIZE( x ) );
 #define PREPAREARR(x) \
                if ( isort( (void*)ARRPTR( x ), ARRSIZE( x ) ) )\
                        x = _int_unique( x );\
        }
+
+/* bigint defines */
+#define BITBYTE 8
+#define SIGLENINT  128
+#define SIGLEN  ( sizeof(int)*SIGLENINT )
+#define SIGLENBIT (SIGLEN*BITBYTE)
+
+typedef char BITVEC[SIGLEN];
+typedef char* BITVECP;
+#define SIGPTR(x)  ( (BITVECP) ARR_DATA_PTR(x) )
+
+#define NULLIFY(a) MemSet( a, 0, sizeof( BITVEC ) )
+#define NEWSIG(a) \
+        a=(BITVECP) malloc( sizeof( BITVEC );\
+        NULLIFY(a);
+
+#define LOOPBYTE(a) \
+        for(i=0;i<SIGLEN;i++) {\
+                a;\
+        }
+
+#define LOOPBIT(a) \
+        for(i=0;i<SIGLENBIT;i++) {\
+                a;\
+        }
+
+#define getbytebit(x,i) ( *( (char*)(x) + (int)( i / BITBYTE ) ) )
+#define clrbit(x,i)   getbytebit(x,i) &= ~( 0x01 << ( i % BITBYTE ) )
+#define setbit(x,i)   getbytebit(x,i) |=  ( 0x01 << ( i % BITBYTE ) )
+#define getbit(x,i) ( getbytebit(x,i) >> ( i % BITBYTE ) & 0x01 )
+
+#define union_sig(a,b,r) LOOPBYTE(r[i] = a[i] | b[i])
+#define inter_sig(a,b,r) LOOPBYTE(r[i] = a[i] & b[i])
+
 /*
 #define GIST_DEBUG
 #define GIST_QUERY_DEBUG 
@@ -58,17 +93,46 @@ static void printarr ( ArrayType * a, int num ) {
        }
        elog(NOTICE, "\t\t%s", bbb);
 }
+static void printbitvec( BITVEC bv ) {
+        int i;
+       char str[ SIGLENBIT+1 ];
+       str[ SIGLENBIT ] ='\0';
+        LOOPBIT( str[i] = ( getbit(bv,i) ) ? '1' : '0' );
+       
+       elog(NOTICE,"BV: %s", str);
+}
 #endif
 
+/*
+** types for functions
+*/
+typedef ArrayType * (*formarray) (ArrayType*, ArrayType*);
+typedef void (*formfloat) (ArrayType*, float*);
+
 /*
 ** usefull function
 */
-bool isort( int *a, const int len );
-ArrayType * new_intArrayType( int num );
-ArrayType * copy_intArrayType( ArrayType * a );
-ArrayType * resize_intArrayType( ArrayType * a, int num );
-int internal_size( int *a, int len );
-ArrayType * _int_unique( ArrayType * a );
+static bool isort( int *a, const int len );
+static ArrayType * new_intArrayType( int num );
+static ArrayType * copy_intArrayType( ArrayType * a );
+static ArrayType * resize_intArrayType( ArrayType * a, int num );
+static int internal_size( int *a, int len );
+static ArrayType * _int_unique( ArrayType * a );
+
+/* common gist function*/
+static GIST_SPLITVEC *  _int_common_picksplit(bytea *entryvec, 
+               GIST_SPLITVEC *v, 
+               formarray unionf, 
+               formarray interf, 
+               formfloat sizef);
+static float * _int_common_penalty(GISTENTRY *origentry, 
+               GISTENTRY *newentry, 
+               float *result,
+               formarray unionf,
+               formfloat sizef);
+static ArrayType * _int_common_union(bytea *entryvec, 
+               int *sizep, 
+               formarray unionf);
 
 /* 
 ** GiST support methods
@@ -78,7 +142,6 @@ GISTENTRY *      g_int_compress(GISTENTRY *entry);
 GISTENTRY *      g_int_decompress(GISTENTRY *entry);
 float *          g_int_penalty(GISTENTRY *origentry, GISTENTRY *newentry, float *result);
 GIST_SPLITVEC *  g_int_picksplit(bytea *entryvec, GIST_SPLITVEC *v);
-bool             g_int_internal_consistent(ArrayType *key, ArrayType *query, StrategyNumber strategy);
 ArrayType *            g_int_union(bytea *entryvec, int *sizep);
 bool *           g_int_same(ArrayType *b1, ArrayType *b2, bool *result);
 
@@ -100,6 +163,23 @@ ArrayType *    _int_union(ArrayType *a, ArrayType *b);
 ArrayType *    _int_inter(ArrayType *a, ArrayType *b);
 void     rt__int_size(ArrayType *a, float* sz);
 
+/*
+** _intbig methods
+*/
+bool             g_intbig_consistent(GISTENTRY *entry, ArrayType *query, StrategyNumber strategy);
+GISTENTRY *      g_intbig_compress(GISTENTRY *entry);
+GISTENTRY *      g_intbig_decompress(GISTENTRY *entry);
+float *          g_intbig_penalty(GISTENTRY *origentry, GISTENTRY *newentry, float *result);
+GIST_SPLITVEC *  g_intbig_picksplit(bytea *entryvec, GIST_SPLITVEC *v);
+ArrayType *      g_intbig_union(bytea *entryvec, int *sizep);
+bool *           g_intbig_same(ArrayType *a, ArrayType *b, bool *result);
+
+static bool     _intbig_contains(ArrayType *a, ArrayType *b);
+static bool     _intbig_overlap(ArrayType *a, ArrayType *b);
+static ArrayType *    _intbig_union(ArrayType *a, ArrayType *b);
+/*static ArrayType *    _intbig_inter(ArrayType *a, ArrayType *b);*/
+static void     rt__intbig_size(ArrayType *a, float* sz);
+static void gensign(BITVEC sign, int * a, int len);
 
 /*****************************************************************************
  *                         GiST functions
@@ -116,51 +196,33 @@ g_int_consistent(GISTENTRY *entry,
               ArrayType *query,
               StrategyNumber strategy)
 {
+    bool retval;
    
     /* sort query for fast search, key is already sorted */
     if ( ARRISNULL( query ) ) return FALSE; 
     PREPAREARR( query );    
-    /*
-    ** if entry is not leaf, use g_int_internal_consistent,
-    ** else use g_int_leaf_consistent
-    */
-    return(g_int_internal_consistent((ArrayType *)(entry->pred), query, strategy));
+
+    switch(strategy) {
+    case RTOverlapStrategyNumber:
+      retval = (bool)inner_int_overlap((ArrayType *)(entry->pred), query);
+      break;
+    case RTSameStrategyNumber:
+    case RTContainsStrategyNumber:
+      retval = (bool)inner_int_contains((ArrayType *)(entry->pred), query);
+      break;
+    case RTContainedByStrategyNumber:
+      retval = (bool)inner_int_overlap((ArrayType *)(entry->pred), query);
+      break;
+    default:
+      retval = FALSE;
+    }
+    return(retval);
 }
 
-/*
-** The GiST Union method for _intments
-** returns the minimal set that encloses all the entries in entryvec
-*/
 ArrayType *
 g_int_union(bytea *entryvec, int *sizep)
 {
-    int numranges, i;
-    ArrayType *out = (ArrayType *)NULL;
-    ArrayType *tmp;
-
-    numranges = (VARSIZE(entryvec) - VARHDRSZ)/sizeof(GISTENTRY); 
-    tmp = (ArrayType *)(((GISTENTRY *)(VARDATA(entryvec)))[0]).pred;
-
-#ifdef GIST_DEBUG
-    elog(NOTICE, "union %d", numranges);
-#endif
-
-    for (i = 1; i < numranges; i++) {
-       out = inner_int_union(tmp, (ArrayType *)
-                                (((GISTENTRY *)(VARDATA(entryvec)))[i]).pred);
-       if (i > 1 && tmp) pfree(tmp);
-       tmp = out;
-    }
-
-    *sizep = VARSIZE( out );
-#ifdef GIST_DEBUG
-    elog(NOTICE, "\t ENDunion %d %d", *sizep, ARRSIZE( out ) );
-#endif
-    if ( *sizep == 0 ) {
-       pfree( out );
-       return NULL;
-    }
-    return(out);
+       return _int_common_union( entryvec, sizep, inner_int_union );
 }
 
 /*
@@ -194,7 +256,6 @@ g_int_compress(GISTENTRY *entry)
 
 #ifdef GIST_DEBUG
     elog(NOTICE, "COMP IN: %d leaf; %d rel; %d page; %d offset; %d bytes; %d elems", entry->leafkey, (int)entry->rel, (int)entry->page, (int)entry->offset, (int)entry->bytes, len);
-    /* printarr( r, len ); */
 #endif
 
     if ( len >= 2*MAXNUMRANGE ) {  /*compress*/
@@ -260,7 +321,6 @@ g_int_decompress(GISTENTRY *entry)
 
 #ifdef GIST_DEBUG
     elog(NOTICE, "DECOMP IN: %d leaf; %d rel; %d page; %d offset; %d bytes; %d elems", entry->leafkey, (int)entry->rel, (int)entry->page, (int)entry->offset, (int)entry->bytes, lenin);
-    /* printarr( in, lenin ); */
 #endif
 
     lenr = internal_size(din, lenin);
@@ -287,180 +347,19 @@ g_int_decompress(GISTENTRY *entry)
 float *
 g_int_penalty(GISTENTRY *origentry, GISTENTRY *newentry, float *result)
 {
-    Datum ud;
-    float tmp1, tmp2;
-    
-#ifdef GIST_DEBUG
-    elog(NOTICE, "penalty");
-#endif
-    ud = (Datum)inner_int_union((ArrayType *)(origentry->pred), (ArrayType *)(newentry->pred));
-    rt__int_size((ArrayType *)ud, &tmp1);
-    rt__int_size((ArrayType *)(origentry->pred), &tmp2);
-    *result = tmp1 - tmp2;
-    pfree((char *)ud);
-
-#ifdef GIST_DEBUG
-    elog(NOTICE, "--penalty\t%g", *result);
-#endif
-
-    return(result);
+    return _int_common_penalty( origentry, newentry, result, inner_int_union, rt__int_size);
 }
 
 
-
-/*
-** The GiST PickSplit method for _intments
-** We use Guttman's poly time split algorithm 
-*/
 GIST_SPLITVEC *
 g_int_picksplit(bytea *entryvec,
              GIST_SPLITVEC *v)
 {
-    OffsetNumber i, j;
-    ArrayType *datum_alpha, *datum_beta;
-    ArrayType *datum_l, *datum_r;
-    ArrayType *union_d, *union_dl, *union_dr;
-    ArrayType *inter_d;
-    bool firsttime;
-    float size_alpha, size_beta, size_union, size_inter;
-    float size_waste, waste;
-    float size_l, size_r;
-    int nbytes;
-    OffsetNumber seed_1 = 0, seed_2 = 0;
-    OffsetNumber *left, *right;
-    OffsetNumber maxoff;
-
-#ifdef GIST_DEBUG
-    elog(NOTICE, "--------picksplit %d",(VARSIZE(entryvec) - VARHDRSZ)/sizeof(GISTENTRY));
-#endif
-
-    maxoff = ((VARSIZE(entryvec) - VARHDRSZ)/sizeof(GISTENTRY)) - 2;
-    nbytes =  (maxoff + 2) * sizeof(OffsetNumber);
-    v->spl_left = (OffsetNumber *) palloc(nbytes);
-    v->spl_right = (OffsetNumber *) palloc(nbytes);
-    
-    firsttime = true;
-    waste = 0.0;
-    
-    for (i = FirstOffsetNumber; i < maxoff; i = OffsetNumberNext(i)) {
-       datum_alpha = (ArrayType *)(((GISTENTRY *)(VARDATA(entryvec)))[i].pred);
-       for (j = OffsetNumberNext(i); j <= maxoff; j = OffsetNumberNext(j)) {
-           datum_beta = (ArrayType *)(((GISTENTRY *)(VARDATA(entryvec)))[j].pred);
-           
-           /* compute the wasted space by unioning these guys */
-           /* size_waste = size_union - size_inter; */
-           union_d = (ArrayType *)inner_int_union(datum_alpha, datum_beta);
-           rt__int_size(union_d, &size_union);
-           inter_d = (ArrayType *)inner_int_inter(datum_alpha, datum_beta);
-           rt__int_size(inter_d, &size_inter);
-           size_waste = size_union - size_inter;
-           
-           pfree(union_d);
-           
-           if (inter_d != (ArrayType *) NULL)
-               pfree(inter_d);
-           
-           /*
-            *  are these a more promising split that what we've
-            *  already seen?
-            */
-           
-           if (size_waste > waste || firsttime) {
-               waste = size_waste;
-               seed_1 = i;
-               seed_2 = j;
-               firsttime = false;
-           }
-       }
-    }
-   
-    left = v->spl_left;
-    v->spl_nleft = 0;
-    right = v->spl_right;
-    v->spl_nright = 0;
-  
-    datum_alpha = (ArrayType *)(((GISTENTRY *)(VARDATA(entryvec)))[seed_1].pred);
-    datum_l     = copy_intArrayType( datum_alpha ); 
-    rt__int_size((ArrayType *)datum_l, &size_l);
-    datum_beta  = (ArrayType *)(((GISTENTRY *)(VARDATA(entryvec)))[seed_2].pred);
-    datum_r     = copy_intArrayType( datum_beta  ); 
-    rt__int_size((ArrayType *)datum_r, &size_r);
-    
-    /*
-     *  Now split up the regions between the two seeds.  An important
-     *  property of this split algorithm is that the split vector v
-     *  has the indices of items to be split in order in its left and
-     *  right vectors.  We exploit this property by doing a merge in
-     *  the code that actually splits the page.
-     *
-     *  For efficiency, we also place the new index tuple in this loop.
-     *  This is handled at the very end, when we have placed all the
-     *  existing tuples and i == maxoff + 1.
-     */
-    
-    maxoff = OffsetNumberNext(maxoff);
-    for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) {
-
-       
-       /*
-        *  If we've already decided where to place this item, just
-        *  put it on the right list.  Otherwise, we need to figure
-        *  out which page needs the least enlargement in order to
-        *  store the item.
-        */
-       
-       if (i == seed_1) {
-           *left++ = i;
-           v->spl_nleft++;
-           continue;
-       } else if (i == seed_2) {
-           *right++ = i;
-           v->spl_nright++;
-           continue;
-       }
-       
-       /* okay, which page needs least enlargement? */ 
-       datum_alpha = (ArrayType *)(((GISTENTRY *)(VARDATA(entryvec)))[i].pred);
-       union_dl = (ArrayType *)inner_int_union(datum_l, datum_alpha);
-       union_dr = (ArrayType *)inner_int_union(datum_r, datum_alpha);
-       rt__int_size((ArrayType *)union_dl, &size_alpha);
-       rt__int_size((ArrayType *)union_dr, &size_beta);
-
-       /* pick which page to add it to */
-       if (size_alpha - size_l < size_beta - size_r) {
-           if ( datum_l ) pfree(datum_l);
-           if ( union_dr ) pfree(union_dr);
-           datum_l = union_dl;
-           size_l = size_alpha;
-           *left++ = i;
-           v->spl_nleft++;
-       } else {
-           if ( datum_r ) pfree(datum_r);
-           if ( union_dl ) pfree(union_dl);
-           datum_r = union_dr;
-           size_r = size_beta;
-           *right++ = i;
-           v->spl_nright++;
-       }
-    }
-    /**left = *right = FirstOffsetNumber;*/  /* sentinel value, see dosplit() */
-
-    if ( *(left-1) > *(right-1) ) { 
-        *right = FirstOffsetNumber;
-        *(left-1) = InvalidOffsetNumber;
-    } else {
-        *left = FirstOffsetNumber;
-        *(right-1) = InvalidOffsetNumber;
-    }
-
 
-    v->spl_ldatum = (char *)datum_l;
-    v->spl_rdatum = (char *)datum_r;
-
-#ifdef GIST_DEBUG
-    elog(NOTICE, "--------ENDpicksplit %d %d",v->spl_nleft, v->spl_nright);
-#endif
-    return v;
+       return _int_common_picksplit( entryvec, v, 
+               inner_int_union, 
+               inner_int_inter,
+               rt__int_size);  
 }
 
 /*
@@ -478,34 +377,6 @@ g_int_same(ArrayType *b1, ArrayType *b2, bool *result)
   return(result);
 }
 
-bool 
-g_int_internal_consistent(ArrayType *key,
-                       ArrayType *query,
-                       StrategyNumber strategy)
-{
-    bool retval;
-
-#ifdef GIST_QUERY_DEBUG
-  elog(NOTICE, "internal_consistent, %d", strategy);
-#endif
-
-    switch(strategy) {
-    case RTOverlapStrategyNumber:
-      retval = (bool)inner_int_overlap(key, query);
-      break;
-    case RTSameStrategyNumber:
-    case RTContainsStrategyNumber:
-      retval = (bool)inner_int_contains(key, query);
-      break;
-    case RTContainedByStrategyNumber:
-      retval = (bool)inner_int_overlap(key, query);
-      break;
-    default:
-      retval = FALSE;
-    }
-    return(retval);
-}
-
 bool
 _int_contained(ArrayType *a, ArrayType *b)
 {
@@ -653,7 +524,7 @@ inner_int_union ( ArrayType *a, ArrayType *b ) {
        int i,j;
 
 #ifdef GIST_DEBUG
-    /* elog(NOTICE, "inner_union %d %d", ARRISNULL( a ) , ARRISNULL( b ) ); */
+    elog(NOTICE, "inner_union %d %d", ARRISNULL( a ) , ARRISNULL( b ) );
 #endif
 
        if ( ARRISNULL( a ) && ARRISNULL( b ) ) return new_intArrayType(0);
@@ -709,7 +580,7 @@ inner_int_inter ( ArrayType *a, ArrayType *b ) {
        int i,j;
 
 #ifdef GIST_DEBUG
-    /* elog(NOTICE, "inner_inter %d %d", ARRISNULL( a ), ARRISNULL( b ) ); */
+    elog(NOTICE, "inner_inter %d %d", ARRISNULL( a ), ARRISNULL( b ) );
 #endif
 
        if ( ARRISNULL( a ) || ARRISNULL( b ) ) return NULL;
@@ -756,7 +627,8 @@ rt__int_size(ArrayType *a, float *size)
  *****************************************************************************/
 
 /* len >= 2 */
-bool isort ( int *a, int len ) {
+static bool 
+isort ( int *a, int len ) {
         int tmp, index;
         int *cur, *end;
        bool r = FALSE;
@@ -776,7 +648,8 @@ bool isort ( int *a, int len ) {
        return r;
 }
 
-ArrayType * new_intArrayType( int num ) {
+static ArrayType * 
+new_intArrayType( int num ) {
        ArrayType * r;
        int nbytes = ARR_OVERHEAD( NDIM ) + sizeof(int)*num;
        
@@ -795,7 +668,8 @@ ArrayType * new_intArrayType( int num ) {
        return r;       
 } 
 
-ArrayType * resize_intArrayType( ArrayType * a, int num ) {
+static ArrayType * 
+resize_intArrayType( ArrayType * a, int num ) {
        int nbytes = ARR_OVERHEAD( NDIM ) + sizeof(int)*num;
 
        if ( num == ARRSIZE(a) ) return a;
@@ -809,7 +683,8 @@ ArrayType * resize_intArrayType( ArrayType * a, int num ) {
        return a;
 }
 
-ArrayType * copy_intArrayType( ArrayType * a ) {
+static ArrayType * 
+copy_intArrayType( ArrayType * a ) {
        ArrayType * r;
        if ( ! a ) return NULL;
        r = new_intArrayType( ARRSIZE(a) );
@@ -818,7 +693,8 @@ ArrayType * copy_intArrayType( ArrayType * a ) {
 }
 
 /* num for compressed key */
-int internal_size (int *a, int len ) {
+static int 
+internal_size (int *a, int len ) {
         int i,size=0;
 
         for(i=0;i<len;i+=2)
@@ -829,7 +705,8 @@ int internal_size (int *a, int len ) {
 }
 
 /* r is sorted and size of r > 1 */
-ArrayType * _int_unique( ArrayType * r ) {
+static ArrayType * 
+_int_unique( ArrayType * r ) {
        int *tmp, *dr, *data;
        int num = ARRSIZE(r);
        data = tmp = dr = ARRPTR( r );
@@ -839,4 +716,510 @@ ArrayType * _int_unique( ArrayType * r ) {
                else 
                        tmp++; 
        return resize_intArrayType(r, dr + 1 - ARRPTR(r) );
-}      
+}
+
+/*********************************************************************
+** intbig functions
+*********************************************************************/
+
+static void 
+gensign(BITVEC sign, int * a, int len) {
+        int i;
+        NULLIFY(sign);
+        for(i=0; i<len; i++) {
+                setbit( sign, *a%SIGLENBIT );
+                a++;
+        }
+}
+
+static bool  
+_intbig_overlap(ArrayType *a, ArrayType *b) {
+       int i;
+       BITVECP da, db;
+       
+       if ( ARRISNULL( a ) || ARRISNULL( b ) ) return FALSE;
+       da = SIGPTR(a);
+       db = SIGPTR(b);
+
+       LOOPBYTE( if ( da[i] & db[i] ) return TRUE );
+       return FALSE;
+}
+
+static bool     
+_intbig_contains(ArrayType *a, ArrayType *b) {
+       int i;
+       BITVECP da, db;
+       
+       if ( ARRISNULL( a ) || ARRISNULL( b ) ) return FALSE;
+       da = SIGPTR(a);
+       db = SIGPTR(b);
+
+       LOOPBYTE( if ( db[i] & ~da[i] ) return FALSE );
+
+       return TRUE;
+}
+
+static void     
+rt__intbig_size(ArrayType *a, float* sz) {
+       int i, len=0;
+       BITVECP bv;
+
+       if ( ARRISNULL( a ) ) {
+               *sz=0.0;
+               return;
+       }
+
+       bv = SIGPTR(a);
+       LOOPBIT( len += getbit(bv, i) );
+       *sz = (float) len;
+       return;
+}
+
+static ArrayType *    
+_intbig_union(ArrayType *a, ArrayType *b) {
+        ArrayType * r = NULL;
+        BITVECP da, db, dr;
+        int i;
+       
+        if ( ARRISNULL( a ) && ARRISNULL( b ) ) return new_intArrayType(0);
+        if ( ARRISNULL( a ) ) {
+               r = copy_intArrayType( b );
+               return r;
+       }
+        if ( ARRISNULL( b ) ) {
+               r = copy_intArrayType( a );
+               return r;
+       }
+       
+       r = new_intArrayType( SIGLENINT );
+
+       da = SIGPTR(a);
+       db = SIGPTR(b);
+       dr = SIGPTR(r);
+
+       LOOPBYTE(dr[i] = da[i] | db[i]);
+
+        return r;
+} 
+/*
+static ArrayType *    
+_intbig_inter(ArrayType *a, ArrayType *b) {
+        ArrayType * r = NULL;
+        BITVECP da, db, dr;
+        int i;
+        
+        if ( ARRISNULL( a ) || ARRISNULL( b ) ) return NULL;
+
+       r = new_intArrayType( SIGLENINT );
+
+       da = SIGPTR(a);
+       db = SIGPTR(b);
+       dr = SIGPTR(r);
+
+       LOOPBYTE(dr[i] = da[i] & db[i]);
+
+        return r;
+} 
+*/
+bool *
+g_intbig_same(ArrayType *a, ArrayType *b, bool *result) {
+       BITVECP da, db;
+       int i;
+
+       if ( ARRISNULL( a ) || ARRISNULL( b ) ) {
+               *result = ( ARRISNULL( a ) && ARRISNULL( b ) ) ? TRUE : FALSE;
+               return result;
+       }
+
+       da = SIGPTR(a);
+       db = SIGPTR(b);
+
+       LOOPBYTE(
+               if ( da[i] != db[i] ) {
+                       *result = FALSE;
+                       return result;
+               }
+       );
+
+       *result = TRUE;
+       return result;
+}
+
+GISTENTRY *      
+g_intbig_compress(GISTENTRY *entry) {
+       GISTENTRY *retval;
+       ArrayType *r, *in;
+#ifdef PGSQL71
+       if ( entry->pred ) 
+               in = (ArrayType *)PG_DETOAST_DATUM( entry->pred );
+       else 
+               in = NULL;
+#else
+       in = (ArrayType *) entry->pred;
+#endif
+
+       if ( ! entry->leafkey ) return entry;
+       
+       retval = palloc(sizeof(GISTENTRY));
+       if ( ! retval )
+               elog(ERROR,"Can't allocate memory for compression");
+
+       if ( ARRISNULL( in ) )  {
+#ifdef PGSQL71 
+               if ( in ) if ( (char*)in != (char*)entry->pred ) pfree(in);
+#endif
+               gistentryinit(*retval, (char *)NULL, entry->rel, entry->page, entry->offset,0, FALSE);
+               return( retval );
+       }
+       
+       r = new_intArrayType( SIGLENINT );
+       gensign( SIGPTR( r ), 
+                ARRPTR ( in ),
+                ARRSIZE( in ) );
+       
+       gistentryinit(*retval, (char *)r, entry->rel, entry->page, entry->offset, VARSIZE( r ), FALSE);
+
+#ifdef PGSQL71 
+       if ( in ) if ( (char*)in != (char*)entry->pred ) pfree(in);
+#endif
+
+       return(retval);
+}
+
+GISTENTRY *      
+g_intbig_decompress(GISTENTRY *entry) {
+       return entry;
+}
+
+GIST_SPLITVEC *  
+g_intbig_picksplit(bytea *entryvec, GIST_SPLITVEC *v) {
+
+    OffsetNumber k;
+    ArrayType *datum_l, *datum_r, *datum_alpha;
+    ArrayType *unionarr;
+    float size_l, size_r;
+    int nbytes;
+    OffsetNumber *left, *right;
+    OffsetNumber maxoff;
+
+#ifdef GIST_DEBUG
+    elog(NOTICE, "--------picksplit %d",(VARSIZE(entryvec) - VARHDRSZ)/sizeof(GISTENTRY));
+#endif
+
+    maxoff = ((VARSIZE(entryvec) - VARHDRSZ)/sizeof(GISTENTRY)) - 2;
+    nbytes =  (maxoff + 2) * sizeof(OffsetNumber);
+    v->spl_left = (OffsetNumber *) palloc(nbytes);
+    v->spl_right = (OffsetNumber *) palloc(nbytes);
+    left = v->spl_left;
+    v->spl_nleft = 0;
+    right = v->spl_right;
+    v->spl_nright = 0;
+    
+    maxoff = OffsetNumberNext(maxoff);
+    datum_l = datum_r = NULL;
+    
+    for (k = FirstOffsetNumber; k <= maxoff; k = OffsetNumberNext(k)) {
+       datum_alpha = (ArrayType *)(((GISTENTRY *)(VARDATA(entryvec)))[k].pred);
+
+       if ( k != FirstOffsetNumber ) {
+           unionarr = (ArrayType *)_intbig_union(datum_l, datum_alpha);
+           if ( datum_l ) pfree(datum_l);
+           datum_l = unionarr;
+           rt__intbig_size((ArrayType *)unionarr, &size_l);
+           *left++ = k;
+           v->spl_nleft++;
+       } else {
+           unionarr = (ArrayType *)_intbig_union(datum_r, datum_alpha);
+           if ( datum_r ) pfree(datum_r);
+           datum_r = unionarr;
+           rt__intbig_size((ArrayType *)unionarr, &size_r);
+           *right++ = k;
+           v->spl_nright++;
+       }
+    }
+
+    if ( *(left-1) > *(right-1) ) { 
+        *right = FirstOffsetNumber;
+        *(left-1) = InvalidOffsetNumber;
+    } else {
+        *left = FirstOffsetNumber;
+        *(right-1) = InvalidOffsetNumber;
+    }
+
+
+    v->spl_ldatum = (char *)datum_l;
+    v->spl_rdatum = (char *)datum_r;
+
+#ifdef GIST_DEBUG
+    elog(NOTICE, "--------ENDpicksplit %d %d",v->spl_nleft, v->spl_nright);
+#endif
+    return v;
+}
+
+ArrayType *      
+g_intbig_union(bytea *entryvec, int *sizep) {
+    return _int_common_union( entryvec, sizep, _intbig_union );
+}
+
+float *          
+g_intbig_penalty(GISTENTRY *origentry, GISTENTRY *newentry, float *result){
+    _int_common_penalty( origentry, newentry, result, _intbig_union, rt__intbig_size);
+    *result= SIGLENBIT - *result;
+    return result;
+}
+
+bool             
+g_intbig_consistent(GISTENTRY *entry, ArrayType *query, StrategyNumber strategy) {
+    bool retval;
+    ArrayType * q = new_intArrayType( SIGLENINT );
+
+    if ( ARRISNULL( query ) ) return FALSE;
+
+    gensign(   SIGPTR( q ),
+               ARRPTR( query ),
+               ARRSIZE( query ) );
+
+    switch(strategy) {
+    case RTOverlapStrategyNumber:
+      retval = (bool)_intbig_overlap((ArrayType *)(entry->pred), q);
+      break;
+    case RTSameStrategyNumber:
+    case RTContainsStrategyNumber:
+      retval = (bool)_intbig_contains((ArrayType *)(entry->pred), q);
+      break;
+    case RTContainedByStrategyNumber:
+      retval = (bool)_intbig_overlap((ArrayType *)(entry->pred), q);
+      break;
+    default:
+      retval = FALSE;
+    }
+    pfree( q );
+    return(retval);
+}
+
+/*****************************************************************
+** Common GiST Method
+*****************************************************************/
+
+/*
+** The GiST Union method for _intments
+** returns the minimal set that encloses all the entries in entryvec
+*/
+ArrayType *      
+_int_common_union(bytea *entryvec, int *sizep, formarray unionf) {
+    int numranges, i;
+    ArrayType *out = (ArrayType *)NULL;
+    ArrayType *tmp;
+#ifdef GIST_DEBUG
+    elog(NOTICE, "_int_common_union in");
+#endif
+    numranges = (VARSIZE(entryvec) - VARHDRSZ)/sizeof(GISTENTRY); 
+    tmp = (ArrayType *)(((GISTENTRY *)(VARDATA(entryvec)))[0]).pred;
+
+    for (i = 1; i < numranges; i++) {
+       out = (*unionf)(tmp, (ArrayType *)
+                                (((GISTENTRY *)(VARDATA(entryvec)))[i]).pred);
+       if (i > 1 && tmp) pfree(tmp);
+       tmp = out;
+    }
+
+    *sizep = VARSIZE( out );
+    if ( *sizep == 0 ) {
+       pfree( out );
+#ifdef GIST_DEBUG
+    elog(NOTICE, "_int_common_union out1");
+#endif
+       return NULL;
+    }
+#ifdef GIST_DEBUG
+    elog(NOTICE, "_int_common_union out");
+#endif
+    return(out);
+
+}
+
+/*
+** The GiST Penalty method for _intments
+*/
+float *
+_int_common_penalty(GISTENTRY *origentry, GISTENTRY *newentry, float *result,
+               formarray unionf,
+               formfloat sizef)
+{
+    Datum ud;
+    float tmp1, tmp2;
+    
+#ifdef GIST_DEBUG
+    elog(NOTICE, "penalty");
+#endif
+    ud = (Datum)(*unionf)((ArrayType *)(origentry->pred), (ArrayType *)(newentry->pred));
+    (*sizef)((ArrayType *)ud, &tmp1);
+    (*sizef)((ArrayType *)(origentry->pred), &tmp2);
+    *result = tmp1 - tmp2;
+    pfree((char *)ud);
+
+#ifdef GIST_DEBUG
+    elog(NOTICE, "--penalty\t%g", *result);
+#endif
+
+    return(result);
+}
+
+/*
+** The GiST PickSplit method for _intments
+** We use Guttman's poly time split algorithm 
+*/
+GIST_SPLITVEC *
+_int_common_picksplit(bytea *entryvec,
+               GIST_SPLITVEC *v,
+               formarray unionf,
+               formarray interf,
+               formfloat sizef)
+{
+    OffsetNumber i, j;
+    ArrayType *datum_alpha, *datum_beta;
+    ArrayType *datum_l, *datum_r;
+    ArrayType *union_d, *union_dl, *union_dr;
+    ArrayType *inter_d;
+    bool firsttime;
+    float size_alpha, size_beta, size_union, size_inter;
+    float size_waste, waste;
+    float size_l, size_r;
+    int nbytes;
+    OffsetNumber seed_1 = 0, seed_2 = 0;
+    OffsetNumber *left, *right;
+    OffsetNumber maxoff;
+
+#ifdef GIST_DEBUG
+    elog(NOTICE, "--------picksplit %d",(VARSIZE(entryvec) - VARHDRSZ)/sizeof(GISTENTRY));
+#endif
+
+    maxoff = ((VARSIZE(entryvec) - VARHDRSZ)/sizeof(GISTENTRY)) - 2;
+    nbytes =  (maxoff + 2) * sizeof(OffsetNumber);
+    v->spl_left = (OffsetNumber *) palloc(nbytes);
+    v->spl_right = (OffsetNumber *) palloc(nbytes);
+    
+    firsttime = true;
+    waste = 0.0;
+    
+    for (i = FirstOffsetNumber; i < maxoff; i = OffsetNumberNext(i)) {
+       datum_alpha = (ArrayType *)(((GISTENTRY *)(VARDATA(entryvec)))[i].pred);
+       for (j = OffsetNumberNext(i); j <= maxoff; j = OffsetNumberNext(j)) {
+           datum_beta = (ArrayType *)(((GISTENTRY *)(VARDATA(entryvec)))[j].pred);
+           
+           /* compute the wasted space by unioning these guys */
+           /* size_waste = size_union - size_inter; */
+           union_d = (*unionf)(datum_alpha, datum_beta);
+           (*sizef)(union_d, &size_union);
+           inter_d = (*interf)(datum_alpha, datum_beta);
+           (*sizef)(inter_d, &size_inter);
+           size_waste = size_union - size_inter;
+           
+           pfree(union_d);
+           
+           if (inter_d != (ArrayType *) NULL)
+               pfree(inter_d);
+           
+           /*
+            *  are these a more promising split that what we've
+            *  already seen?
+            */
+           
+           if (size_waste > waste || firsttime) {
+               waste = size_waste;
+               seed_1 = i;
+               seed_2 = j;
+               firsttime = false;
+           }
+       }
+    }
+   
+    left = v->spl_left;
+    v->spl_nleft = 0;
+    right = v->spl_right;
+    v->spl_nright = 0;
+  
+    datum_alpha = (ArrayType *)(((GISTENTRY *)(VARDATA(entryvec)))[seed_1].pred);
+    datum_l     = copy_intArrayType( datum_alpha ); 
+    (*sizef)((ArrayType *)datum_l, &size_l);
+    datum_beta  = (ArrayType *)(((GISTENTRY *)(VARDATA(entryvec)))[seed_2].pred);
+    datum_r     = copy_intArrayType( datum_beta  ); 
+    (*sizef)((ArrayType *)datum_r, &size_r);
+    
+    /*
+     *  Now split up the regions between the two seeds.  An important
+     *  property of this split algorithm is that the split vector v
+     *  has the indices of items to be split in order in its left and
+     *  right vectors.  We exploit this property by doing a merge in
+     *  the code that actually splits the page.
+     *
+     *  For efficiency, we also place the new index tuple in this loop.
+     *  This is handled at the very end, when we have placed all the
+     *  existing tuples and i == maxoff + 1.
+     */
+    
+    maxoff = OffsetNumberNext(maxoff);
+    for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) {
+
+       
+       /*
+        *  If we've already decided where to place this item, just
+        *  put it on the right list.  Otherwise, we need to figure
+        *  out which page needs the least enlargement in order to
+        *  store the item.
+        */
+       
+       if (i == seed_1) {
+           *left++ = i;
+           v->spl_nleft++;
+           continue;
+       } else if (i == seed_2) {
+           *right++ = i;
+           v->spl_nright++;
+           continue;
+       }
+       
+       /* okay, which page needs least enlargement? */ 
+       datum_alpha = (ArrayType *)(((GISTENTRY *)(VARDATA(entryvec)))[i].pred);
+       union_dl = (ArrayType *)(*unionf)(datum_l, datum_alpha);
+       union_dr = (ArrayType *)(*unionf)(datum_r, datum_alpha);
+       (*sizef)((ArrayType *)union_dl, &size_alpha);
+       (*sizef)((ArrayType *)union_dr, &size_beta);
+
+       /* pick which page to add it to */
+       if (size_alpha - size_l < size_beta - size_r) {
+           if ( datum_l ) pfree(datum_l);
+           if ( union_dr ) pfree(union_dr);
+           datum_l = union_dl;
+           size_l = size_alpha;
+           *left++ = i;
+           v->spl_nleft++;
+       } else {
+           if ( datum_r ) pfree(datum_r);
+           if ( union_dl ) pfree(union_dl);
+           datum_r = union_dr;
+           size_r = size_beta;
+           *right++ = i;
+           v->spl_nright++;
+       }
+    }
+    /**left = *right = FirstOffsetNumber;*/  /* sentinel value, see dosplit() */
+
+    if ( *(left-1) > *(right-1) ) { 
+        *right = FirstOffsetNumber;
+        *(left-1) = InvalidOffsetNumber;
+    } else {
+        *left = FirstOffsetNumber;
+        *(right-1) = InvalidOffsetNumber;
+    }
+
+
+    v->spl_ldatum = (char *)datum_l;
+    v->spl_rdatum = (char *)datum_r;
+
+#ifdef GIST_DEBUG
+    elog(NOTICE, "--------ENDpicksplit %d %d",v->spl_nleft, v->spl_nright);
+#endif
+    return v;
+}
index ffd384afb21794fac5d9734b17b9fd6b65145dd2..2214bef21f19044848c0d32adb5213e3016ab83c 100644 (file)
@@ -1,4 +1,4 @@
--- Create the user-defined type for the 1-D frloating point indervals (_int4)
+-- Create the user-defined type for the 1-D integer arrays (_int4)
 -- 
 BEGIN TRANSACTION;
 
@@ -208,4 +208,116 @@ INSERT INTO pg_amproc (amid, amopclaid, amproc, amprocnum)
    WHERE  amname = 'gist' and opcname = 'gist__int_ops'
       and proname = 'g_int_same';
 
+
+---------------------------------------------
+-- intbig
+---------------------------------------------
+-- define the GiST support methods
+CREATE FUNCTION g_intbig_consistent(opaque,_int4,int4) RETURNS bool
+       AS 'MODULE_PATHNAME' LANGUAGE 'c';
+
+CREATE FUNCTION g_intbig_compress(opaque) RETURNS opaque 
+       AS 'MODULE_PATHNAME' LANGUAGE 'c';
+
+CREATE FUNCTION g_intbig_decompress(opaque) RETURNS opaque 
+       AS 'MODULE_PATHNAME' LANGUAGE 'c';
+
+CREATE FUNCTION g_intbig_penalty(opaque,opaque,opaque) RETURNS opaque
+       AS 'MODULE_PATHNAME' LANGUAGE 'c';
+
+CREATE FUNCTION g_intbig_picksplit(opaque, opaque) RETURNS opaque
+       AS 'MODULE_PATHNAME' LANGUAGE 'c';
+
+CREATE FUNCTION g_intbig_union(bytea, opaque) RETURNS _int4 
+       AS 'MODULE_PATHNAME' LANGUAGE 'c';
+
+CREATE FUNCTION g_intbig_same(_int4, _int4, opaque) RETURNS opaque 
+       AS 'MODULE_PATHNAME' LANGUAGE 'c';
+
+-- register the default opclass for indexing
+INSERT INTO pg_opclass (opcname, opcdeftype)
+   values ( 'gist__intbig_ops', 0 );
+
+
+-- get the comparators for _intments and store them in a tmp table
+SELECT o.oid AS opoid, o.oprname
+INTO TABLE _int_ops_tmp
+FROM pg_operator o, pg_type t
+WHERE o.oprleft = t.oid and o.oprright = t.oid
+   and t.typname = '_int4';
+
+-- make sure we have the right operators
+-- SELECT * from _int_ops_tmp;
+
+-- using the tmp table, generate the amop entries 
+
+-- _int_overlap
+INSERT INTO pg_amop (amopid, amopclaid, amopopr, amopstrategy)
+   SELECT am.oid, opcl.oid, c.opoid, 3
+   FROM pg_am am, pg_opclass opcl, _int_ops_tmp c
+   WHERE amname = 'gist' and opcname = 'gist__intbig_ops' 
+      and c.oprname = '&&';
+
+-- _int_contains
+INSERT INTO pg_amop (amopid, amopclaid, amopopr, amopstrategy)
+   SELECT am.oid, opcl.oid, c.opoid, 7
+   FROM pg_am am, pg_opclass opcl, _int_ops_tmp c
+   WHERE amname = 'gist' and opcname = 'gist__intbig_ops' 
+      and c.oprname = '@';
+
+-- _int_contained
+INSERT INTO pg_amop (amopid, amopclaid, amopopr, amopstrategy)
+   SELECT am.oid, opcl.oid, c.opoid, 8
+   FROM pg_am am, pg_opclass opcl, _int_ops_tmp c
+   WHERE amname = 'gist' and opcname = 'gist__intbig_ops' 
+      and c.oprname = '~';
+
+DROP TABLE _int_ops_tmp;
+
+
+-- add the entries to amproc for the support methods
+-- note the amprocnum numbers associated with each are specific!
+
+INSERT INTO pg_amproc (amid, amopclaid, amproc, amprocnum)
+   SELECT am.oid, opcl.oid, pro.oid, 1
+   FROM pg_am am, pg_opclass opcl, pg_proc pro
+   WHERE  amname = 'gist' and opcname = 'gist__intbig_ops'
+      and proname = 'g_intbig_consistent';
+
+INSERT INTO pg_amproc (amid, amopclaid, amproc, amprocnum)
+   SELECT am.oid, opcl.oid, pro.oid, 2
+   FROM pg_am am, pg_opclass opcl, pg_proc pro
+   WHERE  amname = 'gist' and opcname = 'gist__intbig_ops'
+      and proname = 'g_intbig_union';
+
+INSERT INTO pg_amproc (amid, amopclaid, amproc, amprocnum)
+   SELECT am.oid, opcl.oid, pro.oid, 3
+   FROM pg_am am, pg_opclass opcl, pg_proc pro
+   WHERE  amname = 'gist' and opcname = 'gist__intbig_ops'
+      and proname = 'g_intbig_compress';
+
+INSERT INTO pg_amproc (amid, amopclaid, amproc, amprocnum)
+   SELECT am.oid, opcl.oid, pro.oid, 4
+   FROM pg_am am, pg_opclass opcl, pg_proc pro
+   WHERE  amname = 'gist' and opcname = 'gist__intbig_ops'
+      and proname = 'g_intbig_decompress';
+
+INSERT INTO pg_amproc (amid, amopclaid, amproc, amprocnum)
+   SELECT am.oid, opcl.oid, pro.oid, 5
+   FROM pg_am am, pg_opclass opcl, pg_proc pro
+   WHERE  amname = 'gist' and opcname = 'gist__intbig_ops'
+      and proname = 'g_intbig_penalty';
+
+INSERT INTO pg_amproc (amid, amopclaid, amproc, amprocnum)
+   SELECT am.oid, opcl.oid, pro.oid, 6
+   FROM pg_am am, pg_opclass opcl, pg_proc pro
+   WHERE  amname = 'gist' and opcname = 'gist__intbig_ops'
+      and proname = 'g_intbig_picksplit';
+
+INSERT INTO pg_amproc (amid, amopclaid, amproc, amprocnum)
+   SELECT am.oid, opcl.oid, pro.oid, 7
+   FROM pg_am am, pg_opclass opcl, pg_proc pro
+   WHERE  amname = 'gist' and opcname = 'gist__intbig_ops'
+      and proname = 'g_intbig_same';
+
 END TRANSACTION;
index 6434fd037de243c03140cc428edd436929225fce..ada064a270cad258d3bd13c5fd5ad849adc955da 100755 (executable)
@@ -49,7 +49,7 @@ print <<EOT;
 CREATE unique index message_key on message ( mid );
 --CREATE unique index message_section_map_key1 on message_section_map ( mid, sid );
 CREATE unique index message_section_map_key2 on message_section_map ( sid, mid );
-CREATE INDEX message_rdtree_idx on message using gist ( sections ) with ( islossy );
+CREATE INDEX message_rdtree_idx on message using gist ( sections gist__int_ops ) with ( islossy );
 VACUUM ANALYZE;
 
 select count(*) from message;
index b38102aa051aa7566e3874bbdb9f7806aede55bd..62748cefaf2398e82d396339462ad839589d5b9c 100644 (file)
@@ -17,3 +17,30 @@ SELECT count(*) from test__int WHERE a @ '{23,50}';
     12
 (1 row)
 
+CREATE INDEX text_idx on test__int using gist ( a gist__int_ops ) with ( islossy );
+SELECT count(*) from test__int WHERE a && '{23,50}';
+ count 
+-------
+   345
+(1 row)
+
+SELECT count(*) from test__int WHERE a @ '{23,50}';
+ count 
+-------
+    12
+(1 row)
+
+drop index text_idx;
+CREATE INDEX text_idx on test__int using gist ( a gist__intbig_ops ) with ( islossy );
+SELECT count(*) from test__int WHERE a && '{23,50}';
+ count 
+-------
+   345
+(1 row)
+
+SELECT count(*) from test__int WHERE a @ '{23,50}';
+ count 
+-------
+    12
+(1 row)
+
index f0176a06166911ac143bb4690f145a0e1f900c67..b23d406a6abc5f18b1de626492119e1248fa0de4 100644 (file)
@@ -13,3 +13,14 @@ CREATE TABLE test__int( a int[] );
 SELECT count(*) from test__int WHERE a && '{23,50}';
 SELECT count(*) from test__int WHERE a @ '{23,50}';
 
+CREATE INDEX text_idx on test__int using gist ( a gist__int_ops ) with ( islossy );
+
+SELECT count(*) from test__int WHERE a && '{23,50}';
+SELECT count(*) from test__int WHERE a @ '{23,50}';
+
+drop index text_idx;
+CREATE INDEX text_idx on test__int using gist ( a gist__intbig_ops ) with ( islossy );
+
+SELECT count(*) from test__int WHERE a && '{23,50}';
+SELECT count(*) from test__int WHERE a @ '{23,50}';
+