diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/utils/adt/multirangetypes.c | 21 | ||||
-rw-r--r-- | src/backend/utils/adt/rangetypes_gist.c | 393 | ||||
-rw-r--r-- | src/include/catalog/catversion.h | 2 | ||||
-rw-r--r-- | src/include/catalog/pg_amop.dat | 80 | ||||
-rw-r--r-- | src/include/catalog/pg_amproc.dat | 18 | ||||
-rw-r--r-- | src/include/catalog/pg_opclass.dat | 2 | ||||
-rw-r--r-- | src/include/catalog/pg_opfamily.dat | 2 | ||||
-rw-r--r-- | src/include/catalog/pg_proc.dat | 8 | ||||
-rw-r--r-- | src/include/utils/multirangetypes.h | 2 | ||||
-rw-r--r-- | src/test/regress/expected/multirangetypes.out | 257 | ||||
-rw-r--r-- | src/test/regress/expected/rangetypes.out | 162 | ||||
-rw-r--r-- | src/test/regress/sql/multirangetypes.sql | 63 | ||||
-rw-r--r-- | src/test/regress/sql/rangetypes.sql | 27 |
13 files changed, 973 insertions, 64 deletions
diff --git a/src/backend/utils/adt/multirangetypes.c b/src/backend/utils/adt/multirangetypes.c index a77299147e7..2d4cee92bcc 100644 --- a/src/backend/utils/adt/multirangetypes.c +++ b/src/backend/utils/adt/multirangetypes.c @@ -769,6 +769,27 @@ multirange_get_bounds(TypeCacheEntry *rangetyp, } /* + * Construct union range from the multirange. + */ +RangeType * +multirange_get_union_range(TypeCacheEntry *rangetyp, + const MultirangeType *mr) +{ + RangeBound lower, + upper, + tmp; + + if (MultirangeIsEmpty(mr)) + return make_empty_range(rangetyp); + + multirange_get_bounds(rangetyp, mr, 0, &lower, &tmp); + multirange_get_bounds(rangetyp, mr, mr->rangeCount - 1, &tmp, &upper); + + return make_range(rangetyp, &lower, &upper, false); +} + + +/* * multirange_deserialize: deconstruct a multirange value * * NB: the given multirange object must be fully detoasted; it cannot have a diff --git a/src/backend/utils/adt/rangetypes_gist.c b/src/backend/utils/adt/rangetypes_gist.c index 75069c3ac2c..435b242c8ab 100644 --- a/src/backend/utils/adt/rangetypes_gist.c +++ b/src/backend/utils/adt/rangetypes_gist.c @@ -19,6 +19,7 @@ #include "utils/datum.h" #include "utils/float.h" #include "utils/fmgrprotos.h" +#include "utils/multirangetypes.h" #include "utils/rangetypes.h" /* @@ -135,12 +136,30 @@ typedef struct static RangeType *range_super_union(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2); -static bool range_gist_consistent_int(TypeCacheEntry *typcache, - StrategyNumber strategy, const RangeType *key, - Datum query); -static bool range_gist_consistent_leaf(TypeCacheEntry *typcache, - StrategyNumber strategy, const RangeType *key, - Datum query); +static bool range_gist_consistent_int_range(TypeCacheEntry *typcache, + StrategyNumber strategy, + const RangeType *key, + const RangeType *query); +static bool range_gist_consistent_int_multirange(TypeCacheEntry *typcache, + StrategyNumber strategy, + const RangeType *key, + const MultirangeType *query); +static bool range_gist_consistent_int_element(TypeCacheEntry *typcache, + StrategyNumber strategy, + const RangeType *key, + Datum query); +static bool range_gist_consistent_leaf_range(TypeCacheEntry *typcache, + StrategyNumber strategy, + const RangeType *key, + const RangeType *query); +static bool range_gist_consistent_leaf_multirange(TypeCacheEntry *typcache, + StrategyNumber strategy, + const RangeType *key, + const MultirangeType *query); +static bool range_gist_consistent_leaf_element(TypeCacheEntry *typcache, + StrategyNumber strategy, + const RangeType *key, + Datum query); static void range_gist_fallback_split(TypeCacheEntry *typcache, GistEntryVector *entryvec, GIST_SPLITVEC *v); @@ -174,8 +193,8 @@ range_gist_consistent(PG_FUNCTION_ARGS) GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); Datum query = PG_GETARG_DATUM(1); StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2); - - /* Oid subtype = PG_GETARG_OID(3); */ + bool result; + Oid subtype = PG_GETARG_OID(3); bool *recheck = (bool *) PG_GETARG_POINTER(4); RangeType *key = DatumGetRangeTypeP(entry->key); TypeCacheEntry *typcache; @@ -185,12 +204,119 @@ range_gist_consistent(PG_FUNCTION_ARGS) typcache = range_get_typcache(fcinfo, RangeTypeGetOid(key)); + /* + * Perform consistent checking using function corresponding to key type + * (leaf or internal) and query subtype (range, multirange, or element). + * Note that invalid subtype means that query type matches key type + * (range). + */ if (GIST_LEAF(entry)) - PG_RETURN_BOOL(range_gist_consistent_leaf(typcache, strategy, - key, query)); + { + if (!OidIsValid(subtype) || subtype == ANYRANGEOID) + result = range_gist_consistent_leaf_range(typcache, strategy, key, + DatumGetRangeTypeP(query)); + else if (subtype == ANYMULTIRANGEOID) + result = range_gist_consistent_leaf_multirange(typcache, strategy, key, + DatumGetMultirangeTypeP(query)); + else + result = range_gist_consistent_leaf_element(typcache, strategy, + key, query); + } else - PG_RETURN_BOOL(range_gist_consistent_int(typcache, strategy, - key, query)); + { + if (!OidIsValid(subtype) || subtype == ANYRANGEOID) + result = range_gist_consistent_int_range(typcache, strategy, key, + DatumGetRangeTypeP(query)); + else if (subtype == ANYMULTIRANGEOID) + result = range_gist_consistent_int_multirange(typcache, strategy, key, + DatumGetMultirangeTypeP(query)); + else + result = range_gist_consistent_int_element(typcache, strategy, + key, query); + } + PG_RETURN_BOOL(result); +} + +/* + * GiST compress method for multiranges: multirange is approximated as union + * range with no gaps. + */ +Datum +multirange_gist_compress(PG_FUNCTION_ARGS) +{ + GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); + + if (entry->leafkey) + { + MultirangeType *mr = DatumGetMultirangeTypeP(entry->key); + RangeType *r; + TypeCacheEntry *typcache; + GISTENTRY *retval = palloc(sizeof(GISTENTRY)); + + typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr)); + r = multirange_get_union_range(typcache->rngtype, mr); + + gistentryinit(*retval, RangeTypePGetDatum(r), + entry->rel, entry->page, entry->offset, false); + + PG_RETURN_POINTER(retval); + } + + PG_RETURN_POINTER(entry); +} + +/* GiST query consistency check for multiranges */ +Datum +multirange_gist_consistent(PG_FUNCTION_ARGS) +{ + GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); + Datum query = PG_GETARG_DATUM(1); + StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2); + bool result; + Oid subtype = PG_GETARG_OID(3); + bool *recheck = (bool *) PG_GETARG_POINTER(4); + RangeType *key = DatumGetRangeTypeP(entry->key); + TypeCacheEntry *typcache; + + /* + * All operators served by this function are inexact because multirange is + * approximated by union range with no gaps. + */ + *recheck = true; + + typcache = range_get_typcache(fcinfo, RangeTypeGetOid(key)); + + /* + * Perform consistent checking using function corresponding to key type + * (leaf or internal) and query subtype (range, multirange, or element). + * Note that invalid subtype means that query type matches key type + * (multirange). + */ + if (GIST_LEAF(entry)) + { + if (!OidIsValid(subtype) || subtype == ANYMULTIRANGEOID) + result = range_gist_consistent_leaf_multirange(typcache, strategy, key, + DatumGetMultirangeTypeP(query)); + else if (subtype == ANYRANGEOID) + result = range_gist_consistent_leaf_range(typcache, strategy, key, + DatumGetRangeTypeP(query)); + else + result = range_gist_consistent_leaf_element(typcache, strategy, + key, query); + } + else + { + if (!OidIsValid(subtype) || subtype == ANYMULTIRANGEOID) + result = range_gist_consistent_int_multirange(typcache, strategy, key, + DatumGetMultirangeTypeP(query)); + else if (subtype == ANYRANGEOID) + result = range_gist_consistent_int_range(typcache, strategy, key, + DatumGetRangeTypeP(query)); + else + result = range_gist_consistent_int_element(typcache, strategy, + key, query); + } + PG_RETURN_BOOL(result); } /* form union range */ @@ -758,49 +884,67 @@ range_super_union(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2) return result; } +static bool +multirange_union_range_equal(TypeCacheEntry *typcache, + const RangeType *r, + const MultirangeType *mr) +{ + RangeBound lower1, + upper1, + lower2, + upper2, + tmp; + bool empty; + + if (RangeIsEmpty(r) || MultirangeIsEmpty(mr)) + return (RangeIsEmpty(r) && MultirangeIsEmpty(mr)); + + range_deserialize(typcache, r, &lower1, &upper1, &empty); + Assert(!empty); + multirange_get_bounds(typcache, mr, 0, &lower2, &tmp); + multirange_get_bounds(typcache, mr, mr->rangeCount - 1, &tmp, &upper2); + + return (range_cmp_bounds(typcache, &lower1, &lower2) == 0 && + range_cmp_bounds(typcache, &upper1, &upper2) == 0); +} + /* - * GiST consistent test on an index internal page + * GiST consistent test on an index internal page with range query */ static bool -range_gist_consistent_int(TypeCacheEntry *typcache, StrategyNumber strategy, - const RangeType *key, Datum query) +range_gist_consistent_int_range(TypeCacheEntry *typcache, + StrategyNumber strategy, + const RangeType *key, + const RangeType *query) { switch (strategy) { case RANGESTRAT_BEFORE: - if (RangeIsEmpty(key) || RangeIsEmpty(DatumGetRangeTypeP(query))) + if (RangeIsEmpty(key) || RangeIsEmpty(query)) return false; - return (!range_overright_internal(typcache, key, - DatumGetRangeTypeP(query))); + return (!range_overright_internal(typcache, key, query)); case RANGESTRAT_OVERLEFT: - if (RangeIsEmpty(key) || RangeIsEmpty(DatumGetRangeTypeP(query))) + if (RangeIsEmpty(key) || RangeIsEmpty(query)) return false; - return (!range_after_internal(typcache, key, - DatumGetRangeTypeP(query))); + return (!range_after_internal(typcache, key, query)); case RANGESTRAT_OVERLAPS: - return range_overlaps_internal(typcache, key, - DatumGetRangeTypeP(query)); + return range_overlaps_internal(typcache, key, query); case RANGESTRAT_OVERRIGHT: - if (RangeIsEmpty(key) || RangeIsEmpty(DatumGetRangeTypeP(query))) + if (RangeIsEmpty(key) || RangeIsEmpty(query)) return false; - return (!range_before_internal(typcache, key, - DatumGetRangeTypeP(query))); + return (!range_before_internal(typcache, key, query)); case RANGESTRAT_AFTER: - if (RangeIsEmpty(key) || RangeIsEmpty(DatumGetRangeTypeP(query))) + if (RangeIsEmpty(key) || RangeIsEmpty(query)) return false; - return (!range_overleft_internal(typcache, key, - DatumGetRangeTypeP(query))); + return (!range_overleft_internal(typcache, key, query)); case RANGESTRAT_ADJACENT: - if (RangeIsEmpty(key) || RangeIsEmpty(DatumGetRangeTypeP(query))) + if (RangeIsEmpty(key) || RangeIsEmpty(query)) return false; - if (range_adjacent_internal(typcache, key, - DatumGetRangeTypeP(query))) + if (range_adjacent_internal(typcache, key, query)) return true; - return range_overlaps_internal(typcache, key, - DatumGetRangeTypeP(query)); + return range_overlaps_internal(typcache, key, query); case RANGESTRAT_CONTAINS: - return range_contains_internal(typcache, key, - DatumGetRangeTypeP(query)); + return range_contains_internal(typcache, key, query); case RANGESTRAT_CONTAINED_BY: /* @@ -810,20 +954,16 @@ range_gist_consistent_int(TypeCacheEntry *typcache, StrategyNumber strategy, */ if (RangeIsOrContainsEmpty(key)) return true; - return range_overlaps_internal(typcache, key, - DatumGetRangeTypeP(query)); - case RANGESTRAT_CONTAINS_ELEM: - return range_contains_elem_internal(typcache, key, query); + return range_overlaps_internal(typcache, key, query); case RANGESTRAT_EQ: /* * If query is empty, descend only if the key is or contains any * empty ranges. Otherwise, descend if key contains query. */ - if (RangeIsEmpty(DatumGetRangeTypeP(query))) + if (RangeIsEmpty(query)) return RangeIsOrContainsEmpty(key); - return range_contains_internal(typcache, key, - DatumGetRangeTypeP(query)); + return range_contains_internal(typcache, key, query); default: elog(ERROR, "unrecognized range strategy: %d", strategy); return false; /* keep compiler quiet */ @@ -831,42 +971,169 @@ range_gist_consistent_int(TypeCacheEntry *typcache, StrategyNumber strategy, } /* - * GiST consistent test on an index leaf page + * GiST consistent test on an index internal page with multirange query */ static bool -range_gist_consistent_leaf(TypeCacheEntry *typcache, StrategyNumber strategy, - const RangeType *key, Datum query) +range_gist_consistent_int_multirange(TypeCacheEntry *typcache, + StrategyNumber strategy, + const RangeType *key, + const MultirangeType *query) { switch (strategy) { case RANGESTRAT_BEFORE: - return range_before_internal(typcache, key, - DatumGetRangeTypeP(query)); + if (RangeIsEmpty(key) || MultirangeIsEmpty(query)) + return false; + return (!range_overright_multirange_internal(typcache, key, query)); case RANGESTRAT_OVERLEFT: - return range_overleft_internal(typcache, key, - DatumGetRangeTypeP(query)); + if (RangeIsEmpty(key) || MultirangeIsEmpty(query)) + return false; + return (!range_after_multirange_internal(typcache, key, query)); case RANGESTRAT_OVERLAPS: - return range_overlaps_internal(typcache, key, - DatumGetRangeTypeP(query)); + return range_overlaps_multirange_internal(typcache, key, query); case RANGESTRAT_OVERRIGHT: - return range_overright_internal(typcache, key, - DatumGetRangeTypeP(query)); + if (RangeIsEmpty(key) || MultirangeIsEmpty(query)) + return false; + return (!range_before_multirange_internal(typcache, key, query)); case RANGESTRAT_AFTER: - return range_after_internal(typcache, key, - DatumGetRangeTypeP(query)); + if (RangeIsEmpty(key) || MultirangeIsEmpty(query)) + return false; + return (!range_overleft_multirange_internal(typcache, key, query)); case RANGESTRAT_ADJACENT: - return range_adjacent_internal(typcache, key, - DatumGetRangeTypeP(query)); + if (RangeIsEmpty(key) || MultirangeIsEmpty(query)) + return false; + if (range_adjacent_multirange_internal(typcache, key, query)) + return true; + return range_overlaps_multirange_internal(typcache, key, query); case RANGESTRAT_CONTAINS: - return range_contains_internal(typcache, key, - DatumGetRangeTypeP(query)); + return range_contains_multirange_internal(typcache, key, query); case RANGESTRAT_CONTAINED_BY: - return range_contained_by_internal(typcache, key, - DatumGetRangeTypeP(query)); + + /* + * Empty ranges are contained by anything, so if key is or + * contains any empty ranges, we must descend into it. Otherwise, + * descend only if key overlaps the query. + */ + if (RangeIsOrContainsEmpty(key)) + return true; + return range_overlaps_multirange_internal(typcache, key, query); + case RANGESTRAT_EQ: + + /* + * If query is empty, descend only if the key is or contains any + * empty ranges. Otherwise, descend if key contains query. + */ + if (MultirangeIsEmpty(query)) + return RangeIsOrContainsEmpty(key); + return range_contains_multirange_internal(typcache, key, query); + default: + elog(ERROR, "unrecognized range strategy: %d", strategy); + return false; /* keep compiler quiet */ + } +} + +/* + * GiST consistent test on an index internal page with element query + */ +static bool +range_gist_consistent_int_element(TypeCacheEntry *typcache, + StrategyNumber strategy, + const RangeType *key, + Datum query) +{ + switch (strategy) + { case RANGESTRAT_CONTAINS_ELEM: return range_contains_elem_internal(typcache, key, query); + default: + elog(ERROR, "unrecognized range strategy: %d", strategy); + return false; /* keep compiler quiet */ + } +} + +/* + * GiST consistent test on an index leaf page with range query + */ +static bool +range_gist_consistent_leaf_range(TypeCacheEntry *typcache, + StrategyNumber strategy, + const RangeType *key, + const RangeType *query) +{ + switch (strategy) + { + case RANGESTRAT_BEFORE: + return range_before_internal(typcache, key, query); + case RANGESTRAT_OVERLEFT: + return range_overleft_internal(typcache, key, query); + case RANGESTRAT_OVERLAPS: + return range_overlaps_internal(typcache, key, query); + case RANGESTRAT_OVERRIGHT: + return range_overright_internal(typcache, key, query); + case RANGESTRAT_AFTER: + return range_after_internal(typcache, key, query); + case RANGESTRAT_ADJACENT: + return range_adjacent_internal(typcache, key, query); + case RANGESTRAT_CONTAINS: + return range_contains_internal(typcache, key, query); + case RANGESTRAT_CONTAINED_BY: + return range_contained_by_internal(typcache, key, query); + case RANGESTRAT_EQ: + return range_eq_internal(typcache, key, query); + default: + elog(ERROR, "unrecognized range strategy: %d", strategy); + return false; /* keep compiler quiet */ + } +} + +/* + * GiST consistent test on an index leaf page with multirange query + */ +static bool +range_gist_consistent_leaf_multirange(TypeCacheEntry *typcache, + StrategyNumber strategy, + const RangeType *key, + const MultirangeType *query) +{ + switch (strategy) + { + case RANGESTRAT_BEFORE: + return range_before_multirange_internal(typcache, key, query); + case RANGESTRAT_OVERLEFT: + return range_overleft_multirange_internal(typcache, key, query); + case RANGESTRAT_OVERLAPS: + return range_overlaps_multirange_internal(typcache, key, query); + case RANGESTRAT_OVERRIGHT: + return range_overright_multirange_internal(typcache, key, query); + case RANGESTRAT_AFTER: + return range_after_multirange_internal(typcache, key, query); + case RANGESTRAT_ADJACENT: + return range_adjacent_multirange_internal(typcache, key, query); + case RANGESTRAT_CONTAINS: + return range_contains_multirange_internal(typcache, key, query); + case RANGESTRAT_CONTAINED_BY: + return multirange_contains_range_internal(typcache, query, key); case RANGESTRAT_EQ: - return range_eq_internal(typcache, key, DatumGetRangeTypeP(query)); + return multirange_union_range_equal(typcache, key, query); + default: + elog(ERROR, "unrecognized range strategy: %d", strategy); + return false; /* keep compiler quiet */ + } +} + +/* + * GiST consistent test on an index leaf page with element query + */ +static bool +range_gist_consistent_leaf_element(TypeCacheEntry *typcache, + StrategyNumber strategy, + const RangeType *key, + Datum query) +{ + switch (strategy) + { + case RANGESTRAT_CONTAINS_ELEM: + return range_contains_elem_internal(typcache, key, query); default: elog(ERROR, "unrecognized range strategy: %d", strategy); return false; /* keep compiler quiet */ diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 4fd88a47730..db4814e57af 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 202012291 +#define CATALOG_VERSION_NO 202012293 #endif diff --git a/src/include/catalog/pg_amop.dat b/src/include/catalog/pg_amop.dat index 78d7d2c5232..bbe1a6ddf8e 100644 --- a/src/include/catalog/pg_amop.dat +++ b/src/include/catalog/pg_amop.dat @@ -1347,33 +1347,113 @@ amoprighttype => 'anyrange', amopstrategy => '1', amopopr => '<<(anyrange,anyrange)', amopmethod => 'gist' }, { amopfamily => 'gist/range_ops', amoplefttype => 'anyrange', + amoprighttype => 'anymultirange', amopstrategy => '1', + amopopr => '<<(anyrange,anymultirange)', amopmethod => 'gist' }, +{ amopfamily => 'gist/range_ops', amoplefttype => 'anyrange', amoprighttype => 'anyrange', amopstrategy => '2', amopopr => '&<(anyrange,anyrange)', amopmethod => 'gist' }, { amopfamily => 'gist/range_ops', amoplefttype => 'anyrange', + amoprighttype => 'anymultirange', amopstrategy => '2', + amopopr => '&<(anyrange,anymultirange)', amopmethod => 'gist' }, +{ amopfamily => 'gist/range_ops', amoplefttype => 'anyrange', amoprighttype => 'anyrange', amopstrategy => '3', amopopr => '&&(anyrange,anyrange)', amopmethod => 'gist' }, { amopfamily => 'gist/range_ops', amoplefttype => 'anyrange', + amoprighttype => 'anymultirange', amopstrategy => '3', + amopopr => '&&(anyrange,anymultirange)', amopmethod => 'gist' }, +{ amopfamily => 'gist/range_ops', amoplefttype => 'anyrange', amoprighttype => 'anyrange', amopstrategy => '4', amopopr => '&>(anyrange,anyrange)', amopmethod => 'gist' }, { amopfamily => 'gist/range_ops', amoplefttype => 'anyrange', + amoprighttype => 'anymultirange', amopstrategy => '4', + amopopr => '&>(anyrange,anymultirange)', amopmethod => 'gist' }, +{ amopfamily => 'gist/range_ops', amoplefttype => 'anyrange', amoprighttype => 'anyrange', amopstrategy => '5', amopopr => '>>(anyrange,anyrange)', amopmethod => 'gist' }, { amopfamily => 'gist/range_ops', amoplefttype => 'anyrange', + amoprighttype => 'anymultirange', amopstrategy => '5', + amopopr => '>>(anyrange,anymultirange)', amopmethod => 'gist' }, +{ amopfamily => 'gist/range_ops', amoplefttype => 'anyrange', amoprighttype => 'anyrange', amopstrategy => '6', amopopr => '-|-(anyrange,anyrange)', amopmethod => 'gist' }, { amopfamily => 'gist/range_ops', amoplefttype => 'anyrange', + amoprighttype => 'anymultirange', amopstrategy => '6', + amopopr => '-|-(anyrange,anymultirange)', amopmethod => 'gist' }, +{ amopfamily => 'gist/range_ops', amoplefttype => 'anyrange', amoprighttype => 'anyrange', amopstrategy => '7', amopopr => '@>(anyrange,anyrange)', amopmethod => 'gist' }, { amopfamily => 'gist/range_ops', amoplefttype => 'anyrange', + amoprighttype => 'anymultirange', amopstrategy => '7', + amopopr => '@>(anyrange,anymultirange)', amopmethod => 'gist' }, +{ amopfamily => 'gist/range_ops', amoplefttype => 'anyrange', amoprighttype => 'anyrange', amopstrategy => '8', amopopr => '<@(anyrange,anyrange)', amopmethod => 'gist' }, { amopfamily => 'gist/range_ops', amoplefttype => 'anyrange', + amoprighttype => 'anymultirange', amopstrategy => '8', + amopopr => '<@(anyrange,anymultirange)', amopmethod => 'gist' }, +{ amopfamily => 'gist/range_ops', amoplefttype => 'anyrange', amoprighttype => 'anyelement', amopstrategy => '16', amopopr => '@>(anyrange,anyelement)', amopmethod => 'gist' }, { amopfamily => 'gist/range_ops', amoplefttype => 'anyrange', amoprighttype => 'anyrange', amopstrategy => '18', amopopr => '=(anyrange,anyrange)', amopmethod => 'gist' }, +# GiST multirange_ops +{ amopfamily => 'gist/multirange_ops', amoplefttype => 'anymultirange', + amoprighttype => 'anymultirange', amopstrategy => '1', + amopopr => '<<(anymultirange,anymultirange)', amopmethod => 'gist' }, +{ amopfamily => 'gist/multirange_ops', amoplefttype => 'anymultirange', + amoprighttype => 'anyrange', amopstrategy => '1', + amopopr => '<<(anymultirange,anyrange)', amopmethod => 'gist' }, +{ amopfamily => 'gist/multirange_ops', amoplefttype => 'anymultirange', + amoprighttype => 'anymultirange', amopstrategy => '2', + amopopr => '&<(anymultirange,anymultirange)', amopmethod => 'gist' }, +{ amopfamily => 'gist/multirange_ops', amoplefttype => 'anymultirange', + amoprighttype => 'anyrange', amopstrategy => '2', + amopopr => '&<(anymultirange,anyrange)', amopmethod => 'gist' }, +{ amopfamily => 'gist/multirange_ops', amoplefttype => 'anymultirange', + amoprighttype => 'anymultirange', amopstrategy => '3', + amopopr => '&&(anymultirange,anymultirange)', amopmethod => 'gist' }, +{ amopfamily => 'gist/multirange_ops', amoplefttype => 'anymultirange', + amoprighttype => 'anyrange', amopstrategy => '3', + amopopr => '&&(anymultirange,anyrange)', amopmethod => 'gist' }, +{ amopfamily => 'gist/multirange_ops', amoplefttype => 'anymultirange', + amoprighttype => 'anymultirange', amopstrategy => '4', + amopopr => '&>(anymultirange,anymultirange)', amopmethod => 'gist' }, +{ amopfamily => 'gist/multirange_ops', amoplefttype => 'anymultirange', + amoprighttype => 'anyrange', amopstrategy => '4', + amopopr => '&>(anymultirange,anyrange)', amopmethod => 'gist' }, +{ amopfamily => 'gist/multirange_ops', amoplefttype => 'anymultirange', + amoprighttype => 'anymultirange', amopstrategy => '5', + amopopr => '>>(anymultirange,anymultirange)', amopmethod => 'gist' }, +{ amopfamily => 'gist/multirange_ops', amoplefttype => 'anymultirange', + amoprighttype => 'anyrange', amopstrategy => '5', + amopopr => '>>(anymultirange,anyrange)', amopmethod => 'gist' }, +{ amopfamily => 'gist/multirange_ops', amoplefttype => 'anymultirange', + amoprighttype => 'anymultirange', amopstrategy => '6', + amopopr => '-|-(anymultirange,anymultirange)', amopmethod => 'gist' }, +{ amopfamily => 'gist/multirange_ops', amoplefttype => 'anymultirange', + amoprighttype => 'anyrange', amopstrategy => '6', + amopopr => '-|-(anymultirange,anyrange)', amopmethod => 'gist' }, +{ amopfamily => 'gist/multirange_ops', amoplefttype => 'anymultirange', + amoprighttype => 'anymultirange', amopstrategy => '7', + amopopr => '@>(anymultirange,anymultirange)', amopmethod => 'gist' }, +{ amopfamily => 'gist/multirange_ops', amoplefttype => 'anymultirange', + amoprighttype => 'anyrange', amopstrategy => '7', + amopopr => '@>(anymultirange,anyrange)', amopmethod => 'gist' }, +{ amopfamily => 'gist/multirange_ops', amoplefttype => 'anymultirange', + amoprighttype => 'anymultirange', amopstrategy => '8', + amopopr => '<@(anymultirange,anymultirange)', amopmethod => 'gist' }, +{ amopfamily => 'gist/multirange_ops', amoplefttype => 'anymultirange', + amoprighttype => 'anyrange', amopstrategy => '8', + amopopr => '<@(anymultirange,anyrange)', amopmethod => 'gist' }, +{ amopfamily => 'gist/multirange_ops', amoplefttype => 'anymultirange', + amoprighttype => 'anyelement', amopstrategy => '16', + amopopr => '@>(anymultirange,anyelement)', amopmethod => 'gist' }, +{ amopfamily => 'gist/multirange_ops', amoplefttype => 'anymultirange', + amoprighttype => 'anymultirange', amopstrategy => '18', + amopopr => '=(anymultirange,anymultirange)', amopmethod => 'gist' }, + # btree multirange_ops { amopfamily => 'btree/multirange_ops', amoplefttype => 'anymultirange', amoprighttype => 'anymultirange', amopstrategy => '1', diff --git a/src/include/catalog/pg_amproc.dat b/src/include/catalog/pg_amproc.dat index 9d423d535cd..68d72ec732a 100644 --- a/src/include/catalog/pg_amproc.dat +++ b/src/include/catalog/pg_amproc.dat @@ -612,6 +612,24 @@ amprocrighttype => 'inet', amprocnum => '7', amproc => 'inet_gist_same' }, { amprocfamily => 'gist/network_ops', amproclefttype => 'inet', amprocrighttype => 'inet', amprocnum => '9', amproc => 'inet_gist_fetch' }, +{ amprocfamily => 'gist/multirange_ops', amproclefttype => 'anymultirange', + amprocrighttype => 'anymultirange', amprocnum => '1', + amproc => 'multirange_gist_consistent' }, +{ amprocfamily => 'gist/multirange_ops', amproclefttype => 'anymultirange', + amprocrighttype => 'anymultirange', amprocnum => '2', + amproc => 'range_gist_union' }, +{ amprocfamily => 'gist/multirange_ops', amproclefttype => 'anymultirange', + amprocrighttype => 'anymultirange', amprocnum => '3', + amproc => 'multirange_gist_compress' }, +{ amprocfamily => 'gist/multirange_ops', amproclefttype => 'anymultirange', + amprocrighttype => 'anymultirange', amprocnum => '5', + amproc => 'range_gist_penalty' }, +{ amprocfamily => 'gist/multirange_ops', amproclefttype => 'anymultirange', + amprocrighttype => 'anymultirange', amprocnum => '6', + amproc => 'range_gist_picksplit' }, +{ amprocfamily => 'gist/multirange_ops', amproclefttype => 'anymultirange', + amprocrighttype => 'anymultirange', amprocnum => '7', + amproc => 'range_gist_same' }, # gin { amprocfamily => 'gin/array_ops', amproclefttype => 'anyarray', diff --git a/src/include/catalog/pg_opclass.dat b/src/include/catalog/pg_opclass.dat index 4c5e475ff7b..12cad694186 100644 --- a/src/include/catalog/pg_opclass.dat +++ b/src/include/catalog/pg_opclass.dat @@ -236,6 +236,8 @@ opcintype => 'anymultirange' }, { opcmethod => 'hash', opcname => 'multirange_ops', opcfamily => 'hash/multirange_ops', opcintype => 'anymultirange' }, +{ opcmethod => 'gist', opcname => 'multirange_ops', opcfamily => 'gist/multirange_ops', + opcintype => 'anymultirange', opckeytype => 'anyrange' }, { opcmethod => 'spgist', opcname => 'box_ops', opcfamily => 'spgist/box_ops', opcintype => 'box' }, { opcmethod => 'spgist', opcname => 'quad_point_ops', diff --git a/src/include/catalog/pg_opfamily.dat b/src/include/catalog/pg_opfamily.dat index fe42dfc0f8f..ac8338f34b1 100644 --- a/src/include/catalog/pg_opfamily.dat +++ b/src/include/catalog/pg_opfamily.dat @@ -236,5 +236,7 @@ opfmethod => 'btree', opfname => 'multirange_ops' }, { oid => '4225', opfmethod => 'hash', opfname => 'multirange_ops' }, +{ oid => '8021', + opfmethod => 'gist', opfname => 'multirange_ops' }, ] diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index 834ee86c791..139f4a08bd5 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -9922,6 +9922,14 @@ { oid => '3881', descr => 'GiST support', proname => 'range_gist_same', prorettype => 'internal', proargtypes => 'anyrange anyrange internal', prosrc => 'range_gist_same' }, +{ oid => '8017', descr => 'GiST support', + proname => 'multirange_gist_consistent', prorettype => 'bool', + proargtypes => 'internal anymultirange int2 oid internal', + prosrc => 'multirange_gist_consistent' }, +{ oid => '8019', descr => 'GiST support', + proname => 'multirange_gist_compress', prorettype => 'internal', + proargtypes => 'internal', + prosrc => 'multirange_gist_compress' }, { oid => '3902', descr => 'hash a range', proname => 'hash_range', prorettype => 'int4', proargtypes => 'anyrange', prosrc => 'hash_range' }, diff --git a/src/include/utils/multirangetypes.h b/src/include/utils/multirangetypes.h index ff2e58744a9..1d877f08b56 100644 --- a/src/include/utils/multirangetypes.h +++ b/src/include/utils/multirangetypes.h @@ -129,5 +129,7 @@ extern void multirange_get_bounds(TypeCacheEntry *rangetyp, RangeBound *lower, RangeBound *upper); extern RangeType *multirange_get_range(TypeCacheEntry *rangetyp, const MultirangeType *multirange, int i); +extern RangeType *multirange_get_union_range(TypeCacheEntry *rangetyp, + const MultirangeType *mr); #endif /* MULTIRANGETYPES_H */ diff --git a/src/test/regress/expected/multirangetypes.out b/src/test/regress/expected/multirangetypes.out index aa7232efc57..86011a02a1e 100644 --- a/src/test/regress/expected/multirangetypes.out +++ b/src/test/regress/expected/multirangetypes.out @@ -2219,6 +2219,263 @@ SELECT '{[1,4), [7,10)}'::nummultirange * '{[0,2), [3,8), [9,12)}'::nummultirang {[1,2),[3,4),[7,8),[9,10)} (1 row) +-- test GiST index +create table test_multirange_gist(mr int4multirange); +insert into test_multirange_gist select int4multirange(int4range(g, g+10),int4range(g+20, g+30),int4range(g+40, g+50)) from generate_series(1,2000) g; +insert into test_multirange_gist select '{}'::int4multirange from generate_series(1,500) g; +insert into test_multirange_gist select int4multirange(int4range(g, g+10000)) from generate_series(1,1000) g; +insert into test_multirange_gist select int4multirange(int4range(NULL, g*10, '(]'), int4range(g*10, g*20, '(]')) from generate_series(1,100) g; +insert into test_multirange_gist select int4multirange(int4range(g*10, g*20, '(]'), int4range(g*20, NULL, '(]')) from generate_series(1,100) g; +create index test_mulrirange_gist_idx on test_multirange_gist using gist (mr); +-- first, verify non-indexed results +SET enable_seqscan = t; +SET enable_indexscan = f; +SET enable_bitmapscan = f; +select count(*) from test_multirange_gist where mr @> 'empty'::int4range; + count +------- + 3700 +(1 row) + +select count(*) from test_multirange_gist where mr = int4multirange(int4range(10,20), int4range(30,40), int4range(50,60)); + count +------- + 1 +(1 row) + +select count(*) from test_multirange_gist where mr @> 10; + count +------- + 120 +(1 row) + +select count(*) from test_multirange_gist where mr @> int4range(10,20); + count +------- + 111 +(1 row) + +select count(*) from test_multirange_gist where mr && int4range(10,20); + count +------- + 139 +(1 row) + +select count(*) from test_multirange_gist where mr <@ int4range(10,50); + count +------- + 500 +(1 row) + +select count(*) from test_multirange_gist where mr << int4range(100,500); + count +------- + 54 +(1 row) + +select count(*) from test_multirange_gist where mr >> int4range(100,500); + count +------- + 2053 +(1 row) + +select count(*) from test_multirange_gist where mr &< int4range(100,500); + count +------- + 474 +(1 row) + +select count(*) from test_multirange_gist where mr &> int4range(100,500); + count +------- + 2893 +(1 row) + +select count(*) from test_multirange_gist where mr -|- int4range(100,500); + count +------- + 3 +(1 row) + +select count(*) from test_multirange_gist where mr @> '{}'::int4multirange; + count +------- + 3700 +(1 row) + +select count(*) from test_multirange_gist where mr @> int4multirange(int4range(10,20), int4range(30,40)); + count +------- + 110 +(1 row) + +select count(*) from test_multirange_gist where mr && '{(10,20),(30,40),(50,60)}'::int4multirange; + count +------- + 218 +(1 row) + +select count(*) from test_multirange_gist where mr <@ '{(10,30),(40,60),(70,90)}'::int4multirange; + count +------- + 500 +(1 row) + +select count(*) from test_multirange_gist where mr << int4multirange(int4range(100,200), int4range(400,500)); + count +------- + 54 +(1 row) + +select count(*) from test_multirange_gist where mr >> int4multirange(int4range(100,200), int4range(400,500)); + count +------- + 2053 +(1 row) + +select count(*) from test_multirange_gist where mr &< int4multirange(int4range(100,200), int4range(400,500)); + count +------- + 474 +(1 row) + +select count(*) from test_multirange_gist where mr &> int4multirange(int4range(100,200), int4range(400,500)); + count +------- + 2893 +(1 row) + +select count(*) from test_multirange_gist where mr -|- int4multirange(int4range(100,200), int4range(400,500)); + count +------- + 3 +(1 row) + +-- now check same queries using index +SET enable_seqscan = f; +SET enable_indexscan = t; +SET enable_bitmapscan = f; +select count(*) from test_multirange_gist where mr @> 'empty'::int4range; + count +------- + 3700 +(1 row) + +select count(*) from test_multirange_gist where mr = int4multirange(int4range(10,20), int4range(30,40), int4range(50,60)); + count +------- + 1 +(1 row) + +select count(*) from test_multirange_gist where mr @> 10; + count +------- + 120 +(1 row) + +select count(*) from test_multirange_gist where mr @> int4range(10,20); + count +------- + 111 +(1 row) + +select count(*) from test_multirange_gist where mr && int4range(10,20); + count +------- + 139 +(1 row) + +select count(*) from test_multirange_gist where mr <@ int4range(10,50); + count +------- + 500 +(1 row) + +select count(*) from test_multirange_gist where mr << int4range(100,500); + count +------- + 54 +(1 row) + +select count(*) from test_multirange_gist where mr >> int4range(100,500); + count +------- + 2053 +(1 row) + +select count(*) from test_multirange_gist where mr &< int4range(100,500); + count +------- + 474 +(1 row) + +select count(*) from test_multirange_gist where mr &> int4range(100,500); + count +------- + 2893 +(1 row) + +select count(*) from test_multirange_gist where mr -|- int4range(100,500); + count +------- + 3 +(1 row) + +select count(*) from test_multirange_gist where mr @> '{}'::int4multirange; + count +------- + 3700 +(1 row) + +select count(*) from test_multirange_gist where mr @> int4multirange(int4range(10,20), int4range(30,40)); + count +------- + 110 +(1 row) + +select count(*) from test_multirange_gist where mr && '{(10,20),(30,40),(50,60)}'::int4multirange; + count +------- + 218 +(1 row) + +select count(*) from test_multirange_gist where mr <@ '{(10,30),(40,60),(70,90)}'::int4multirange; + count +------- + 500 +(1 row) + +select count(*) from test_multirange_gist where mr << int4multirange(int4range(100,200), int4range(400,500)); + count +------- + 54 +(1 row) + +select count(*) from test_multirange_gist where mr >> int4multirange(int4range(100,200), int4range(400,500)); + count +------- + 2053 +(1 row) + +select count(*) from test_multirange_gist where mr &< int4multirange(int4range(100,200), int4range(400,500)); + count +------- + 474 +(1 row) + +select count(*) from test_multirange_gist where mr &> int4multirange(int4range(100,200), int4range(400,500)); + count +------- + 2893 +(1 row) + +select count(*) from test_multirange_gist where mr -|- int4multirange(int4range(100,200), int4range(400,500)); + count +------- + 3 +(1 row) + +drop table test_multirange_gist; -- -- range_agg function -- diff --git a/src/test/regress/expected/rangetypes.out b/src/test/regress/expected/rangetypes.out index 6a1bbadc91a..28dc995e599 100644 --- a/src/test/regress/expected/rangetypes.out +++ b/src/test/regress/expected/rangetypes.out @@ -862,6 +862,60 @@ select count(*) from test_range_gist where ir -|- int4range(100,500); 5 (1 row) +select count(*) from test_range_gist where ir @> '{}'::int4multirange; + count +------- + 6200 +(1 row) + +select count(*) from test_range_gist where ir @> int4multirange(int4range(10,20), int4range(30,40)); + count +------- + 107 +(1 row) + +select count(*) from test_range_gist where ir && '{(10,20),(30,40),(50,60)}'::int4multirange; + count +------- + 271 +(1 row) + +select count(*) from test_range_gist where ir <@ '{(10,30),(40,60),(70,90)}'::int4multirange; + count +------- + 1060 +(1 row) + +select count(*) from test_range_gist where ir << int4multirange(int4range(100,200), int4range(400,500)); + count +------- + 189 +(1 row) + +select count(*) from test_range_gist where ir >> int4multirange(int4range(100,200), int4range(400,500)); + count +------- + 3554 +(1 row) + +select count(*) from test_range_gist where ir &< int4multirange(int4range(100,200), int4range(400,500)); + count +------- + 1029 +(1 row) + +select count(*) from test_range_gist where ir &> int4multirange(int4range(100,200), int4range(400,500)); + count +------- + 4794 +(1 row) + +select count(*) from test_range_gist where ir -|- int4multirange(int4range(100,200), int4range(400,500)); + count +------- + 5 +(1 row) + -- now check same queries using index SET enable_seqscan = f; SET enable_indexscan = t; @@ -932,6 +986,60 @@ select count(*) from test_range_gist where ir -|- int4range(100,500); 5 (1 row) +select count(*) from test_range_gist where ir @> '{}'::int4multirange; + count +------- + 6200 +(1 row) + +select count(*) from test_range_gist where ir @> int4multirange(int4range(10,20), int4range(30,40)); + count +------- + 107 +(1 row) + +select count(*) from test_range_gist where ir && '{(10,20),(30,40),(50,60)}'::int4multirange; + count +------- + 271 +(1 row) + +select count(*) from test_range_gist where ir <@ '{(10,30),(40,60),(70,90)}'::int4multirange; + count +------- + 1060 +(1 row) + +select count(*) from test_range_gist where ir << int4multirange(int4range(100,200), int4range(400,500)); + count +------- + 189 +(1 row) + +select count(*) from test_range_gist where ir >> int4multirange(int4range(100,200), int4range(400,500)); + count +------- + 3554 +(1 row) + +select count(*) from test_range_gist where ir &< int4multirange(int4range(100,200), int4range(400,500)); + count +------- + 1029 +(1 row) + +select count(*) from test_range_gist where ir &> int4multirange(int4range(100,200), int4range(400,500)); + count +------- + 4794 +(1 row) + +select count(*) from test_range_gist where ir -|- int4multirange(int4range(100,200), int4range(400,500)); + count +------- + 5 +(1 row) + -- now check same queries using a bulk-loaded index drop index test_range_gist_idx; create index test_range_gist_idx on test_range_gist using gist (ir); @@ -1001,6 +1109,60 @@ select count(*) from test_range_gist where ir -|- int4range(100,500); 5 (1 row) +select count(*) from test_range_gist where ir @> '{}'::int4multirange; + count +------- + 6200 +(1 row) + +select count(*) from test_range_gist where ir @> int4multirange(int4range(10,20), int4range(30,40)); + count +------- + 107 +(1 row) + +select count(*) from test_range_gist where ir && '{(10,20),(30,40),(50,60)}'::int4multirange; + count +------- + 271 +(1 row) + +select count(*) from test_range_gist where ir <@ '{(10,30),(40,60),(70,90)}'::int4multirange; + count +------- + 1060 +(1 row) + +select count(*) from test_range_gist where ir << int4multirange(int4range(100,200), int4range(400,500)); + count +------- + 189 +(1 row) + +select count(*) from test_range_gist where ir >> int4multirange(int4range(100,200), int4range(400,500)); + count +------- + 3554 +(1 row) + +select count(*) from test_range_gist where ir &< int4multirange(int4range(100,200), int4range(400,500)); + count +------- + 1029 +(1 row) + +select count(*) from test_range_gist where ir &> int4multirange(int4range(100,200), int4range(400,500)); + count +------- + 4794 +(1 row) + +select count(*) from test_range_gist where ir -|- int4multirange(int4range(100,200), int4range(400,500)); + count +------- + 5 +(1 row) + -- test SP-GiST index that's been built incrementally create table test_range_spgist(ir int4range); create index test_range_spgist_idx on test_range_spgist using spgist (ir); diff --git a/src/test/regress/sql/multirangetypes.sql b/src/test/regress/sql/multirangetypes.sql index 9d7af404c98..2a2ee4dcdfd 100644 --- a/src/test/regress/sql/multirangetypes.sql +++ b/src/test/regress/sql/multirangetypes.sql @@ -414,6 +414,69 @@ SELECT '{[1,4), [7,10)}'::nummultirange * '{[-5,-4), [5,6), [9,12)}'::nummultira SELECT '{[1,4), [7,10)}'::nummultirange * '{[0,2), [3,8), [9,12)}'::nummultirange; SELECT '{[1,4), [7,10)}'::nummultirange * '{[0,2), [3,8), [9,12)}'::nummultirange; +-- test GiST index +create table test_multirange_gist(mr int4multirange); +insert into test_multirange_gist select int4multirange(int4range(g, g+10),int4range(g+20, g+30),int4range(g+40, g+50)) from generate_series(1,2000) g; +insert into test_multirange_gist select '{}'::int4multirange from generate_series(1,500) g; +insert into test_multirange_gist select int4multirange(int4range(g, g+10000)) from generate_series(1,1000) g; +insert into test_multirange_gist select int4multirange(int4range(NULL, g*10, '(]'), int4range(g*10, g*20, '(]')) from generate_series(1,100) g; +insert into test_multirange_gist select int4multirange(int4range(g*10, g*20, '(]'), int4range(g*20, NULL, '(]')) from generate_series(1,100) g; +create index test_mulrirange_gist_idx on test_multirange_gist using gist (mr); + +-- first, verify non-indexed results +SET enable_seqscan = t; +SET enable_indexscan = f; +SET enable_bitmapscan = f; + +select count(*) from test_multirange_gist where mr @> 'empty'::int4range; +select count(*) from test_multirange_gist where mr = int4multirange(int4range(10,20), int4range(30,40), int4range(50,60)); +select count(*) from test_multirange_gist where mr @> 10; +select count(*) from test_multirange_gist where mr @> int4range(10,20); +select count(*) from test_multirange_gist where mr && int4range(10,20); +select count(*) from test_multirange_gist where mr <@ int4range(10,50); +select count(*) from test_multirange_gist where mr << int4range(100,500); +select count(*) from test_multirange_gist where mr >> int4range(100,500); +select count(*) from test_multirange_gist where mr &< int4range(100,500); +select count(*) from test_multirange_gist where mr &> int4range(100,500); +select count(*) from test_multirange_gist where mr -|- int4range(100,500); +select count(*) from test_multirange_gist where mr @> '{}'::int4multirange; +select count(*) from test_multirange_gist where mr @> int4multirange(int4range(10,20), int4range(30,40)); +select count(*) from test_multirange_gist where mr && '{(10,20),(30,40),(50,60)}'::int4multirange; +select count(*) from test_multirange_gist where mr <@ '{(10,30),(40,60),(70,90)}'::int4multirange; +select count(*) from test_multirange_gist where mr << int4multirange(int4range(100,200), int4range(400,500)); +select count(*) from test_multirange_gist where mr >> int4multirange(int4range(100,200), int4range(400,500)); +select count(*) from test_multirange_gist where mr &< int4multirange(int4range(100,200), int4range(400,500)); +select count(*) from test_multirange_gist where mr &> int4multirange(int4range(100,200), int4range(400,500)); +select count(*) from test_multirange_gist where mr -|- int4multirange(int4range(100,200), int4range(400,500)); + +-- now check same queries using index +SET enable_seqscan = f; +SET enable_indexscan = t; +SET enable_bitmapscan = f; + +select count(*) from test_multirange_gist where mr @> 'empty'::int4range; +select count(*) from test_multirange_gist where mr = int4multirange(int4range(10,20), int4range(30,40), int4range(50,60)); +select count(*) from test_multirange_gist where mr @> 10; +select count(*) from test_multirange_gist where mr @> int4range(10,20); +select count(*) from test_multirange_gist where mr && int4range(10,20); +select count(*) from test_multirange_gist where mr <@ int4range(10,50); +select count(*) from test_multirange_gist where mr << int4range(100,500); +select count(*) from test_multirange_gist where mr >> int4range(100,500); +select count(*) from test_multirange_gist where mr &< int4range(100,500); +select count(*) from test_multirange_gist where mr &> int4range(100,500); +select count(*) from test_multirange_gist where mr -|- int4range(100,500); +select count(*) from test_multirange_gist where mr @> '{}'::int4multirange; +select count(*) from test_multirange_gist where mr @> int4multirange(int4range(10,20), int4range(30,40)); +select count(*) from test_multirange_gist where mr && '{(10,20),(30,40),(50,60)}'::int4multirange; +select count(*) from test_multirange_gist where mr <@ '{(10,30),(40,60),(70,90)}'::int4multirange; +select count(*) from test_multirange_gist where mr << int4multirange(int4range(100,200), int4range(400,500)); +select count(*) from test_multirange_gist where mr >> int4multirange(int4range(100,200), int4range(400,500)); +select count(*) from test_multirange_gist where mr &< int4multirange(int4range(100,200), int4range(400,500)); +select count(*) from test_multirange_gist where mr &> int4multirange(int4range(100,200), int4range(400,500)); +select count(*) from test_multirange_gist where mr -|- int4multirange(int4range(100,200), int4range(400,500)); + +drop table test_multirange_gist; + -- -- range_agg function -- diff --git a/src/test/regress/sql/rangetypes.sql b/src/test/regress/sql/rangetypes.sql index b69efede3ae..51eddabf60f 100644 --- a/src/test/regress/sql/rangetypes.sql +++ b/src/test/regress/sql/rangetypes.sql @@ -232,6 +232,15 @@ select count(*) from test_range_gist where ir >> int4range(100,500); select count(*) from test_range_gist where ir &< int4range(100,500); select count(*) from test_range_gist where ir &> int4range(100,500); select count(*) from test_range_gist where ir -|- int4range(100,500); +select count(*) from test_range_gist where ir @> '{}'::int4multirange; +select count(*) from test_range_gist where ir @> int4multirange(int4range(10,20), int4range(30,40)); +select count(*) from test_range_gist where ir && '{(10,20),(30,40),(50,60)}'::int4multirange; +select count(*) from test_range_gist where ir <@ '{(10,30),(40,60),(70,90)}'::int4multirange; +select count(*) from test_range_gist where ir << int4multirange(int4range(100,200), int4range(400,500)); +select count(*) from test_range_gist where ir >> int4multirange(int4range(100,200), int4range(400,500)); +select count(*) from test_range_gist where ir &< int4multirange(int4range(100,200), int4range(400,500)); +select count(*) from test_range_gist where ir &> int4multirange(int4range(100,200), int4range(400,500)); +select count(*) from test_range_gist where ir -|- int4multirange(int4range(100,200), int4range(400,500)); -- now check same queries using index SET enable_seqscan = f; @@ -249,6 +258,15 @@ select count(*) from test_range_gist where ir >> int4range(100,500); select count(*) from test_range_gist where ir &< int4range(100,500); select count(*) from test_range_gist where ir &> int4range(100,500); select count(*) from test_range_gist where ir -|- int4range(100,500); +select count(*) from test_range_gist where ir @> '{}'::int4multirange; +select count(*) from test_range_gist where ir @> int4multirange(int4range(10,20), int4range(30,40)); +select count(*) from test_range_gist where ir && '{(10,20),(30,40),(50,60)}'::int4multirange; +select count(*) from test_range_gist where ir <@ '{(10,30),(40,60),(70,90)}'::int4multirange; +select count(*) from test_range_gist where ir << int4multirange(int4range(100,200), int4range(400,500)); +select count(*) from test_range_gist where ir >> int4multirange(int4range(100,200), int4range(400,500)); +select count(*) from test_range_gist where ir &< int4multirange(int4range(100,200), int4range(400,500)); +select count(*) from test_range_gist where ir &> int4multirange(int4range(100,200), int4range(400,500)); +select count(*) from test_range_gist where ir -|- int4multirange(int4range(100,200), int4range(400,500)); -- now check same queries using a bulk-loaded index drop index test_range_gist_idx; @@ -265,6 +283,15 @@ select count(*) from test_range_gist where ir >> int4range(100,500); select count(*) from test_range_gist where ir &< int4range(100,500); select count(*) from test_range_gist where ir &> int4range(100,500); select count(*) from test_range_gist where ir -|- int4range(100,500); +select count(*) from test_range_gist where ir @> '{}'::int4multirange; +select count(*) from test_range_gist where ir @> int4multirange(int4range(10,20), int4range(30,40)); +select count(*) from test_range_gist where ir && '{(10,20),(30,40),(50,60)}'::int4multirange; +select count(*) from test_range_gist where ir <@ '{(10,30),(40,60),(70,90)}'::int4multirange; +select count(*) from test_range_gist where ir << int4multirange(int4range(100,200), int4range(400,500)); +select count(*) from test_range_gist where ir >> int4multirange(int4range(100,200), int4range(400,500)); +select count(*) from test_range_gist where ir &< int4multirange(int4range(100,200), int4range(400,500)); +select count(*) from test_range_gist where ir &> int4multirange(int4range(100,200), int4range(400,500)); +select count(*) from test_range_gist where ir -|- int4multirange(int4range(100,200), int4range(400,500)); -- test SP-GiST index that's been built incrementally create table test_range_spgist(ir int4range); |