Commit db6335b5 authored by Alexander Korotkov's avatar Alexander Korotkov

Add support of multirange matching to the existing range GiST indexes

6df7a969 has introduced a set of operators between ranges and multiranges.
Existing GiST indexes for ranges could easily support majority of them.
This commit adds support for new operators to the existing range GiST indexes.
New operators resides the same strategy numbers as existing ones.  Appropriate
check function is determined using the subtype.

Catversion is bumped.
parent d1d61a8b
......@@ -116,6 +116,29 @@
<row><entry><literal>&gt;= (inet,inet)</literal></entry></row>
<row><entry><literal>&amp;&amp; (inet,inet)</literal></entry></row>
<row>
<entry valign="middle" morerows="17"><literal>multirange_ops</literal></entry>
<entry><literal>= (anymultirange,anymultirange)</literal></entry>
<entry valign="middle" morerows="17"></entry>
</row>
<row><entry><literal>&amp;&amp; (anymultirange,anymultirange)</literal></entry></row>
<row><entry><literal>&amp;&amp; (anymultirange,anyrange)</literal></entry></row>
<row><entry><literal>@&gt; (anymultirange,anyelement)</literal></entry></row>
<row><entry><literal>@&gt; (anymultirange,anymultirange)</literal></entry></row>
<row><entry><literal>@&gt; (anymultirange,anyrange)</literal></entry></row>
<row><entry><literal>&lt;@ (anymultirange,anymultirange)</literal></entry></row>
<row><entry><literal>&lt;@ (anymultirange,anyrange)</literal></entry></row>
<row><entry><literal>&lt;&lt; (anymultirange,anymultirange)</literal></entry></row>
<row><entry><literal>&lt;&lt; (anymultirange,anyrange)</literal></entry></row>
<row><entry><literal>&gt;&gt; (anymultirange,anymultirange)</literal></entry></row>
<row><entry><literal>&gt;&gt; (anymultirange,anyrange)</literal></entry></row>
<row><entry><literal>&amp;&lt; (anymultirange,anymultirange)</literal></entry></row>
<row><entry><literal>&amp;&lt; (anymultirange,anyrange)</literal></entry></row>
<row><entry><literal>&amp;&gt; (anymultirange,anymultirange)</literal></entry></row>
<row><entry><literal>&amp;&gt; (anymultirange,anyrange)</literal></entry></row>
<row><entry><literal>-|- (anymultirange,anymultirange)</literal></entry></row>
<row><entry><literal>-|- (anymultirange,anyrange)</literal></entry></row>
<row>
<entry valign="middle" morerows="7"><literal>point_ops</literal></entry>
<entry><literal>|&gt;&gt; (point,point)</literal></entry>
......@@ -149,19 +172,27 @@
<row><entry><literal>~ (polygon,polygon)</literal></entry></row>
<row>
<entry valign="middle" morerows="9"><literal>range_ops</literal></entry>
<entry valign="middle" morerows="17"><literal>range_ops</literal></entry>
<entry><literal>= (anyrange,anyrange)</literal></entry>
<entry valign="middle" morerows="9"></entry>
<entry valign="middle" morerows="17"></entry>
</row>
<row><entry><literal>&amp;&amp; (anyrange,anyrange)</literal></entry></row>
<row><entry><literal>&amp;&amp; (anyrange,anymultirange)</literal></entry></row>
<row><entry><literal>@&gt; (anyrange,anyelement)</literal></entry></row>
<row><entry><literal>@&gt; (anyrange,anyrange)</literal></entry></row>
<row><entry><literal>@&gt; (anyrange,anymultirange)</literal></entry></row>
<row><entry><literal>&lt;@ (anyrange,anyrange)</literal></entry></row>
<row><entry><literal>&lt;@ (anyrange,anymultirange)</literal></entry></row>
<row><entry><literal>&lt;&lt; (anyrange,anyrange)</literal></entry></row>
<row><entry><literal>&lt;&lt; (anyrange,anymultirange)</literal></entry></row>
<row><entry><literal>&gt;&gt; (anyrange,anyrange)</literal></entry></row>
<row><entry><literal>&gt;&gt; (anyrange,anymultirange)</literal></entry></row>
<row><entry><literal>&amp;&lt; (anyrange,anyrange)</literal></entry></row>
<row><entry><literal>&amp;&lt; (anyrange,anymultirange)</literal></entry></row>
<row><entry><literal>&amp;&gt; (anyrange,anyrange)</literal></entry></row>
<row><entry><literal>&amp;&gt; (anyrange,anymultirange)</literal></entry></row>
<row><entry><literal>-|- (anyrange,anyrange)</literal></entry></row>
<row><entry><literal>-|- (anyrange,anymultirange)</literal></entry></row>
<row>
<entry valign="middle" morerows="1"><literal>tsquery_ops</literal></entry>
......
......@@ -469,11 +469,13 @@ SELECT '[11:10, 23:00]'::timerange;
<para>
GiST and SP-GiST indexes can be created for table columns of range types.
GiST indexes can be also created for table columns of multirange types.
For instance, to create a GiST index:
<programlisting>
CREATE INDEX reservation_idx ON reservation USING GIST (during);
</programlisting>
A GiST or SP-GiST index can accelerate queries involving these range operators:
A GiST or SP-GiST index on ranges can accelerate queries involving these
range operators:
<literal>=</literal>,
<literal>&amp;&amp;</literal>,
<literal>&lt;@</literal>,
......@@ -482,8 +484,21 @@ CREATE INDEX reservation_idx ON reservation USING GIST (during);
<literal>&gt;&gt;</literal>,
<literal>-|-</literal>,
<literal>&amp;&lt;</literal>, and
<literal>&amp;&gt;</literal>
(see <xref linkend="range-operators-table"/> for more information).
<literal>&amp;&gt;</literal>.
A GiST index on multiranges can accelerate queries involving the same
set of multirange operators.
A GiST index on ranges and GiST index on multiranges can also accelerate
queries involving these cross-type range to multirange and multirange to
range operators correspondingly:
<literal>&amp;&amp;</literal>,
<literal>&lt;@</literal>,
<literal>@&gt;</literal>,
<literal>&lt;&lt;</literal>,
<literal>&gt;&gt;</literal>,
<literal>-|-</literal>,
<literal>&amp;&lt;</literal>, and
<literal>&amp;&gt;</literal>.
See <xref linkend="range-operators-table"/> for more information.
</para>
<para>
......
......@@ -768,6 +768,27 @@ multirange_get_bounds(TypeCacheEntry *rangetyp,
upper->lower = false;
}
/*
* 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
*
......
......@@ -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,11 +136,29 @@ 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,
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(TypeCacheEntry *typcache,
StrategyNumber strategy, const RangeType *key,
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,
......@@ -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))
{
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
{
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))
PG_RETURN_BOOL(range_gist_consistent_leaf(typcache, strategy,
key, query));
{
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
PG_RETURN_BOOL(range_gist_consistent_int(typcache, strategy,
key, query));
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, DatumGetRangeTypeP(query));
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 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 */
......
......@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 202012291
#define CATALOG_VERSION_NO 202012293
#endif
......@@ -1346,27 +1346,51 @@
{ amopfamily => 'gist/range_ops', amoplefttype => 'anyrange',
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' },
......@@ -1374,6 +1398,62 @@
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',
......
......@@ -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',
......
......@@ -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',
......
......@@ -236,5 +236,7 @@
opfmethod => 'btree', opfname => 'multirange_ops' },
{ oid => '4225',
opfmethod => 'hash', opfname => 'multirange_ops' },
{ oid => '8021',
opfmethod => 'gist', opfname => 'multirange_ops' },
]
......@@ -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' },
......
......@@ -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 */
......@@ -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
--
......
......@@ -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);
......
......@@ -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
--
......
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment