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 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

static MultirangeTypeDatumGetMultirangeTypeP (Datum X)
 
static MultirangeTypeDatumGetMultirangeTypePCopy (Datum X)
 
static Datum MultirangeTypePGetDatum (const MultirangeType *X)
 
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 val)
 
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 *multirange, int32 *range_count, RangeType ***ranges)
 
MultirangeTypemake_multirange (Oid mltrngtypoid, TypeCacheEntry *rangetyp, 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

◆ 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.

◆ PG_GETARG_MULTIRANGE_P

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

Definition at line 65 of file multirangetypes.h.

◆ PG_GETARG_MULTIRANGE_P_COPY

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

Definition at line 66 of file multirangetypes.h.

◆ PG_RETURN_MULTIRANGE_P

#define PG_RETURN_MULTIRANGE_P (   x)    return MultirangeTypePGetDatum(x)

Definition at line 67 of file multirangetypes.h.

Function Documentation

◆ DatumGetMultirangeTypeP()

static MultirangeType* DatumGetMultirangeTypeP ( Datum  X)
inlinestatic

Definition at line 48 of file multirangetypes.h.

49 {
50  return (MultirangeType *) PG_DETOAST_DATUM(X);
51 }
#define PG_DETOAST_DATUM(datum)
Definition: fmgr.h:240

References PG_DETOAST_DATUM.

Referenced by compute_range_stats(), multirange_gist_compress(), multirange_gist_consistent(), multirangesel(), and range_gist_consistent().

◆ DatumGetMultirangeTypePCopy()

static MultirangeType* DatumGetMultirangeTypePCopy ( Datum  X)
inlinestatic

Definition at line 54 of file multirangetypes.h.

55 {
57 }
#define PG_DETOAST_DATUM_COPY(datum)
Definition: fmgr.h:242

References PG_DETOAST_DATUM_COPY.

◆ make_empty_multirange()

MultirangeType* make_empty_multirange ( Oid  mltrngtypoid,
TypeCacheEntry rangetyp 
)

Definition at line 848 of file multirangetypes.c.

849 {
850  return make_multirange(mltrngtypoid, rangetyp, 0, NULL);
851 }
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 rangetyp,
int32  range_count,
RangeType **  ranges 
)

Definition at line 646 of file multirangetypes.c.

648 {
649  MultirangeType *multirange;
650  Size size;
651 
652  /* Sort and merge input ranges. */
653  range_count = multirange_canonicalize(rangetyp, range_count, ranges);
654 
655  /* Note: zero-fill is required here, just as in heap tuples */
656  size = multirange_size_estimate(rangetyp, range_count, ranges);
657  multirange = palloc0(size);
658  SET_VARSIZE(multirange, size);
659 
660  /* Now fill in the datum */
661  multirange->multirangetypid = mltrngtypoid;
662  multirange->rangeCount = range_count;
663 
664  write_multirange_data(multirange, rangetyp, range_count, ranges);
665 
666  return multirange;
667 }
size_t Size
Definition: c.h:605
void * palloc0(Size size)
Definition: mcxt.c:1346
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)
static pg_noinline void Size size
Definition: slab.c:607
#define SET_VARSIZE(PTR, len)
Definition: varatt.h:305

References multirange_canonicalize(), multirange_size_estimate(), MultirangeType::multirangetypid, palloc0(), MultirangeType::rangeCount, SET_VARSIZE, size, 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 2424 of file multirangetypes.c.

2427 {
2428  RangeBound lower1,
2429  upper1,
2430  lower2,
2431  upper2;
2432 
2433  if (MultirangeIsEmpty(mr1) || MultirangeIsEmpty(mr2))
2434  return false;
2435 
2436  multirange_get_bounds(rangetyp, mr1, mr1->rangeCount - 1,
2437  &lower1, &upper1);
2438  multirange_get_bounds(rangetyp, mr2, 0,
2439  &lower2, &upper2);
2440 
2441  return (range_cmp_bounds(rangetyp, &upper1, &lower2) < 0);
2442 }
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:2016

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  val 
)

Definition at line 1707 of file multirangetypes.c.

1709 {
1710  if (MultirangeIsEmpty(mr))
1711  return false;
1712 
1713  return multirange_bsearch_match(rangetyp, mr, &val,
1715 }
long val
Definition: informix.c:670
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 2266 of file multirangetypes.c.

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

1804 {
1805  RangeBound bounds[2];
1806  bool empty;
1807 
1808  /*
1809  * Every multirange contains an infinite number of empty ranges, even an
1810  * empty one.
1811  */
1812  if (RangeIsEmpty(r))
1813  return true;
1814 
1815  if (MultirangeIsEmpty(mr))
1816  return false;
1817 
1818  range_deserialize(rangetyp, r, &bounds[0], &bounds[1], &empty);
1819  Assert(!empty);
1820 
1821  return multirange_bsearch_match(rangetyp, mr, bounds,
1823 }
#define Assert(condition)
Definition: c.h:858
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:1856
#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 multirange,
int32 range_count,
RangeType ***  ranges 
)

Definition at line 826 of file multirangetypes.c.

829 {
830  *range_count = multirange->rangeCount;
831 
832  /* Convert each ShortRangeType into a RangeType */
833  if (*range_count > 0)
834  {
835  int i;
836 
837  *ranges = palloc(*range_count * sizeof(RangeType *));
838  for (i = 0; i < *range_count; i++)
839  (*ranges)[i] = multirange_get_range(rangetyp, multirange, i);
840  }
841  else
842  {
843  *ranges = NULL;
844  }
845 }
int i
Definition: isn.c:73
void * palloc(Size size)
Definition: mcxt.c:1316
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 1864 of file multirangetypes.c.

1867 {
1868  int32 range_count_1;
1869  int32 range_count_2;
1870  int32 i;
1871  RangeBound lower1,
1872  upper1,
1873  lower2,
1874  upper2;
1875 
1876  /* Different types should be prevented by ANYMULTIRANGE matching rules */
1877  if (MultirangeTypeGetOid(mr1) != MultirangeTypeGetOid(mr2))
1878  elog(ERROR, "multirange types do not match");
1879 
1880  range_count_1 = mr1->rangeCount;
1881  range_count_2 = mr2->rangeCount;
1882 
1883  if (range_count_1 != range_count_2)
1884  return false;
1885 
1886  for (i = 0; i < range_count_1; i++)
1887  {
1888  multirange_get_bounds(rangetyp, mr1, i, &lower1, &upper1);
1889  multirange_get_bounds(rangetyp, mr2, i, &lower2, &upper2);
1890 
1891  if (range_cmp_bounds(rangetyp, &lower1, &lower2) != 0 ||
1892  range_cmp_bounds(rangetyp, &upper1, &upper2) != 0)
1893  return false;
1894  }
1895 
1896  return true;
1897 }
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:224
#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 744 of file multirangetypes.c.

747 {
748  uint32 offset;
749  uint8 flags;
750  Pointer ptr;
751  int16 typlen = rangetyp->rngelemtype->typlen;
752  char typalign = rangetyp->rngelemtype->typalign;
753  bool typbyval = rangetyp->rngelemtype->typbyval;
754  Datum lbound;
755  Datum ubound;
756 
757  Assert(i < multirange->rangeCount);
758 
759  offset = multirange_get_bounds_offset(multirange, i);
760  flags = MultirangeGetFlagsPtr(multirange)[i];
761  ptr = MultirangeGetBoundariesPtr(multirange, typalign) + offset;
762 
763  /* multirange can't contain empty ranges */
764  Assert((flags & RANGE_EMPTY) == 0);
765 
766  /* fetch lower bound, if any */
767  if (RANGE_HAS_LBOUND(flags))
768  {
769  /* att_align_pointer cannot be necessary here */
770  lbound = fetch_att(ptr, typbyval, typlen);
771  ptr = (Pointer) att_addlength_pointer(ptr, typlen, ptr);
772  }
773  else
774  lbound = (Datum) 0;
775 
776  /* fetch upper bound, if any */
777  if (RANGE_HAS_UBOUND(flags))
778  {
779  ptr = (Pointer) att_align_pointer(ptr, typalign, typlen, ptr);
780  ubound = fetch_att(ptr, typbyval, typlen);
781  /* no need for att_addlength_pointer */
782  }
783  else
784  ubound = (Datum) 0;
785 
786  /* emit results */
787  lower->val = lbound;
788  lower->infinite = (flags & RANGE_LB_INF) != 0;
789  lower->inclusive = (flags & RANGE_LB_INC) != 0;
790  lower->lower = true;
791 
792  upper->val = ubound;
793  upper->infinite = (flags & RANGE_UB_INF) != 0;
794  upper->inclusive = (flags & RANGE_UB_INC) != 0;
795  upper->lower = false;
796 }
unsigned int uint32
Definition: c.h:506
signed short int16
Definition: c.h:493
char * Pointer
Definition: c.h:483
unsigned char uint8
Definition: c.h:504
#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:49
Datum upper(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:80
char typalign
Definition: pg_type.h:176
uintptr_t Datum
Definition: postgres.h:64
#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:107
#define att_addlength_pointer(cur_offset, attlen, attptr)
Definition: tupmacs.h:157
static Datum fetch_att(const void *T, bool attbyval, int attlen)
Definition: tupmacs.h:52

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 695 of file multirangetypes.c.

697 {
698  uint32 offset;
699  uint8 flags;
700  Pointer begin,
701  ptr;
702  int16 typlen = rangetyp->rngelemtype->typlen;
703  char typalign = rangetyp->rngelemtype->typalign;
704  uint32 len;
705  RangeType *range;
706 
707  Assert(i < multirange->rangeCount);
708 
709  offset = multirange_get_bounds_offset(multirange, i);
710  flags = MultirangeGetFlagsPtr(multirange)[i];
711  ptr = begin = MultirangeGetBoundariesPtr(multirange, typalign) + offset;
712 
713  /*
714  * Calculate the size of bound values. In principle, we could get offset
715  * of the next range bound values and calculate accordingly. But range
716  * bound values are aligned, so we have to walk the values to get the
717  * exact size.
718  */
719  if (RANGE_HAS_LBOUND(flags))
720  ptr = (Pointer) att_addlength_pointer(ptr, typlen, ptr);
721  if (RANGE_HAS_UBOUND(flags))
722  {
723  ptr = (Pointer) att_align_pointer(ptr, typalign, typlen, ptr);
724  ptr = (Pointer) att_addlength_pointer(ptr, typlen, ptr);
725  }
726  len = (ptr - begin) + sizeof(RangeType) + sizeof(uint8);
727 
728  range = palloc0(len);
730  range->rangetypid = rangetyp->type_id;
731 
732  memcpy(range + 1, begin, ptr - begin);
733  *((uint8 *) (range + 1) + (ptr - begin)) = flags;
734 
735  return range;
736 }
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 548 of file multirangetypes.c.

549 {
550  TypeCacheEntry *typcache = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
551 
552  if (typcache == NULL ||
553  typcache->type_id != mltrngtypid)
554  {
555  typcache = lookup_type_cache(mltrngtypid, TYPECACHE_MULTIRANGE_INFO);
556  if (typcache->rngtype == NULL)
557  elog(ERROR, "type %u is not a multirange type", mltrngtypid);
558  fcinfo->flinfo->fn_extra = (void *) typcache;
559  }
560 
561  return typcache;
562 }
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
void * fn_extra
Definition: fmgr.h:64
FmgrInfo * flinfo
Definition: fmgr.h:87
struct TypeCacheEntry * rngtype
Definition: typcache.h:108
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:346
#define TYPECACHE_MULTIRANGE_INFO
Definition: typcache.h:153

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 802 of file multirangetypes.c.

804 {
806  upper,
807  tmp;
808 
809  if (MultirangeIsEmpty(mr))
810  return make_empty_range(rangetyp);
811 
812  multirange_get_bounds(rangetyp, mr, 0, &lower, &tmp);
813  multirange_get_bounds(rangetyp, mr, mr->rangeCount - 1, &tmp, &upper);
814 
815  return make_range(rangetyp, &lower, &upper, false, NULL);
816 }
RangeType * make_range(TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper, bool empty, struct Node *escontext)
Definition: rangetypes.c:1952
RangeType * make_empty_range(TypeCacheEntry *typcache)
Definition: rangetypes.c:2165

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 1260 of file multirangetypes.c.

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

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 1144 of file multirangetypes.c.

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

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 1914 of file multirangetypes.c.

1917 {
1918  return (!multirange_eq_internal(rangetyp, mr1, mr2));
1919 }
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 2015 of file multirangetypes.c.

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

◆ MultirangeTypePGetDatum()

static Datum MultirangeTypePGetDatum ( const MultirangeType X)
inlinestatic

Definition at line 60 of file multirangetypes.h.

61 {
62  return PointerGetDatum(X);
63 }
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322

References PointerGetDatum().

◆ range_adjacent_multirange_internal()

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

Definition at line 2471 of file multirangetypes.c.

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

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 2446 of file multirangetypes.c.

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

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 2402 of file multirangetypes.c.

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

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 1829 of file multirangetypes.c.

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

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 1993 of file multirangetypes.c.

1996 {
1997  RangeBound bounds[2];
1998  bool empty;
1999 
2000  /*
2001  * Empties never overlap, even with empties. (This seems strange since
2002  * they *do* contain each other, but we want to follow how ranges work.)
2003  */
2004  if (RangeIsEmpty(r) || MultirangeIsEmpty(mr))
2005  return false;
2006 
2007  range_deserialize(rangetyp, r, &bounds[0], &bounds[1], &empty);
2008  Assert(!empty);
2009 
2010  return multirange_bsearch_match(rangetyp, mr, bounds,
2012 }
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 2073 of file multirangetypes.c.

2076 {
2077  RangeBound lower1,
2078  upper1,
2079  lower2,
2080  upper2;
2081  bool empty;
2082 
2083  if (RangeIsEmpty(r) || MultirangeIsEmpty(mr))
2084  PG_RETURN_BOOL(false);
2085 
2086 
2087  range_deserialize(rangetyp, r, &lower1, &upper1, &empty);
2088  Assert(!empty);
2089  multirange_get_bounds(rangetyp, mr, mr->rangeCount - 1,
2090  &lower2, &upper2);
2091 
2092  PG_RETURN_BOOL(range_cmp_bounds(rangetyp, &upper1, &upper2) <= 0);
2093 }
#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 2158 of file multirangetypes.c.

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

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().