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/btree_ts.c | |
parent | 4996eea81cd52833cb8413c5105aba6937971748 (diff) | |
download | postgresql-4efbbd731899df673cab4415b9111744d9537a62.tar.gz postgresql-4efbbd731899df673cab4415b9111744d9537a62.zip |
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/btree_ts.c')
-rw-r--r-- | contrib/btree_gist/btree_ts.c | 282 |
1 files changed, 282 insertions, 0 deletions
diff --git a/contrib/btree_gist/btree_ts.c b/contrib/btree_gist/btree_ts.c new file mode 100644 index 00000000000..8af765f3d77 --- /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); +} |