diff options
author | Teodor Sigaev <teodor@sigaev.ru> | 2004-05-28 10:43:32 +0000 |
---|---|---|
committer | Teodor Sigaev <teodor@sigaev.ru> | 2004-05-28 10:43:32 +0000 |
commit | 42d069886f38687839388c615af608706508b557 (patch) | |
tree | 0409615407a17d22e2511ac14745277467853453 /contrib/btree_gist/btree_ts.c | |
parent | 1a321f26d88e5c64bccba9d36920aede1e201729 (diff) |
New version. Add support for int2, int8, float4, float8, timestamp with/without time zone, time with/without time zone, date, interval, oid, money and macaddr, char, varchar/text, bytea, numeric, bit, varbit, inet/cidr types for GiST
Diffstat (limited to 'contrib/btree_gist/btree_ts.c')
-rw-r--r-- | contrib/btree_gist/btree_ts.c | 467 |
1 files changed, 230 insertions, 237 deletions
diff --git a/contrib/btree_gist/btree_ts.c b/contrib/btree_gist/btree_ts.c index 658528dcb99..3c73a7b83cc 100644 --- a/contrib/btree_gist/btree_ts.c +++ b/contrib/btree_gist/btree_ts.c @@ -1,288 +1,281 @@ #include "btree_gist.h" +#include "btree_utils_num.h" - -typedef struct tskey +typedef struct { - Timestamp lower; - Timestamp upper; -} TSKEY; - + Timestamp lower; + Timestamp upper; +} tsKEY; /* -** tskey in/out +** timestamp ops */ -PG_FUNCTION_INFO_V1(tskey_in); -PG_FUNCTION_INFO_V1(tskey_out); -Datum tskey_in(PG_FUNCTION_ARGS); -Datum tskey_out(PG_FUNCTION_ARGS); +PG_FUNCTION_INFO_V1(gbt_ts_compress); +PG_FUNCTION_INFO_V1(gbt_tstz_compress); +PG_FUNCTION_INFO_V1(gbt_ts_union); +PG_FUNCTION_INFO_V1(gbt_ts_picksplit); +PG_FUNCTION_INFO_V1(gbt_ts_consistent); +PG_FUNCTION_INFO_V1(gbt_tstz_consistent); +PG_FUNCTION_INFO_V1(gbt_ts_penalty); +PG_FUNCTION_INFO_V1(gbt_ts_same); + +Datum gbt_ts_compress(PG_FUNCTION_ARGS); +Datum gbt_tstz_compress(PG_FUNCTION_ARGS); +Datum gbt_ts_union(PG_FUNCTION_ARGS); +Datum gbt_ts_picksplit(PG_FUNCTION_ARGS); +Datum gbt_ts_consistent(PG_FUNCTION_ARGS); +Datum gbt_tstz_consistent(PG_FUNCTION_ARGS); +Datum gbt_ts_penalty(PG_FUNCTION_ARGS); +Datum gbt_ts_same(PG_FUNCTION_ARGS); + + +static bool gbt_tsgt (const void *a, const void *b) +{ + return DatumGetBool( + DirectFunctionCall2(timestamp_gt,PointerGetDatum( a ), PointerGetDatum( b ) ) + ); +} +static bool gbt_tsge (const void *a, const void *b) +{ + return DatumGetBool( + DirectFunctionCall2(timestamp_ge,PointerGetDatum( a ), PointerGetDatum( 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 ) \ -))) +static bool gbt_tseq (const void *a, const void *b) +{ + return DatumGetBool( + DirectFunctionCall2(timestamp_eq,PointerGetDatum( a ), PointerGetDatum( b ) ) + ); +} + +static bool gbt_tsle (const void *a, const void *b) +{ + return DatumGetBool( + DirectFunctionCall2(timestamp_le,PointerGetDatum( a ), PointerGetDatum( b ) ) + ); +} + +static bool gbt_tslt (const void *a, const void *b) +{ + return DatumGetBool( + DirectFunctionCall2(timestamp_lt,PointerGetDatum( a ), PointerGetDatum( b ) ) + ); +} + + +static int +gbt_tskey_cmp(const void *a, const void *b) +{ + if ( gbt_tsgt( (void*)&(((Nsrt *) a)->t[0]) , (void*)&(((Nsrt *) b)->t[0]) ) ){ + return 1; + } else + if ( gbt_tslt( (void*)&(((Nsrt *) a)->t[0]) , (void*)&(((Nsrt *) b)->t[0]) ) ){ + return -1; + } + return 0; +} +static const gbtree_ninfo tinfo = +{ + gbt_t_ts, + sizeof(Timestamp), + gbt_tsgt, + gbt_tsge, + gbt_tseq, + gbt_tsle, + gbt_tslt, + gbt_tskey_cmp +}; + /************************************************** * timestamp ops **************************************************/ -Datum -gts_compress(PG_FUNCTION_ARGS) + + +static Timestamp * tstz_to_ts_gmt ( Timestamp * gmt, TimestampTz * ts ) { - 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); + int val, tz ; + + *gmt = *ts; + DecodeSpecial(0, "gmt", &val); + + if ( ! TIMESTAMP_NOT_FINITE(*ts)) + { + tz = val * 60; + +#ifdef HAVE_INT64_TIMESTAMP + *gmt -= (tz * INT64CONST(1000000)); +#else + *gmt -= tz; + *gmt = JROUND(*gmt); +#endif + + } + return gmt; } + + + Datum -gts_consistent(PG_FUNCTION_ARGS) +gbt_ts_compress(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); + GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); + GISTENTRY *retval = NULL; + PG_RETURN_POINTER( gbt_num_compress( retval , entry , &tinfo )); } + Datum -gts_union(PG_FUNCTION_ARGS) +gbt_tstz_compress(PG_FUNCTION_ARGS) { - GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0); - int i, - numranges; - TSKEY *cur, - *out = palloc(sizeof(TSKEY)); - - numranges = entryvec->n; - *(int *) PG_GETARG_POINTER(1) = sizeof(TSKEY); - - cur = (TSKEY *) DatumGetPointer((entryvec->vector[0].key)); - out->lower = cur->lower; - out->upper = cur->upper; - - for (i = 1; i < numranges; i++) - { - cur = (TSKEY *) DatumGetPointer((entryvec->vector[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); + GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); + GISTENTRY *retval ; + + if (entry->leafkey) + { + tsKEY *r = (tsKEY *) palloc(sizeof(tsKEY)); + + TimestampTz ts = *(TimestampTz *) DatumGetPointer(entry->key); + Timestamp gmt ; + + tstz_to_ts_gmt ( &gmt, &ts ); + + retval = palloc(sizeof(GISTENTRY)); + r->lower = r->upper = gmt ; + gistentryinit(*retval, PointerGetDatum(r), + entry->rel, entry->page, + entry->offset, sizeof(tsKEY), FALSE); + } + else + retval = entry; + + PG_RETURN_POINTER( retval ); } + Datum -gts_penalty(PG_FUNCTION_ARGS) +gbt_ts_consistent(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); + GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); + Timestamp *query = (Timestamp *) PG_GETARG_POINTER(1); + tsKEY *kkk = (tsKEY *) DatumGetPointer(entry->key); + GBT_NUMKEY_R key ; + StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2); + key.lower = (GBT_NUMKEY*) &kkk->lower ; + key.upper = (GBT_NUMKEY*) &kkk->upper ; + + PG_RETURN_BOOL( + gbt_num_consistent( &key, (void*)query,&strategy,GIST_LEAF(entry),&tinfo) + ); } Datum -gts_picksplit(PG_FUNCTION_ARGS) +gbt_tstz_consistent(PG_FUNCTION_ARGS) { - PG_RETURN_POINTER(btree_picksplit( - (GistEntryVector *) PG_GETARG_POINTER(0), - (GIST_SPLITVEC *) PG_GETARG_POINTER(1), - gts_binary_union, - tskey_cmp - )); + GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); + TimestampTz *query = (Timestamp *) PG_GETARG_POINTER(1); + tsKEY *kkk = (tsKEY *) DatumGetPointer(entry->key); + GBT_NUMKEY_R key ; + StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2); + Timestamp qqq ; + key.lower = (GBT_NUMKEY*) &kkk->lower ; + key.upper = (GBT_NUMKEY*) &kkk->upper ; + tstz_to_ts_gmt ( &qqq, query ); + + PG_RETURN_BOOL( + gbt_num_consistent( &key, (void*)&qqq,&strategy,GIST_LEAF(entry),&tinfo) + ); } + Datum -gts_same(PG_FUNCTION_ARGS) +gbt_ts_union(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); + GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0); + void *out = palloc(sizeof(tsKEY)); + *(int *) PG_GETARG_POINTER(1) = sizeof(tsKEY); + PG_RETURN_POINTER( gbt_num_union ( (void*)out, entryvec, &tinfo ) ); } -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) +Datum +gbt_ts_penalty(PG_FUNCTION_ARGS) { - return DatumGetInt32( - DirectFunctionCall2( - timestamp_cmp, - TimestampGetDatumFast(((TSKEY *) (((RIX *) a)->r))->lower), - TimestampGetDatumFast(((TSKEY *) (((RIX *) b)->r))->lower) - ) - ); -} + 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; +#ifdef HAVE_INT64_TIMESTAMP + int64 res; +#else + double res; +#endif + + intr = DatumGetIntervalP(DirectFunctionCall2( + timestamp_mi, + TimestampGetDatum(newentry->upper), + TimestampGetDatum(origentry->upper) + )); + + /* see interval_larger */ + + res = Max(intr->time + intr->month * (30 * 86400), 0); + pfree(intr); + + intr = DatumGetIntervalP(DirectFunctionCall2( + timestamp_mi, + TimestampGetDatum(origentry->lower), + TimestampGetDatum(newentry->lower) + )); + + /* see interval_larger */ + res += Max(intr->time + intr->month * (30 * 86400), 0); + pfree(intr); + + *result = 0.0; + + if ( res > 0 ){ + intr = DatumGetIntervalP(DirectFunctionCall2( + timestamp_mi, + TimestampGetDatum(origentry->upper), + TimestampGetDatum(origentry->lower) + )); + *result += FLT_MIN ; + *result += (float) ( res / ( (double) ( res + intr->time + intr->month * (30 * 86400) ) ) ); + *result *= ( FLT_MAX / ( ( (GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1 ) ); + pfree(intr); + } + + PG_RETURN_POINTER(result); + +} -/************************************************** - * In/Out for keys, not really needed - **************************************************/ Datum -tskey_in(PG_FUNCTION_ARGS) +gbt_ts_picksplit(PG_FUNCTION_ARGS) { - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("feature not implemented"))); - - PG_RETURN_POINTER(NULL); + PG_RETURN_POINTER(gbt_num_picksplit( + (GistEntryVector *) PG_GETARG_POINTER(0), + (GIST_SPLITVEC *) PG_GETARG_POINTER(1), + &tinfo + )); } Datum -tskey_out(PG_FUNCTION_ARGS) +gbt_ts_same(PG_FUNCTION_ARGS) { - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("feature not implemented"))); + tsKEY *b1 = (tsKEY *) PG_GETARG_POINTER(0); + tsKEY *b2 = (tsKEY *) PG_GETARG_POINTER(1); + bool *result = (bool *) PG_GETARG_POINTER(2); - PG_RETURN_POINTER(NULL); + *result = gbt_num_same ( (void*)b1, (void*)b2, &tinfo ); + PG_RETURN_POINTER(result); } + |