diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2011-03-02 14:43:24 -0500 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2011-03-02 14:44:33 -0500 |
commit | 8436489c81c23af637696ac69cdaafddcc907ee1 (patch) | |
tree | f9aabf47bbe6dba2f132dc472f855b306c2fe30c /contrib/btree_gist/btree_ts.c | |
parent | 6094c242d1ee40a08f3138811425d7540e8269e4 (diff) | |
download | postgresql-8436489c81c23af637696ac69cdaafddcc907ee1.tar.gz postgresql-8436489c81c23af637696ac69cdaafddcc907ee1.zip |
Add KNNGIST support to contrib/btree_gist.
This extends GiST's support for nearest-neighbor searches to many of the
standard data types.
Teodor Sigaev
Diffstat (limited to 'contrib/btree_gist/btree_ts.c')
-rw-r--r-- | contrib/btree_gist/btree_ts.c | 122 |
1 files changed, 121 insertions, 1 deletions
diff --git a/contrib/btree_gist/btree_ts.c b/contrib/btree_gist/btree_ts.c index 2b13d14ad19..9a0ec07a1e7 100644 --- a/contrib/btree_gist/btree_ts.c +++ b/contrib/btree_gist/btree_ts.c @@ -3,6 +3,7 @@ */ #include "btree_gist.h" #include "btree_utils_num.h" +#include "utils/builtins.h" #include "utils/datetime.h" typedef struct @@ -19,7 +20,9 @@ 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_ts_distance); PG_FUNCTION_INFO_V1(gbt_tstz_consistent); +PG_FUNCTION_INFO_V1(gbt_tstz_distance); PG_FUNCTION_INFO_V1(gbt_ts_penalty); PG_FUNCTION_INFO_V1(gbt_ts_same); @@ -28,7 +31,9 @@ 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_ts_distance(PG_FUNCTION_ARGS); Datum gbt_tstz_consistent(PG_FUNCTION_ARGS); +Datum gbt_tstz_distance(PG_FUNCTION_ARGS); Datum gbt_ts_penalty(PG_FUNCTION_ARGS); Datum gbt_ts_same(PG_FUNCTION_ARGS); @@ -110,6 +115,22 @@ gbt_tskey_cmp(const void *a, const void *b) return res; } +static float8 +gbt_ts_dist(const void *a, const void *b) +{ + const Timestamp *aa = (const Timestamp *) a; + const Timestamp *bb = (const Timestamp *) b; + Interval *i; + + if (TIMESTAMP_NOT_FINITE(*aa) || TIMESTAMP_NOT_FINITE(*bb)) + return get_float8_infinity(); + + i = DatumGetIntervalP(DirectFunctionCall2(timestamp_mi, + TimestampGetDatumFast(*aa), + TimestampGetDatumFast(*bb))); + return (float8) Abs(INTERVAL_TO_SEC(i)); +} + static const gbtree_ninfo tinfo = { @@ -120,10 +141,71 @@ static const gbtree_ninfo tinfo = gbt_tseq, gbt_tsle, gbt_tslt, - gbt_tskey_cmp + gbt_tskey_cmp, + gbt_ts_dist }; +PG_FUNCTION_INFO_V1(ts_dist); +Datum ts_dist(PG_FUNCTION_ARGS); +Datum +ts_dist(PG_FUNCTION_ARGS) +{ + Timestamp a = PG_GETARG_TIMESTAMP(0); + Timestamp b = PG_GETARG_TIMESTAMP(1); + Interval *r; + + if (TIMESTAMP_NOT_FINITE(a) || TIMESTAMP_NOT_FINITE(b)) + { + Interval *p = palloc(sizeof(Interval)); + + p->day = INT_MAX; + p->month = INT_MAX; +#ifdef HAVE_INT64_TIMESTAMP + p->time = INT64CONST(0x7FFFFFFFFFFFFFFF); +#else + p->time = DBL_MAX; +#endif + PG_RETURN_INTERVAL_P(p); + } + else + + r = DatumGetIntervalP(DirectFunctionCall2(timestamp_mi, + PG_GETARG_DATUM(0), + PG_GETARG_DATUM(1))); + PG_RETURN_INTERVAL_P( abs_interval(r) ); +} + +PG_FUNCTION_INFO_V1(tstz_dist); +Datum tstz_dist(PG_FUNCTION_ARGS); +Datum +tstz_dist(PG_FUNCTION_ARGS) +{ + TimestampTz a = PG_GETARG_TIMESTAMPTZ(0); + TimestampTz b = PG_GETARG_TIMESTAMPTZ(1); + Interval *r; + + if (TIMESTAMP_NOT_FINITE(a) || TIMESTAMP_NOT_FINITE(b)) + { + Interval *p = palloc(sizeof(Interval)); + + p->day = INT_MAX; + p->month = INT_MAX; +#ifdef HAVE_INT64_TIMESTAMP + p->time = INT64CONST(0x7FFFFFFFFFFFFFFF); +#else + p->time = DBL_MAX; +#endif + PG_RETURN_INTERVAL_P(p); + } + + r = DatumGetIntervalP(DirectFunctionCall2(timestamp_mi, + PG_GETARG_DATUM(0), + PG_GETARG_DATUM(1))); + PG_RETURN_INTERVAL_P( abs_interval(r) ); +} + + /************************************************** * timestamp ops **************************************************/ @@ -214,6 +296,24 @@ gbt_ts_consistent(PG_FUNCTION_ARGS) } Datum +gbt_ts_distance(PG_FUNCTION_ARGS) +{ + GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); + Timestamp query = PG_GETARG_TIMESTAMP(1); + + /* Oid subtype = PG_GETARG_OID(3); */ + tsKEY *kkk = (tsKEY *) DatumGetPointer(entry->key); + GBT_NUMKEY_R key; + + key.lower = (GBT_NUMKEY *) &kkk->lower; + key.upper = (GBT_NUMKEY *) &kkk->upper; + + PG_RETURN_FLOAT8( + gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo) + ); +} + +Datum gbt_tstz_consistent(PG_FUNCTION_ARGS) { GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); @@ -238,6 +338,26 @@ gbt_tstz_consistent(PG_FUNCTION_ARGS) ); } +Datum +gbt_tstz_distance(PG_FUNCTION_ARGS) +{ + GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); + TimestampTz query = PG_GETARG_TIMESTAMPTZ(1); + + /* Oid subtype = PG_GETARG_OID(3); */ + char *kkk = (char *) DatumGetPointer(entry->key); + GBT_NUMKEY_R key; + Timestamp qqq; + + key.lower = (GBT_NUMKEY *) &kkk[0]; + key.upper = (GBT_NUMKEY *) &kkk[MAXALIGN(tinfo.size)]; + qqq = tstz_to_ts_gmt(query); + + PG_RETURN_FLOAT8( + gbt_num_distance(&key, (void *) &qqq, GIST_LEAF(entry), &tinfo) + ); +} + Datum gbt_ts_union(PG_FUNCTION_ARGS) |