aboutsummaryrefslogtreecommitdiff
path: root/contrib/btree_gist/btree_ts.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2011-03-02 14:43:24 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2011-03-02 14:44:33 -0500
commit8436489c81c23af637696ac69cdaafddcc907ee1 (patch)
treef9aabf47bbe6dba2f132dc472f855b306c2fe30c /contrib/btree_gist/btree_ts.c
parent6094c242d1ee40a08f3138811425d7540e8269e4 (diff)
downloadpostgresql-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.c122
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)