1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-11 20:28:21 +03:00

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
This commit is contained in:
Tom Lane
2011-03-02 14:43:24 -05:00
parent 6094c242d1
commit 8436489c81
40 changed files with 1546 additions and 59 deletions

View File

@ -18,6 +18,7 @@ PG_FUNCTION_INFO_V1(gbt_cash_compress);
PG_FUNCTION_INFO_V1(gbt_cash_union);
PG_FUNCTION_INFO_V1(gbt_cash_picksplit);
PG_FUNCTION_INFO_V1(gbt_cash_consistent);
PG_FUNCTION_INFO_V1(gbt_cash_distance);
PG_FUNCTION_INFO_V1(gbt_cash_penalty);
PG_FUNCTION_INFO_V1(gbt_cash_same);
@ -25,6 +26,7 @@ Datum gbt_cash_compress(PG_FUNCTION_ARGS);
Datum gbt_cash_union(PG_FUNCTION_ARGS);
Datum gbt_cash_picksplit(PG_FUNCTION_ARGS);
Datum gbt_cash_consistent(PG_FUNCTION_ARGS);
Datum gbt_cash_distance(PG_FUNCTION_ARGS);
Datum gbt_cash_penalty(PG_FUNCTION_ARGS);
Datum gbt_cash_same(PG_FUNCTION_ARGS);
@ -71,6 +73,12 @@ gbt_cashkey_cmp(const void *a, const void *b)
return (ia->lower > ib->lower) ? 1 : -1;
}
static float8
gbt_cash_dist(const void *a, const void *b)
{
return GET_FLOAT_DISTANCE(Cash, a, b);
}
static const gbtree_ninfo tinfo =
{
@ -81,10 +89,33 @@ static const gbtree_ninfo tinfo =
gbt_casheq,
gbt_cashle,
gbt_cashlt,
gbt_cashkey_cmp
gbt_cashkey_cmp,
gbt_cash_dist
};
PG_FUNCTION_INFO_V1(cash_dist);
Datum cash_dist(PG_FUNCTION_ARGS);
Datum
cash_dist(PG_FUNCTION_ARGS)
{
Cash a = PG_GETARG_CASH(0);
Cash b = PG_GETARG_CASH(1);
Cash r;
Cash ra;
r = a - b;
ra = Abs(r);
/* Overflow check. */
if (ra < 0 || (!SAMESIGN(a, b) && !SAMESIGN(r, a)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("money out of range")));
PG_RETURN_CASH(ra);
}
/**************************************************
* Cash ops
**************************************************/
@ -124,6 +155,25 @@ gbt_cash_consistent(PG_FUNCTION_ARGS)
}
Datum
gbt_cash_distance(PG_FUNCTION_ARGS)
{
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
Cash query = PG_GETARG_CASH(1);
/* Oid subtype = PG_GETARG_OID(3); */
cashKEY *kkk = (cashKEY *) 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_cash_union(PG_FUNCTION_ARGS)
{

View File

@ -18,6 +18,7 @@ PG_FUNCTION_INFO_V1(gbt_date_compress);
PG_FUNCTION_INFO_V1(gbt_date_union);
PG_FUNCTION_INFO_V1(gbt_date_picksplit);
PG_FUNCTION_INFO_V1(gbt_date_consistent);
PG_FUNCTION_INFO_V1(gbt_date_distance);
PG_FUNCTION_INFO_V1(gbt_date_penalty);
PG_FUNCTION_INFO_V1(gbt_date_same);
@ -25,6 +26,7 @@ Datum gbt_date_compress(PG_FUNCTION_ARGS);
Datum gbt_date_union(PG_FUNCTION_ARGS);
Datum gbt_date_picksplit(PG_FUNCTION_ARGS);
Datum gbt_date_consistent(PG_FUNCTION_ARGS);
Datum gbt_date_distance(PG_FUNCTION_ARGS);
Datum gbt_date_penalty(PG_FUNCTION_ARGS);
Datum gbt_date_same(PG_FUNCTION_ARGS);
@ -84,6 +86,17 @@ gbt_datekey_cmp(const void *a, const void *b)
return res;
}
static float8
gdb_date_dist(const void *a, const void *b)
{
/* we assume the difference can't overflow */
Datum diff = DirectFunctionCall2(date_mi,
DateADTGetDatum(*((const DateADT *) a)),
DateADTGetDatum(*((const DateADT *) b)));
return (float8) Abs(DatumGetInt32(diff));
}
static const gbtree_ninfo tinfo =
{
@ -94,10 +107,25 @@ static const gbtree_ninfo tinfo =
gbt_dateeq,
gbt_datele,
gbt_datelt,
gbt_datekey_cmp
gbt_datekey_cmp,
gdb_date_dist
};
PG_FUNCTION_INFO_V1(date_dist);
Datum date_dist(PG_FUNCTION_ARGS);
Datum
date_dist(PG_FUNCTION_ARGS)
{
/* we assume the difference can't overflow */
Datum diff = DirectFunctionCall2(date_mi,
PG_GETARG_DATUM(0),
PG_GETARG_DATUM(1));
PG_RETURN_INT32(Abs(DatumGetInt32(diff)));
}
/**************************************************
* date ops
**************************************************/
@ -139,6 +167,25 @@ gbt_date_consistent(PG_FUNCTION_ARGS)
}
Datum
gbt_date_distance(PG_FUNCTION_ARGS)
{
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
DateADT query = PG_GETARG_DATEADT(1);
/* Oid subtype = PG_GETARG_OID(3); */
dateKEY *kkk = (dateKEY *) 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_date_union(PG_FUNCTION_ARGS)
{

View File

@ -17,6 +17,7 @@ PG_FUNCTION_INFO_V1(gbt_float4_compress);
PG_FUNCTION_INFO_V1(gbt_float4_union);
PG_FUNCTION_INFO_V1(gbt_float4_picksplit);
PG_FUNCTION_INFO_V1(gbt_float4_consistent);
PG_FUNCTION_INFO_V1(gbt_float4_distance);
PG_FUNCTION_INFO_V1(gbt_float4_penalty);
PG_FUNCTION_INFO_V1(gbt_float4_same);
@ -24,6 +25,7 @@ Datum gbt_float4_compress(PG_FUNCTION_ARGS);
Datum gbt_float4_union(PG_FUNCTION_ARGS);
Datum gbt_float4_picksplit(PG_FUNCTION_ARGS);
Datum gbt_float4_consistent(PG_FUNCTION_ARGS);
Datum gbt_float4_distance(PG_FUNCTION_ARGS);
Datum gbt_float4_penalty(PG_FUNCTION_ARGS);
Datum gbt_float4_same(PG_FUNCTION_ARGS);
@ -70,6 +72,12 @@ gbt_float4key_cmp(const void *a, const void *b)
return (ia->lower > ib->lower) ? 1 : -1;
}
static float8
gbt_float4_dist(const void *a, const void *b)
{
return GET_FLOAT_DISTANCE(float4, a, b);
}
static const gbtree_ninfo tinfo =
{
@ -80,10 +88,27 @@ static const gbtree_ninfo tinfo =
gbt_float4eq,
gbt_float4le,
gbt_float4lt,
gbt_float4key_cmp
gbt_float4key_cmp,
gbt_float4_dist
};
PG_FUNCTION_INFO_V1(float4_dist);
Datum float4_dist(PG_FUNCTION_ARGS);
Datum
float4_dist(PG_FUNCTION_ARGS)
{
float4 a = PG_GETARG_FLOAT4(0);
float4 b = PG_GETARG_FLOAT4(1);
float4 r;
r = a - b;
CHECKFLOATVAL(r, isinf(a) || isinf(b), true);
PG_RETURN_FLOAT4( Abs(r) );
}
/**************************************************
* float4 ops
**************************************************/
@ -123,6 +148,25 @@ gbt_float4_consistent(PG_FUNCTION_ARGS)
}
Datum
gbt_float4_distance(PG_FUNCTION_ARGS)
{
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
float4 query = PG_GETARG_FLOAT4(1);
/* Oid subtype = PG_GETARG_OID(3); */
float4KEY *kkk = (float4KEY *) 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_float4_union(PG_FUNCTION_ARGS)
{

View File

@ -17,6 +17,7 @@ PG_FUNCTION_INFO_V1(gbt_float8_compress);
PG_FUNCTION_INFO_V1(gbt_float8_union);
PG_FUNCTION_INFO_V1(gbt_float8_picksplit);
PG_FUNCTION_INFO_V1(gbt_float8_consistent);
PG_FUNCTION_INFO_V1(gbt_float8_distance);
PG_FUNCTION_INFO_V1(gbt_float8_penalty);
PG_FUNCTION_INFO_V1(gbt_float8_same);
@ -24,6 +25,7 @@ Datum gbt_float8_compress(PG_FUNCTION_ARGS);
Datum gbt_float8_union(PG_FUNCTION_ARGS);
Datum gbt_float8_picksplit(PG_FUNCTION_ARGS);
Datum gbt_float8_consistent(PG_FUNCTION_ARGS);
Datum gbt_float8_distance(PG_FUNCTION_ARGS);
Datum gbt_float8_penalty(PG_FUNCTION_ARGS);
Datum gbt_float8_same(PG_FUNCTION_ARGS);
@ -71,6 +73,19 @@ gbt_float8key_cmp(const void *a, const void *b)
return (ia->lower > ib->lower) ? 1 : -1;
}
static float8
gbt_float8_dist(const void *a, const void *b)
{
float8 arg1 = *(const float8 *)a;
float8 arg2 = *(const float8 *)b;
float8 r;
r = arg1 - arg2;
CHECKFLOATVAL(r, isinf(arg1) || isinf(arg2), true);
return Abs(r);
}
static const gbtree_ninfo tinfo =
{
@ -81,10 +96,26 @@ static const gbtree_ninfo tinfo =
gbt_float8eq,
gbt_float8le,
gbt_float8lt,
gbt_float8key_cmp
gbt_float8key_cmp,
gbt_float8_dist
};
PG_FUNCTION_INFO_V1(float8_dist);
Datum float8_dist(PG_FUNCTION_ARGS);
Datum
float8_dist(PG_FUNCTION_ARGS)
{
float8 a = PG_GETARG_FLOAT8(0);
float8 b = PG_GETARG_FLOAT8(1);
float8 r;
r = a - b;
CHECKFLOATVAL(r, isinf(a) || isinf(b), true);
PG_RETURN_FLOAT8( Abs(r) );
}
/**************************************************
* float8 ops
**************************************************/
@ -124,6 +155,25 @@ gbt_float8_consistent(PG_FUNCTION_ARGS)
}
Datum
gbt_float8_distance(PG_FUNCTION_ARGS)
{
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
float8 query = PG_GETARG_FLOAT8(1);
/* Oid subtype = PG_GETARG_OID(3); */
float8KEY *kkk = (float8KEY *) 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_float8_union(PG_FUNCTION_ARGS)
{

View File

@ -81,6 +81,151 @@ CREATE TYPE gbtreekey_var (
STORAGE = EXTENDED
);
--distance operators
CREATE FUNCTION cash_dist(money, money)
RETURNS money
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE OPERATOR <-> (
LEFTARG = money,
RIGHTARG = money,
PROCEDURE = cash_dist,
COMMUTATOR = '<->'
);
CREATE FUNCTION date_dist(date, date)
RETURNS int4
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE OPERATOR <-> (
LEFTARG = date,
RIGHTARG = date,
PROCEDURE = date_dist,
COMMUTATOR = '<->'
);
CREATE FUNCTION float4_dist(float4, float4)
RETURNS float4
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE OPERATOR <-> (
LEFTARG = float4,
RIGHTARG = float4,
PROCEDURE = float4_dist,
COMMUTATOR = '<->'
);
CREATE FUNCTION float8_dist(float8, float8)
RETURNS float8
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE OPERATOR <-> (
LEFTARG = float8,
RIGHTARG = float8,
PROCEDURE = float8_dist,
COMMUTATOR = '<->'
);
CREATE FUNCTION int2_dist(int2, int2)
RETURNS int2
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE OPERATOR <-> (
LEFTARG = int2,
RIGHTARG = int2,
PROCEDURE = int2_dist,
COMMUTATOR = '<->'
);
CREATE FUNCTION int4_dist(int4, int4)
RETURNS int4
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE OPERATOR <-> (
LEFTARG = int4,
RIGHTARG = int4,
PROCEDURE = int4_dist,
COMMUTATOR = '<->'
);
CREATE FUNCTION int8_dist(int8, int8)
RETURNS int8
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE OPERATOR <-> (
LEFTARG = int8,
RIGHTARG = int8,
PROCEDURE = int8_dist,
COMMUTATOR = '<->'
);
CREATE FUNCTION interval_dist(interval, interval)
RETURNS interval
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE OPERATOR <-> (
LEFTARG = interval,
RIGHTARG = interval,
PROCEDURE = interval_dist,
COMMUTATOR = '<->'
);
CREATE FUNCTION oid_dist(oid, oid)
RETURNS oid
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE OPERATOR <-> (
LEFTARG = oid,
RIGHTARG = oid,
PROCEDURE = oid_dist,
COMMUTATOR = '<->'
);
CREATE FUNCTION time_dist(time, time)
RETURNS interval
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE OPERATOR <-> (
LEFTARG = time,
RIGHTARG = time,
PROCEDURE = time_dist,
COMMUTATOR = '<->'
);
CREATE FUNCTION ts_dist(timestamp, timestamp)
RETURNS interval
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE OPERATOR <-> (
LEFTARG = timestamp,
RIGHTARG = timestamp,
PROCEDURE = ts_dist,
COMMUTATOR = '<->'
);
CREATE FUNCTION tstz_dist(timestamptz, timestamptz)
RETURNS interval
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE OPERATOR <-> (
LEFTARG = timestamptz,
RIGHTARG = timestamptz,
PROCEDURE = tstz_dist,
COMMUTATOR = '<->'
);
--
@ -96,6 +241,11 @@ RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION gbt_oid_distance(internal,oid,int2,oid)
RETURNS float8
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION gbt_oid_compress(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
@ -154,7 +304,9 @@ AS
-- that's the only state that can be reproduced during an upgrade from 9.0.
ALTER OPERATOR FAMILY gist_oid_ops USING gist ADD
OPERATOR 6 <> (oid, oid) ;
OPERATOR 6 <> (oid, oid) ,
OPERATOR 15 <-> (oid, oid) FOR ORDER BY pg_catalog.oid_ops ,
FUNCTION 8 (oid, oid) gbt_oid_distance (internal, oid, int2, oid) ;
--
@ -170,6 +322,11 @@ RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION gbt_int2_distance(internal,int2,int2,oid)
RETURNS float8
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION gbt_int2_compress(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
@ -214,7 +371,9 @@ AS
STORAGE gbtreekey4;
ALTER OPERATOR FAMILY gist_int2_ops USING gist ADD
OPERATOR 6 <> (int2, int2) ;
OPERATOR 6 <> (int2, int2) ,
OPERATOR 15 <-> (int2, int2) FOR ORDER BY pg_catalog.integer_ops ,
FUNCTION 8 (int2, int2) gbt_int2_distance (internal, int2, int2, oid) ;
--
@ -230,6 +389,11 @@ RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION gbt_int4_distance(internal,int4,int2,oid)
RETURNS float8
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION gbt_int4_compress(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
@ -274,7 +438,9 @@ AS
STORAGE gbtreekey8;
ALTER OPERATOR FAMILY gist_int4_ops USING gist ADD
OPERATOR 6 <> (int4, int4) ;
OPERATOR 6 <> (int4, int4) ,
OPERATOR 15 <-> (int4, int4) FOR ORDER BY pg_catalog.integer_ops ,
FUNCTION 8 (int4, int4) gbt_int4_distance (internal, int4, int2, oid) ;
--
@ -290,6 +456,11 @@ RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION gbt_int8_distance(internal,int8,int2,oid)
RETURNS float8
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION gbt_int8_compress(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
@ -334,7 +505,9 @@ AS
STORAGE gbtreekey16;
ALTER OPERATOR FAMILY gist_int8_ops USING gist ADD
OPERATOR 6 <> (int8, int8) ;
OPERATOR 6 <> (int8, int8) ,
OPERATOR 15 <-> (int8, int8) FOR ORDER BY pg_catalog.integer_ops ,
FUNCTION 8 (int8, int8) gbt_int8_distance (internal, int8, int2, oid) ;
--
@ -350,6 +523,11 @@ RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION gbt_float4_distance(internal,float4,int2,oid)
RETURNS float8
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION gbt_float4_compress(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
@ -394,7 +572,9 @@ AS
STORAGE gbtreekey8;
ALTER OPERATOR FAMILY gist_float4_ops USING gist ADD
OPERATOR 6 <> (float4, float4) ;
OPERATOR 6 <> (float4, float4) ,
OPERATOR 15 <-> (float4, float4) FOR ORDER BY pg_catalog.float_ops ,
FUNCTION 8 (float4, float4) gbt_float4_distance (internal, float4, int2, oid) ;
--
@ -410,6 +590,11 @@ RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION gbt_float8_distance(internal,float8,int2,oid)
RETURNS float8
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION gbt_float8_compress(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
@ -454,7 +639,9 @@ AS
STORAGE gbtreekey16;
ALTER OPERATOR FAMILY gist_float8_ops USING gist ADD
OPERATOR 6 <> (float8, float8) ;
OPERATOR 6 <> (float8, float8) ,
OPERATOR 15 <-> (float8, float8) FOR ORDER BY pg_catalog.float_ops ,
FUNCTION 8 (float8, float8) gbt_float8_distance (internal, float8, int2, oid) ;
--
@ -470,11 +657,21 @@ RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION gbt_ts_distance(internal,timestamp,int2,oid)
RETURNS float8
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION gbt_tstz_consistent(internal,timestamptz,int2,oid,internal)
RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION gbt_tstz_distance(internal,timestamptz,int2,oid)
RETURNS float8
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION gbt_ts_compress(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
@ -524,7 +721,9 @@ AS
STORAGE gbtreekey16;
ALTER OPERATOR FAMILY gist_timestamp_ops USING gist ADD
OPERATOR 6 <> (timestamp, timestamp) ;
OPERATOR 6 <> (timestamp, timestamp) ,
OPERATOR 15 <-> (timestamp, timestamp) FOR ORDER BY pg_catalog.interval_ops ,
FUNCTION 8 (timestamp, timestamp) gbt_ts_distance (internal, timestamp, int2, oid) ;
-- Create the operator class
@ -546,7 +745,9 @@ AS
STORAGE gbtreekey16;
ALTER OPERATOR FAMILY gist_timestamptz_ops USING gist ADD
OPERATOR 6 <> (timestamptz, timestamptz) ;
OPERATOR 6 <> (timestamptz, timestamptz) ,
OPERATOR 15 <-> (timestamptz, timestamptz) FOR ORDER BY pg_catalog.interval_ops ,
FUNCTION 8 (timestamptz, timestamptz) gbt_tstz_distance (internal, timestamptz, int2, oid) ;
--
@ -562,6 +763,11 @@ RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION gbt_time_distance(internal,time,int2,oid)
RETURNS float8
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION gbt_timetz_consistent(internal,timetz,int2,oid,internal)
RETURNS bool
AS 'MODULE_PATHNAME'
@ -616,7 +822,9 @@ AS
STORAGE gbtreekey16;
ALTER OPERATOR FAMILY gist_time_ops USING gist ADD
OPERATOR 6 <> (time, time) ;
OPERATOR 6 <> (time, time) ,
OPERATOR 15 <-> (time, time) FOR ORDER BY pg_catalog.interval_ops ,
FUNCTION 8 (time, time) gbt_time_distance (internal, time, int2, oid) ;
CREATE OPERATOR CLASS gist_timetz_ops
@ -653,6 +861,11 @@ RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION gbt_date_distance(internal,date,int2,oid)
RETURNS float8
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION gbt_date_compress(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
@ -697,7 +910,9 @@ AS
STORAGE gbtreekey8;
ALTER OPERATOR FAMILY gist_date_ops USING gist ADD
OPERATOR 6 <> (date, date) ;
OPERATOR 6 <> (date, date) ,
OPERATOR 15 <-> (date, date) FOR ORDER BY pg_catalog.integer_ops ,
FUNCTION 8 (date, date) gbt_date_distance (internal, date, int2, oid) ;
--
@ -713,6 +928,11 @@ RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION gbt_intv_distance(internal,interval,int2,oid)
RETURNS float8
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION gbt_intv_compress(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
@ -762,7 +982,9 @@ AS
STORAGE gbtreekey32;
ALTER OPERATOR FAMILY gist_interval_ops USING gist ADD
OPERATOR 6 <> (interval, interval) ;
OPERATOR 6 <> (interval, interval) ,
OPERATOR 15 <-> (interval, interval) FOR ORDER BY pg_catalog.interval_ops ,
FUNCTION 8 (interval, interval) gbt_intv_distance (internal, interval, int2, oid) ;
--
@ -778,6 +1000,11 @@ RETURNS bool
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION gbt_cash_distance(internal,money,int2,oid)
RETURNS float8
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION gbt_cash_compress(internal)
RETURNS internal
AS 'MODULE_PATHNAME'
@ -822,7 +1049,9 @@ AS
STORAGE gbtreekey16;
ALTER OPERATOR FAMILY gist_cash_ops USING gist ADD
OPERATOR 6 <> (money, money) ;
OPERATOR 6 <> (money, money) ,
OPERATOR 15 <-> (money, money) FOR ORDER BY pg_catalog.money_ops ,
FUNCTION 8 (money, money) gbt_cash_distance (internal, money, int2, oid) ;
--

View File

@ -171,46 +171,282 @@ ALTER EXTENSION btree_gist ADD operator class gist_inet_ops using gist;
ALTER EXTENSION btree_gist ADD operator family gist_cidr_ops using gist;
ALTER EXTENSION btree_gist ADD operator class gist_cidr_ops using gist;
-- Add functions and operators that are new in 9.1
--distance operators
CREATE FUNCTION cash_dist(money, money)
RETURNS money
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE OPERATOR <-> (
LEFTARG = money,
RIGHTARG = money,
PROCEDURE = cash_dist,
COMMUTATOR = '<->'
);
CREATE FUNCTION date_dist(date, date)
RETURNS int4
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE OPERATOR <-> (
LEFTARG = date,
RIGHTARG = date,
PROCEDURE = date_dist,
COMMUTATOR = '<->'
);
CREATE FUNCTION float4_dist(float4, float4)
RETURNS float4
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE OPERATOR <-> (
LEFTARG = float4,
RIGHTARG = float4,
PROCEDURE = float4_dist,
COMMUTATOR = '<->'
);
CREATE FUNCTION float8_dist(float8, float8)
RETURNS float8
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE OPERATOR <-> (
LEFTARG = float8,
RIGHTARG = float8,
PROCEDURE = float8_dist,
COMMUTATOR = '<->'
);
CREATE FUNCTION int2_dist(int2, int2)
RETURNS int2
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE OPERATOR <-> (
LEFTARG = int2,
RIGHTARG = int2,
PROCEDURE = int2_dist,
COMMUTATOR = '<->'
);
CREATE FUNCTION int4_dist(int4, int4)
RETURNS int4
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE OPERATOR <-> (
LEFTARG = int4,
RIGHTARG = int4,
PROCEDURE = int4_dist,
COMMUTATOR = '<->'
);
CREATE FUNCTION int8_dist(int8, int8)
RETURNS int8
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE OPERATOR <-> (
LEFTARG = int8,
RIGHTARG = int8,
PROCEDURE = int8_dist,
COMMUTATOR = '<->'
);
CREATE FUNCTION interval_dist(interval, interval)
RETURNS interval
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE OPERATOR <-> (
LEFTARG = interval,
RIGHTARG = interval,
PROCEDURE = interval_dist,
COMMUTATOR = '<->'
);
CREATE FUNCTION oid_dist(oid, oid)
RETURNS oid
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE OPERATOR <-> (
LEFTARG = oid,
RIGHTARG = oid,
PROCEDURE = oid_dist,
COMMUTATOR = '<->'
);
CREATE FUNCTION time_dist(time, time)
RETURNS interval
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE OPERATOR <-> (
LEFTARG = time,
RIGHTARG = time,
PROCEDURE = time_dist,
COMMUTATOR = '<->'
);
CREATE FUNCTION ts_dist(timestamp, timestamp)
RETURNS interval
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE OPERATOR <-> (
LEFTARG = timestamp,
RIGHTARG = timestamp,
PROCEDURE = ts_dist,
COMMUTATOR = '<->'
);
CREATE FUNCTION tstz_dist(timestamptz, timestamptz)
RETURNS interval
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE OPERATOR <-> (
LEFTARG = timestamptz,
RIGHTARG = timestamptz,
PROCEDURE = tstz_dist,
COMMUTATOR = '<->'
);
-- Support functions for distance operators
CREATE FUNCTION gbt_oid_distance(internal,oid,int2,oid)
RETURNS float8
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION gbt_int2_distance(internal,int2,int2,oid)
RETURNS float8
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION gbt_int4_distance(internal,int4,int2,oid)
RETURNS float8
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION gbt_int8_distance(internal,int8,int2,oid)
RETURNS float8
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION gbt_float4_distance(internal,float4,int2,oid)
RETURNS float8
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION gbt_float8_distance(internal,float8,int2,oid)
RETURNS float8
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION gbt_ts_distance(internal,timestamp,int2,oid)
RETURNS float8
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION gbt_tstz_distance(internal,timestamptz,int2,oid)
RETURNS float8
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION gbt_time_distance(internal,time,int2,oid)
RETURNS float8
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION gbt_date_distance(internal,date,int2,oid)
RETURNS float8
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION gbt_intv_distance(internal,interval,int2,oid)
RETURNS float8
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION gbt_cash_distance(internal,money,int2,oid)
RETURNS float8
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
-- Add new-in-9.1 stuff to the operator classes.
ALTER OPERATOR FAMILY gist_oid_ops USING gist ADD
OPERATOR 6 <> (oid, oid) ;
OPERATOR 6 <> (oid, oid) ,
OPERATOR 15 <-> (oid, oid) FOR ORDER BY pg_catalog.oid_ops ,
FUNCTION 8 (oid, oid) gbt_oid_distance (internal, oid, int2, oid) ;
ALTER OPERATOR FAMILY gist_int2_ops USING gist ADD
OPERATOR 6 <> (int2, int2) ;
OPERATOR 6 <> (int2, int2) ,
OPERATOR 15 <-> (int2, int2) FOR ORDER BY pg_catalog.integer_ops ,
FUNCTION 8 (int2, int2) gbt_int2_distance (internal, int2, int2, oid) ;
ALTER OPERATOR FAMILY gist_int4_ops USING gist ADD
OPERATOR 6 <> (int4, int4) ;
OPERATOR 6 <> (int4, int4) ,
OPERATOR 15 <-> (int4, int4) FOR ORDER BY pg_catalog.integer_ops ,
FUNCTION 8 (int4, int4) gbt_int4_distance (internal, int4, int2, oid) ;
ALTER OPERATOR FAMILY gist_int8_ops USING gist ADD
OPERATOR 6 <> (int8, int8) ;
OPERATOR 6 <> (int8, int8) ,
OPERATOR 15 <-> (int8, int8) FOR ORDER BY pg_catalog.integer_ops ,
FUNCTION 8 (int8, int8) gbt_int8_distance (internal, int8, int2, oid) ;
ALTER OPERATOR FAMILY gist_float4_ops USING gist ADD
OPERATOR 6 <> (float4, float4) ;
OPERATOR 6 <> (float4, float4) ,
OPERATOR 15 <-> (float4, float4) FOR ORDER BY pg_catalog.float_ops ,
FUNCTION 8 (float4, float4) gbt_float4_distance (internal, float4, int2, oid) ;
ALTER OPERATOR FAMILY gist_float8_ops USING gist ADD
OPERATOR 6 <> (float8, float8) ;
OPERATOR 6 <> (float8, float8) ,
OPERATOR 15 <-> (float8, float8) FOR ORDER BY pg_catalog.float_ops ,
FUNCTION 8 (float8, float8) gbt_float8_distance (internal, float8, int2, oid) ;
ALTER OPERATOR FAMILY gist_timestamp_ops USING gist ADD
OPERATOR 6 <> (timestamp, timestamp) ;
OPERATOR 6 <> (timestamp, timestamp) ,
OPERATOR 15 <-> (timestamp, timestamp) FOR ORDER BY pg_catalog.interval_ops ,
FUNCTION 8 (timestamp, timestamp) gbt_ts_distance (internal, timestamp, int2, oid) ;
ALTER OPERATOR FAMILY gist_timestamptz_ops USING gist ADD
OPERATOR 6 <> (timestamptz, timestamptz) ;
OPERATOR 6 <> (timestamptz, timestamptz) ,
OPERATOR 15 <-> (timestamptz, timestamptz) FOR ORDER BY pg_catalog.interval_ops ,
FUNCTION 8 (timestamptz, timestamptz) gbt_tstz_distance (internal, timestamptz, int2, oid) ;
ALTER OPERATOR FAMILY gist_time_ops USING gist ADD
OPERATOR 6 <> (time, time) ;
OPERATOR 6 <> (time, time) ,
OPERATOR 15 <-> (time, time) FOR ORDER BY pg_catalog.interval_ops ,
FUNCTION 8 (time, time) gbt_time_distance (internal, time, int2, oid) ;
ALTER OPERATOR FAMILY gist_timetz_ops USING gist ADD
OPERATOR 6 <> (timetz, timetz) ;
ALTER OPERATOR FAMILY gist_date_ops USING gist ADD
OPERATOR 6 <> (date, date) ;
OPERATOR 6 <> (date, date) ,
OPERATOR 15 <-> (date, date) FOR ORDER BY pg_catalog.integer_ops ,
FUNCTION 8 (date, date) gbt_date_distance (internal, date, int2, oid) ;
ALTER OPERATOR FAMILY gist_interval_ops USING gist ADD
OPERATOR 6 <> (interval, interval) ;
OPERATOR 6 <> (interval, interval) ,
OPERATOR 15 <-> (interval, interval) FOR ORDER BY pg_catalog.interval_ops ,
FUNCTION 8 (interval, interval) gbt_intv_distance (internal, interval, int2, oid) ;
ALTER OPERATOR FAMILY gist_cash_ops USING gist ADD
OPERATOR 6 <> (money, money) ;
OPERATOR 6 <> (money, money) ,
OPERATOR 15 <-> (money, money) FOR ORDER BY pg_catalog.money_ops ,
FUNCTION 8 (money, money) gbt_cash_distance (internal, money, int2, oid) ;
ALTER OPERATOR FAMILY gist_macaddr_ops USING gist ADD
OPERATOR 6 <> (macaddr, macaddr) ;

View File

@ -84,7 +84,8 @@ static const gbtree_ninfo tinfo =
gbt_ineteq,
gbt_inetle,
gbt_inetlt,
gbt_inetkey_cmp
gbt_inetkey_cmp,
NULL
};

View File

@ -17,6 +17,7 @@ PG_FUNCTION_INFO_V1(gbt_int2_compress);
PG_FUNCTION_INFO_V1(gbt_int2_union);
PG_FUNCTION_INFO_V1(gbt_int2_picksplit);
PG_FUNCTION_INFO_V1(gbt_int2_consistent);
PG_FUNCTION_INFO_V1(gbt_int2_distance);
PG_FUNCTION_INFO_V1(gbt_int2_penalty);
PG_FUNCTION_INFO_V1(gbt_int2_same);
@ -24,6 +25,7 @@ Datum gbt_int2_compress(PG_FUNCTION_ARGS);
Datum gbt_int2_union(PG_FUNCTION_ARGS);
Datum gbt_int2_picksplit(PG_FUNCTION_ARGS);
Datum gbt_int2_consistent(PG_FUNCTION_ARGS);
Datum gbt_int2_distance(PG_FUNCTION_ARGS);
Datum gbt_int2_penalty(PG_FUNCTION_ARGS);
Datum gbt_int2_same(PG_FUNCTION_ARGS);
@ -70,6 +72,12 @@ gbt_int2key_cmp(const void *a, const void *b)
return (ia->lower > ib->lower) ? 1 : -1;
}
static float8
gbt_int2_dist(const void *a, const void *b)
{
return GET_FLOAT_DISTANCE(int2, a, b);
}
static const gbtree_ninfo tinfo =
{
@ -80,12 +88,32 @@ static const gbtree_ninfo tinfo =
gbt_int2eq,
gbt_int2le,
gbt_int2lt,
gbt_int2key_cmp
gbt_int2key_cmp,
gbt_int2_dist
};
PG_FUNCTION_INFO_V1(int2_dist);
Datum int2_dist(PG_FUNCTION_ARGS);
Datum
int2_dist(PG_FUNCTION_ARGS)
{
int2 a = PG_GETARG_INT16(0);
int2 b = PG_GETARG_INT16(1);
int2 r;
int2 ra;
r = a - b;
ra = Abs(r);
/* Overflow check. */
if (ra < 0 || (!SAMESIGN(a, b) && !SAMESIGN(r, a)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("smallint out of range")));
PG_RETURN_INT16(ra);
}
/**************************************************
@ -127,6 +155,25 @@ gbt_int2_consistent(PG_FUNCTION_ARGS)
}
Datum
gbt_int2_distance(PG_FUNCTION_ARGS)
{
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
int16 query = PG_GETARG_INT16(1);
/* Oid subtype = PG_GETARG_OID(3); */
int16KEY *kkk = (int16KEY *) 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_int2_union(PG_FUNCTION_ARGS)
{

View File

@ -17,6 +17,7 @@ PG_FUNCTION_INFO_V1(gbt_int4_compress);
PG_FUNCTION_INFO_V1(gbt_int4_union);
PG_FUNCTION_INFO_V1(gbt_int4_picksplit);
PG_FUNCTION_INFO_V1(gbt_int4_consistent);
PG_FUNCTION_INFO_V1(gbt_int4_distance);
PG_FUNCTION_INFO_V1(gbt_int4_penalty);
PG_FUNCTION_INFO_V1(gbt_int4_same);
@ -24,6 +25,7 @@ Datum gbt_int4_compress(PG_FUNCTION_ARGS);
Datum gbt_int4_union(PG_FUNCTION_ARGS);
Datum gbt_int4_picksplit(PG_FUNCTION_ARGS);
Datum gbt_int4_consistent(PG_FUNCTION_ARGS);
Datum gbt_int4_distance(PG_FUNCTION_ARGS);
Datum gbt_int4_penalty(PG_FUNCTION_ARGS);
Datum gbt_int4_same(PG_FUNCTION_ARGS);
@ -71,6 +73,12 @@ gbt_int4key_cmp(const void *a, const void *b)
return (ia->lower > ib->lower) ? 1 : -1;
}
static float8
gbt_int4_dist(const void *a, const void *b)
{
return GET_FLOAT_DISTANCE(int4, a, b);
}
static const gbtree_ninfo tinfo =
{
@ -81,10 +89,34 @@ static const gbtree_ninfo tinfo =
gbt_int4eq,
gbt_int4le,
gbt_int4lt,
gbt_int4key_cmp
gbt_int4key_cmp,
gbt_int4_dist
};
PG_FUNCTION_INFO_V1(int4_dist);
Datum int4_dist(PG_FUNCTION_ARGS);
Datum
int4_dist(PG_FUNCTION_ARGS)
{
int4 a = PG_GETARG_INT32(0);
int4 b = PG_GETARG_INT32(1);
int4 r;
int4 ra;
r = a - b;
ra = Abs(r);
/* Overflow check. */
if (ra < 0 || (!SAMESIGN(a, b) && !SAMESIGN(r, a)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("integer out of range")));
PG_RETURN_INT32(ra);
}
/**************************************************
* int32 ops
**************************************************/
@ -124,6 +156,25 @@ gbt_int4_consistent(PG_FUNCTION_ARGS)
}
Datum
gbt_int4_distance(PG_FUNCTION_ARGS)
{
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
int32 query = PG_GETARG_INT32(1);
/* Oid subtype = PG_GETARG_OID(3); */
int32KEY *kkk = (int32KEY *) 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_int4_union(PG_FUNCTION_ARGS)
{

View File

@ -17,6 +17,7 @@ PG_FUNCTION_INFO_V1(gbt_int8_compress);
PG_FUNCTION_INFO_V1(gbt_int8_union);
PG_FUNCTION_INFO_V1(gbt_int8_picksplit);
PG_FUNCTION_INFO_V1(gbt_int8_consistent);
PG_FUNCTION_INFO_V1(gbt_int8_distance);
PG_FUNCTION_INFO_V1(gbt_int8_penalty);
PG_FUNCTION_INFO_V1(gbt_int8_same);
@ -24,6 +25,7 @@ Datum gbt_int8_compress(PG_FUNCTION_ARGS);
Datum gbt_int8_union(PG_FUNCTION_ARGS);
Datum gbt_int8_picksplit(PG_FUNCTION_ARGS);
Datum gbt_int8_consistent(PG_FUNCTION_ARGS);
Datum gbt_int8_distance(PG_FUNCTION_ARGS);
Datum gbt_int8_penalty(PG_FUNCTION_ARGS);
Datum gbt_int8_same(PG_FUNCTION_ARGS);
@ -71,6 +73,12 @@ gbt_int8key_cmp(const void *a, const void *b)
return (ia->lower > ib->lower) ? 1 : -1;
}
static float8
gbt_int8_dist(const void *a, const void *b)
{
return GET_FLOAT_DISTANCE(int64, a, b);
}
static const gbtree_ninfo tinfo =
{
@ -81,10 +89,34 @@ static const gbtree_ninfo tinfo =
gbt_int8eq,
gbt_int8le,
gbt_int8lt,
gbt_int8key_cmp
gbt_int8key_cmp,
gbt_int8_dist
};
PG_FUNCTION_INFO_V1(int8_dist);
Datum int8_dist(PG_FUNCTION_ARGS);
Datum
int8_dist(PG_FUNCTION_ARGS)
{
int64 a = PG_GETARG_INT64(0);
int64 b = PG_GETARG_INT64(1);
int64 r;
int64 ra;
r = a - b;
ra = Abs(r);
/* Overflow check. */
if (ra < 0 || (!SAMESIGN(a, b) && !SAMESIGN(r, a)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
PG_RETURN_INT64(ra);
}
/**************************************************
* int64 ops
**************************************************/
@ -124,6 +156,25 @@ gbt_int8_consistent(PG_FUNCTION_ARGS)
}
Datum
gbt_int8_distance(PG_FUNCTION_ARGS)
{
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
int64 query = PG_GETARG_INT64(1);
/* Oid subtype = PG_GETARG_OID(3); */
int64KEY *kkk = (int64KEY *) 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_int8_union(PG_FUNCTION_ARGS)
{

View File

@ -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
**************************************************/
@ -190,6 +226,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)
{

View File

@ -84,7 +84,8 @@ static const gbtree_ninfo tinfo =
gbt_macadeq,
gbt_macadle,
gbt_macadlt,
gbt_macadkey_cmp
gbt_macadkey_cmp,
NULL
};

View File

@ -17,6 +17,7 @@ PG_FUNCTION_INFO_V1(gbt_oid_compress);
PG_FUNCTION_INFO_V1(gbt_oid_union);
PG_FUNCTION_INFO_V1(gbt_oid_picksplit);
PG_FUNCTION_INFO_V1(gbt_oid_consistent);
PG_FUNCTION_INFO_V1(gbt_oid_distance);
PG_FUNCTION_INFO_V1(gbt_oid_penalty);
PG_FUNCTION_INFO_V1(gbt_oid_same);
@ -24,6 +25,7 @@ Datum gbt_oid_compress(PG_FUNCTION_ARGS);
Datum gbt_oid_union(PG_FUNCTION_ARGS);
Datum gbt_oid_picksplit(PG_FUNCTION_ARGS);
Datum gbt_oid_consistent(PG_FUNCTION_ARGS);
Datum gbt_oid_distance(PG_FUNCTION_ARGS);
Datum gbt_oid_penalty(PG_FUNCTION_ARGS);
Datum gbt_oid_same(PG_FUNCTION_ARGS);
@ -71,6 +73,18 @@ gbt_oidkey_cmp(const void *a, const void *b)
return (ia->lower > ib->lower) ? 1 : -1;
}
static float8
gbt_oid_dist(const void *a, const void *b)
{
Oid aa = *(const Oid *) a;
Oid bb = *(const Oid *) b;
if (aa < bb)
return (float8) (bb - aa);
else
return (float8) (aa - bb);
}
static const gbtree_ninfo tinfo =
{
@ -81,10 +95,28 @@ static const gbtree_ninfo tinfo =
gbt_oideq,
gbt_oidle,
gbt_oidlt,
gbt_oidkey_cmp
gbt_oidkey_cmp,
gbt_oid_dist
};
PG_FUNCTION_INFO_V1(oid_dist);
Datum oid_dist(PG_FUNCTION_ARGS);
Datum
oid_dist(PG_FUNCTION_ARGS)
{
Oid a = PG_GETARG_OID(0);
Oid b = PG_GETARG_OID(1);
Oid res;
if (a < b)
res = b - a;
else
res = a - b;
PG_RETURN_OID(res);
}
/**************************************************
* Oid ops
**************************************************/
@ -124,6 +156,25 @@ gbt_oid_consistent(PG_FUNCTION_ARGS)
}
Datum
gbt_oid_distance(PG_FUNCTION_ARGS)
{
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
Oid query = PG_GETARG_OID(1);
/* Oid subtype = PG_GETARG_OID(3); */
oidKEY *kkk = (oidKEY *) 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_oid_union(PG_FUNCTION_ARGS)
{

View File

@ -20,6 +20,7 @@ PG_FUNCTION_INFO_V1(gbt_timetz_compress);
PG_FUNCTION_INFO_V1(gbt_time_union);
PG_FUNCTION_INFO_V1(gbt_time_picksplit);
PG_FUNCTION_INFO_V1(gbt_time_consistent);
PG_FUNCTION_INFO_V1(gbt_time_distance);
PG_FUNCTION_INFO_V1(gbt_timetz_consistent);
PG_FUNCTION_INFO_V1(gbt_time_penalty);
PG_FUNCTION_INFO_V1(gbt_time_same);
@ -29,6 +30,7 @@ Datum gbt_timetz_compress(PG_FUNCTION_ARGS);
Datum gbt_time_union(PG_FUNCTION_ARGS);
Datum gbt_time_picksplit(PG_FUNCTION_ARGS);
Datum gbt_time_consistent(PG_FUNCTION_ARGS);
Datum gbt_time_distance(PG_FUNCTION_ARGS);
Datum gbt_timetz_consistent(PG_FUNCTION_ARGS);
Datum gbt_time_penalty(PG_FUNCTION_ARGS);
Datum gbt_time_same(PG_FUNCTION_ARGS);
@ -112,6 +114,19 @@ gbt_timekey_cmp(const void *a, const void *b)
return res;
}
static float8
gbt_time_dist(const void *a, const void *b)
{
const TimeADT *aa = (const TimeADT *) a;
const TimeADT *bb = (const TimeADT *) b;
Interval *i;
i = DatumGetIntervalP(DirectFunctionCall2(time_mi_time,
TimeADTGetDatumFast(*aa),
TimeADTGetDatumFast(*bb)));
return (float8) Abs(INTERVAL_TO_SEC(i));
}
static const gbtree_ninfo tinfo =
{
@ -122,10 +137,24 @@ static const gbtree_ninfo tinfo =
gbt_timeeq,
gbt_timele,
gbt_timelt,
gbt_timekey_cmp
gbt_timekey_cmp,
gbt_time_dist
};
PG_FUNCTION_INFO_V1(time_dist);
Datum time_dist(PG_FUNCTION_ARGS);
Datum
time_dist(PG_FUNCTION_ARGS)
{
Datum diff = DirectFunctionCall2(time_mi_time,
PG_GETARG_DATUM(0),
PG_GETARG_DATUM(1));
PG_RETURN_INTERVAL_P(abs_interval(DatumGetIntervalP(diff)));
}
/**************************************************
* time ops
**************************************************/
@ -196,6 +225,24 @@ gbt_time_consistent(PG_FUNCTION_ARGS)
);
}
Datum
gbt_time_distance(PG_FUNCTION_ARGS)
{
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
TimeADT query = PG_GETARG_TIMEADT(1);
/* Oid subtype = PG_GETARG_OID(3); */
timeKEY *kkk = (timeKEY *) 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_timetz_consistent(PG_FUNCTION_ARGS)
{

View File

@ -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
**************************************************/
@ -213,6 +295,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)
{
@ -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)

View File

@ -188,16 +188,13 @@ gbt_num_bin_union(Datum *u, GBT_NUMKEY *e, const gbtree_ninfo *tinfo)
*/
bool
gbt_num_consistent(
const GBT_NUMKEY_R *key,
gbt_num_consistent(const GBT_NUMKEY_R *key,
const void *query,
const StrategyNumber *strategy,
bool is_leaf,
const gbtree_ninfo *tinfo
)
const gbtree_ninfo *tinfo)
{
bool retval = FALSE;
bool retval;
switch (*strategy)
{
@ -214,7 +211,7 @@ gbt_num_consistent(
if (is_leaf)
retval = (*tinfo->f_eq) (query, key->lower);
else
retval = (*tinfo->f_le) (key->lower, query) && (*tinfo->f_le) (query, key->upper);
retval = ((*tinfo->f_le) (key->lower, query) && (*tinfo->f_le) (query, key->upper)) ? true : false;
break;
case BTGreaterStrategyNumber:
if (is_leaf)
@ -226,17 +223,43 @@ gbt_num_consistent(
retval = (*tinfo->f_le) (query, key->upper);
break;
case BtreeGistNotEqualStrategyNumber:
retval = ! ((*tinfo->f_eq) (query, key->lower) &&
(*tinfo->f_eq) (query, key->upper));
retval = (! ((*tinfo->f_eq) (query, key->lower) &&
(*tinfo->f_eq) (query, key->upper))) ? true : false;
break;
default:
retval = FALSE;
retval = false;
}
return (retval);
}
/*
** The GiST distance method (for KNN-Gist)
*/
float8
gbt_num_distance(const GBT_NUMKEY_R *key,
const void *query,
bool is_leaf,
const gbtree_ninfo *tinfo)
{
float8 retval;
if (tinfo->f_dist == NULL)
elog(ERROR, "KNN search is not supported for btree_gist type %d",
(int) tinfo->t);
if ( tinfo->f_le(query, key->lower) )
retval = tinfo->f_dist(query, key->lower);
else if ( tinfo->f_ge(query, key->upper) )
retval = tinfo->f_dist(query, key->upper);
else
retval = 0.0;
return retval;
}
GIST_SPLITVEC *
gbt_num_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v,
const gbtree_ninfo *tinfo)

View File

@ -40,24 +40,25 @@ typedef struct
/* Methods */
bool (*f_gt) (const void *, const void *); /* greater then */
bool (*f_ge) (const void *, const void *); /* greater equal */
bool (*f_gt) (const void *, const void *); /* greater than */
bool (*f_ge) (const void *, const void *); /* greater or equal */
bool (*f_eq) (const void *, const void *); /* equal */
bool (*f_le) (const void *, const void *); /* less equal */
bool (*f_lt) (const void *, const void *); /* less then */
bool (*f_le) (const void *, const void *); /* less or equal */
bool (*f_lt) (const void *, const void *); /* less than */
int (*f_cmp) (const void *, const void *); /* key compare function */
float8 (*f_dist) (const void *, const void *); /* key distance function */
} gbtree_ninfo;
/*
* Numeric btree functions
*/
*/
/*
* Note: The factor 0.49 in following macro avoids floating point overflows
*/
*/
#define penalty_num(result,olower,oupper,nlower,nupper) do { \
double tmp = 0.0F; \
(*(result)) = 0.0F; \
@ -91,11 +92,37 @@ typedef struct
(ivp)->month * (30.0 * SECS_PER_DAY))
#endif
#define GET_FLOAT_DISTANCE(t, arg1, arg2) Abs( ((float8) *((const t *) (arg1))) - ((float8) *((const t *) (arg2))) )
#define SAMESIGN(a,b) (((a) < 0) == ((b) < 0))
/*
* check to see if a float4/8 val has underflowed or overflowed
* borrowed from src/backend/utils/adt/float.c
*/
#define CHECKFLOATVAL(val, inf_is_valid, zero_is_valid) \
do { \
if (isinf(val) && !(inf_is_valid)) \
ereport(ERROR, \
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), \
errmsg("value out of range: overflow"))); \
\
if ((val) == 0.0 && !(zero_is_valid)) \
ereport(ERROR, \
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), \
errmsg("value out of range: underflow"))); \
} while(0)
extern Interval *abs_interval(Interval *a);
extern bool gbt_num_consistent(const GBT_NUMKEY_R *key, const void *query,
const StrategyNumber *strategy, bool is_leaf,
const gbtree_ninfo *tinfo);
extern float8 gbt_num_distance(const GBT_NUMKEY_R *key, const void *query,
bool is_leaf, const gbtree_ninfo *tinfo);
extern GIST_SPLITVEC *gbt_num_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v,
const gbtree_ninfo *tinfo);

View File

@ -32,6 +32,14 @@ SELECT count(*) FROM moneytmp WHERE a > '22649.64';
253
(1 row)
SELECT a, a <-> '21472.79' FROM moneytmp ORDER BY a <-> '21472.79' LIMIT 3;
a | ?column?
------------+----------
$21,472.79 | $0.00
$21,469.25 | $3.54
$21,915.01 | $442.22
(3 rows)
CREATE INDEX moneyidx ON moneytmp USING gist ( a );
SET enable_seqscan=off;
SELECT count(*) FROM moneytmp WHERE a < '22649.64'::money;
@ -64,3 +72,20 @@ SELECT count(*) FROM moneytmp WHERE a > '22649.64'::money;
253
(1 row)
EXPLAIN (COSTS OFF)
SELECT a, a <-> '21472.79' FROM moneytmp ORDER BY a <-> '21472.79' LIMIT 3;
QUERY PLAN
-----------------------------------------------
Limit
-> Index Scan using moneyidx on moneytmp
Order By: (a <-> '$21,472.79'::money)
(3 rows)
SELECT a, a <-> '21472.79' FROM moneytmp ORDER BY a <-> '21472.79' LIMIT 3;
a | ?column?
------------+----------
$21,472.79 | $0.00
$21,469.25 | $3.54
$21,915.01 | $442.22
(3 rows)

View File

@ -32,6 +32,14 @@ SELECT count(*) FROM datetmp WHERE a > '2001-02-13';
313
(1 row)
SELECT a, a <-> '2001-02-13' FROM datetmp ORDER BY a <-> '2001-02-13' LIMIT 3;
a | ?column?
------------+----------
02-13-2001 | 0
02-11-2001 | 2
03-24-2001 | 39
(3 rows)
CREATE INDEX dateidx ON datetmp USING gist ( a );
SET enable_seqscan=off;
SELECT count(*) FROM datetmp WHERE a < '2001-02-13'::date;
@ -64,3 +72,20 @@ SELECT count(*) FROM datetmp WHERE a > '2001-02-13'::date;
313
(1 row)
EXPLAIN (COSTS OFF)
SELECT a, a <-> '2001-02-13' FROM datetmp ORDER BY a <-> '2001-02-13' LIMIT 3;
QUERY PLAN
----------------------------------------------
Limit
-> Index Scan using dateidx on datetmp
Order By: (a <-> '02-13-2001'::date)
(3 rows)
SELECT a, a <-> '2001-02-13' FROM datetmp ORDER BY a <-> '2001-02-13' LIMIT 3;
a | ?column?
------------+----------
02-13-2001 | 0
02-11-2001 | 2
03-24-2001 | 39
(3 rows)

View File

@ -32,6 +32,14 @@ SELECT count(*) FROM float4tmp WHERE a > -179.0;
302
(1 row)
SELECT a, a <-> '-179.0' FROM float4tmp ORDER BY a <-> '-179.0' LIMIT 3;
a | ?column?
----------+----------
-179 | 0
-189.024 | 10.0239
-158.177 | 20.8226
(3 rows)
CREATE INDEX float4idx ON float4tmp USING gist ( a );
SET enable_seqscan=off;
SELECT count(*) FROM float4tmp WHERE a < -179.0::float4;
@ -64,3 +72,20 @@ SELECT count(*) FROM float4tmp WHERE a > -179.0::float4;
302
(1 row)
EXPLAIN (COSTS OFF)
SELECT a, a <-> '-179.0' FROM float4tmp ORDER BY a <-> '-179.0' LIMIT 3;
QUERY PLAN
-----------------------------------------------
Limit
-> Index Scan using float4idx on float4tmp
Order By: (a <-> (-179)::real)
(3 rows)
SELECT a, a <-> '-179.0' FROM float4tmp ORDER BY a <-> '-179.0' LIMIT 3;
a | ?column?
----------+----------
-179 | 0
-189.024 | 10.0239
-158.177 | 20.8226
(3 rows)

View File

@ -32,6 +32,14 @@ SELECT count(*) FROM float8tmp WHERE a > -1890.0;
306
(1 row)
SELECT a, a <-> '-1890.0' FROM float8tmp ORDER BY a <-> '-1890.0' LIMIT 3;
a | ?column?
--------------+------------
-1890 | 0
-2003.634512 | 113.634512
-1769.73634 | 120.26366
(3 rows)
CREATE INDEX float8idx ON float8tmp USING gist ( a );
SET enable_seqscan=off;
SELECT count(*) FROM float8tmp WHERE a < -1890.0::float8;
@ -64,3 +72,20 @@ SELECT count(*) FROM float8tmp WHERE a > -1890.0::float8;
306
(1 row)
EXPLAIN (COSTS OFF)
SELECT a, a <-> '-1890.0' FROM float8tmp ORDER BY a <-> '-1890.0' LIMIT 3;
QUERY PLAN
-----------------------------------------------------
Limit
-> Index Scan using float8idx on float8tmp
Order By: (a <-> (-1890)::double precision)
(3 rows)
SELECT a, a <-> '-1890.0' FROM float8tmp ORDER BY a <-> '-1890.0' LIMIT 3;
a | ?column?
--------------+------------
-1890 | 0
-2003.634512 | 113.634512
-1769.73634 | 120.26366
(3 rows)

View File

@ -32,6 +32,14 @@ SELECT count(*) FROM int2tmp WHERE a > 237;
248
(1 row)
SELECT a, a <-> '237' FROM int2tmp ORDER BY a <-> '237' LIMIT 3;
a | ?column?
-----+----------
237 | 0
232 | 5
228 | 9
(3 rows)
CREATE INDEX int2idx ON int2tmp USING gist ( a );
SET enable_seqscan=off;
SELECT count(*) FROM int2tmp WHERE a < 237::int2;
@ -64,3 +72,20 @@ SELECT count(*) FROM int2tmp WHERE a > 237::int2;
248
(1 row)
EXPLAIN (COSTS OFF)
SELECT a, a <-> '237' FROM int2tmp ORDER BY a <-> '237' LIMIT 3;
QUERY PLAN
-------------------------------------------
Limit
-> Index Scan using int2idx on int2tmp
Order By: (a <-> 237::smallint)
(3 rows)
SELECT a, a <-> '237' FROM int2tmp ORDER BY a <-> '237' LIMIT 3;
a | ?column?
-----+----------
237 | 0
232 | 5
228 | 9
(3 rows)

View File

@ -32,6 +32,14 @@ SELECT count(*) FROM int4tmp WHERE a > 237;
248
(1 row)
SELECT a, a <-> '237' FROM int4tmp ORDER BY a <-> '237' LIMIT 3;
a | ?column?
-----+----------
237 | 0
232 | 5
228 | 9
(3 rows)
CREATE INDEX int4idx ON int4tmp USING gist ( a );
SET enable_seqscan=off;
SELECT count(*) FROM int4tmp WHERE a < 237::int4;
@ -64,3 +72,20 @@ SELECT count(*) FROM int4tmp WHERE a > 237::int4;
248
(1 row)
EXPLAIN (COSTS OFF)
SELECT a, a <-> '237' FROM int4tmp ORDER BY a <-> '237' LIMIT 3;
QUERY PLAN
-------------------------------------------
Limit
-> Index Scan using int4idx on int4tmp
Order By: (a <-> 237)
(3 rows)
SELECT a, a <-> '237' FROM int4tmp ORDER BY a <-> '237' LIMIT 3;
a | ?column?
-----+----------
237 | 0
232 | 5
228 | 9
(3 rows)

View File

@ -32,6 +32,14 @@ SELECT count(*) FROM int8tmp WHERE a > 464571291354841;
270
(1 row)
SELECT a, a <-> '464571291354841' FROM int8tmp ORDER BY a <-> '464571291354841' LIMIT 3;
a | ?column?
-----------------+----------------
464571291354841 | 0
457257666629329 | 7313624725512
478227196042750 | 13655904687909
(3 rows)
CREATE INDEX int8idx ON int8tmp USING gist ( a );
SET enable_seqscan=off;
SELECT count(*) FROM int8tmp WHERE a < 464571291354841::int8;
@ -64,3 +72,20 @@ SELECT count(*) FROM int8tmp WHERE a > 464571291354841::int8;
270
(1 row)
EXPLAIN (COSTS OFF)
SELECT a, a <-> '464571291354841' FROM int8tmp ORDER BY a <-> '464571291354841' LIMIT 3;
QUERY PLAN
---------------------------------------------------
Limit
-> Index Scan using int8idx on int8tmp
Order By: (a <-> 464571291354841::bigint)
(3 rows)
SELECT a, a <-> '464571291354841' FROM int8tmp ORDER BY a <-> '464571291354841' LIMIT 3;
a | ?column?
-----------------+----------------
464571291354841 | 0
457257666629329 | 7313624725512
478227196042750 | 13655904687909
(3 rows)

View File

@ -32,6 +32,14 @@ SELECT count(*) FROM intervaltmp WHERE a > '199 days 21:21:23';
270
(1 row)
SELECT a, a <-> '199 days 21:21:23' FROM intervaltmp ORDER BY a <-> '199 days 21:21:23' LIMIT 3;
a | ?column?
-------------------------------------+--------------------------------------
@ 199 days 21 hours 21 mins 23 secs | @ 0
@ 183 days 6 hours 52 mins 48 secs | @ 16 days 14 hours 28 mins 35 secs
@ 220 days 19 hours 5 mins 42 secs | @ 21 days -2 hours -15 mins -41 secs
(3 rows)
CREATE INDEX intervalidx ON intervaltmp USING gist ( a );
SET enable_seqscan=off;
SELECT count(*) FROM intervaltmp WHERE a < '199 days 21:21:23'::interval;
@ -64,3 +72,20 @@ SELECT count(*) FROM intervaltmp WHERE a > '199 days 21:21:23'::interval;
270
(1 row)
EXPLAIN (COSTS OFF)
SELECT a, a <-> '199 days 21:21:23' FROM intervaltmp ORDER BY a <-> '199 days 21:21:23' LIMIT 3;
QUERY PLAN
---------------------------------------------------------------------------
Limit
-> Index Scan using intervalidx on intervaltmp
Order By: (a <-> '@ 199 days 21 hours 21 mins 23 secs'::interval)
(3 rows)
SELECT a, a <-> '199 days 21:21:23' FROM intervaltmp ORDER BY a <-> '199 days 21:21:23' LIMIT 3;
a | ?column?
-------------------------------------+--------------------------------------
@ 199 days 21 hours 21 mins 23 secs | @ 0
@ 183 days 6 hours 52 mins 48 secs | @ 16 days 14 hours 28 mins 35 secs
@ 220 days 19 hours 5 mins 42 secs | @ 21 days -2 hours -15 mins -41 secs
(3 rows)

View File

@ -32,6 +32,14 @@ SELECT count(*) FROM timetmp WHERE a > '10:57:11';
292
(1 row)
SELECT a, a <-> '10:57:11' FROM timetmp ORDER BY a <-> '10:57:11' LIMIT 3;
a | ?column?
----------+-----------------
10:57:11 | @ 0
10:57:10 | @ 1 sec
10:55:32 | @ 1 min 39 secs
(3 rows)
CREATE INDEX timeidx ON timetmp USING gist ( a );
SET enable_seqscan=off;
SELECT count(*) FROM timetmp WHERE a < '10:57:11'::time;
@ -64,3 +72,20 @@ SELECT count(*) FROM timetmp WHERE a > '10:57:11'::time;
292
(1 row)
EXPLAIN (COSTS OFF)
SELECT a, a <-> '10:57:11' FROM timetmp ORDER BY a <-> '10:57:11' LIMIT 3;
QUERY PLAN
--------------------------------------------------------------
Limit
-> Index Scan using timeidx on timetmp
Order By: (a <-> '10:57:11'::time without time zone)
(3 rows)
SELECT a, a <-> '10:57:11' FROM timetmp ORDER BY a <-> '10:57:11' LIMIT 3;
a | ?column?
----------+-----------------
10:57:11 | @ 0
10:57:10 | @ 1 sec
10:55:32 | @ 1 min 39 secs
(3 rows)

View File

@ -32,6 +32,14 @@ SELECT count(*) FROM timestamptmp WHERE a > '2004-10-26 08:55:08';
289
(1 row)
SELECT a, a <-> '2004-10-26 08:55:08' FROM timestamptmp ORDER BY a <-> '2004-10-26 08:55:08' LIMIT 3;
a | ?column?
--------------------------+------------------------------------
Tue Oct 26 08:55:08 2004 | @ 0
Sun Oct 31 06:35:03 2004 | @ 4 days 21 hours 39 mins 55 secs
Mon Nov 29 20:12:43 2004 | @ 34 days 11 hours 17 mins 35 secs
(3 rows)
CREATE INDEX timestampidx ON timestamptmp USING gist ( a );
SET enable_seqscan=off;
SELECT count(*) FROM timestamptmp WHERE a < '2004-10-26 08:55:08'::timestamp;
@ -64,3 +72,20 @@ SELECT count(*) FROM timestamptmp WHERE a > '2004-10-26 08:55:08'::timestamp;
289
(1 row)
EXPLAIN (COSTS OFF)
SELECT a, a <-> '2004-10-26 08:55:08' FROM timestamptmp ORDER BY a <-> '2004-10-26 08:55:08' LIMIT 3;
QUERY PLAN
-----------------------------------------------------------------------------------
Limit
-> Index Scan using timestampidx on timestamptmp
Order By: (a <-> 'Tue Oct 26 08:55:08 2004'::timestamp without time zone)
(3 rows)
SELECT a, a <-> '2004-10-26 08:55:08' FROM timestamptmp ORDER BY a <-> '2004-10-26 08:55:08' LIMIT 3;
a | ?column?
--------------------------+------------------------------------
Tue Oct 26 08:55:08 2004 | @ 0
Sun Oct 31 06:35:03 2004 | @ 4 days 21 hours 39 mins 55 secs
Mon Nov 29 20:12:43 2004 | @ 34 days 11 hours 17 mins 35 secs
(3 rows)

View File

@ -92,6 +92,14 @@ SELECT count(*) FROM timestamptztmp WHERE a > '2018-12-18 10:59:54 GMT+4';
157
(1 row)
SELECT a, a <-> '2018-12-18 10:59:54 GMT+2' FROM timestamptztmp ORDER BY a <-> '2018-12-18 10:59:54 GMT+2' LIMIT 3;
a | ?column?
------------------------------+-----------------------------------
Tue Dec 18 05:59:54 2018 PST | @ 1 hour
Thu Jan 10 03:01:34 2019 PST | @ 22 days 22 hours 1 min 40 secs
Thu Jan 24 12:28:12 2019 PST | @ 37 days 7 hours 28 mins 18 secs
(3 rows)
CREATE INDEX timestamptzidx ON timestamptztmp USING gist ( a );
SET enable_seqscan=off;
SELECT count(*) FROM timestamptztmp WHERE a < '2018-12-18 10:59:54 GMT+3'::timestamptz;
@ -184,3 +192,20 @@ SELECT count(*) FROM timestamptztmp WHERE a > '2018-12-18 10:59:54 GMT+4'::time
157
(1 row)
EXPLAIN (COSTS OFF)
SELECT a, a <-> '2018-12-18 10:59:54 GMT+2' FROM timestamptztmp ORDER BY a <-> '2018-12-18 10:59:54 GMT+2' LIMIT 3;
QUERY PLAN
------------------------------------------------------------------------------------
Limit
-> Index Scan using timestamptzidx on timestamptztmp
Order By: (a <-> 'Tue Dec 18 04:59:54 2018 PST'::timestamp with time zone)
(3 rows)
SELECT a, a <-> '2018-12-18 10:59:54 GMT+2' FROM timestamptztmp ORDER BY a <-> '2018-12-18 10:59:54 GMT+2' LIMIT 3;
a | ?column?
------------------------------+-----------------------------------
Tue Dec 18 05:59:54 2018 PST | @ 1 hour
Thu Jan 10 03:01:34 2019 PST | @ 22 days 22 hours 1 min 40 secs
Thu Jan 24 12:28:12 2019 PST | @ 37 days 7 hours 28 mins 18 secs
(3 rows)

View File

@ -16,6 +16,8 @@ SELECT count(*) FROM moneytmp WHERE a >= '22649.64';
SELECT count(*) FROM moneytmp WHERE a > '22649.64';
SELECT a, a <-> '21472.79' FROM moneytmp ORDER BY a <-> '21472.79' LIMIT 3;
CREATE INDEX moneyidx ON moneytmp USING gist ( a );
SET enable_seqscan=off;
@ -29,3 +31,7 @@ SELECT count(*) FROM moneytmp WHERE a = '22649.64'::money;
SELECT count(*) FROM moneytmp WHERE a >= '22649.64'::money;
SELECT count(*) FROM moneytmp WHERE a > '22649.64'::money;
EXPLAIN (COSTS OFF)
SELECT a, a <-> '21472.79' FROM moneytmp ORDER BY a <-> '21472.79' LIMIT 3;
SELECT a, a <-> '21472.79' FROM moneytmp ORDER BY a <-> '21472.79' LIMIT 3;

View File

@ -16,6 +16,8 @@ SELECT count(*) FROM datetmp WHERE a >= '2001-02-13';
SELECT count(*) FROM datetmp WHERE a > '2001-02-13';
SELECT a, a <-> '2001-02-13' FROM datetmp ORDER BY a <-> '2001-02-13' LIMIT 3;
CREATE INDEX dateidx ON datetmp USING gist ( a );
SET enable_seqscan=off;
@ -29,3 +31,7 @@ SELECT count(*) FROM datetmp WHERE a = '2001-02-13'::date;
SELECT count(*) FROM datetmp WHERE a >= '2001-02-13'::date;
SELECT count(*) FROM datetmp WHERE a > '2001-02-13'::date;
EXPLAIN (COSTS OFF)
SELECT a, a <-> '2001-02-13' FROM datetmp ORDER BY a <-> '2001-02-13' LIMIT 3;
SELECT a, a <-> '2001-02-13' FROM datetmp ORDER BY a <-> '2001-02-13' LIMIT 3;

View File

@ -16,6 +16,8 @@ SELECT count(*) FROM float4tmp WHERE a >= -179.0;
SELECT count(*) FROM float4tmp WHERE a > -179.0;
SELECT a, a <-> '-179.0' FROM float4tmp ORDER BY a <-> '-179.0' LIMIT 3;
CREATE INDEX float4idx ON float4tmp USING gist ( a );
SET enable_seqscan=off;
@ -29,3 +31,7 @@ SELECT count(*) FROM float4tmp WHERE a = -179.0::float4;
SELECT count(*) FROM float4tmp WHERE a >= -179.0::float4;
SELECT count(*) FROM float4tmp WHERE a > -179.0::float4;
EXPLAIN (COSTS OFF)
SELECT a, a <-> '-179.0' FROM float4tmp ORDER BY a <-> '-179.0' LIMIT 3;
SELECT a, a <-> '-179.0' FROM float4tmp ORDER BY a <-> '-179.0' LIMIT 3;

View File

@ -16,6 +16,8 @@ SELECT count(*) FROM float8tmp WHERE a >= -1890.0;
SELECT count(*) FROM float8tmp WHERE a > -1890.0;
SELECT a, a <-> '-1890.0' FROM float8tmp ORDER BY a <-> '-1890.0' LIMIT 3;
CREATE INDEX float8idx ON float8tmp USING gist ( a );
SET enable_seqscan=off;
@ -29,3 +31,7 @@ SELECT count(*) FROM float8tmp WHERE a = -1890.0::float8;
SELECT count(*) FROM float8tmp WHERE a >= -1890.0::float8;
SELECT count(*) FROM float8tmp WHERE a > -1890.0::float8;
EXPLAIN (COSTS OFF)
SELECT a, a <-> '-1890.0' FROM float8tmp ORDER BY a <-> '-1890.0' LIMIT 3;
SELECT a, a <-> '-1890.0' FROM float8tmp ORDER BY a <-> '-1890.0' LIMIT 3;

View File

@ -16,6 +16,8 @@ SELECT count(*) FROM int2tmp WHERE a >= 237;
SELECT count(*) FROM int2tmp WHERE a > 237;
SELECT a, a <-> '237' FROM int2tmp ORDER BY a <-> '237' LIMIT 3;
CREATE INDEX int2idx ON int2tmp USING gist ( a );
SET enable_seqscan=off;
@ -29,3 +31,7 @@ SELECT count(*) FROM int2tmp WHERE a = 237::int2;
SELECT count(*) FROM int2tmp WHERE a >= 237::int2;
SELECT count(*) FROM int2tmp WHERE a > 237::int2;
EXPLAIN (COSTS OFF)
SELECT a, a <-> '237' FROM int2tmp ORDER BY a <-> '237' LIMIT 3;
SELECT a, a <-> '237' FROM int2tmp ORDER BY a <-> '237' LIMIT 3;

View File

@ -16,6 +16,8 @@ SELECT count(*) FROM int4tmp WHERE a >= 237;
SELECT count(*) FROM int4tmp WHERE a > 237;
SELECT a, a <-> '237' FROM int4tmp ORDER BY a <-> '237' LIMIT 3;
CREATE INDEX int4idx ON int4tmp USING gist ( a );
SET enable_seqscan=off;
@ -29,3 +31,7 @@ SELECT count(*) FROM int4tmp WHERE a = 237::int4;
SELECT count(*) FROM int4tmp WHERE a >= 237::int4;
SELECT count(*) FROM int4tmp WHERE a > 237::int4;
EXPLAIN (COSTS OFF)
SELECT a, a <-> '237' FROM int4tmp ORDER BY a <-> '237' LIMIT 3;
SELECT a, a <-> '237' FROM int4tmp ORDER BY a <-> '237' LIMIT 3;

View File

@ -16,6 +16,8 @@ SELECT count(*) FROM int8tmp WHERE a >= 464571291354841;
SELECT count(*) FROM int8tmp WHERE a > 464571291354841;
SELECT a, a <-> '464571291354841' FROM int8tmp ORDER BY a <-> '464571291354841' LIMIT 3;
CREATE INDEX int8idx ON int8tmp USING gist ( a );
SET enable_seqscan=off;
@ -29,3 +31,7 @@ SELECT count(*) FROM int8tmp WHERE a = 464571291354841::int8;
SELECT count(*) FROM int8tmp WHERE a >= 464571291354841::int8;
SELECT count(*) FROM int8tmp WHERE a > 464571291354841::int8;
EXPLAIN (COSTS OFF)
SELECT a, a <-> '464571291354841' FROM int8tmp ORDER BY a <-> '464571291354841' LIMIT 3;
SELECT a, a <-> '464571291354841' FROM int8tmp ORDER BY a <-> '464571291354841' LIMIT 3;

View File

@ -16,6 +16,8 @@ SELECT count(*) FROM intervaltmp WHERE a >= '199 days 21:21:23';
SELECT count(*) FROM intervaltmp WHERE a > '199 days 21:21:23';
SELECT a, a <-> '199 days 21:21:23' FROM intervaltmp ORDER BY a <-> '199 days 21:21:23' LIMIT 3;
CREATE INDEX intervalidx ON intervaltmp USING gist ( a );
SET enable_seqscan=off;
@ -29,3 +31,7 @@ SELECT count(*) FROM intervaltmp WHERE a = '199 days 21:21:23'::interval;
SELECT count(*) FROM intervaltmp WHERE a >= '199 days 21:21:23'::interval;
SELECT count(*) FROM intervaltmp WHERE a > '199 days 21:21:23'::interval;
EXPLAIN (COSTS OFF)
SELECT a, a <-> '199 days 21:21:23' FROM intervaltmp ORDER BY a <-> '199 days 21:21:23' LIMIT 3;
SELECT a, a <-> '199 days 21:21:23' FROM intervaltmp ORDER BY a <-> '199 days 21:21:23' LIMIT 3;

View File

@ -16,6 +16,8 @@ SELECT count(*) FROM timetmp WHERE a >= '10:57:11';
SELECT count(*) FROM timetmp WHERE a > '10:57:11';
SELECT a, a <-> '10:57:11' FROM timetmp ORDER BY a <-> '10:57:11' LIMIT 3;
CREATE INDEX timeidx ON timetmp USING gist ( a );
SET enable_seqscan=off;
@ -29,3 +31,7 @@ SELECT count(*) FROM timetmp WHERE a = '10:57:11'::time;
SELECT count(*) FROM timetmp WHERE a >= '10:57:11'::time;
SELECT count(*) FROM timetmp WHERE a > '10:57:11'::time;
EXPLAIN (COSTS OFF)
SELECT a, a <-> '10:57:11' FROM timetmp ORDER BY a <-> '10:57:11' LIMIT 3;
SELECT a, a <-> '10:57:11' FROM timetmp ORDER BY a <-> '10:57:11' LIMIT 3;

View File

@ -16,6 +16,8 @@ SELECT count(*) FROM timestamptmp WHERE a >= '2004-10-26 08:55:08';
SELECT count(*) FROM timestamptmp WHERE a > '2004-10-26 08:55:08';
SELECT a, a <-> '2004-10-26 08:55:08' FROM timestamptmp ORDER BY a <-> '2004-10-26 08:55:08' LIMIT 3;
CREATE INDEX timestampidx ON timestamptmp USING gist ( a );
SET enable_seqscan=off;
@ -29,3 +31,7 @@ SELECT count(*) FROM timestamptmp WHERE a = '2004-10-26 08:55:08'::timestamp;
SELECT count(*) FROM timestamptmp WHERE a >= '2004-10-26 08:55:08'::timestamp;
SELECT count(*) FROM timestamptmp WHERE a > '2004-10-26 08:55:08'::timestamp;
EXPLAIN (COSTS OFF)
SELECT a, a <-> '2004-10-26 08:55:08' FROM timestamptmp ORDER BY a <-> '2004-10-26 08:55:08' LIMIT 3;
SELECT a, a <-> '2004-10-26 08:55:08' FROM timestamptmp ORDER BY a <-> '2004-10-26 08:55:08' LIMIT 3;

View File

@ -37,7 +37,7 @@ SELECT count(*) FROM timestamptztmp WHERE a >= '2018-12-18 10:59:54 GMT+4';
SELECT count(*) FROM timestamptztmp WHERE a > '2018-12-18 10:59:54 GMT+4';
SELECT a, a <-> '2018-12-18 10:59:54 GMT+2' FROM timestamptztmp ORDER BY a <-> '2018-12-18 10:59:54 GMT+2' LIMIT 3;
CREATE INDEX timestamptzidx ON timestamptztmp USING gist ( a );
@ -74,3 +74,7 @@ SELECT count(*) FROM timestamptztmp WHERE a = '2018-12-18 10:59:54 GMT+4'::time
SELECT count(*) FROM timestamptztmp WHERE a >= '2018-12-18 10:59:54 GMT+4'::timestamptz;
SELECT count(*) FROM timestamptztmp WHERE a > '2018-12-18 10:59:54 GMT+4'::timestamptz;
EXPLAIN (COSTS OFF)
SELECT a, a <-> '2018-12-18 10:59:54 GMT+2' FROM timestamptztmp ORDER BY a <-> '2018-12-18 10:59:54 GMT+2' LIMIT 3;
SELECT a, a <-> '2018-12-18 10:59:54 GMT+2' FROM timestamptztmp ORDER BY a <-> '2018-12-18 10:59:54 GMT+2' LIMIT 3;