1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-07 00:36:50 +03:00

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.
This commit is contained in:
Alexander Korotkov
2020-12-29 23:35:33 +03:00
parent a5b81b6f00
commit 4d7684cc75
9 changed files with 381 additions and 3 deletions

View File

@ -1631,6 +1631,18 @@ multirange_contains_range(PG_FUNCTION_ARGS)
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? */
Datum
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));
}
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
* key range using binary search.
@ -1701,6 +1725,42 @@ multirange_contains_range_internal(TypeCacheEntry *typcache, MultirangeType *mr,
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 */

View File

@ -86,6 +86,8 @@ default_multirange_selectivity(Oid operator)
case OID_RANGE_OVERLAPS_MULTIRANGE_OP:
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_MULTIRANGE_OP:
case OID_MULTIRANGE_RANGE_CONTAINED_OP:
@ -224,7 +226,8 @@ multirangesel(PG_FUNCTION_ARGS)
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_LEFT_RANGE_OP ||
operator == OID_MULTIRANGE_OVERLAPS_RIGHT_RANGE_OP ||
@ -248,6 +251,7 @@ multirangesel(PG_FUNCTION_ARGS)
operator == OID_RANGE_OVERLAPS_RIGHT_MULTIRANGE_OP ||
operator == OID_RANGE_LEFT_MULTIRANGE_OP ||
operator == OID_RANGE_RIGHT_MULTIRANGE_OP ||
operator == OID_RANGE_CONTAINS_MULTIRANGE_OP ||
operator == OID_MULTIRANGE_ELEM_CONTAINED_OP ||
operator == OID_MULTIRANGE_RANGE_CONTAINED_OP)
{