Commit 4d7684cc authored by Alexander Korotkov's avatar Alexander Korotkov

Implement operators for checking if the range contains a multirange

We have operators for checking if the multirange contains a range but don't
have the opposite.  This commit improves completeness of the operator set by
adding two new operators: @> (anyrange,anymultirange) and
<@(anymultirange,anyrange).

Catversion is bumped.
parent a5b81b6f
...@@ -18182,6 +18182,20 @@ SELECT NULLIF(value, '(none)') ... ...@@ -18182,6 +18182,20 @@ SELECT NULLIF(value, '(none)') ...
</para></entry> </para></entry>
</row> </row>
<row>
<entry role="func_table_entry"><para role="func_signature">
<type>anyrange</type> <literal>@&gt;</literal> <type>anymultirange</type>
<returnvalue>boolean</returnvalue>
</para>
<para>
Does the range contain the multirange?
</para>
<para>
<literal>'[2,4)'::int4range @&gt; '{[2,3)}'::int4multirange</literal>
<returnvalue>t</returnvalue>
</para></entry>
</row>
<row> <row>
<entry role="func_table_entry"><para role="func_signature"> <entry role="func_table_entry"><para role="func_signature">
<type>anymultirange</type> <literal>&lt;@</literal> <type>anymultirange</type> <type>anymultirange</type> <literal>&lt;@</literal> <type>anymultirange</type>
......
...@@ -1631,6 +1631,18 @@ multirange_contains_range(PG_FUNCTION_ARGS) ...@@ -1631,6 +1631,18 @@ multirange_contains_range(PG_FUNCTION_ARGS)
PG_RETURN_BOOL(multirange_contains_range_internal(typcache, mr, r)); PG_RETURN_BOOL(multirange_contains_range_internal(typcache, mr, r));
} }
Datum
range_contains_multirange(PG_FUNCTION_ARGS)
{
RangeType *r = PG_GETARG_RANGE_P(0);
MultirangeType *mr = PG_GETARG_MULTIRANGE_P(1);
TypeCacheEntry *typcache;
typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr));
PG_RETURN_BOOL(range_contains_multirange_internal(typcache, r, mr));
}
/* contained by? */ /* contained by? */
Datum Datum
range_contained_by_multirange(PG_FUNCTION_ARGS) range_contained_by_multirange(PG_FUNCTION_ARGS)
...@@ -1644,6 +1656,18 @@ range_contained_by_multirange(PG_FUNCTION_ARGS) ...@@ -1644,6 +1656,18 @@ range_contained_by_multirange(PG_FUNCTION_ARGS)
PG_RETURN_BOOL(multirange_contains_range_internal(typcache, mr, r)); PG_RETURN_BOOL(multirange_contains_range_internal(typcache, mr, r));
} }
Datum
multirange_contained_by_range(PG_FUNCTION_ARGS)
{
MultirangeType *mr = PG_GETARG_MULTIRANGE_P(0);
RangeType *r = PG_GETARG_RANGE_P(1);
TypeCacheEntry *typcache;
typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr));
PG_RETURN_BOOL(range_contains_multirange_internal(typcache, r, mr));
}
/* /*
* Comparison function for checking if any range of multirange contains given * Comparison function for checking if any range of multirange contains given
* key range using binary search. * key range using binary search.
...@@ -1701,6 +1725,42 @@ multirange_contains_range_internal(TypeCacheEntry *typcache, MultirangeType *mr, ...@@ -1701,6 +1725,42 @@ multirange_contains_range_internal(TypeCacheEntry *typcache, MultirangeType *mr,
multirange_range_contains_bsearch_comparison); multirange_range_contains_bsearch_comparison);
} }
/*
* Test whether range r contains a multirange mr.
*/
bool
range_contains_multirange_internal(TypeCacheEntry *typcache, RangeType *r,
MultirangeType *mr)
{
TypeCacheEntry *rangetyp;
RangeBound lower1,
upper1,
lower2,
upper2,
tmp;
bool empty;
rangetyp = typcache->rngtype;
/*
* Every range contains an infinite number of empty multiranges, even an
* empty one.
*/
if (MultirangeIsEmpty(mr))
return true;
if (RangeIsEmpty(r))
return false;
/* Range contains multirange iff it contains its union range. */
range_deserialize(rangetyp, r, &lower1, &upper1, &empty);
Assert(!empty);
multirange_get_bounds(rangetyp, mr, 0, &lower2, &tmp);
multirange_get_bounds(rangetyp, mr, mr->rangeCount - 1, &tmp, &upper2);
return range_bounds_contains(rangetyp, &lower1, &upper1, &lower2, &upper2);
}
/* multirange, multirange -> bool functions */ /* multirange, multirange -> bool functions */
......
...@@ -86,6 +86,8 @@ default_multirange_selectivity(Oid operator) ...@@ -86,6 +86,8 @@ default_multirange_selectivity(Oid operator)
case OID_RANGE_OVERLAPS_MULTIRANGE_OP: case OID_RANGE_OVERLAPS_MULTIRANGE_OP:
return 0.01; return 0.01;
case OID_RANGE_CONTAINS_MULTIRANGE_OP:
case OID_RANGE_MULTIRANGE_CONTAINED_OP:
case OID_MULTIRANGE_CONTAINS_RANGE_OP: case OID_MULTIRANGE_CONTAINS_RANGE_OP:
case OID_MULTIRANGE_CONTAINS_MULTIRANGE_OP: case OID_MULTIRANGE_CONTAINS_MULTIRANGE_OP:
case OID_MULTIRANGE_RANGE_CONTAINED_OP: case OID_MULTIRANGE_RANGE_CONTAINED_OP:
...@@ -224,7 +226,8 @@ multirangesel(PG_FUNCTION_ARGS) ...@@ -224,7 +226,8 @@ multirangesel(PG_FUNCTION_ARGS)
1, &constrange); 1, &constrange);
} }
} }
else if (operator == OID_MULTIRANGE_CONTAINS_RANGE_OP || else if (operator == OID_RANGE_MULTIRANGE_CONTAINED_OP ||
operator == OID_MULTIRANGE_CONTAINS_RANGE_OP ||
operator == OID_MULTIRANGE_OVERLAPS_RANGE_OP || operator == OID_MULTIRANGE_OVERLAPS_RANGE_OP ||
operator == OID_MULTIRANGE_OVERLAPS_LEFT_RANGE_OP || operator == OID_MULTIRANGE_OVERLAPS_LEFT_RANGE_OP ||
operator == OID_MULTIRANGE_OVERLAPS_RIGHT_RANGE_OP || operator == OID_MULTIRANGE_OVERLAPS_RIGHT_RANGE_OP ||
...@@ -248,6 +251,7 @@ multirangesel(PG_FUNCTION_ARGS) ...@@ -248,6 +251,7 @@ multirangesel(PG_FUNCTION_ARGS)
operator == OID_RANGE_OVERLAPS_RIGHT_MULTIRANGE_OP || operator == OID_RANGE_OVERLAPS_RIGHT_MULTIRANGE_OP ||
operator == OID_RANGE_LEFT_MULTIRANGE_OP || operator == OID_RANGE_LEFT_MULTIRANGE_OP ||
operator == OID_RANGE_RIGHT_MULTIRANGE_OP || operator == OID_RANGE_RIGHT_MULTIRANGE_OP ||
operator == OID_RANGE_CONTAINS_MULTIRANGE_OP ||
operator == OID_MULTIRANGE_ELEM_CONTAINED_OP || operator == OID_MULTIRANGE_ELEM_CONTAINED_OP ||
operator == OID_MULTIRANGE_RANGE_CONTAINED_OP) operator == OID_MULTIRANGE_RANGE_CONTAINED_OP)
{ {
......
...@@ -53,6 +53,6 @@ ...@@ -53,6 +53,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 202012201 #define CATALOG_VERSION_NO 202012291
#endif #endif
...@@ -3360,6 +3360,18 @@ ...@@ -3360,6 +3360,18 @@
oprresult => 'bool', oprcom => '@>(anymultirange,anymultirange)', oprresult => 'bool', oprcom => '@>(anymultirange,anymultirange)',
oprcode => 'multirange_contained_by_multirange', oprrest => 'multirangesel', oprcode => 'multirange_contained_by_multirange', oprrest => 'multirangesel',
oprjoin => 'contjoinsel' }, oprjoin => 'contjoinsel' },
{ oid => '4539', oid_symbol => 'OID_RANGE_CONTAINS_MULTIRANGE_OP',
descr => 'contains',
oprname => '@>', oprleft => 'anyrange', oprright => 'anymultirange',
oprresult => 'bool', oprcom => '<@(anymultirange,anyrange)',
oprcode => 'range_contains_multirange', oprrest => 'multirangesel',
oprjoin => 'contjoinsel' },
{ oid => '4540', oid_symbol => 'OID_RANGE_MULTIRANGE_CONTAINED_OP',
descr => 'is contained by',
oprname => '<@', oprleft => 'anymultirange', oprright => 'anyrange',
oprresult => 'bool', oprcom => '@>(anyrange,anymultirange)',
oprcode => 'multirange_contained_by_range', oprrest => 'multirangesel',
oprjoin => 'contjoinsel' },
{ oid => '2875', oid_symbol => 'OID_RANGE_OVERLAPS_LEFT_MULTIRANGE_OP', { oid => '2875', oid_symbol => 'OID_RANGE_OVERLAPS_LEFT_MULTIRANGE_OP',
descr => 'overlaps or is left of', descr => 'overlaps or is left of',
oprname => '&<', oprleft => 'anyrange', oprright => 'anymultirange', oprname => '&<', oprleft => 'anyrange', oprright => 'anymultirange',
......
...@@ -10085,6 +10085,12 @@ ...@@ -10085,6 +10085,12 @@
{ oid => '4253', { oid => '4253',
proname => 'range_contained_by_multirange', prorettype => 'bool', proname => 'range_contained_by_multirange', prorettype => 'bool',
proargtypes => 'anyrange anymultirange', prosrc => 'range_contained_by_multirange' }, proargtypes => 'anyrange anymultirange', prosrc => 'range_contained_by_multirange' },
{ oid => '4541',
proname => 'range_contains_multirange', prorettype => 'bool',
proargtypes => 'anyrange anymultirange', prosrc => 'range_contains_multirange' },
{ oid => '4542',
proname => 'multirange_contained_by_range', prorettype => 'bool',
proargtypes => 'anymultirange anyrange', prosrc => 'multirange_contained_by_range' },
{ oid => '4254', { oid => '4254',
proname => 'multirange_contained_by_multirange', prorettype => 'bool', proname => 'multirange_contained_by_multirange', prorettype => 'bool',
proargtypes => 'anymultirange anymultirange', prosrc => 'multirange_contained_by_multirange' }, proargtypes => 'anymultirange anymultirange', prosrc => 'multirange_contained_by_multirange' },
......
...@@ -64,6 +64,8 @@ extern bool multirange_contains_elem_internal(TypeCacheEntry *typcache, Multiran ...@@ -64,6 +64,8 @@ extern bool multirange_contains_elem_internal(TypeCacheEntry *typcache, Multiran
Datum elem); Datum elem);
extern bool multirange_contains_range_internal(TypeCacheEntry *typcache, MultirangeType *mr, extern bool multirange_contains_range_internal(TypeCacheEntry *typcache, MultirangeType *mr,
RangeType *r); RangeType *r);
extern bool range_contains_multirange_internal(TypeCacheEntry *typcache, RangeType *r,
MultirangeType *mr);
extern bool multirange_contains_multirange_internal(TypeCacheEntry *typcache, extern bool multirange_contains_multirange_internal(TypeCacheEntry *typcache,
MultirangeType *mr1, MultirangeType *mr1,
MultirangeType *mr2); MultirangeType *mr2);
......
...@@ -979,6 +979,126 @@ select '{(10,20),(30,40),(50,60)}'::nummultirange @> '(52,56)'::numrange; ...@@ -979,6 +979,126 @@ select '{(10,20),(30,40),(50,60)}'::nummultirange @> '(52,56)'::numrange;
t t
(1 row) (1 row)
SELECT numrange(null,null) @> nummultirange(numrange(1,2));
?column?
----------
t
(1 row)
SELECT numrange(null,null) @> nummultirange(numrange(null,2));
?column?
----------
t
(1 row)
SELECT numrange(null,null) @> nummultirange(numrange(2,null));
?column?
----------
t
(1 row)
SELECT numrange(null,5) @> nummultirange(numrange(null,3));
?column?
----------
t
(1 row)
SELECT numrange(null,5) @> nummultirange(numrange(null,8));
?column?
----------
f
(1 row)
SELECT numrange(5,null) @> nummultirange(numrange(8,null));
?column?
----------
t
(1 row)
SELECT numrange(5,null) @> nummultirange(numrange(3,null));
?column?
----------
f
(1 row)
SELECT numrange(1,5) @> nummultirange(numrange(8,9));
?column?
----------
f
(1 row)
SELECT numrange(1,5) @> nummultirange(numrange(3,9));
?column?
----------
f
(1 row)
SELECT numrange(1,5) @> nummultirange(numrange(1,4));
?column?
----------
t
(1 row)
SELECT numrange(1,5) @> nummultirange(numrange(1,5));
?column?
----------
t
(1 row)
SELECT numrange(1,9) @> nummultirange(numrange(-4,-2), numrange(1,5));
?column?
----------
f
(1 row)
SELECT numrange(1,9) @> nummultirange(numrange(1,5), numrange(8,9));
?column?
----------
t
(1 row)
SELECT numrange(1,9) @> nummultirange(numrange(1,5), numrange(6,9));
?column?
----------
t
(1 row)
SELECT numrange(1,9) @> nummultirange(numrange(1,5), numrange(6,10));
?column?
----------
f
(1 row)
SELECT '{[1,9)}' @> '{[1,5)}'::nummultirange;
?column?
----------
t
(1 row)
SELECT '{[1,9)}' @> '{[-4,-2), [1,5)}'::nummultirange;
?column?
----------
f
(1 row)
SELECT '{[1,9)}' @> '{[1,5), [8,9)}'::nummultirange;
?column?
----------
t
(1 row)
SELECT '{[1,9)}' @> '{[1,5), [6,9)}'::nummultirange;
?column?
----------
t
(1 row)
SELECT '{[1,9)}' @> '{[1,5), [6,10)}'::nummultirange;
?column?
----------
f
(1 row)
-- is contained by -- is contained by
SELECT nummultirange() <@ nummultirange(); SELECT nummultirange() <@ nummultirange();
?column? ?column?
...@@ -1112,6 +1232,126 @@ SELECT '{[6,7)}' <@ '{[1,5), [6,9)}'::nummultirange; ...@@ -1112,6 +1232,126 @@ SELECT '{[6,7)}' <@ '{[1,5), [6,9)}'::nummultirange;
t t
(1 row) (1 row)
SELECT nummultirange(numrange(1,2)) <@ numrange(null,null);
?column?
----------
t
(1 row)
SELECT nummultirange(numrange(null,2)) <@ numrange(null,null);
?column?
----------
t
(1 row)
SELECT nummultirange(numrange(2,null)) <@ numrange(null,null);
?column?
----------
t
(1 row)
SELECT nummultirange(numrange(null,3)) <@ numrange(null,5);
?column?
----------
t
(1 row)
SELECT nummultirange(numrange(null,8)) <@ numrange(null,5);
?column?
----------
f
(1 row)
SELECT nummultirange(numrange(8,null)) <@ numrange(5,null);
?column?
----------
t
(1 row)
SELECT nummultirange(numrange(3,null)) <@ numrange(5,null);
?column?
----------
f
(1 row)
SELECT nummultirange(numrange(8,9)) <@ numrange(1,5);
?column?
----------
f
(1 row)
SELECT nummultirange(numrange(3,9)) <@ numrange(1,5);
?column?
----------
f
(1 row)
SELECT nummultirange(numrange(1,4)) <@ numrange(1,5);
?column?
----------
t
(1 row)
SELECT nummultirange(numrange(1,5)) <@ numrange(1,5);
?column?
----------
t
(1 row)
SELECT nummultirange(numrange(-4,-2), numrange(1,5)) <@ numrange(1,9);
?column?
----------
f
(1 row)
SELECT nummultirange(numrange(1,5), numrange(8,9)) <@ numrange(1,9);
?column?
----------
t
(1 row)
SELECT nummultirange(numrange(1,5), numrange(6,9)) <@ numrange(1,9);
?column?
----------
t
(1 row)
SELECT nummultirange(numrange(1,5), numrange(6,10)) <@ numrange(1,9);
?column?
----------
f
(1 row)
SELECT '{[1,5)}'::nummultirange <@ '{[1,9)}';
?column?
----------
t
(1 row)
SELECT '{[-4,-2), [1,5)}'::nummultirange <@ '{[1,9)}';
?column?
----------
f
(1 row)
SELECT '{[1,5), [8,9)}'::nummultirange <@ '{[1,9)}';
?column?
----------
t
(1 row)
SELECT '{[1,5), [6,9)}'::nummultirange <@ '{[1,9)}';
?column?
----------
t
(1 row)
SELECT '{[1,5), [6,10)}'::nummultirange <@ '{[1,9)}';
?column?
----------
f
(1 row)
-- overleft -- overleft
SELECT 'empty'::numrange &< nummultirange(); SELECT 'empty'::numrange &< nummultirange();
?column? ?column?
......
...@@ -188,6 +188,26 @@ SELECT '{[1,5), [8,9)}'::nummultirange @> '{[1,5)}'; ...@@ -188,6 +188,26 @@ SELECT '{[1,5), [8,9)}'::nummultirange @> '{[1,5)}';
SELECT '{[1,5), [8,9)}'::nummultirange @> '{[6,7)}'; SELECT '{[1,5), [8,9)}'::nummultirange @> '{[6,7)}';
SELECT '{[1,5), [6,9)}'::nummultirange @> '{[6,7)}'; SELECT '{[1,5), [6,9)}'::nummultirange @> '{[6,7)}';
select '{(10,20),(30,40),(50,60)}'::nummultirange @> '(52,56)'::numrange; select '{(10,20),(30,40),(50,60)}'::nummultirange @> '(52,56)'::numrange;
SELECT numrange(null,null) @> nummultirange(numrange(1,2));
SELECT numrange(null,null) @> nummultirange(numrange(null,2));
SELECT numrange(null,null) @> nummultirange(numrange(2,null));
SELECT numrange(null,5) @> nummultirange(numrange(null,3));
SELECT numrange(null,5) @> nummultirange(numrange(null,8));
SELECT numrange(5,null) @> nummultirange(numrange(8,null));
SELECT numrange(5,null) @> nummultirange(numrange(3,null));
SELECT numrange(1,5) @> nummultirange(numrange(8,9));
SELECT numrange(1,5) @> nummultirange(numrange(3,9));
SELECT numrange(1,5) @> nummultirange(numrange(1,4));
SELECT numrange(1,5) @> nummultirange(numrange(1,5));
SELECT numrange(1,9) @> nummultirange(numrange(-4,-2), numrange(1,5));
SELECT numrange(1,9) @> nummultirange(numrange(1,5), numrange(8,9));
SELECT numrange(1,9) @> nummultirange(numrange(1,5), numrange(6,9));
SELECT numrange(1,9) @> nummultirange(numrange(1,5), numrange(6,10));
SELECT '{[1,9)}' @> '{[1,5)}'::nummultirange;
SELECT '{[1,9)}' @> '{[-4,-2), [1,5)}'::nummultirange;
SELECT '{[1,9)}' @> '{[1,5), [8,9)}'::nummultirange;
SELECT '{[1,9)}' @> '{[1,5), [6,9)}'::nummultirange;
SELECT '{[1,9)}' @> '{[1,5), [6,10)}'::nummultirange;
-- is contained by -- is contained by
SELECT nummultirange() <@ nummultirange(); SELECT nummultirange() <@ nummultirange();
...@@ -212,6 +232,26 @@ SELECT '{[1,5)}' <@ '{[-4,-2), [1,5)}'::nummultirange; ...@@ -212,6 +232,26 @@ SELECT '{[1,5)}' <@ '{[-4,-2), [1,5)}'::nummultirange;
SELECT '{[1,5)}' <@ '{[1,5), [8,9)}'::nummultirange; SELECT '{[1,5)}' <@ '{[1,5), [8,9)}'::nummultirange;
SELECT '{[6,7)}' <@ '{[1,5), [8,9)}'::nummultirange; SELECT '{[6,7)}' <@ '{[1,5), [8,9)}'::nummultirange;
SELECT '{[6,7)}' <@ '{[1,5), [6,9)}'::nummultirange; SELECT '{[6,7)}' <@ '{[1,5), [6,9)}'::nummultirange;
SELECT nummultirange(numrange(1,2)) <@ numrange(null,null);
SELECT nummultirange(numrange(null,2)) <@ numrange(null,null);
SELECT nummultirange(numrange(2,null)) <@ numrange(null,null);
SELECT nummultirange(numrange(null,3)) <@ numrange(null,5);
SELECT nummultirange(numrange(null,8)) <@ numrange(null,5);
SELECT nummultirange(numrange(8,null)) <@ numrange(5,null);
SELECT nummultirange(numrange(3,null)) <@ numrange(5,null);
SELECT nummultirange(numrange(8,9)) <@ numrange(1,5);
SELECT nummultirange(numrange(3,9)) <@ numrange(1,5);
SELECT nummultirange(numrange(1,4)) <@ numrange(1,5);
SELECT nummultirange(numrange(1,5)) <@ numrange(1,5);
SELECT nummultirange(numrange(-4,-2), numrange(1,5)) <@ numrange(1,9);
SELECT nummultirange(numrange(1,5), numrange(8,9)) <@ numrange(1,9);
SELECT nummultirange(numrange(1,5), numrange(6,9)) <@ numrange(1,9);
SELECT nummultirange(numrange(1,5), numrange(6,10)) <@ numrange(1,9);
SELECT '{[1,5)}'::nummultirange <@ '{[1,9)}';
SELECT '{[-4,-2), [1,5)}'::nummultirange <@ '{[1,9)}';
SELECT '{[1,5), [8,9)}'::nummultirange <@ '{[1,9)}';
SELECT '{[1,5), [6,9)}'::nummultirange <@ '{[1,9)}';
SELECT '{[1,5), [6,10)}'::nummultirange <@ '{[1,9)}';
-- overleft -- overleft
SELECT 'empty'::numrange &< nummultirange(); SELECT 'empty'::numrange &< nummultirange();
......
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