PostgreSQL Source Code  git master
multirangetypes.h File Reference
#include "utils/rangetypes.h"
#include "utils/typcache.h"
Include dependency graph for multirangetypes.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  MultirangeType
 

Macros

#define MultirangeTypeGetOid(mr)   ((mr)->multirangetypid)
 
#define MultirangeIsEmpty(mr)   ((mr)->rangeCount == 0)
 
#define DatumGetMultirangeTypeP(X)   ((MultirangeType *) PG_DETOAST_DATUM(X))
 
#define DatumGetMultirangeTypePCopy(X)   ((MultirangeType *) PG_DETOAST_DATUM_COPY(X))
 
#define MultirangeTypePGetDatum(X)   PointerGetDatum(X)
 
#define PG_GETARG_MULTIRANGE_P(n)   DatumGetMultirangeTypeP(PG_GETARG_DATUM(n))
 
#define PG_GETARG_MULTIRANGE_P_COPY(n)   DatumGetMultirangeTypePCopy(PG_GETARG_DATUM(n))
 
#define PG_RETURN_MULTIRANGE_P(x)   return MultirangeTypePGetDatum(x)
 

Functions

bool multirange_eq_internal (TypeCacheEntry *rangetyp, const MultirangeType *mr1, const MultirangeType *mr2)
 
bool multirange_ne_internal (TypeCacheEntry *rangetyp, const MultirangeType *mr1, const MultirangeType *mr2)
 
bool multirange_contains_elem_internal (TypeCacheEntry *rangetyp, const MultirangeType *mr, Datum elem)
 
bool multirange_contains_range_internal (TypeCacheEntry *rangetyp, const MultirangeType *mr, const RangeType *r)
 
bool range_contains_multirange_internal (TypeCacheEntry *rangetyp, const RangeType *r, const MultirangeType *mr)
 
bool multirange_contains_multirange_internal (TypeCacheEntry *rangetyp, const MultirangeType *mr1, const MultirangeType *mr2)
 
bool range_overlaps_multirange_internal (TypeCacheEntry *rangetyp, const RangeType *r, const MultirangeType *mr)
 
bool multirange_overlaps_multirange_internal (TypeCacheEntry *rangetyp, const MultirangeType *mr1, const MultirangeType *mr2)
 
bool range_overleft_multirange_internal (TypeCacheEntry *rangetyp, const RangeType *r, const MultirangeType *mr)
 
bool range_overright_multirange_internal (TypeCacheEntry *rangetyp, const RangeType *r, const MultirangeType *mr)
 
bool range_before_multirange_internal (TypeCacheEntry *rangetyp, const RangeType *r, const MultirangeType *mr)
 
bool range_after_multirange_internal (TypeCacheEntry *rangetyp, const RangeType *r, const MultirangeType *mr)
 
bool range_adjacent_multirange_internal (TypeCacheEntry *rangetyp, const RangeType *r, const MultirangeType *mr)
 
bool multirange_before_multirange_internal (TypeCacheEntry *rangetyp, const MultirangeType *mr1, const MultirangeType *mr2)
 
MultirangeTypemultirange_minus_internal (Oid mltrngtypoid, TypeCacheEntry *rangetyp, int32 range_count1, RangeType **ranges1, int32 range_count2, RangeType **ranges2)
 
MultirangeTypemultirange_intersect_internal (Oid mltrngtypoid, TypeCacheEntry *rangetyp, int32 range_count1, RangeType **ranges1, int32 range_count2, RangeType **ranges2)
 
TypeCacheEntrymultirange_get_typcache (FunctionCallInfo fcinfo, Oid mltrngtypid)
 
void multirange_deserialize (TypeCacheEntry *rangetyp, const MultirangeType *range, int32 *range_count, RangeType ***ranges)
 
MultirangeTypemake_multirange (Oid mltrngtypoid, TypeCacheEntry *typcache, int32 range_count, RangeType **ranges)
 
MultirangeTypemake_empty_multirange (Oid mltrngtypoid, TypeCacheEntry *rangetyp)
 
void multirange_get_bounds (TypeCacheEntry *rangetyp, const MultirangeType *multirange, uint32 i, RangeBound *lower, RangeBound *upper)
 
RangeTypemultirange_get_range (TypeCacheEntry *rangetyp, const MultirangeType *multirange, int i)
 
RangeTypemultirange_get_union_range (TypeCacheEntry *rangetyp, const MultirangeType *mr)
 

Macro Definition Documentation

◆ DatumGetMultirangeTypeP

#define DatumGetMultirangeTypeP (   X)    ((MultirangeType *) PG_DETOAST_DATUM(X))

Definition at line 47 of file multirangetypes.h.

◆ DatumGetMultirangeTypePCopy

#define DatumGetMultirangeTypePCopy (   X)    ((MultirangeType *) PG_DETOAST_DATUM_COPY(X))

Definition at line 48 of file multirangetypes.h.

◆ MultirangeIsEmpty

#define MultirangeIsEmpty (   mr)    ((mr)->rangeCount == 0)

Definition at line 42 of file multirangetypes.h.

◆ MultirangeTypeGetOid

#define MultirangeTypeGetOid (   mr)    ((mr)->multirangetypid)

Definition at line 41 of file multirangetypes.h.

◆ MultirangeTypePGetDatum

#define MultirangeTypePGetDatum (   X)    PointerGetDatum(X)

Definition at line 49 of file multirangetypes.h.

◆ PG_GETARG_MULTIRANGE_P

#define PG_GETARG_MULTIRANGE_P (   n)    DatumGetMultirangeTypeP(PG_GETARG_DATUM(n))

Definition at line 50 of file multirangetypes.h.

◆ PG_GETARG_MULTIRANGE_P_COPY

#define PG_GETARG_MULTIRANGE_P_COPY (   n)    DatumGetMultirangeTypePCopy(PG_GETARG_DATUM(n))

Definition at line 51 of file multirangetypes.h.

◆ PG_RETURN_MULTIRANGE_P

#define PG_RETURN_MULTIRANGE_P (   x)    return MultirangeTypePGetDatum(x)

Definition at line 52 of file multirangetypes.h.

Function Documentation

◆ make_empty_multirange()

MultirangeType* make_empty_multirange ( Oid  mltrngtypoid,
TypeCacheEntry rangetyp 
)

Definition at line 843 of file multirangetypes.c.

844 {
845  return make_multirange(mltrngtypoid, rangetyp, 0, NULL);
846 }
MultirangeType * make_multirange(Oid mltrngtypoid, TypeCacheEntry *rangetyp, int32 range_count, RangeType **ranges)

References make_multirange().

Referenced by multirange_intersect().

◆ make_multirange()

MultirangeType* make_multirange ( Oid  mltrngtypoid,
TypeCacheEntry typcache,
int32  range_count,
RangeType **  ranges 
)

Definition at line 641 of file multirangetypes.c.

643 {
644  MultirangeType *multirange;
645  Size size;
646 
647  /* Sort and merge input ranges. */
648  range_count = multirange_canonicalize(rangetyp, range_count, ranges);
649 
650  /* Note: zero-fill is required here, just as in heap tuples */
651  size = multirange_size_estimate(rangetyp, range_count, ranges);
652  multirange = palloc0(size);
653  SET_VARSIZE(multirange, size);
654 
655  /* Now fill in the datum */
656  multirange->multirangetypid = mltrngtypoid;
657  multirange->rangeCount = range_count;
658 
659  write_multirange_data(multirange, rangetyp, range_count, ranges);
660 
661  return multirange;
662 }
size_t Size
Definition: c.h:540
void * palloc0(Size size)
Definition: mcxt.c:1099
static int32 multirange_canonicalize(TypeCacheEntry *rangetyp, int32 input_range_count, RangeType **ranges)
static Size multirange_size_estimate(TypeCacheEntry *rangetyp, int32 range_count, RangeType **ranges)
static void write_multirange_data(MultirangeType *multirange, TypeCacheEntry *rangetyp, int32 range_count, RangeType **ranges)
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:342

References multirange_canonicalize(), multirange_size_estimate(), MultirangeType::multirangetypid, palloc0(), MultirangeType::rangeCount, SET_VARSIZE, and write_multirange_data().

Referenced by make_empty_multirange(), multirange_constructor0(), multirange_constructor1(), multirange_constructor2(), multirange_in(), multirange_intersect_internal(), multirange_minus_internal(), multirange_recv(), multirange_union(), multirangesel(), and range_agg_finalfn().

◆ multirange_before_multirange_internal()

bool multirange_before_multirange_internal ( TypeCacheEntry rangetyp,
const MultirangeType mr1,
const MultirangeType mr2 
)

Definition at line 2419 of file multirangetypes.c.

2422 {
2423  RangeBound lower1,
2424  upper1,
2425  lower2,
2426  upper2;
2427 
2428  if (MultirangeIsEmpty(mr1) || MultirangeIsEmpty(mr2))
2429  return false;
2430 
2431  multirange_get_bounds(rangetyp, mr1, mr1->rangeCount - 1,
2432  &lower1, &upper1);
2433  multirange_get_bounds(rangetyp, mr2, 0,
2434  &lower2, &upper2);
2435 
2436  return (range_cmp_bounds(rangetyp, &upper1, &lower2) < 0);
2437 }
void multirange_get_bounds(TypeCacheEntry *rangetyp, const MultirangeType *multirange, uint32 i, RangeBound *lower, RangeBound *upper)
#define MultirangeIsEmpty(mr)
int range_cmp_bounds(TypeCacheEntry *typcache, const RangeBound *b1, const RangeBound *b2)
Definition: rangetypes.c:1924

References multirange_get_bounds(), MultirangeIsEmpty, range_cmp_bounds(), and MultirangeType::rangeCount.

Referenced by multirange_after_multirange(), and multirange_before_multirange().

◆ multirange_contains_elem_internal()

bool multirange_contains_elem_internal ( TypeCacheEntry rangetyp,
const MultirangeType mr,
Datum  elem 
)

Definition at line 1702 of file multirangetypes.c.

1704 {
1705  if (MultirangeIsEmpty(mr))
1706  return false;
1707 
1708  return multirange_bsearch_match(rangetyp, mr, &val,
1710 }
long val
Definition: informix.c:664
static bool multirange_bsearch_match(TypeCacheEntry *typcache, const MultirangeType *mr, void *key, multirange_bsearch_comparison cmp_func)
static int multirange_elem_bsearch_comparison(TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper, void *key, bool *match)

References multirange_bsearch_match(), multirange_elem_bsearch_comparison(), MultirangeIsEmpty, and val.

Referenced by elem_contained_by_multirange(), and multirange_contains_elem().

◆ multirange_contains_multirange_internal()

bool multirange_contains_multirange_internal ( TypeCacheEntry rangetyp,
const MultirangeType mr1,
const MultirangeType mr2 
)

Definition at line 2261 of file multirangetypes.c.

2264 {
2265  int32 range_count1 = mr1->rangeCount;
2266  int32 range_count2 = mr2->rangeCount;
2267  int i1,
2268  i2;
2269  RangeBound lower1,
2270  upper1,
2271  lower2,
2272  upper2;
2273 
2274  /*
2275  * We follow the same logic for empties as ranges: - an empty multirange
2276  * contains an empty range/multirange. - an empty multirange can't contain
2277  * any other range/multirange. - an empty multirange is contained by any
2278  * other range/multirange.
2279  */
2280 
2281  if (range_count2 == 0)
2282  return true;
2283  if (range_count1 == 0)
2284  return false;
2285 
2286  /*
2287  * Every range in mr2 must be contained by some range in mr1. To avoid
2288  * O(n^2) we walk through both ranges in tandem.
2289  */
2290  i1 = 0;
2291  multirange_get_bounds(rangetyp, mr1, i1, &lower1, &upper1);
2292  for (i2 = 0; i2 < range_count2; i2++)
2293  {
2294  multirange_get_bounds(rangetyp, mr2, i2, &lower2, &upper2);
2295 
2296  /* Discard r1s while r1 << r2 */
2297  while (range_cmp_bounds(rangetyp, &upper1, &lower2) < 0)
2298  {
2299  if (++i1 >= range_count1)
2300  return false;
2301  multirange_get_bounds(rangetyp, mr1, i1, &lower1, &upper1);
2302  }
2303 
2304  /*
2305  * If r1 @> r2, go to the next r2, otherwise return false (since every
2306  * r1[n] and r1[n+1] must have a gap). Note this will give weird
2307  * answers if you don't canonicalize, e.g. with a custom
2308  * int2multirange {[1,1], [2,2]} there is a "gap". But that is
2309  * consistent with other range operators, e.g. '[1,1]'::int2range -|-
2310  * '[2,2]'::int2range is false.
2311  */
2312  if (!range_bounds_contains(rangetyp, &lower1, &upper1,
2313  &lower2, &upper2))
2314  return false;
2315  }
2316 
2317  /* All ranges in mr2 are satisfied */
2318  return true;
2319 }
signed int int32
Definition: c.h:429
static bool range_bounds_contains(TypeCacheEntry *typcache, RangeBound *lower1, RangeBound *upper1, RangeBound *lower2, RangeBound *upper2)

References multirange_get_bounds(), range_bounds_contains(), range_cmp_bounds(), and MultirangeType::rangeCount.

Referenced by multirange_contained_by_multirange(), and multirange_contains_multirange().

◆ multirange_contains_range_internal()

bool multirange_contains_range_internal ( TypeCacheEntry rangetyp,
const MultirangeType mr,
const RangeType r 
)

Definition at line 1796 of file multirangetypes.c.

1799 {
1800  RangeBound bounds[2];
1801  bool empty;
1802 
1803  /*
1804  * Every multirange contains an infinite number of empty ranges, even an
1805  * empty one.
1806  */
1807  if (RangeIsEmpty(r))
1808  return true;
1809 
1810  if (MultirangeIsEmpty(mr))
1811  return false;
1812 
1813  range_deserialize(rangetyp, r, &bounds[0], &bounds[1], &empty);
1814  Assert(!empty);
1815 
1816  return multirange_bsearch_match(rangetyp, mr, bounds,
1818 }
Assert(fmt[strlen(fmt) - 1] !='\n')
static int multirange_range_contains_bsearch_comparison(TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper, void *key, bool *match)
void range_deserialize(TypeCacheEntry *typcache, const RangeType *range, RangeBound *lower, RangeBound *upper, bool *empty)
Definition: rangetypes.c:1788
#define RangeIsEmpty(r)
Definition: rangetypes.h:55

References Assert(), multirange_bsearch_match(), multirange_range_contains_bsearch_comparison(), MultirangeIsEmpty, range_deserialize(), and RangeIsEmpty.

Referenced by multirange_contains_range(), range_contained_by_multirange(), and range_gist_consistent_leaf_multirange().

◆ multirange_deserialize()

void multirange_deserialize ( TypeCacheEntry rangetyp,
const MultirangeType range,
int32 range_count,
RangeType ***  ranges 
)

Definition at line 821 of file multirangetypes.c.

824 {
825  *range_count = multirange->rangeCount;
826 
827  /* Convert each ShortRangeType into a RangeType */
828  if (*range_count > 0)
829  {
830  int i;
831 
832  *ranges = palloc(*range_count * sizeof(RangeType *));
833  for (i = 0; i < *range_count; i++)
834  (*ranges)[i] = multirange_get_range(rangetyp, multirange, i);
835  }
836  else
837  {
838  *ranges = NULL;
839  }
840 }
int i
Definition: isn.c:73
void * palloc(Size size)
Definition: mcxt.c:1068
RangeType * multirange_get_range(TypeCacheEntry *rangetyp, const MultirangeType *multirange, int i)

References i, multirange_get_range(), palloc(), and MultirangeType::rangeCount.

Referenced by multirange_agg_transfn(), multirange_intersect(), multirange_intersect_agg_transfn(), multirange_minus(), multirange_out(), multirange_send(), and multirange_union().

◆ multirange_eq_internal()

bool multirange_eq_internal ( TypeCacheEntry rangetyp,
const MultirangeType mr1,
const MultirangeType mr2 
)

Definition at line 1859 of file multirangetypes.c.

1862 {
1863  int32 range_count_1;
1864  int32 range_count_2;
1865  int32 i;
1866  RangeBound lower1,
1867  upper1,
1868  lower2,
1869  upper2;
1870 
1871  /* Different types should be prevented by ANYMULTIRANGE matching rules */
1872  if (MultirangeTypeGetOid(mr1) != MultirangeTypeGetOid(mr2))
1873  elog(ERROR, "multirange types do not match");
1874 
1875  range_count_1 = mr1->rangeCount;
1876  range_count_2 = mr2->rangeCount;
1877 
1878  if (range_count_1 != range_count_2)
1879  return false;
1880 
1881  for (i = 0; i < range_count_1; i++)
1882  {
1883  multirange_get_bounds(rangetyp, mr1, i, &lower1, &upper1);
1884  multirange_get_bounds(rangetyp, mr2, i, &lower2, &upper2);
1885 
1886  if (range_cmp_bounds(rangetyp, &lower1, &lower2) != 0 ||
1887  range_cmp_bounds(rangetyp, &upper1, &upper2) != 0)
1888  return false;
1889  }
1890 
1891  return true;
1892 }
#define ERROR
Definition: elog.h:33
#define elog(elevel,...)
Definition: elog.h:218
#define MultirangeTypeGetOid(mr)

References elog, ERROR, i, multirange_get_bounds(), MultirangeTypeGetOid, range_cmp_bounds(), and MultirangeType::rangeCount.

Referenced by multirange_eq(), and multirange_ne_internal().

◆ multirange_get_bounds()

void multirange_get_bounds ( TypeCacheEntry rangetyp,
const MultirangeType multirange,
uint32  i,
RangeBound lower,
RangeBound upper 
)

Definition at line 739 of file multirangetypes.c.

742 {
743  uint32 offset;
744  uint8 flags;
745  Pointer ptr;
746  int16 typlen = rangetyp->rngelemtype->typlen;
747  char typalign = rangetyp->rngelemtype->typalign;
748  bool typbyval = rangetyp->rngelemtype->typbyval;
749  Datum lbound;
750  Datum ubound;
751 
752  Assert(i < multirange->rangeCount);
753 
754  offset = multirange_get_bounds_offset(multirange, i);
755  flags = MultirangeGetFlagsPtr(multirange)[i];
756  ptr = MultirangeGetBoundariesPtr(multirange, typalign) + offset;
757 
758  /* multirange can't contain empty ranges */
759  Assert((flags & RANGE_EMPTY) == 0);
760 
761  /* fetch lower bound, if any */
762  if (RANGE_HAS_LBOUND(flags))
763  {
764  /* att_align_pointer cannot be necessary here */
765  lbound = fetch_att(ptr, typbyval, typlen);
766  ptr = (Pointer) att_addlength_pointer(ptr, typlen, ptr);
767  }
768  else
769  lbound = (Datum) 0;
770 
771  /* fetch upper bound, if any */
772  if (RANGE_HAS_UBOUND(flags))
773  {
774  ptr = (Pointer) att_align_pointer(ptr, typalign, typlen, ptr);
775  ubound = fetch_att(ptr, typbyval, typlen);
776  /* no need for att_addlength_pointer */
777  }
778  else
779  ubound = (Datum) 0;
780 
781  /* emit results */
782  lower->val = lbound;
783  lower->infinite = (flags & RANGE_LB_INF) != 0;
784  lower->inclusive = (flags & RANGE_LB_INC) != 0;
785  lower->lower = true;
786 
787  upper->val = ubound;
788  upper->infinite = (flags & RANGE_UB_INF) != 0;
789  upper->inclusive = (flags & RANGE_UB_INC) != 0;
790  upper->lower = false;
791 }
unsigned int uint32
Definition: c.h:441
signed short int16
Definition: c.h:428
char * Pointer
Definition: c.h:418
unsigned char uint8
Definition: c.h:439
#define MultirangeGetFlagsPtr(mr)
static uint32 multirange_get_bounds_offset(const MultirangeType *multirange, int32 i)
#define MultirangeGetBoundariesPtr(mr, align)
Datum lower(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:48
Datum upper(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:79
char typalign
Definition: pg_type.h:176
uintptr_t Datum
Definition: postgres.h:411
#define RANGE_HAS_UBOUND(flags)
Definition: rangetypes.h:51
#define RANGE_UB_INC
Definition: rangetypes.h:40
#define RANGE_LB_INC
Definition: rangetypes.h:39
#define RANGE_UB_INF
Definition: rangetypes.h:42
#define RANGE_EMPTY
Definition: rangetypes.h:38
#define RANGE_HAS_LBOUND(flags)
Definition: rangetypes.h:47
#define RANGE_LB_INF
Definition: rangetypes.h:41
char typalign
Definition: typcache.h:41
struct TypeCacheEntry * rngelemtype
Definition: typcache.h:98
bool typbyval
Definition: typcache.h:40
int16 typlen
Definition: typcache.h:39
#define att_align_pointer(cur_offset, attalign, attlen, attptr)
Definition: tupmacs.h:126
#define att_addlength_pointer(cur_offset, attlen, attptr)
Definition: tupmacs.h:176
#define fetch_att(T, attbyval, attlen)
Definition: tupmacs.h:75

References Assert(), att_addlength_pointer, att_align_pointer, fetch_att, i, lower(), multirange_get_bounds_offset(), MultirangeGetBoundariesPtr, MultirangeGetFlagsPtr, RANGE_EMPTY, RANGE_HAS_LBOUND, RANGE_HAS_UBOUND, RANGE_LB_INC, RANGE_LB_INF, RANGE_UB_INC, RANGE_UB_INF, TypeCacheEntry::rngelemtype, typalign, TypeCacheEntry::typalign, TypeCacheEntry::typbyval, TypeCacheEntry::typlen, and upper().

Referenced by calc_hist_selectivity(), compute_range_stats(), hash_multirange(), hash_multirange_extended(), multirange_adjacent_multirange(), multirange_before_multirange_internal(), multirange_bsearch_match(), multirange_cmp(), multirange_contains_multirange_internal(), multirange_eq_internal(), multirange_get_union_range(), multirange_lower(), multirange_lower_inc(), multirange_lower_inf(), multirange_overlaps_multirange_internal(), multirange_overleft_multirange(), multirange_overleft_range(), multirange_overright_multirange(), multirange_overright_range(), multirange_union_range_equal(), multirange_upper(), multirange_upper_inc(), multirange_upper_inf(), range_adjacent_multirange_internal(), range_after_multirange_internal(), range_before_multirange_internal(), range_contains_multirange_internal(), range_merge_from_multirange(), range_overleft_multirange_internal(), and range_overright_multirange_internal().

◆ multirange_get_range()

RangeType* multirange_get_range ( TypeCacheEntry rangetyp,
const MultirangeType multirange,
int  i 
)

Definition at line 690 of file multirangetypes.c.

692 {
693  uint32 offset;
694  uint8 flags;
695  Pointer begin,
696  ptr;
697  int16 typlen = rangetyp->rngelemtype->typlen;
698  char typalign = rangetyp->rngelemtype->typalign;
699  uint32 len;
700  RangeType *range;
701 
702  Assert(i < multirange->rangeCount);
703 
704  offset = multirange_get_bounds_offset(multirange, i);
705  flags = MultirangeGetFlagsPtr(multirange)[i];
706  ptr = begin = MultirangeGetBoundariesPtr(multirange, typalign) + offset;
707 
708  /*
709  * Calculate the size of bound values. In principle, we could get offset
710  * of the next range bound values and calculate accordingly. But range
711  * bound values are aligned, so we have to walk the values to get the
712  * exact size.
713  */
714  if (RANGE_HAS_LBOUND(flags))
715  ptr = (Pointer) att_addlength_pointer(ptr, typlen, ptr);
716  if (RANGE_HAS_UBOUND(flags))
717  {
718  ptr = (Pointer) att_align_pointer(ptr, typalign, typlen, ptr);
719  ptr = (Pointer) att_addlength_pointer(ptr, typlen, ptr);
720  }
721  len = (ptr - begin) + sizeof(RangeType) + sizeof(uint8);
722 
723  range = palloc0(len);
725  range->rangetypid = rangetyp->type_id;
726 
727  memcpy(range + 1, begin, ptr - begin);
728  *((uint8 *) (range + 1) + (ptr - begin)) = flags;
729 
730  return range;
731 }
const void size_t len
static struct cvec * range(struct vars *v, chr a, chr b, int cases)
Definition: regc_locale.c:412

References Assert(), att_addlength_pointer, att_align_pointer, i, len, multirange_get_bounds_offset(), MultirangeGetBoundariesPtr, MultirangeGetFlagsPtr, palloc0(), range(), RANGE_HAS_LBOUND, RANGE_HAS_UBOUND, TypeCacheEntry::rngelemtype, SET_VARSIZE, typalign, TypeCacheEntry::typalign, TypeCacheEntry::type_id, and TypeCacheEntry::typlen.

Referenced by multirange_deserialize(), multirange_unnest(), and range_merge_from_multirange().

◆ multirange_get_typcache()

TypeCacheEntry* multirange_get_typcache ( FunctionCallInfo  fcinfo,
Oid  mltrngtypid 
)

Definition at line 543 of file multirangetypes.c.

544 {
545  TypeCacheEntry *typcache = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
546 
547  if (typcache == NULL ||
548  typcache->type_id != mltrngtypid)
549  {
550  typcache = lookup_type_cache(mltrngtypid, TYPECACHE_MULTIRANGE_INFO);
551  if (typcache->rngtype == NULL)
552  elog(ERROR, "type %u is not a multirange type", mltrngtypid);
553  fcinfo->flinfo->fn_extra = (void *) typcache;
554  }
555 
556  return typcache;
557 }
void * fn_extra
Definition: fmgr.h:64
FmgrInfo * flinfo
Definition: fmgr.h:87
struct TypeCacheEntry * rngtype
Definition: typcache.h:107
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:339
#define TYPECACHE_MULTIRANGE_INFO
Definition: typcache.h:152

References elog, ERROR, FunctionCallInfoBaseData::flinfo, FmgrInfo::fn_extra, if(), lookup_type_cache(), TypeCacheEntry::rngtype, TypeCacheEntry::type_id, and TYPECACHE_MULTIRANGE_INFO.

Referenced by elem_contained_by_multirange(), hash_multirange(), hash_multirange_extended(), multirange_adjacent_multirange(), multirange_adjacent_range(), multirange_after_multirange(), multirange_after_range(), multirange_agg_transfn(), multirange_before_multirange(), multirange_before_range(), multirange_cmp(), multirange_constructor0(), multirange_constructor1(), multirange_constructor2(), multirange_contained_by_multirange(), multirange_contained_by_range(), multirange_contains_elem(), multirange_contains_multirange(), multirange_contains_range(), multirange_eq(), multirange_gist_compress(), multirange_intersect(), multirange_intersect_agg_transfn(), multirange_lower(), multirange_lower_inc(), multirange_lower_inf(), multirange_minus(), multirange_ne(), multirange_overlaps_multirange(), multirange_overlaps_range(), multirange_overleft_multirange(), multirange_overleft_range(), multirange_overright_multirange(), multirange_overright_range(), multirange_typanalyze(), multirange_union(), multirange_upper(), multirange_upper_inc(), multirange_upper_inf(), multirangesel(), range_adjacent_multirange(), range_after_multirange(), range_agg_finalfn(), range_before_multirange(), range_contained_by_multirange(), range_contains_multirange(), range_merge_from_multirange(), range_overlaps_multirange(), range_overleft_multirange(), and range_overright_multirange().

◆ multirange_get_union_range()

RangeType* multirange_get_union_range ( TypeCacheEntry rangetyp,
const MultirangeType mr 
)

Definition at line 797 of file multirangetypes.c.

799 {
801  upper,
802  tmp;
803 
804  if (MultirangeIsEmpty(mr))
805  return make_empty_range(rangetyp);
806 
807  multirange_get_bounds(rangetyp, mr, 0, &lower, &tmp);
808  multirange_get_bounds(rangetyp, mr, mr->rangeCount - 1, &tmp, &upper);
809 
810  return make_range(rangetyp, &lower, &upper, false);
811 }
RangeType * make_empty_range(TypeCacheEntry *typcache)
Definition: rangetypes.c:2073
RangeType * make_range(TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper, bool empty)
Definition: rangetypes.c:1884

References lower(), make_empty_range(), make_range(), multirange_get_bounds(), MultirangeIsEmpty, MultirangeType::rangeCount, and upper().

Referenced by multirange_gist_compress().

◆ multirange_intersect_internal()

MultirangeType* multirange_intersect_internal ( Oid  mltrngtypoid,
TypeCacheEntry rangetyp,
int32  range_count1,
RangeType **  ranges1,
int32  range_count2,
RangeType **  ranges2 
)

Definition at line 1255 of file multirangetypes.c.

1258 {
1259  RangeType *r1;
1260  RangeType *r2;
1261  RangeType **ranges3;
1262  int32 range_count3;
1263  int32 i1;
1264  int32 i2;
1265 
1266  if (range_count1 == 0 || range_count2 == 0)
1267  return make_multirange(mltrngtypoid, rangetyp, 0, NULL);
1268 
1269  /*-----------------------------------------------
1270  * Worst case is a stitching pattern like this:
1271  *
1272  * mr1: --- --- --- ---
1273  * mr2: --- --- ---
1274  * mr3: - - - - - -
1275  *
1276  * That seems to be range_count1 + range_count2 - 1,
1277  * but one extra won't hurt.
1278  *-----------------------------------------------
1279  */
1280  ranges3 = palloc0((range_count1 + range_count2) * sizeof(RangeType *));
1281  range_count3 = 0;
1282 
1283  /*
1284  * For each range in mr1, keep intersecting until the ranges in mr2 have
1285  * passed it. The parallel progress through mr1 and mr2 is similar to
1286  * multirange_minus_multirange_internal, but we don't have to assign back
1287  * to r1.
1288  */
1289  r2 = ranges2[0];
1290  for (i1 = 0, i2 = 0; i1 < range_count1; i1++)
1291  {
1292  r1 = ranges1[i1];
1293 
1294  /* Discard r2s while r2 << r1 */
1295  while (r2 != NULL && range_before_internal(rangetyp, r2, r1))
1296  {
1297  r2 = ++i2 >= range_count2 ? NULL : ranges2[i2];
1298  }
1299 
1300  while (r2 != NULL)
1301  {
1302  if (range_overlaps_internal(rangetyp, r1, r2))
1303  {
1304  /* Keep the overlapping part */
1305  ranges3[range_count3++] = range_intersect_internal(rangetyp, r1, r2);
1306 
1307  /* If we "used up" all of r2, go to the next one... */
1308  if (range_overleft_internal(rangetyp, r2, r1))
1309  r2 = ++i2 >= range_count2 ? NULL : ranges2[i2];
1310 
1311  /* ...otherwise go to the next r1 */
1312  else
1313  break;
1314  }
1315  else
1316  /* We're past r1, so move to the next one */
1317  break;
1318  }
1319 
1320  /* If we're out of r2s, there can be no more intersections */
1321  if (r2 == NULL)
1322  break;
1323  }
1324 
1325  return make_multirange(mltrngtypoid, rangetyp, range_count3, ranges3);
1326 }
bool range_overlaps_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:823
bool range_before_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:646
bool range_overleft_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:869
RangeType * range_intersect_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:1125

References make_multirange(), palloc0(), range_before_internal(), range_intersect_internal(), range_overlaps_internal(), and range_overleft_internal().

Referenced by multirange_intersect(), and multirange_intersect_agg_transfn().

◆ multirange_minus_internal()

MultirangeType* multirange_minus_internal ( Oid  mltrngtypoid,
TypeCacheEntry rangetyp,
int32  range_count1,
RangeType **  ranges1,
int32  range_count2,
RangeType **  ranges2 
)

Definition at line 1139 of file multirangetypes.c.

1142 {
1143  RangeType *r1;
1144  RangeType *r2;
1145  RangeType **ranges3;
1146  int32 range_count3;
1147  int32 i1;
1148  int32 i2;
1149 
1150  /*
1151  * Worst case: every range in ranges1 makes a different cut to some range
1152  * in ranges2.
1153  */
1154  ranges3 = palloc0((range_count1 + range_count2) * sizeof(RangeType *));
1155  range_count3 = 0;
1156 
1157  /*
1158  * For each range in mr1, keep subtracting until it's gone or the ranges
1159  * in mr2 have passed it. After a subtraction we assign what's left back
1160  * to r1. The parallel progress through mr1 and mr2 is similar to
1161  * multirange_overlaps_multirange_internal.
1162  */
1163  r2 = ranges2[0];
1164  for (i1 = 0, i2 = 0; i1 < range_count1; i1++)
1165  {
1166  r1 = ranges1[i1];
1167 
1168  /* Discard r2s while r2 << r1 */
1169  while (r2 != NULL && range_before_internal(rangetyp, r2, r1))
1170  {
1171  r2 = ++i2 >= range_count2 ? NULL : ranges2[i2];
1172  }
1173 
1174  while (r2 != NULL)
1175  {
1176  if (range_split_internal(rangetyp, r1, r2, &ranges3[range_count3], &r1))
1177  {
1178  /*
1179  * If r2 takes a bite out of the middle of r1, we need two
1180  * outputs
1181  */
1182  range_count3++;
1183  r2 = ++i2 >= range_count2 ? NULL : ranges2[i2];
1184  }
1185  else if (range_overlaps_internal(rangetyp, r1, r2))
1186  {
1187  /*
1188  * If r2 overlaps r1, replace r1 with r1 - r2.
1189  */
1190  r1 = range_minus_internal(rangetyp, r1, r2);
1191 
1192  /*
1193  * If r2 goes past r1, then we need to stay with it, in case
1194  * it hits future r1s. Otherwise we need to keep r1, in case
1195  * future r2s hit it. Since we already subtracted, there's no
1196  * point in using the overright/overleft calls.
1197  */
1198  if (RangeIsEmpty(r1) || range_before_internal(rangetyp, r1, r2))
1199  break;
1200  else
1201  r2 = ++i2 >= range_count2 ? NULL : ranges2[i2];
1202  }
1203  else
1204  {
1205  /*
1206  * This and all future r2s are past r1, so keep them. Also
1207  * assign whatever is left of r1 to the result.
1208  */
1209  break;
1210  }
1211  }
1212 
1213  /*
1214  * Nothing else can remove anything from r1, so keep it. Even if r1 is
1215  * empty here, make_multirange will remove it.
1216  */
1217  ranges3[range_count3++] = r1;
1218  }
1219 
1220  return make_multirange(mltrngtypoid, rangetyp, range_count3, ranges3);
1221 }
bool range_split_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2, RangeType **output1, RangeType **output2)
Definition: rangetypes.c:1164
RangeType * range_minus_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
Definition: rangetypes.c:975

References make_multirange(), palloc0(), range_before_internal(), range_minus_internal(), range_overlaps_internal(), range_split_internal(), and RangeIsEmpty.

Referenced by multirange_minus().

◆ multirange_ne_internal()

bool multirange_ne_internal ( TypeCacheEntry rangetyp,
const MultirangeType mr1,
const MultirangeType mr2 
)

Definition at line 1909 of file multirangetypes.c.

1912 {
1913  return (!multirange_eq_internal(rangetyp, mr1, mr2));
1914 }
bool multirange_eq_internal(TypeCacheEntry *rangetyp, const MultirangeType *mr1, const MultirangeType *mr2)

References multirange_eq_internal().

Referenced by multirange_ne().

◆ multirange_overlaps_multirange_internal()

bool multirange_overlaps_multirange_internal ( TypeCacheEntry rangetyp,
const MultirangeType mr1,
const MultirangeType mr2 
)

Definition at line 2010 of file multirangetypes.c.

2013 {
2014  int32 range_count1;
2015  int32 range_count2;
2016  int32 i1;
2017  int32 i2;
2018  RangeBound lower1,
2019  upper1,
2020  lower2,
2021  upper2;
2022 
2023  /*
2024  * Empties never overlap, even with empties. (This seems strange since
2025  * they *do* contain each other, but we want to follow how ranges work.)
2026  */
2027  if (MultirangeIsEmpty(mr1) || MultirangeIsEmpty(mr2))
2028  return false;
2029 
2030  range_count1 = mr1->rangeCount;
2031  range_count2 = mr2->rangeCount;
2032 
2033  /*
2034  * Every range in mr1 gets a chance to overlap with the ranges in mr2, but
2035  * we can use their ordering to avoid O(n^2). This is similar to
2036  * range_overlaps_multirange where r1 : r2 :: mrr : r, but there if we
2037  * don't find an overlap with r we're done, and here if we don't find an
2038  * overlap with r2 we try the next r2.
2039  */
2040  i1 = 0;
2041  multirange_get_bounds(rangetyp, mr1, i1, &lower1, &upper1);
2042  for (i1 = 0, i2 = 0; i2 < range_count2; i2++)
2043  {
2044  multirange_get_bounds(rangetyp, mr2, i2, &lower2, &upper2);
2045 
2046  /* Discard r1s while r1 << r2 */
2047  while (range_cmp_bounds(rangetyp, &upper1, &lower2) < 0)
2048  {
2049  if (++i1 >= range_count1)
2050  return false;
2051  multirange_get_bounds(rangetyp, mr1, i1, &lower1, &upper1);
2052  }
2053 
2054  /*
2055  * If r1 && r2, we're done, otherwise we failed to find an overlap for
2056  * r2, so go to the next one.
2057  */
2058  if (range_bounds_overlaps(rangetyp, &lower1, &upper1, &lower2, &upper2))
2059  return true;
2060  }
2061 
2062  /* We looked through all of mr2 without finding an overlap */
2063  return false;
2064 }
static bool range_bounds_overlaps(TypeCacheEntry *typcache, RangeBound *lower1, RangeBound *upper1, RangeBound *lower2, RangeBound *upper2)

References multirange_get_bounds(), MultirangeIsEmpty, range_bounds_overlaps(), range_cmp_bounds(), and MultirangeType::rangeCount.

Referenced by multirange_overlaps_multirange().

◆ range_adjacent_multirange_internal()

bool range_adjacent_multirange_internal ( TypeCacheEntry rangetyp,
const RangeType r,
const MultirangeType mr 
)

Definition at line 2466 of file multirangetypes.c.

2469 {
2470  RangeBound lower1,
2471  upper1,
2472  lower2,
2473  upper2;
2474  bool empty;
2475  int32 range_count;
2476 
2477  if (RangeIsEmpty(r) || MultirangeIsEmpty(mr))
2478  return false;
2479 
2480  range_deserialize(rangetyp, r, &lower1, &upper1, &empty);
2481  Assert(!empty);
2482 
2483  range_count = mr->rangeCount;
2484  multirange_get_bounds(rangetyp, mr, 0,
2485  &lower2, &upper2);
2486 
2487  if (bounds_adjacent(rangetyp, upper1, lower2))
2488  return true;
2489 
2490  if (range_count > 1)
2491  multirange_get_bounds(rangetyp, mr, range_count - 1,
2492  &lower2, &upper2);
2493 
2494  if (bounds_adjacent(rangetyp, upper2, lower1))
2495  return true;
2496 
2497  return false;
2498 }
bool bounds_adjacent(TypeCacheEntry *typcache, RangeBound boundA, RangeBound boundB)
Definition: rangetypes.c:739

References Assert(), bounds_adjacent(), multirange_get_bounds(), MultirangeIsEmpty, range_deserialize(), MultirangeType::rangeCount, and RangeIsEmpty.

Referenced by multirange_adjacent_range(), range_adjacent_multirange(), range_gist_consistent_int_multirange(), and range_gist_consistent_leaf_multirange().

◆ range_after_multirange_internal()

bool range_after_multirange_internal ( TypeCacheEntry rangetyp,
const RangeType r,
const MultirangeType mr 
)

Definition at line 2441 of file multirangetypes.c.

2444 {
2445  RangeBound lower1,
2446  upper1,
2447  lower2,
2448  upper2;
2449  bool empty;
2450  int32 range_count;
2451 
2452  if (RangeIsEmpty(r) || MultirangeIsEmpty(mr))
2453  return false;
2454 
2455  range_deserialize(rangetyp, r, &lower1, &upper1, &empty);
2456  Assert(!empty);
2457 
2458  range_count = mr->rangeCount;
2459  multirange_get_bounds(rangetyp, mr, range_count - 1,
2460  &lower2, &upper2);
2461 
2462  return (range_cmp_bounds(rangetyp, &lower1, &upper2) > 0);
2463 }

References Assert(), multirange_get_bounds(), MultirangeIsEmpty, range_cmp_bounds(), range_deserialize(), MultirangeType::rangeCount, and RangeIsEmpty.

Referenced by multirange_before_range(), range_after_multirange(), range_gist_consistent_int_multirange(), and range_gist_consistent_leaf_multirange().

◆ range_before_multirange_internal()

bool range_before_multirange_internal ( TypeCacheEntry rangetyp,
const RangeType r,
const MultirangeType mr 
)

Definition at line 2397 of file multirangetypes.c.

2400 {
2401  RangeBound lower1,
2402  upper1,
2403  lower2,
2404  upper2;
2405  bool empty;
2406 
2407  if (RangeIsEmpty(r) || MultirangeIsEmpty(mr))
2408  return false;
2409 
2410  range_deserialize(rangetyp, r, &lower1, &upper1, &empty);
2411  Assert(!empty);
2412 
2413  multirange_get_bounds(rangetyp, mr, 0, &lower2, &upper2);
2414 
2415  return (range_cmp_bounds(rangetyp, &upper1, &lower2) < 0);
2416 }

References Assert(), multirange_get_bounds(), MultirangeIsEmpty, range_cmp_bounds(), range_deserialize(), and RangeIsEmpty.

Referenced by multirange_after_range(), range_before_multirange(), range_gist_consistent_int_multirange(), and range_gist_consistent_leaf_multirange().

◆ range_contains_multirange_internal()

bool range_contains_multirange_internal ( TypeCacheEntry rangetyp,
const RangeType r,
const MultirangeType mr 
)

Definition at line 1824 of file multirangetypes.c.

1827 {
1828  RangeBound lower1,
1829  upper1,
1830  lower2,
1831  upper2,
1832  tmp;
1833  bool empty;
1834 
1835  /*
1836  * Every range contains an infinite number of empty multiranges, even an
1837  * empty one.
1838  */
1839  if (MultirangeIsEmpty(mr))
1840  return true;
1841 
1842  if (RangeIsEmpty(r))
1843  return false;
1844 
1845  /* Range contains multirange iff it contains its union range. */
1846  range_deserialize(rangetyp, r, &lower1, &upper1, &empty);
1847  Assert(!empty);
1848  multirange_get_bounds(rangetyp, mr, 0, &lower2, &tmp);
1849  multirange_get_bounds(rangetyp, mr, mr->rangeCount - 1, &tmp, &upper2);
1850 
1851  return range_bounds_contains(rangetyp, &lower1, &upper1, &lower2, &upper2);
1852 }

References Assert(), multirange_get_bounds(), MultirangeIsEmpty, range_bounds_contains(), range_deserialize(), MultirangeType::rangeCount, and RangeIsEmpty.

Referenced by multirange_contained_by_range(), range_contains_multirange(), range_gist_consistent_int_multirange(), and range_gist_consistent_leaf_multirange().

◆ range_overlaps_multirange_internal()

bool range_overlaps_multirange_internal ( TypeCacheEntry rangetyp,
const RangeType r,
const MultirangeType mr 
)

Definition at line 1988 of file multirangetypes.c.

1991 {
1992  RangeBound bounds[2];
1993  bool empty;
1994 
1995  /*
1996  * Empties never overlap, even with empties. (This seems strange since
1997  * they *do* contain each other, but we want to follow how ranges work.)
1998  */
1999  if (RangeIsEmpty(r) || MultirangeIsEmpty(mr))
2000  return false;
2001 
2002  range_deserialize(rangetyp, r, &bounds[0], &bounds[1], &empty);
2003  Assert(!empty);
2004 
2005  return multirange_bsearch_match(rangetyp, mr, bounds,
2007 }
static int multirange_range_overlaps_bsearch_comparison(TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper, void *key, bool *match)

References Assert(), multirange_bsearch_match(), multirange_range_overlaps_bsearch_comparison(), MultirangeIsEmpty, range_deserialize(), and RangeIsEmpty.

Referenced by multirange_overlaps_range(), range_gist_consistent_int_multirange(), range_gist_consistent_leaf_multirange(), and range_overlaps_multirange().

◆ range_overleft_multirange_internal()

bool range_overleft_multirange_internal ( TypeCacheEntry rangetyp,
const RangeType r,
const MultirangeType mr 
)

Definition at line 2068 of file multirangetypes.c.

2071 {
2072  RangeBound lower1,
2073  upper1,
2074  lower2,
2075  upper2;
2076  bool empty;
2077 
2078  if (RangeIsEmpty(r) || MultirangeIsEmpty(mr))
2079  PG_RETURN_BOOL(false);
2080 
2081 
2082  range_deserialize(rangetyp, r, &lower1, &upper1, &empty);
2083  Assert(!empty);
2084  multirange_get_bounds(rangetyp, mr, mr->rangeCount - 1,
2085  &lower2, &upper2);
2086 
2087  PG_RETURN_BOOL(range_cmp_bounds(rangetyp, &upper1, &upper2) <= 0);
2088 }
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359

References Assert(), multirange_get_bounds(), MultirangeIsEmpty, PG_RETURN_BOOL, range_cmp_bounds(), range_deserialize(), MultirangeType::rangeCount, and RangeIsEmpty.

Referenced by range_gist_consistent_int_multirange(), range_gist_consistent_leaf_multirange(), and range_overleft_multirange().

◆ range_overright_multirange_internal()

bool range_overright_multirange_internal ( TypeCacheEntry rangetyp,
const RangeType r,
const MultirangeType mr 
)

Definition at line 2153 of file multirangetypes.c.

2156 {
2157  RangeBound lower1,
2158  upper1,
2159  lower2,
2160  upper2;
2161  bool empty;
2162 
2163  if (RangeIsEmpty(r) || MultirangeIsEmpty(mr))
2164  PG_RETURN_BOOL(false);
2165 
2166  range_deserialize(rangetyp, r, &lower1, &upper1, &empty);
2167  Assert(!empty);
2168  multirange_get_bounds(rangetyp, mr, 0, &lower2, &upper2);
2169 
2170  return (range_cmp_bounds(rangetyp, &lower1, &lower2) >= 0);
2171 }

References Assert(), multirange_get_bounds(), MultirangeIsEmpty, PG_RETURN_BOOL, range_cmp_bounds(), range_deserialize(), and RangeIsEmpty.

Referenced by range_gist_consistent_int_multirange(), range_gist_consistent_leaf_multirange(), and range_overright_multirange().