summaryrefslogtreecommitdiff
path: root/contrib/btree_gist/btree_interval.c
diff options
context:
space:
mode:
authorTom Lane2011-03-02 19:43:24 +0000
committerTom Lane2011-03-02 19:44:33 +0000
commit8436489c81c23af637696ac69cdaafddcc907ee1 (patch)
treef9aabf47bbe6dba2f132dc472f855b306c2fe30c /contrib/btree_gist/btree_interval.c
parent6094c242d1ee40a08f3138811425d7540e8269e4 (diff)
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_interval.c')
-rw-r--r--contrib/btree_gist/btree_interval.c57
1 files changed, 56 insertions, 1 deletions
diff --git a/contrib/btree_gist/btree_interval.c b/contrib/btree_gist/btree_interval.c
index 0715346f234..5195284afa1 100644
--- a/contrib/btree_gist/btree_interval.c
+++ b/contrib/btree_gist/btree_interval.c
@@ -20,6 +20,7 @@ PG_FUNCTION_INFO_V1(gbt_intv_decompress);
PG_FUNCTION_INFO_V1(gbt_intv_union);
PG_FUNCTION_INFO_V1(gbt_intv_picksplit);
PG_FUNCTION_INFO_V1(gbt_intv_consistent);
+PG_FUNCTION_INFO_V1(gbt_intv_distance);
PG_FUNCTION_INFO_V1(gbt_intv_penalty);
PG_FUNCTION_INFO_V1(gbt_intv_same);
@@ -28,6 +29,7 @@ Datum gbt_intv_decompress(PG_FUNCTION_ARGS);
Datum gbt_intv_union(PG_FUNCTION_ARGS);
Datum gbt_intv_picksplit(PG_FUNCTION_ARGS);
Datum gbt_intv_consistent(PG_FUNCTION_ARGS);
+Datum gbt_intv_distance(PG_FUNCTION_ARGS);
Datum gbt_intv_penalty(PG_FUNCTION_ARGS);
Datum gbt_intv_same(PG_FUNCTION_ARGS);
@@ -83,6 +85,12 @@ intr2num(const Interval *i)
return INTERVAL_TO_SEC(i);
}
+static float8
+gbt_intv_dist(const void *a, const void *b)
+{
+ return (float8)Abs(intr2num((Interval*)a) - intr2num((Interval*)b));
+}
+
/*
* INTERVALSIZE should be the actual size-on-disk of an Interval, as shown
* in pg_type. This might be less than sizeof(Interval) if the compiler
@@ -99,10 +107,38 @@ static const gbtree_ninfo tinfo =
gbt_intveq,
gbt_intvle,
gbt_intvlt,
- gbt_intvkey_cmp
+ gbt_intvkey_cmp,
+ gbt_intv_dist
};
+Interval *
+abs_interval(Interval *a)
+{
+ static Interval zero = {0, 0, 0};
+
+ if (DatumGetBool(DirectFunctionCall2(interval_lt,
+ IntervalPGetDatum(a),
+ IntervalPGetDatum(&zero))))
+ a = DatumGetIntervalP(DirectFunctionCall1(interval_um,
+ IntervalPGetDatum(a)));
+
+ return a;
+}
+
+PG_FUNCTION_INFO_V1(interval_dist);
+Datum interval_dist(PG_FUNCTION_ARGS);
+Datum
+interval_dist(PG_FUNCTION_ARGS)
+{
+ Datum diff = DirectFunctionCall2(interval_mi,
+ PG_GETARG_DATUM(0),
+ PG_GETARG_DATUM(1));
+
+ PG_RETURN_INTERVAL_P(abs_interval(DatumGetIntervalP(diff)));
+}
+
+
/**************************************************
* interval ops
**************************************************/
@@ -191,6 +227,25 @@ gbt_intv_consistent(PG_FUNCTION_ARGS)
Datum
+gbt_intv_distance(PG_FUNCTION_ARGS)
+{
+ GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+ Interval *query = PG_GETARG_INTERVAL_P(1);
+
+ /* Oid subtype = PG_GETARG_OID(3); */
+ intvKEY *kkk = (intvKEY *) 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_intv_union(PG_FUNCTION_ARGS)
{
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);