diff --git a/contrib/btree_gin/Makefile b/contrib/btree_gin/Makefile new file mode 100644 index a9e9925..d36f5ad *** a/contrib/btree_gin/Makefile --- b/contrib/btree_gin/Makefile *************** PGFILEDESC = "btree_gin - B-tree equival *** 11,17 **** REGRESS = install_btree_gin int2 int4 int8 float4 float8 money oid \ timestamp timestamptz time timetz date interval \ macaddr macaddr8 inet cidr text varchar char bytea bit varbit \ ! numeric enum uuid name bool bpchar ifdef USE_PGXS PG_CONFIG = pg_config --- 11,17 ---- REGRESS = install_btree_gin int2 int4 int8 float4 float8 money oid \ timestamp timestamptz time timetz date interval \ macaddr macaddr8 inet cidr text varchar char bytea bit varbit \ ! numeric enum uuid name bool anyrange bpchar ifdef USE_PGXS PG_CONFIG = pg_config diff --git a/contrib/btree_gin/btree_gin--1.2--1.3.sql b/contrib/btree_gin/btree_gin--1.2--1.3.sql new file mode 100644 index db675b7..f7523a3 *** a/contrib/btree_gin/btree_gin--1.2--1.3.sql --- b/contrib/btree_gin/btree_gin--1.2--1.3.sql *************** AS *** 96,101 **** --- 96,137 ---- FUNCTION 5 gin_compare_prefix_bool(bool,bool,int2, internal), STORAGE bool; + -- anyrange datatype support new in 1.3. + CREATE FUNCTION gin_anyrange_cmp(anyrange, anyrange) + RETURNS int4 + AS 'MODULE_PATHNAME' + LANGUAGE C STRICT IMMUTABLE; + + CREATE FUNCTION gin_extract_value_anyrange(anyrange, internal) + RETURNS internal + AS 'MODULE_PATHNAME' + LANGUAGE C STRICT IMMUTABLE; + + CREATE FUNCTION gin_compare_prefix_anyrange(anyrange, anyrange, int2, internal) + RETURNS int4 + AS 'MODULE_PATHNAME' + LANGUAGE C STRICT IMMUTABLE; + + CREATE FUNCTION gin_extract_query_anyrange(anyrange, internal, int2, internal, internal) + RETURNS internal + AS 'MODULE_PATHNAME' + LANGUAGE C STRICT IMMUTABLE; + + CREATE OPERATOR CLASS anyrange_ops + DEFAULT FOR TYPE anyrange USING gin + AS + OPERATOR 1 <, + OPERATOR 2 <=, + OPERATOR 3 =, + OPERATOR 4 >=, + OPERATOR 5 >, + FUNCTION 1 gin_anyrange_cmp(anyrange,anyrange), + FUNCTION 2 gin_extract_value_anyrange(anyrange, internal), + FUNCTION 3 gin_extract_query_anyrange(anyrange, internal, int2, internal, internal), + FUNCTION 4 gin_btree_consistent(internal, int2, anyelement, int4, internal, internal), + FUNCTION 5 gin_compare_prefix_anyrange(anyrange,anyrange,int2, internal), + STORAGE anyrange; + -- bpchar datatype support new in 1.3. CREATE FUNCTION gin_extract_value_bpchar(bpchar, internal) RETURNS internal diff --git a/contrib/btree_gin/btree_gin.c b/contrib/btree_gin/btree_gin.c new file mode 100644 index a660681..37e0740 *** a/contrib/btree_gin/btree_gin.c --- b/contrib/btree_gin/btree_gin.c *************** *** 15,20 **** --- 15,21 ---- #include "utils/timestamp.h" #include "utils/varbit.h" #include "utils/uuid.h" + #include "utils/rangetypes.h" PG_MODULE_MAGIC; *************** leftmostvalue_bool(void) *** 506,508 **** --- 507,560 ---- } GIN_SUPPORT(bool, false, leftmostvalue_bool, btboolcmp) + + /* + * Similarly to Numeric, we don't know the left-most value, although for + * different reasons (numeric does not have one, while for anyarray we + * don't even know the concrete type). We could try to build a fake empty + * range, but we simply use PointerGetDatum(NULL) just like for Numeric. + */ + #define ANYRANGE_IS_LEFTMOST(x) ((x) == NULL) + + PG_FUNCTION_INFO_V1(gin_anyrange_cmp); + + /* + * Note that we use CallerFInfoFunctionCall2 here so that range_cmp + * gets a valid fn_extra to work with. Unlike most other type comparison + * routines it needs it, so we can't use DirectFunctionCall2. + */ + Datum + gin_anyrange_cmp(PG_FUNCTION_ARGS) + { + RangeType *a = (RangeType *) PG_GETARG_POINTER(0); + RangeType *b = (RangeType *) PG_GETARG_POINTER(1); + int res = 0; + + if (ANYRANGE_IS_LEFTMOST(a)) + { + res = (ANYRANGE_IS_LEFTMOST(b)) ? 0 : -1; + } + else if (ANYRANGE_IS_LEFTMOST(b)) + { + res = 1; + } + else + { + res = DatumGetInt32(CallerFInfoFunctionCall2( + range_cmp, + fcinfo->flinfo, + PG_GET_COLLATION(), + RangeTypePGetDatum(a), + RangeTypePGetDatum(b))); + } + + PG_RETURN_INT32(res); + } + + static Datum + leftmostvalue_anyrange(void) + { + return PointerGetDatum(NULL); + } + + GIN_SUPPORT(anyrange, false, leftmostvalue_anyrange, gin_anyrange_cmp) diff --git a/contrib/btree_gin/expected/anyrange.out b/contrib/btree_gin/expected/anyrange.out new file mode 100644 index ...93b24f4 *** a/contrib/btree_gin/expected/anyrange.out --- b/contrib/btree_gin/expected/anyrange.out *************** *** 0 **** --- 1,113 ---- + set enable_seqscan=off; + CREATE TABLE test_tsrange ( + i tsrange + ); + INSERT INTO test_tsrange VALUES + ( 'empty' ), + ( '(,)' ), + ( '[2018-02-02 03:55:08,2018-04-02 03:55:08)' ), + ( '[2018-02-02 04:55:08,2018-04-02 04:55:08)' ), + ( '[2018-02-02 05:55:08,2018-04-02 05:55:08)' ), + ( '[2018-02-02 08:55:08,2018-04-02 08:55:08)' ), + ( '[2018-02-02 09:55:08,2018-04-02 09:55:08)' ), + ( '[2018-02-02 10:55:08,2018-04-02 10:55:08)' ), + ( '[infinity,infinity]' ) + ; + CREATE INDEX idx_tsrange ON test_tsrange USING gin (i); + SELECT * FROM test_tsrange WHERE i<'[2018-02-02 08:55:08,2018-04-02 08:55:08)'::tsrange ORDER BY i; + i + --------------------------------------------------------- + empty + (,) + ["Fri Feb 02 03:55:08 2018","Mon Apr 02 03:55:08 2018") + ["Fri Feb 02 04:55:08 2018","Mon Apr 02 04:55:08 2018") + ["Fri Feb 02 05:55:08 2018","Mon Apr 02 05:55:08 2018") + (5 rows) + + SELECT * FROM test_tsrange WHERE i<='[2018-02-02 08:55:08,2018-04-02 08:55:08)'::tsrange ORDER BY i; + i + --------------------------------------------------------- + empty + (,) + ["Fri Feb 02 03:55:08 2018","Mon Apr 02 03:55:08 2018") + ["Fri Feb 02 04:55:08 2018","Mon Apr 02 04:55:08 2018") + ["Fri Feb 02 05:55:08 2018","Mon Apr 02 05:55:08 2018") + ["Fri Feb 02 08:55:08 2018","Mon Apr 02 08:55:08 2018") + (6 rows) + + SELECT * FROM test_tsrange WHERE i='[2018-02-02 08:55:08,2018-04-02 08:55:08)'::tsrange ORDER BY i; + i + --------------------------------------------------------- + ["Fri Feb 02 08:55:08 2018","Mon Apr 02 08:55:08 2018") + (1 row) + + SELECT * FROM test_tsrange WHERE i>='[2018-02-02 08:55:08,2018-04-02 08:55:08)'::tsrange ORDER BY i; + i + --------------------------------------------------------- + ["Fri Feb 02 08:55:08 2018","Mon Apr 02 08:55:08 2018") + ["Fri Feb 02 09:55:08 2018","Mon Apr 02 09:55:08 2018") + ["Fri Feb 02 10:55:08 2018","Mon Apr 02 10:55:08 2018") + [infinity,infinity] + (4 rows) + + SELECT * FROM test_tsrange WHERE i>'[2018-02-02 08:55:08,2018-04-02 08:55:08)'::tsrange ORDER BY i; + i + --------------------------------------------------------- + ["Fri Feb 02 09:55:08 2018","Mon Apr 02 09:55:08 2018") + ["Fri Feb 02 10:55:08 2018","Mon Apr 02 10:55:08 2018") + [infinity,infinity] + (3 rows) + + EXPLAIN (COSTS OFF) SELECT * FROM test_tsrange WHERE i<'[2018-02-02 08:55:08,2018-04-02 08:55:08)'::tsrange ORDER BY i; + QUERY PLAN + ---------------------------------------------------------------------------------------------------- + Sort + Sort Key: i + -> Bitmap Heap Scan on test_tsrange + Recheck Cond: (i < '["Fri Feb 02 08:55:08 2018","Mon Apr 02 08:55:08 2018")'::tsrange) + -> Bitmap Index Scan on idx_tsrange + Index Cond: (i < '["Fri Feb 02 08:55:08 2018","Mon Apr 02 08:55:08 2018")'::tsrange) + (6 rows) + + EXPLAIN (COSTS OFF) SELECT * FROM test_tsrange WHERE i<='[2018-02-02 08:55:08,2018-04-02 08:55:08)'::tsrange ORDER BY i; + QUERY PLAN + ----------------------------------------------------------------------------------------------------- + Sort + Sort Key: i + -> Bitmap Heap Scan on test_tsrange + Recheck Cond: (i <= '["Fri Feb 02 08:55:08 2018","Mon Apr 02 08:55:08 2018")'::tsrange) + -> Bitmap Index Scan on idx_tsrange + Index Cond: (i <= '["Fri Feb 02 08:55:08 2018","Mon Apr 02 08:55:08 2018")'::tsrange) + (6 rows) + + EXPLAIN (COSTS OFF) SELECT * FROM test_tsrange WHERE i='[2018-02-02 08:55:08,2018-04-02 08:55:08)'::tsrange ORDER BY i; + QUERY PLAN + ---------------------------------------------------------------------------------------------- + Bitmap Heap Scan on test_tsrange + Recheck Cond: (i = '["Fri Feb 02 08:55:08 2018","Mon Apr 02 08:55:08 2018")'::tsrange) + -> Bitmap Index Scan on idx_tsrange + Index Cond: (i = '["Fri Feb 02 08:55:08 2018","Mon Apr 02 08:55:08 2018")'::tsrange) + (4 rows) + + EXPLAIN (COSTS OFF) SELECT * FROM test_tsrange WHERE i>='[2018-02-02 08:55:08,2018-04-02 08:55:08)'::tsrange ORDER BY i; + QUERY PLAN + ----------------------------------------------------------------------------------------------------- + Sort + Sort Key: i + -> Bitmap Heap Scan on test_tsrange + Recheck Cond: (i >= '["Fri Feb 02 08:55:08 2018","Mon Apr 02 08:55:08 2018")'::tsrange) + -> Bitmap Index Scan on idx_tsrange + Index Cond: (i >= '["Fri Feb 02 08:55:08 2018","Mon Apr 02 08:55:08 2018")'::tsrange) + (6 rows) + + EXPLAIN (COSTS OFF) SELECT * FROM test_tsrange WHERE i>'[2018-02-02 08:55:08,2018-04-02 08:55:08)'::tsrange ORDER BY i; + QUERY PLAN + ---------------------------------------------------------------------------------------------------- + Sort + Sort Key: i + -> Bitmap Heap Scan on test_tsrange + Recheck Cond: (i > '["Fri Feb 02 08:55:08 2018","Mon Apr 02 08:55:08 2018")'::tsrange) + -> Bitmap Index Scan on idx_tsrange + Index Cond: (i > '["Fri Feb 02 08:55:08 2018","Mon Apr 02 08:55:08 2018")'::tsrange) + (6 rows) + diff --git a/contrib/btree_gin/sql/anyrange.sql b/contrib/btree_gin/sql/anyrange.sql new file mode 100644 index ...97157ad *** a/contrib/btree_gin/sql/anyrange.sql --- b/contrib/btree_gin/sql/anyrange.sql *************** *** 0 **** --- 1,31 ---- + set enable_seqscan=off; + + CREATE TABLE test_tsrange ( + i tsrange + ); + + INSERT INTO test_tsrange VALUES + ( 'empty' ), + ( '(,)' ), + ( '[2018-02-02 03:55:08,2018-04-02 03:55:08)' ), + ( '[2018-02-02 04:55:08,2018-04-02 04:55:08)' ), + ( '[2018-02-02 05:55:08,2018-04-02 05:55:08)' ), + ( '[2018-02-02 08:55:08,2018-04-02 08:55:08)' ), + ( '[2018-02-02 09:55:08,2018-04-02 09:55:08)' ), + ( '[2018-02-02 10:55:08,2018-04-02 10:55:08)' ), + ( '[infinity,infinity]' ) + ; + + CREATE INDEX idx_tsrange ON test_tsrange USING gin (i); + + SELECT * FROM test_tsrange WHERE i<'[2018-02-02 08:55:08,2018-04-02 08:55:08)'::tsrange ORDER BY i; + SELECT * FROM test_tsrange WHERE i<='[2018-02-02 08:55:08,2018-04-02 08:55:08)'::tsrange ORDER BY i; + SELECT * FROM test_tsrange WHERE i='[2018-02-02 08:55:08,2018-04-02 08:55:08)'::tsrange ORDER BY i; + SELECT * FROM test_tsrange WHERE i>='[2018-02-02 08:55:08,2018-04-02 08:55:08)'::tsrange ORDER BY i; + SELECT * FROM test_tsrange WHERE i>'[2018-02-02 08:55:08,2018-04-02 08:55:08)'::tsrange ORDER BY i; + + EXPLAIN (COSTS OFF) SELECT * FROM test_tsrange WHERE i<'[2018-02-02 08:55:08,2018-04-02 08:55:08)'::tsrange ORDER BY i; + EXPLAIN (COSTS OFF) SELECT * FROM test_tsrange WHERE i<='[2018-02-02 08:55:08,2018-04-02 08:55:08)'::tsrange ORDER BY i; + EXPLAIN (COSTS OFF) SELECT * FROM test_tsrange WHERE i='[2018-02-02 08:55:08,2018-04-02 08:55:08)'::tsrange ORDER BY i; + EXPLAIN (COSTS OFF) SELECT * FROM test_tsrange WHERE i>='[2018-02-02 08:55:08,2018-04-02 08:55:08)'::tsrange ORDER BY i; + EXPLAIN (COSTS OFF) SELECT * FROM test_tsrange WHERE i>'[2018-02-02 08:55:08,2018-04-02 08:55:08)'::tsrange ORDER BY i; diff --git a/doc/src/sgml/btree-gin.sgml b/doc/src/sgml/btree-gin.sgml new file mode 100644 index 314e001..e1315da *** a/doc/src/sgml/btree-gin.sgml --- b/doc/src/sgml/btree-gin.sgml *************** *** 18,24 **** varchar, text, bytea, bit, varbit, macaddr, macaddr8, inet, cidr, uuid, name, bool, ! bpchar, and all enum types. --- 18,24 ---- varchar, text, bytea, bit, varbit, macaddr, macaddr8, inet, cidr, uuid, name, bool, ! bpchar, and all enum and anyrange types.