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
This commit is contained in:
Bruce Momjian 2003-02-19 03:46:00 +00:00
parent 4996eea81c
commit 4efbbd7318
10 changed files with 975 additions and 602 deletions

View file

@ -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' < $< > $@

View file

@ -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.

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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);

View file

@ -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;
--
--

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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

View file

@ -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';