diff options
author | Bruce Momjian <bruce@momjian.us> | 2003-02-19 03:46:00 +0000 |
---|---|---|
committer | Bruce Momjian <bruce@momjian.us> | 2003-02-19 03:46:00 +0000 |
commit | 4efbbd731899df673cab4415b9111744d9537a62 (patch) | |
tree | 493cf019daee5421f46dd296294a10e592eb79d4 /contrib/btree_gist | |
parent | 4996eea81cd52833cb8413c5105aba6937971748 (diff) | |
download | postgresql-4efbbd731899df673cab4415b9111744d9537a62.tar.gz |
We just released new version of contrib/btree_gist
(7.3 and current CVS) with support of int8, float4, float8
in addition to int4. Thanks Janko Richter for contribution.
Oleg Bartunov
Diffstat (limited to 'contrib/btree_gist')
-rw-r--r-- | contrib/btree_gist/Makefile | 18 | ||||
-rw-r--r-- | contrib/btree_gist/README.btree_gist | 9 | ||||
-rw-r--r-- | contrib/btree_gist/btree_common.c | 69 | ||||
-rw-r--r-- | contrib/btree_gist/btree_gist.c | 584 | ||||
-rw-r--r-- | contrib/btree_gist/btree_gist.h | 29 | ||||
-rw-r--r-- | contrib/btree_gist/btree_gist.sql.in | 223 | ||||
-rw-r--r-- | contrib/btree_gist/btree_num.c.in | 254 | ||||
-rw-r--r-- | contrib/btree_gist/btree_ts.c | 282 | ||||
-rw-r--r-- | contrib/btree_gist/expected/btree_gist.out | 67 | ||||
-rw-r--r-- | contrib/btree_gist/sql/btree_gist.sql | 42 |
10 files changed, 975 insertions, 602 deletions
diff --git a/contrib/btree_gist/Makefile b/contrib/btree_gist/Makefile index 03aa1479be..d132396574 100644 --- a/contrib/btree_gist/Makefile +++ b/contrib/btree_gist/Makefile @@ -1,12 +1,26 @@ -# $Header: /cvsroot/pgsql/contrib/btree_gist/Makefile,v 1.3 2001/09/06 10:49:29 petere Exp $ subdir = contrib/btree_gist top_builddir = ../.. include $(top_builddir)/src/Makefile.global -MODULES = btree_gist +MODULE_big = btree_gist +OBJS= btree_common.o btree_int4.o btree_int8.o btree_float4.o btree_float8.o btree_ts.o DATA_built = btree_gist.sql DOCS = README.btree_gist REGRESS = btree_gist +EXTRA_CLEAN = btree_int4.c btree_int8.c btree_float4.c btree_float8.c + include $(top_srcdir)/contrib/contrib-global.mk + +btree_int4.c: btree_num.c.in + sed 's,__DEFINE_BTREE_TYPE_HERE__,BTREE_GIST_INT4,g;s,__BTREE_GIST_TYPE__,int32,g;s,__BTREE_GIST_TYPE2__,int4,g' < $< > $@ + +btree_int8.c: btree_num.c.in + sed 's,__DEFINE_BTREE_TYPE_HERE__,BTREE_GIST_INT8,g;s,__BTREE_GIST_TYPE__,int64,g;s,__BTREE_GIST_TYPE2__,int8,g' < $< > $@ + +btree_float4.c: btree_num.c.in + sed 's,__DEFINE_BTREE_TYPE_HERE__,BTREE_GIST_FLOAT4,g;s,__BTREE_GIST_TYPE__,float4,g;s,__BTREE_GIST_TYPE2__,float4,g' < $< > $@ + +btree_float8.c: btree_num.c.in + sed 's,__DEFINE_BTREE_TYPE_HERE__,BTREE_GIST_FLOAT8,g;s,__BTREE_GIST_TYPE__,float8,g;s,__BTREE_GIST_TYPE2__,float8,g' < $< > $@ diff --git a/contrib/btree_gist/README.btree_gist b/contrib/btree_gist/README.btree_gist index d61db62c3c..ec0e3cc9b6 100644 --- a/contrib/btree_gist/README.btree_gist +++ b/contrib/btree_gist/README.btree_gist @@ -1,12 +1,17 @@ -This is B-Tree implementation using GiST for int4 and +This is B-Tree implementation using GiST for int4, int8, float4, float8 timestamp types. All work was done by Teodor Sigaev (teodor@stack.net) and Oleg Bartunov (oleg@sai.msu.su). See http://www.sai.msu.su/~megera/postgres/gist for additional information. +NEWS: + Feb 5, 2003 - btree_gist now support int8, float4, float8 ! + Thank Janko Richter <jankorichter@yahoo.de> for + contribution. + NOTICE: - This version will works only with postgresql version 7.2 and above + This version will works only with postgresql version 7.3 and above because of changes in interface of function calling and in system tables. diff --git a/contrib/btree_gist/btree_common.c b/contrib/btree_gist/btree_common.c new file mode 100644 index 0000000000..9873af911c --- /dev/null +++ b/contrib/btree_gist/btree_common.c @@ -0,0 +1,69 @@ +#include "btree_gist.h" + +PG_FUNCTION_INFO_V1(btree_decompress); +Datum btree_decompress(PG_FUNCTION_ARGS); + +/* +** GiST DeCompress methods +** do not do anything. +*/ +Datum +btree_decompress(PG_FUNCTION_ARGS) +{ + PG_RETURN_POINTER(PG_GETARG_POINTER(0)); +} + + +/************************************************** + * Common btree-function (for all ops) + **************************************************/ + +/* +** The GiST PickSplit method +*/ +extern GIST_SPLITVEC * +btree_picksplit(bytea *entryvec, GIST_SPLITVEC *v, BINARY_UNION bu, CMPFUNC cmp) +{ + OffsetNumber i; + RIX *array; + OffsetNumber maxoff; + int nbytes; + + maxoff = ((VARSIZE(entryvec) - VARHDRSZ) / sizeof(GISTENTRY)) - 1; + nbytes = (maxoff + 2) * sizeof(OffsetNumber); + v->spl_left = (OffsetNumber *) palloc(nbytes); + v->spl_right = (OffsetNumber *) palloc(nbytes); + v->spl_nleft = 0; + v->spl_nright = 0; + v->spl_ldatum = PointerGetDatum(0); + v->spl_rdatum = PointerGetDatum(0); + array = (RIX *) palloc(sizeof(RIX) * (maxoff + 1)); + + /* copy the data into RIXes, and sort the RIXes */ + for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) + { + array[i].index = i; + array[i].r = (char *) DatumGetPointer((((GISTENTRY *) (VARDATA(entryvec)))[i].key)); + } + qsort((void *) &array[FirstOffsetNumber], maxoff - FirstOffsetNumber + 1, + sizeof(RIX), cmp); + + for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) + { + if (i <= (maxoff - FirstOffsetNumber + 1) / 2) + { + v->spl_left[v->spl_nleft] = array[i].index; + v->spl_nleft++; + (*bu) (&v->spl_ldatum, array[i].r); + } + else + { + v->spl_right[v->spl_nright] = array[i].index; + v->spl_nright++; + (*bu) (&v->spl_rdatum, array[i].r); + } + } + pfree(array); + + return (v); +} diff --git a/contrib/btree_gist/btree_gist.c b/contrib/btree_gist/btree_gist.c deleted file mode 100644 index ec84ec5a5b..0000000000 --- a/contrib/btree_gist/btree_gist.c +++ /dev/null @@ -1,584 +0,0 @@ -#include "postgres.h" - -#include "access/gist.h" -#include "access/itup.h" -#include "access/nbtree.h" - -#include "utils/palloc.h" -#include "utils/geo_decls.h" -#include "utils/elog.h" - -typedef int (*CMPFUNC) (const void *a, const void *b); -typedef void (*BINARY_UNION) (Datum *, char *); - -typedef struct intkey -{ - int4 lower; - int4 upper; -} INT4KEY; - -typedef struct tskey -{ - Timestamp lower; - Timestamp upper; -} TSKEY; - -/* used for sorting */ -typedef struct rix -{ - int index; - char *r; -} RIX; - -/* -** int4key in/out -*/ -PG_FUNCTION_INFO_V1(int4key_in); -PG_FUNCTION_INFO_V1(int4key_out); -Datum int4key_in(PG_FUNCTION_ARGS); -Datum int4key_out(PG_FUNCTION_ARGS); - -/* -** tskey in/out -*/ -PG_FUNCTION_INFO_V1(tskey_in); -PG_FUNCTION_INFO_V1(tskey_out); -Datum tskey_in(PG_FUNCTION_ARGS); -Datum tskey_out(PG_FUNCTION_ARGS); - -/* -** int4 ops -*/ -PG_FUNCTION_INFO_V1(gint4_compress); -PG_FUNCTION_INFO_V1(gint4_union); -PG_FUNCTION_INFO_V1(gint4_picksplit); -PG_FUNCTION_INFO_V1(gint4_consistent); -PG_FUNCTION_INFO_V1(gint4_penalty); -PG_FUNCTION_INFO_V1(gint4_same); - -Datum gint4_compress(PG_FUNCTION_ARGS); -Datum gint4_union(PG_FUNCTION_ARGS); -Datum gint4_picksplit(PG_FUNCTION_ARGS); -Datum gint4_consistent(PG_FUNCTION_ARGS); -Datum gint4_penalty(PG_FUNCTION_ARGS); -Datum gint4_same(PG_FUNCTION_ARGS); - -static void gint4_binary_union(Datum *r1, char *r2); -static int int4key_cmp(const void *a, const void *b); - -/* -** timestamp ops -*/ -PG_FUNCTION_INFO_V1(gts_compress); -PG_FUNCTION_INFO_V1(gts_union); -PG_FUNCTION_INFO_V1(gts_picksplit); -PG_FUNCTION_INFO_V1(gts_consistent); -PG_FUNCTION_INFO_V1(gts_penalty); -PG_FUNCTION_INFO_V1(gts_same); - -Datum gts_compress(PG_FUNCTION_ARGS); -Datum gts_union(PG_FUNCTION_ARGS); -Datum gts_picksplit(PG_FUNCTION_ARGS); -Datum gts_consistent(PG_FUNCTION_ARGS); -Datum gts_penalty(PG_FUNCTION_ARGS); -Datum gts_same(PG_FUNCTION_ARGS); - -static void gts_binary_union(Datum *r1, char *r2); -static int tskey_cmp(const void *a, const void *b); - -#define TimestampGetDatumFast(X) Float8GetDatumFast(X) - -/* define for comparison */ -#define TSGE( ts1, ts2 ) (DatumGetBool(DirectFunctionCall2( \ - timestamp_ge, \ - PointerGetDatum( ts1 ), \ - PointerGetDatum( ts2 ) \ -))) -#define TSGT( ts1, ts2 ) (DatumGetBool(DirectFunctionCall2( \ - timestamp_gt, \ - PointerGetDatum( ts1 ), \ - PointerGetDatum( ts2 ) \ -))) -#define TSEQ( ts1, ts2 ) (DatumGetBool(DirectFunctionCall2( \ - timestamp_eq, \ - PointerGetDatum( ts1 ), \ - PointerGetDatum( ts2 ) \ -))) -#define TSLT( ts1, ts2 ) (DatumGetBool(DirectFunctionCall2( \ - timestamp_lt, \ - PointerGetDatum( ts1 ), \ - PointerGetDatum( ts2 ) \ -))) -#define TSLE( ts1, ts2 ) (DatumGetBool(DirectFunctionCall2( \ - timestamp_le, \ - PointerGetDatum( ts1 ), \ - PointerGetDatum( ts2 ) \ -))) - -/* -** Common btree-function (for all ops) -*/ -static GIST_SPLITVEC *btree_picksplit(bytea *entryvec, GIST_SPLITVEC *v, - BINARY_UNION bu, CMPFUNC cmp); - -PG_FUNCTION_INFO_V1(btree_decompress); -Datum btree_decompress(PG_FUNCTION_ARGS); - -/************************************************** - * int4 ops - **************************************************/ - -Datum -gint4_compress(PG_FUNCTION_ARGS) -{ - GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); - GISTENTRY *retval; - - if (entry->leafkey) - { - INT4KEY *r = palloc(sizeof(INT4KEY)); - - retval = palloc(sizeof(GISTENTRY)); - r->lower = r->upper = (entry->key); - - gistentryinit(*retval, PointerGetDatum(r), entry->rel, entry->page, - entry->offset, sizeof(INT4KEY), FALSE); - - } - else - retval = entry; - PG_RETURN_POINTER(retval); -} - -Datum -gint4_consistent(PG_FUNCTION_ARGS) -{ - GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); - int4 query = PG_GETARG_INT32(1); - INT4KEY *kkk = (INT4KEY *) DatumGetPointer(entry->key); - StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2); - bool retval; - - switch (strategy) - { - case BTLessEqualStrategyNumber: - retval = (query >= kkk->lower); - break; - case BTLessStrategyNumber: - if (GIST_LEAF(entry)) - retval = (query > kkk->lower); - else - retval = (query >= kkk->lower); - break; - case BTEqualStrategyNumber: - /* in leaf page kkk->lower always = kkk->upper */ - if (GIST_LEAF(entry)) - retval = (query == kkk->lower); - else - retval = (kkk->lower <= query && query <= kkk->upper); - break; - case BTGreaterStrategyNumber: - if (GIST_LEAF(entry)) - retval = (query < kkk->upper); - else - retval = (query <= kkk->upper); - break; - case BTGreaterEqualStrategyNumber: - retval = (query <= kkk->upper); - break; - default: - retval = FALSE; - } - PG_RETURN_BOOL(retval); -} - -Datum -gint4_union(PG_FUNCTION_ARGS) -{ - bytea *entryvec = (bytea *) PG_GETARG_POINTER(0); - int i, - numranges; - INT4KEY *cur, - *out = palloc(sizeof(INT4KEY)); - - numranges = (VARSIZE(entryvec) - VARHDRSZ) / sizeof(GISTENTRY); - *(int *) PG_GETARG_POINTER(1) = sizeof(INT4KEY); - - cur = (INT4KEY *) DatumGetPointer((((GISTENTRY *) (VARDATA(entryvec)))[0].key)); - out->lower = cur->lower; - out->upper = cur->upper; - - for (i = 1; i < numranges; i++) - { - cur = (INT4KEY *) DatumGetPointer((((GISTENTRY *) (VARDATA(entryvec)))[i].key)); - if (out->lower > cur->lower) - out->lower = cur->lower; - if (out->upper < cur->upper) - out->upper = cur->upper; - } - - PG_RETURN_POINTER(out); -} - -Datum -gint4_penalty(PG_FUNCTION_ARGS) -{ - INT4KEY *origentry = (INT4KEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key); - INT4KEY *newentry = (INT4KEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key); - float *result = (float *) PG_GETARG_POINTER(2); - - *result = Max(newentry->upper - origentry->upper, 0) + - Max(origentry->lower - newentry->lower, 0); - - PG_RETURN_POINTER(result); -} - -Datum -gint4_picksplit(PG_FUNCTION_ARGS) -{ - PG_RETURN_POINTER(btree_picksplit( - (bytea *) PG_GETARG_POINTER(0), - (GIST_SPLITVEC *) PG_GETARG_POINTER(1), - gint4_binary_union, - int4key_cmp - )); -} - -Datum -gint4_same(PG_FUNCTION_ARGS) -{ - INT4KEY *b1 = (INT4KEY *) PG_GETARG_POINTER(0); - INT4KEY *b2 = (INT4KEY *) PG_GETARG_POINTER(1); - bool *result = (bool *) PG_GETARG_POINTER(2); - - *result = (b1->lower == b2->lower && b1->upper == b2->upper) ? TRUE : FALSE; - PG_RETURN_POINTER(result); -} - -static void -gint4_binary_union(Datum *r1, char *r2) -{ - INT4KEY *b1; - INT4KEY *b2 = (INT4KEY *) r2; - - if (!DatumGetPointer(*r1)) - { - *r1 = PointerGetDatum(palloc(sizeof(INT4KEY))); - b1 = (INT4KEY *) DatumGetPointer(*r1); - b1->upper = b2->upper; - b1->lower = b2->lower; - } - else - { - b1 = (INT4KEY *) DatumGetPointer(*r1); - - b1->lower = (b1->lower > b2->lower) ? - b2->lower : b1->lower; - b1->upper = (b1->upper > b2->upper) ? - b1->upper : b2->upper; - } -} - - -static int -int4key_cmp(const void *a, const void *b) -{ - return (((INT4KEY *) (((RIX *) a)->r))->lower - ((INT4KEY *) (((RIX *) b)->r))->lower); -} - -/************************************************** - * timestamp ops - **************************************************/ - -Datum -gts_compress(PG_FUNCTION_ARGS) -{ - GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); - GISTENTRY *retval; - - if (entry->leafkey) - { - TSKEY *r = (TSKEY *) palloc(sizeof(TSKEY)); - - retval = palloc(sizeof(GISTENTRY)); - r->lower = r->upper = *(Timestamp *) (entry->key); - gistentryinit(*retval, PointerGetDatum(r), - entry->rel, entry->page, - entry->offset, sizeof(TSKEY), FALSE); - } - else - retval = entry; - PG_RETURN_POINTER(retval); -} - -Datum -gts_consistent(PG_FUNCTION_ARGS) -{ - GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); - Timestamp *query = (Timestamp *) PG_GETARG_POINTER(1); - StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2); - bool retval; - TSKEY *key; - - /* - * * if entry is not leaf, use gbox_internal_consistent, * else use - * gbox_leaf_consistent - */ - if (!entry->key) - return FALSE; - key = (TSKEY *) DatumGetPointer(entry->key); - - switch (strategy) - { - case BTLessEqualStrategyNumber: - retval = TSGE(query, &(key->lower)); - break; - case BTLessStrategyNumber: - if (GIST_LEAF(entry)) - retval = TSGT(query, &(key->lower)); - else - retval = TSGE(query, &(key->lower)); - break; - case BTEqualStrategyNumber: - /* in leaf page key->lower always = key->upper */ - if (GIST_LEAF(entry)) - retval = TSEQ(query, &(key->lower)); - else - retval = (TSLE(&(key->lower), query) && TSLE(query, &(key->upper))); - break; - case BTGreaterStrategyNumber: - if (GIST_LEAF(entry)) - retval = TSLT(query, &(key->upper)); - else - retval = TSLE(query, &(key->upper)); - break; - case BTGreaterEqualStrategyNumber: - retval = TSLE(query, &(key->upper)); - break; - default: - retval = FALSE; - } - PG_RETURN_BOOL(retval); -} - -Datum -gts_union(PG_FUNCTION_ARGS) -{ - bytea *entryvec = (bytea *) PG_GETARG_POINTER(0); - int i, - numranges; - TSKEY *cur, - *out = palloc(sizeof(TSKEY)); - - numranges = (VARSIZE(entryvec) - VARHDRSZ) / sizeof(GISTENTRY); - *(int *) PG_GETARG_POINTER(1) = sizeof(TSKEY); - - cur = (TSKEY *) DatumGetPointer((((GISTENTRY *) (VARDATA(entryvec)))[0].key)); - out->lower = cur->lower; - out->upper = cur->upper; - - for (i = 1; i < numranges; i++) - { - cur = (TSKEY *) DatumGetPointer((((GISTENTRY *) (VARDATA(entryvec)))[i].key)); - if (TSGT(&out->lower, &cur->lower)) - out->lower = cur->lower; - if (TSLT(&out->upper, &cur->upper)) - out->upper = cur->upper; - } - - PG_RETURN_POINTER(out); -} - -Datum -gts_penalty(PG_FUNCTION_ARGS) -{ - TSKEY *origentry = (TSKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key); - TSKEY *newentry = (TSKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key); - float *result = (float *) PG_GETARG_POINTER(2); - Interval *intr; - - intr = DatumGetIntervalP(DirectFunctionCall2( - timestamp_mi, - TimestampGetDatumFast(newentry->upper), - TimestampGetDatumFast(origentry->upper))); - - /* see interval_larger */ - *result = Max(intr->time + intr->month * (30.0 * 86400), 0); - pfree(intr); - - intr = DatumGetIntervalP(DirectFunctionCall2( - timestamp_mi, - TimestampGetDatumFast(origentry->lower), - TimestampGetDatumFast(newentry->lower))); - - /* see interval_larger */ - *result += Max(intr->time + intr->month * (30.0 * 86400), 0); - pfree(intr); - - PG_RETURN_POINTER(result); -} - -Datum -gts_picksplit(PG_FUNCTION_ARGS) -{ - PG_RETURN_POINTER(btree_picksplit( - (bytea *) PG_GETARG_POINTER(0), - (GIST_SPLITVEC *) PG_GETARG_POINTER(1), - gts_binary_union, - tskey_cmp - )); -} - -Datum -gts_same(PG_FUNCTION_ARGS) -{ - TSKEY *b1 = (TSKEY *) PG_GETARG_POINTER(0); - TSKEY *b2 = (TSKEY *) PG_GETARG_POINTER(1); - - bool *result = (bool *) PG_GETARG_POINTER(2); - - if (b1 && b2) - *result = (TSEQ(&(b1->lower), &(b2->lower)) && TSEQ(&(b1->upper), &(b2->upper))) ? TRUE : FALSE; - else - *result = (b1 == NULL && b2 == NULL) ? TRUE : FALSE; - PG_RETURN_POINTER(result); -} - -static void -gts_binary_union(Datum *r1, char *r2) -{ - TSKEY *b1; - TSKEY *b2 = (TSKEY *) r2; - - if (!DatumGetPointer(*r1)) - { - *r1 = PointerGetDatum(palloc(sizeof(TSKEY))); - b1 = (TSKEY *) DatumGetPointer(*r1); - b1->upper = b2->upper; - b1->lower = b2->lower; - } - else - { - b1 = (TSKEY *) DatumGetPointer(*r1); - - b1->lower = (TSGT(&b1->lower, &b2->lower)) ? - b2->lower : b1->lower; - b1->upper = (TSGT(&b1->upper, &b2->upper)) ? - b1->upper : b2->upper; - } -} - -static int -tskey_cmp(const void *a, const void *b) -{ - return DatumGetInt32( - DirectFunctionCall2( - timestamp_cmp, - TimestampGetDatumFast(((TSKEY *) (((RIX *) a)->r))->lower), - TimestampGetDatumFast(((TSKEY *) (((RIX *) b)->r))->lower) - ) - ); -} - -/************************************************** - * Common btree-function (for all ops) - **************************************************/ - -/* -** The GiST PickSplit method -*/ -static GIST_SPLITVEC * -btree_picksplit(bytea *entryvec, GIST_SPLITVEC *v, BINARY_UNION bu, CMPFUNC cmp) -{ - OffsetNumber i; - RIX *array; - OffsetNumber maxoff; - int nbytes; - - maxoff = ((VARSIZE(entryvec) - VARHDRSZ) / sizeof(GISTENTRY)) - 1; - nbytes = (maxoff + 2) * sizeof(OffsetNumber); - v->spl_left = (OffsetNumber *) palloc(nbytes); - v->spl_right = (OffsetNumber *) palloc(nbytes); - v->spl_nleft = 0; - v->spl_nright = 0; - v->spl_ldatum = PointerGetDatum(0); - v->spl_rdatum = PointerGetDatum(0); - array = (RIX *) palloc(sizeof(RIX) * (maxoff + 1)); - - /* copy the data into RIXes, and sort the RIXes */ - for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) - { - array[i].index = i; - array[i].r = (char *) DatumGetPointer((((GISTENTRY *) (VARDATA(entryvec)))[i].key)); - } - qsort((void *) &array[FirstOffsetNumber], maxoff - FirstOffsetNumber + 1, - sizeof(RIX), cmp); - - for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) - { - if (i <= (maxoff - FirstOffsetNumber + 1) / 2) - { - v->spl_left[v->spl_nleft] = array[i].index; - v->spl_nleft++; - (*bu) (&v->spl_ldatum, array[i].r); - } - else - { - v->spl_right[v->spl_nright] = array[i].index; - v->spl_nright++; - (*bu) (&v->spl_rdatum, array[i].r); - } - } - pfree(array); - - return (v); -} - -/* -** GiST DeCompress methods -** do not do anything. -*/ -Datum -btree_decompress(PG_FUNCTION_ARGS) -{ - PG_RETURN_POINTER(PG_GETARG_POINTER(0)); -} - - -/************************************************** - * In/Out for keys, not really needed - **************************************************/ -Datum -int4key_in(PG_FUNCTION_ARGS) -{ - INT4KEY *key = palloc(sizeof(INT4KEY)); - - if (sscanf(PG_GETARG_POINTER(0), "%d|%d", &(key->lower), &(key->upper)) != 2) - elog(ERROR, "Error in input format"); - - PG_RETURN_POINTER(key); -} - -Datum -int4key_out(PG_FUNCTION_ARGS) -{ - INT4KEY *key = (INT4KEY *) PG_GETARG_POINTER(0); - char *str = palloc(sizeof(char) * 22); - - sprintf(str, "%d|%d", key->lower, key->upper); - PG_RETURN_POINTER(str); -} - -Datum -tskey_in(PG_FUNCTION_ARGS) -{ - elog(ERROR, "Not implemented"); - PG_RETURN_POINTER(NULL); -} - -Datum -tskey_out(PG_FUNCTION_ARGS) -{ - elog(ERROR, "Not implemented"); - PG_RETURN_POINTER(NULL); -} diff --git a/contrib/btree_gist/btree_gist.h b/contrib/btree_gist/btree_gist.h new file mode 100644 index 0000000000..0859002d03 --- /dev/null +++ b/contrib/btree_gist/btree_gist.h @@ -0,0 +1,29 @@ +#include "postgres.h" + +#include "access/gist.h" +#include "access/itup.h" +#include "access/nbtree.h" + +#include "utils/palloc.h" +#include "utils/geo_decls.h" +#include "utils/elog.h" + +typedef int (*CMPFUNC) (const void *a, const void *b); +typedef void (*BINARY_UNION) (Datum *, char *); + + +/* used for sorting */ + +typedef struct rix +{ + int index; + char *r; +} RIX; + +/* +** Common btree-function (for all ops) +*/ + +extern GIST_SPLITVEC *btree_picksplit(bytea *entryvec, GIST_SPLITVEC *v, + BINARY_UNION bu, CMPFUNC cmp); + diff --git a/contrib/btree_gist/btree_gist.sql.in b/contrib/btree_gist/btree_gist.sql.in index be3c979a6c..20bd46b5fa 100644 --- a/contrib/btree_gist/btree_gist.sql.in +++ b/contrib/btree_gist/btree_gist.sql.in @@ -20,6 +20,57 @@ INPUT = int4key_in, OUTPUT = int4key_out ); +-- create type of int8 key +CREATE FUNCTION int8key_in(cstring) +RETURNS int8key +AS 'MODULE_PATHNAME' +LANGUAGE 'c' WITH (isstrict); + +CREATE FUNCTION int8key_out(int8key) +RETURNS cstring +AS 'MODULE_PATHNAME' +LANGUAGE 'c' WITH (isstrict); + +CREATE TYPE int8key ( +INTERNALLENGTH = 16, +INPUT = int8key_in, +OUTPUT = int8key_out +); + +-- create type of float4 key +CREATE FUNCTION float4key_in(cstring) +RETURNS float4key +AS 'MODULE_PATHNAME' +LANGUAGE 'c' WITH (isstrict); + +CREATE FUNCTION float4key_out(float4key) +RETURNS cstring +AS 'MODULE_PATHNAME' +LANGUAGE 'c' WITH (isstrict); + +CREATE TYPE float4key ( +INTERNALLENGTH = 8, +INPUT = float4key_in, +OUTPUT = float4key_out +); + + +-- create type of float8 key +CREATE FUNCTION float8key_in(cstring) +RETURNS float8key +AS 'MODULE_PATHNAME' +LANGUAGE 'c' WITH (isstrict); + +CREATE FUNCTION float8key_out(float8key) +RETURNS cstring +AS 'MODULE_PATHNAME' +LANGUAGE 'c' WITH (isstrict); + +CREATE TYPE float8key ( +INTERNALLENGTH = 16, +INPUT = float8key_in, +OUTPUT = float8key_out +); -- -- @@ -82,6 +133,178 @@ AS FUNCTION 7 gint4_same (internal, internal, internal), STORAGE int4key; +-- +-- +-- +-- int8 ops +-- +-- +-- +-- define the GiST support methods +CREATE FUNCTION gint8_consistent(internal,int8,int2) +RETURNS bool +AS 'MODULE_PATHNAME' +LANGUAGE 'C'; + +CREATE FUNCTION gint8_compress(internal) +RETURNS internal +AS 'MODULE_PATHNAME' +LANGUAGE 'C'; + +CREATE FUNCTION gint8_penalty(internal,internal,internal) +RETURNS internal +AS 'MODULE_PATHNAME' +LANGUAGE 'C' WITH (isstrict); + +CREATE FUNCTION gint8_picksplit(internal, internal) +RETURNS internal +AS 'MODULE_PATHNAME' +LANGUAGE 'C'; + +CREATE FUNCTION gint8_union(bytea, internal) +RETURNS int8key +AS 'MODULE_PATHNAME' +LANGUAGE 'C'; + +CREATE FUNCTION gint8_same(int8key, int8key, internal) +RETURNS internal +AS 'MODULE_PATHNAME' +LANGUAGE 'C'; + +-- Create the operator class +CREATE OPERATOR CLASS gist_int8_ops +DEFAULT FOR TYPE int8 USING gist +AS + OPERATOR 1 < , + OPERATOR 2 <= , + OPERATOR 3 = , + OPERATOR 4 >= , + OPERATOR 5 > , + FUNCTION 1 gint8_consistent (internal, int8, int2), + FUNCTION 2 gint8_union (bytea, internal), + FUNCTION 3 gint8_compress (internal), + FUNCTION 4 btree_decompress (internal), + FUNCTION 5 gint8_penalty (internal, internal, internal), + FUNCTION 6 gint8_picksplit (internal, internal), + FUNCTION 7 gint8_same (int8key, int8key, internal), + STORAGE int8key; + + +-- +-- +-- +-- float4 ops +-- +-- +-- +-- define the GiST support methods +CREATE FUNCTION gfloat4_consistent(internal,float4,int2) +RETURNS bool +AS 'MODULE_PATHNAME' +LANGUAGE 'C'; + +CREATE FUNCTION gfloat4_compress(internal) +RETURNS internal +AS 'MODULE_PATHNAME' +LANGUAGE 'C'; + +CREATE FUNCTION gfloat4_penalty(internal,internal,internal) +RETURNS internal +AS 'MODULE_PATHNAME' +LANGUAGE 'C' WITH (isstrict); + +CREATE FUNCTION gfloat4_picksplit(internal, internal) +RETURNS internal +AS 'MODULE_PATHNAME' +LANGUAGE 'C'; + +CREATE FUNCTION gfloat4_union(bytea, internal) +RETURNS int4 +AS 'MODULE_PATHNAME' +LANGUAGE 'C'; + +CREATE FUNCTION gfloat4_same(internal, internal, internal) +RETURNS internal +AS 'MODULE_PATHNAME' +LANGUAGE 'C'; + +-- Create the operator class +CREATE OPERATOR CLASS gist_float4_ops +DEFAULT FOR TYPE float4 USING gist +AS + OPERATOR 1 < , + OPERATOR 2 <= , + OPERATOR 3 = , + OPERATOR 4 >= , + OPERATOR 5 > , + FUNCTION 1 gfloat4_consistent (internal, float4, int2), + FUNCTION 2 gfloat4_union (bytea, internal), + FUNCTION 3 gfloat4_compress (internal), + FUNCTION 4 btree_decompress (internal), + FUNCTION 5 gfloat4_penalty (internal, internal, internal), + FUNCTION 6 gfloat4_picksplit (internal, internal), + FUNCTION 7 gfloat4_same (internal, internal, internal), + STORAGE float4key; + + + + +-- +-- +-- +-- float8 ops +-- +-- +-- +-- define the GiST support methods +CREATE FUNCTION gfloat8_consistent(internal,float8,int2) +RETURNS bool +AS 'MODULE_PATHNAME' +LANGUAGE 'C'; + +CREATE FUNCTION gfloat8_compress(internal) +RETURNS internal +AS 'MODULE_PATHNAME' +LANGUAGE 'C'; + +CREATE FUNCTION gfloat8_penalty(internal,internal,internal) +RETURNS internal +AS 'MODULE_PATHNAME' +LANGUAGE 'C' WITH (isstrict); + +CREATE FUNCTION gfloat8_picksplit(internal, internal) +RETURNS internal +AS 'MODULE_PATHNAME' +LANGUAGE 'C'; + +CREATE FUNCTION gfloat8_union(bytea, internal) +RETURNS int4 +AS 'MODULE_PATHNAME' +LANGUAGE 'C'; + +CREATE FUNCTION gfloat8_same(internal, internal, internal) +RETURNS internal +AS 'MODULE_PATHNAME' +LANGUAGE 'C'; + +-- Create the operator class +CREATE OPERATOR CLASS gist_float8_ops +DEFAULT FOR TYPE float8 USING gist +AS + OPERATOR 1 < , + OPERATOR 2 <= , + OPERATOR 3 = , + OPERATOR 4 >= , + OPERATOR 5 > , + FUNCTION 1 gfloat8_consistent (internal, float8, int2), + FUNCTION 2 gfloat8_union (bytea, internal), + FUNCTION 3 gfloat8_compress (internal), + FUNCTION 4 btree_decompress (internal), + FUNCTION 5 gfloat8_penalty (internal, internal, internal), + FUNCTION 6 gfloat8_picksplit (internal, internal), + FUNCTION 7 gfloat8_same (internal, internal, internal), + STORAGE float8key; + -- -- diff --git a/contrib/btree_gist/btree_num.c.in b/contrib/btree_gist/btree_num.c.in new file mode 100644 index 0000000000..04e496eb0a --- /dev/null +++ b/contrib/btree_gist/btree_num.c.in @@ -0,0 +1,254 @@ +#include "btree_gist.h" + +#define __DEFINE_BTREE_TYPE_HERE__ 1 + +typedef struct __BTREE_GIST_TYPE__key +{ + __BTREE_GIST_TYPE__ lower; + __BTREE_GIST_TYPE__ upper; +} __BTREE_GIST_TYPE__KEY; + + +/* +** __BTREE_GIST_TYPE__key in/out +*/ +PG_FUNCTION_INFO_V1(__BTREE_GIST_TYPE2__key_in); +PG_FUNCTION_INFO_V1(__BTREE_GIST_TYPE2__key_out); +Datum __BTREE_GIST_TYPE2__key_in(PG_FUNCTION_ARGS); +Datum __BTREE_GIST_TYPE2__key_out(PG_FUNCTION_ARGS); + +/* +** __BTREE_GIST_TYPE__ ops +*/ +PG_FUNCTION_INFO_V1(g__BTREE_GIST_TYPE2___compress); +PG_FUNCTION_INFO_V1(g__BTREE_GIST_TYPE2___union); +PG_FUNCTION_INFO_V1(g__BTREE_GIST_TYPE2___picksplit); +PG_FUNCTION_INFO_V1(g__BTREE_GIST_TYPE2___consistent); +PG_FUNCTION_INFO_V1(g__BTREE_GIST_TYPE2___penalty); +PG_FUNCTION_INFO_V1(g__BTREE_GIST_TYPE2___same); + +Datum g__BTREE_GIST_TYPE2___compress(PG_FUNCTION_ARGS); +Datum g__BTREE_GIST_TYPE2___union(PG_FUNCTION_ARGS); +Datum g__BTREE_GIST_TYPE2___picksplit(PG_FUNCTION_ARGS); +Datum g__BTREE_GIST_TYPE2___consistent(PG_FUNCTION_ARGS); +Datum g__BTREE_GIST_TYPE2___penalty(PG_FUNCTION_ARGS); +Datum g__BTREE_GIST_TYPE2___same(PG_FUNCTION_ARGS); + +static void g__BTREE_GIST_TYPE2___binary_union(Datum *r1, char *r2); +static int __BTREE_GIST_TYPE2__key_cmp(const void *a, const void *b); + + +/************************************************** + * __BTREE_GIST_TYPE__ ops + **************************************************/ + +Datum +g__BTREE_GIST_TYPE2___compress(PG_FUNCTION_ARGS) +{ + GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); + GISTENTRY *retval; + + if (entry->leafkey) + { + __BTREE_GIST_TYPE__KEY *r = ( __BTREE_GIST_TYPE__KEY * ) palloc(sizeof(__BTREE_GIST_TYPE__KEY)); + #ifdef BTREE_GIST_INT4 + int32 leaf = DatumGetInt32(entry->key); + #endif + #ifdef BTREE_GIST_INT8 + int64 leaf = DatumGetInt64(entry->key); + #endif + #ifdef BTREE_GIST_FLOAT4 + float4 leaf = DatumGetFloat4(entry->key); + #endif + #ifdef BTREE_GIST_FLOAT8 + float8 leaf = DatumGetFloat8(entry->key); + #endif + + retval = palloc(sizeof(GISTENTRY)); + r->lower = r->upper = leaf ; + + gistentryinit(*retval, PointerGetDatum(r), entry->rel, entry->page, + entry->offset, sizeof(__BTREE_GIST_TYPE__KEY), FALSE); + + } + else + retval = entry; + PG_RETURN_POINTER(retval); +} + +Datum +g__BTREE_GIST_TYPE2___consistent(PG_FUNCTION_ARGS) +{ + GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); + #ifdef BTREE_GIST_INT4 + int32 query = PG_GETARG_INT32(1); + #endif + #ifdef BTREE_GIST_INT8 + int64 query = PG_GETARG_INT64(1); + #endif + #ifdef BTREE_GIST_FLOAT4 + float4 query = PG_GETARG_FLOAT4(1); + #endif + #ifdef BTREE_GIST_FLOAT8 + float8 query = PG_GETARG_FLOAT8(1); + #endif + __BTREE_GIST_TYPE__KEY *kkk = (__BTREE_GIST_TYPE__KEY *) DatumGetPointer(entry->key); + StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2); + bool retval; + + switch (strategy) + { + case BTLessEqualStrategyNumber: + retval = (query >= kkk->lower); + break; + case BTLessStrategyNumber: + if (GIST_LEAF(entry)) + retval = (query > kkk->lower); + else + retval = (query >= kkk->lower); + break; + case BTEqualStrategyNumber: + /* in leaf page kkk->lower always = kkk->upper */ + if (GIST_LEAF(entry)) + retval = (query == kkk->lower); + else + retval = (kkk->lower <= query && query <= kkk->upper); + break; + case BTGreaterStrategyNumber: + if (GIST_LEAF(entry)) + retval = (query < kkk->upper); + else + retval = (query <= kkk->upper); + break; + case BTGreaterEqualStrategyNumber: + retval = (query <= kkk->upper); + break; + default: + retval = FALSE; + } + PG_RETURN_BOOL(retval); +} + +Datum +g__BTREE_GIST_TYPE2___union(PG_FUNCTION_ARGS) +{ + bytea *entryvec = (bytea *) PG_GETARG_POINTER(0); + int i, + numranges; + __BTREE_GIST_TYPE__KEY *cur, + *out = palloc(sizeof(__BTREE_GIST_TYPE__KEY)); + + numranges = (VARSIZE(entryvec) - VARHDRSZ) / sizeof(GISTENTRY); + *(int *) PG_GETARG_POINTER(1) = sizeof(__BTREE_GIST_TYPE__KEY); + + cur = (__BTREE_GIST_TYPE__KEY *) DatumGetPointer((((GISTENTRY *) (VARDATA(entryvec)))[0].key)); + out->lower = cur->lower; + out->upper = cur->upper; + + for (i = 1; i < numranges; i++) + { + cur = (__BTREE_GIST_TYPE__KEY *) DatumGetPointer((((GISTENTRY *) (VARDATA(entryvec)))[i].key)); + if (out->lower > cur->lower) + out->lower = cur->lower; + if (out->upper < cur->upper) + out->upper = cur->upper; + } + + PG_RETURN_POINTER(out); +} + +Datum +g__BTREE_GIST_TYPE2___penalty(PG_FUNCTION_ARGS) +{ + __BTREE_GIST_TYPE__KEY *origentry = (__BTREE_GIST_TYPE__KEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key); + __BTREE_GIST_TYPE__KEY *newentry = (__BTREE_GIST_TYPE__KEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key); + float *result = (float *) PG_GETARG_POINTER(2); + + *result = Max(newentry->upper - origentry->upper, 0) + + Max(origentry->lower - newentry->lower, 0); + + PG_RETURN_POINTER(result); +} + +Datum +g__BTREE_GIST_TYPE2___picksplit(PG_FUNCTION_ARGS) +{ + PG_RETURN_POINTER(btree_picksplit( + (bytea *) PG_GETARG_POINTER(0), + (GIST_SPLITVEC *) PG_GETARG_POINTER(1), + g__BTREE_GIST_TYPE2___binary_union, + __BTREE_GIST_TYPE2__key_cmp + )); +} + +Datum +g__BTREE_GIST_TYPE2___same(PG_FUNCTION_ARGS) +{ + __BTREE_GIST_TYPE__KEY *b1 = (__BTREE_GIST_TYPE__KEY *) PG_GETARG_POINTER(0); + __BTREE_GIST_TYPE__KEY *b2 = (__BTREE_GIST_TYPE__KEY *) PG_GETARG_POINTER(1); + bool *result = (bool *) PG_GETARG_POINTER(2); + + *result = (b1->lower == b2->lower && b1->upper == b2->upper) ? TRUE : FALSE; + PG_RETURN_POINTER(result); +} + +static void +g__BTREE_GIST_TYPE2___binary_union(Datum *r1, char *r2) +{ + __BTREE_GIST_TYPE__KEY *b1; + __BTREE_GIST_TYPE__KEY *b2 = (__BTREE_GIST_TYPE__KEY *) r2; + + if (!DatumGetPointer(*r1)) + { + *r1 = PointerGetDatum(palloc(sizeof(__BTREE_GIST_TYPE__KEY))); + b1 = (__BTREE_GIST_TYPE__KEY *) DatumGetPointer(*r1); + b1->upper = b2->upper; + b1->lower = b2->lower; + } + else + { + b1 = (__BTREE_GIST_TYPE__KEY *) DatumGetPointer(*r1); + + b1->lower = (b1->lower > b2->lower) ? + b2->lower : b1->lower; + b1->upper = (b1->upper > b2->upper) ? + b1->upper : b2->upper; + } + +} + + +static int +__BTREE_GIST_TYPE2__key_cmp(const void *a, const void *b) +{ + + + if (((__BTREE_GIST_TYPE__KEY *) (((RIX *) a)->r))->lower > ((__BTREE_GIST_TYPE__KEY *) (((RIX *) b)->r))->lower){ + return 1; + } else if (((__BTREE_GIST_TYPE__KEY *) (((RIX *) a)->r))->lower < ((__BTREE_GIST_TYPE__KEY *) (((RIX *) b)->r))->lower){ + return -1; + } else { + return 0; + } + +} + + +/************************************************** + * In/Out for keys + **************************************************/ + +Datum +__BTREE_GIST_TYPE2__key_in(PG_FUNCTION_ARGS) +{ + elog(ERROR, "Not implemented"); + PG_RETURN_POINTER(NULL); +} + +Datum +__BTREE_GIST_TYPE2__key_out(PG_FUNCTION_ARGS) +{ + elog(ERROR, "Not implemented"); + PG_RETURN_POINTER(NULL); +} + diff --git a/contrib/btree_gist/btree_ts.c b/contrib/btree_gist/btree_ts.c new file mode 100644 index 0000000000..8af765f3d7 --- /dev/null +++ b/contrib/btree_gist/btree_ts.c @@ -0,0 +1,282 @@ +#include "btree_gist.h" + + +typedef struct tskey +{ + Timestamp lower; + Timestamp upper; +} TSKEY; + + +/* +** tskey in/out +*/ +PG_FUNCTION_INFO_V1(tskey_in); +PG_FUNCTION_INFO_V1(tskey_out); +Datum tskey_in(PG_FUNCTION_ARGS); +Datum tskey_out(PG_FUNCTION_ARGS); + + +/* +** timestamp ops +*/ +PG_FUNCTION_INFO_V1(gts_compress); +PG_FUNCTION_INFO_V1(gts_union); +PG_FUNCTION_INFO_V1(gts_picksplit); +PG_FUNCTION_INFO_V1(gts_consistent); +PG_FUNCTION_INFO_V1(gts_penalty); +PG_FUNCTION_INFO_V1(gts_same); + +Datum gts_compress(PG_FUNCTION_ARGS); +Datum gts_union(PG_FUNCTION_ARGS); +Datum gts_picksplit(PG_FUNCTION_ARGS); +Datum gts_consistent(PG_FUNCTION_ARGS); +Datum gts_penalty(PG_FUNCTION_ARGS); +Datum gts_same(PG_FUNCTION_ARGS); + +static void gts_binary_union(Datum *r1, char *r2); +static int tskey_cmp(const void *a, const void *b); + +#define TimestampGetDatumFast(X) Float8GetDatumFast(X) + +/* define for comparison */ +#define TSGE( ts1, ts2 ) (DatumGetBool(DirectFunctionCall2( \ + timestamp_ge, \ + PointerGetDatum( ts1 ), \ + PointerGetDatum( ts2 ) \ +))) +#define TSGT( ts1, ts2 ) (DatumGetBool(DirectFunctionCall2( \ + timestamp_gt, \ + PointerGetDatum( ts1 ), \ + PointerGetDatum( ts2 ) \ +))) +#define TSEQ( ts1, ts2 ) (DatumGetBool(DirectFunctionCall2( \ + timestamp_eq, \ + PointerGetDatum( ts1 ), \ + PointerGetDatum( ts2 ) \ +))) +#define TSLT( ts1, ts2 ) (DatumGetBool(DirectFunctionCall2( \ + timestamp_lt, \ + PointerGetDatum( ts1 ), \ + PointerGetDatum( ts2 ) \ +))) +#define TSLE( ts1, ts2 ) (DatumGetBool(DirectFunctionCall2( \ + timestamp_le, \ + PointerGetDatum( ts1 ), \ + PointerGetDatum( ts2 ) \ +))) + + + +/************************************************** + * timestamp ops + **************************************************/ + +Datum +gts_compress(PG_FUNCTION_ARGS) +{ + GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); + GISTENTRY *retval; + + if (entry->leafkey) + { + TSKEY *r = (TSKEY *) palloc(sizeof(TSKEY)); + + retval = palloc(sizeof(GISTENTRY)); + r->lower = r->upper = *(Timestamp *) (entry->key); + gistentryinit(*retval, PointerGetDatum(r), + entry->rel, entry->page, + entry->offset, sizeof(TSKEY), FALSE); + } + else + retval = entry; + PG_RETURN_POINTER(retval); +} + +Datum +gts_consistent(PG_FUNCTION_ARGS) +{ + GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); + Timestamp *query = (Timestamp *) PG_GETARG_POINTER(1); + StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2); + bool retval; + TSKEY *key; + + /* + * * if entry is not leaf, use gbox_internal_consistent, * else use + * gbox_leaf_consistent + */ + if (!entry->key) + return FALSE; + key = (TSKEY *) DatumGetPointer(entry->key); + + switch (strategy) + { + case BTLessEqualStrategyNumber: + retval = TSGE(query, &(key->lower)); + break; + case BTLessStrategyNumber: + if (GIST_LEAF(entry)) + retval = TSGT(query, &(key->lower)); + else + retval = TSGE(query, &(key->lower)); + break; + case BTEqualStrategyNumber: + /* in leaf page key->lower always = key->upper */ + if (GIST_LEAF(entry)) + retval = TSEQ(query, &(key->lower)); + else + retval = (TSLE(&(key->lower), query) && TSLE(query, &(key->upper))); + break; + case BTGreaterStrategyNumber: + if (GIST_LEAF(entry)) + retval = TSLT(query, &(key->upper)); + else + retval = TSLE(query, &(key->upper)); + break; + case BTGreaterEqualStrategyNumber: + retval = TSLE(query, &(key->upper)); + break; + default: + retval = FALSE; + } + PG_RETURN_BOOL(retval); +} + +Datum +gts_union(PG_FUNCTION_ARGS) +{ + bytea *entryvec = (bytea *) PG_GETARG_POINTER(0); + int i, + numranges; + TSKEY *cur, + *out = palloc(sizeof(TSKEY)); + + numranges = (VARSIZE(entryvec) - VARHDRSZ) / sizeof(GISTENTRY); + *(int *) PG_GETARG_POINTER(1) = sizeof(TSKEY); + + cur = (TSKEY *) DatumGetPointer((((GISTENTRY *) (VARDATA(entryvec)))[0].key)); + out->lower = cur->lower; + out->upper = cur->upper; + + for (i = 1; i < numranges; i++) + { + cur = (TSKEY *) DatumGetPointer((((GISTENTRY *) (VARDATA(entryvec)))[i].key)); + if (TSGT(&out->lower, &cur->lower)) + out->lower = cur->lower; + if (TSLT(&out->upper, &cur->upper)) + out->upper = cur->upper; + } + + PG_RETURN_POINTER(out); +} + +Datum +gts_penalty(PG_FUNCTION_ARGS) +{ + TSKEY *origentry = (TSKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key); + TSKEY *newentry = (TSKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key); + float *result = (float *) PG_GETARG_POINTER(2); + Interval *intr; + + intr = DatumGetIntervalP(DirectFunctionCall2( + timestamp_mi, + TimestampGetDatumFast(newentry->upper), + TimestampGetDatumFast(origentry->upper))); + + /* see interval_larger */ + *result = Max(intr->time + intr->month * (30.0 * 86400), 0); + pfree(intr); + + intr = DatumGetIntervalP(DirectFunctionCall2( + timestamp_mi, + TimestampGetDatumFast(origentry->lower), + TimestampGetDatumFast(newentry->lower))); + + /* see interval_larger */ + *result += Max(intr->time + intr->month * (30.0 * 86400), 0); + pfree(intr); + + PG_RETURN_POINTER(result); +} + +Datum +gts_picksplit(PG_FUNCTION_ARGS) +{ + PG_RETURN_POINTER(btree_picksplit( + (bytea *) PG_GETARG_POINTER(0), + (GIST_SPLITVEC *) PG_GETARG_POINTER(1), + gts_binary_union, + tskey_cmp + )); +} + +Datum +gts_same(PG_FUNCTION_ARGS) +{ + TSKEY *b1 = (TSKEY *) PG_GETARG_POINTER(0); + TSKEY *b2 = (TSKEY *) PG_GETARG_POINTER(1); + + bool *result = (bool *) PG_GETARG_POINTER(2); + + if (b1 && b2) + *result = (TSEQ(&(b1->lower), &(b2->lower)) && TSEQ(&(b1->upper), &(b2->upper))) ? TRUE : FALSE; + else + *result = (b1 == NULL && b2 == NULL) ? TRUE : FALSE; + PG_RETURN_POINTER(result); +} + +static void +gts_binary_union(Datum *r1, char *r2) +{ + TSKEY *b1; + TSKEY *b2 = (TSKEY *) r2; + + if (!DatumGetPointer(*r1)) + { + *r1 = PointerGetDatum(palloc(sizeof(TSKEY))); + b1 = (TSKEY *) DatumGetPointer(*r1); + b1->upper = b2->upper; + b1->lower = b2->lower; + } + else + { + b1 = (TSKEY *) DatumGetPointer(*r1); + + b1->lower = (TSGT(&b1->lower, &b2->lower)) ? + b2->lower : b1->lower; + b1->upper = (TSGT(&b1->upper, &b2->upper)) ? + b1->upper : b2->upper; + } +} + +static int +tskey_cmp(const void *a, const void *b) +{ + return DatumGetInt32( + DirectFunctionCall2( + timestamp_cmp, + TimestampGetDatumFast(((TSKEY *) (((RIX *) a)->r))->lower), + TimestampGetDatumFast(((TSKEY *) (((RIX *) b)->r))->lower) + ) + ); +} + + +/************************************************** + * In/Out for keys, not really needed + **************************************************/ + +Datum +tskey_in(PG_FUNCTION_ARGS) +{ + elog(ERROR, "Not implemented"); + PG_RETURN_POINTER(NULL); +} + +Datum +tskey_out(PG_FUNCTION_ARGS) +{ + elog(ERROR, "Not implemented"); + PG_RETURN_POINTER(NULL); +} diff --git a/contrib/btree_gist/expected/btree_gist.out b/contrib/btree_gist/expected/btree_gist.out index 4cd2bed3ce..a3928951e0 100644 --- a/contrib/btree_gist/expected/btree_gist.out +++ b/contrib/btree_gist/expected/btree_gist.out @@ -1,18 +1,48 @@ -- -- first, define the datatype. Turn off echoing so that expected file --- does not depend on contents of seg.sql. +-- does not depend on contents of btree_gist.sql. -- \set ECHO none psql:btree_gist.sql:10: NOTICE: ProcedureCreate: type int4key is not yet defined psql:btree_gist.sql:15: NOTICE: Argument type "int4key" is only a shell -psql:btree_gist.sql:98: NOTICE: ProcedureCreate: type tskey is not yet defined -psql:btree_gist.sql:103: NOTICE: Argument type "tskey" is only a shell -CREATE TABLE inttmp (b int4); -\copy inttmp from 'data/test_btree.data' +psql:btree_gist.sql:27: NOTICE: ProcedureCreate: type int8key is not yet defined +psql:btree_gist.sql:32: NOTICE: Argument type "int8key" is only a shell +psql:btree_gist.sql:44: NOTICE: ProcedureCreate: type float4key is not yet defined +psql:btree_gist.sql:49: NOTICE: Argument type "float4key" is only a shell +psql:btree_gist.sql:62: NOTICE: ProcedureCreate: type float8key is not yet defined +psql:btree_gist.sql:67: NOTICE: Argument type "float8key" is only a shell +psql:btree_gist.sql:321: NOTICE: ProcedureCreate: type tskey is not yet defined +psql:btree_gist.sql:326: NOTICE: Argument type "tskey" is only a shell +CREATE TABLE int4tmp (b int4); +\copy int4tmp from 'data/test_btree.data' +CREATE TABLE int8tmp (b int8); +\copy int8tmp from 'data/test_btree.data' +CREATE TABLE float4tmp (b float4); +\copy float4tmp from 'data/test_btree.data' +CREATE TABLE float8tmp (b float8); +\copy float8tmp from 'data/test_btree.data' CREATE TABLE tstmp ( t timestamp without time zone ); \copy tstmp from 'data/test_btree_ts.data' -- without idx -SELECT count(*) FROM inttmp WHERE b <=10; +SELECT count(*) FROM int4tmp WHERE b <=10; + count +------- + 11 +(1 row) + +SELECT count(*) FROM int8tmp WHERE b <=10; + count +------- + 11 +(1 row) + +SELECT count(*) FROM float4tmp WHERE b <=10; + count +------- + 11 +(1 row) + +SELECT count(*) FROM float8tmp WHERE b <=10; count ------- 11 @@ -25,11 +55,32 @@ SELECT count(*) FROM tstmp WHERE t < '2001-05-29 08:33:09'; (1 row) -- create idx -CREATE INDEX aaaidx ON inttmp USING gist ( b ); +CREATE INDEX aaaidx ON int4tmp USING gist ( b ); +CREATE INDEX bbbidx ON int8tmp USING gist ( b ); +CREATE INDEX cccidx ON float4tmp USING gist ( b ); +CREATE INDEX dddidx ON float8tmp USING gist ( b ); CREATE INDEX tsidx ON tstmp USING gist ( t ); --with idx SET enable_seqscan=off; -SELECT count(*) FROM inttmp WHERE b <=10; +SELECT count(*) FROM int4tmp WHERE b <=10::int4; + count +------- + 11 +(1 row) + +SELECT count(*) FROM int8tmp WHERE b <=10::int8; + count +------- + 11 +(1 row) + +SELECT count(*) FROM float4tmp WHERE b <=10::float4; + count +------- + 11 +(1 row) + +SELECT count(*) FROM float8tmp WHERE b <=10::float8; count ------- 11 diff --git a/contrib/btree_gist/sql/btree_gist.sql b/contrib/btree_gist/sql/btree_gist.sql index 6c369b2aa0..b3f310a790 100644 --- a/contrib/btree_gist/sql/btree_gist.sql +++ b/contrib/btree_gist/sql/btree_gist.sql @@ -1,14 +1,26 @@ -- -- first, define the datatype. Turn off echoing so that expected file --- does not depend on contents of seg.sql. +-- does not depend on contents of btree_gist.sql. -- \set ECHO none \i btree_gist.sql \set ECHO all -CREATE TABLE inttmp (b int4); +CREATE TABLE int4tmp (b int4); -\copy inttmp from 'data/test_btree.data' +\copy int4tmp from 'data/test_btree.data' + +CREATE TABLE int8tmp (b int8); + +\copy int8tmp from 'data/test_btree.data' + +CREATE TABLE float4tmp (b float4); + +\copy float4tmp from 'data/test_btree.data' + +CREATE TABLE float8tmp (b float8); + +\copy float8tmp from 'data/test_btree.data' CREATE TABLE tstmp ( t timestamp without time zone ); @@ -16,13 +28,25 @@ CREATE TABLE tstmp ( t timestamp without time zone ); -- without idx -SELECT count(*) FROM inttmp WHERE b <=10; +SELECT count(*) FROM int4tmp WHERE b <=10; + +SELECT count(*) FROM int8tmp WHERE b <=10; + +SELECT count(*) FROM float4tmp WHERE b <=10; + +SELECT count(*) FROM float8tmp WHERE b <=10; SELECT count(*) FROM tstmp WHERE t < '2001-05-29 08:33:09'; -- create idx -CREATE INDEX aaaidx ON inttmp USING gist ( b ); +CREATE INDEX aaaidx ON int4tmp USING gist ( b ); + +CREATE INDEX bbbidx ON int8tmp USING gist ( b ); + +CREATE INDEX cccidx ON float4tmp USING gist ( b ); + +CREATE INDEX dddidx ON float8tmp USING gist ( b ); CREATE INDEX tsidx ON tstmp USING gist ( t ); @@ -30,7 +54,13 @@ CREATE INDEX tsidx ON tstmp USING gist ( t ); SET enable_seqscan=off; -SELECT count(*) FROM inttmp WHERE b <=10; +SELECT count(*) FROM int4tmp WHERE b <=10::int4; + +SELECT count(*) FROM int8tmp WHERE b <=10::int8; + +SELECT count(*) FROM float4tmp WHERE b <=10::float4; + +SELECT count(*) FROM float8tmp WHERE b <=10::float8; SELECT count(*) FROM tstmp WHERE t < '2001-05-29 08:33:09'; |