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

850 {
851  return make_multirange(mltrngtypoid, rangetyp, 0, NULL);
852 }
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 647 of file multirangetypes.c.

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

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

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

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

1710 {
1711  if (MultirangeIsEmpty(mr))
1712  return false;
1713 
1714  return multirange_bsearch_match(rangetyp, mr, &val,
1716 }
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 2267 of file multirangetypes.c.

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

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

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

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

748 {
749  uint32 offset;
750  uint8 flags;
751  Pointer ptr;
752  int16 typlen = rangetyp->rngelemtype->typlen;
753  char typalign = rangetyp->rngelemtype->typalign;
754  bool typbyval = rangetyp->rngelemtype->typbyval;
755  Datum lbound;
756  Datum ubound;
757 
758  Assert(i < multirange->rangeCount);
759 
760  offset = multirange_get_bounds_offset(multirange, i);
761  flags = MultirangeGetFlagsPtr(multirange)[i];
762  ptr = MultirangeGetBoundariesPtr(multirange, typalign) + offset;
763 
764  /* multirange can't contain empty ranges */
765  Assert((flags & RANGE_EMPTY) == 0);
766 
767  /* fetch lower bound, if any */
768  if (RANGE_HAS_LBOUND(flags))
769  {
770  /* att_align_pointer cannot be necessary here */
771  lbound = fetch_att(ptr, typbyval, typlen);
772  ptr = (Pointer) att_addlength_pointer(ptr, typlen, ptr);
773  }
774  else
775  lbound = (Datum) 0;
776 
777  /* fetch upper bound, if any */
778  if (RANGE_HAS_UBOUND(flags))
779  {
780  ptr = (Pointer) att_align_pointer(ptr, typalign, typlen, ptr);
781  ubound = fetch_att(ptr, typbyval, typlen);
782  /* no need for att_addlength_pointer */
783  }
784  else
785  ubound = (Datum) 0;
786 
787  /* emit results */
788  lower->val = lbound;
789  lower->infinite = (flags & RANGE_LB_INF) != 0;
790  lower->inclusive = (flags & RANGE_LB_INC) != 0;
791  lower->lower = true;
792 
793  upper->val = ubound;
794  upper->infinite = (flags & RANGE_UB_INF) != 0;
795  upper->inclusive = (flags & RANGE_UB_INC) != 0;
796  upper->lower = false;
797 }
unsigned int uint32
Definition: c.h:490
signed short int16
Definition: c.h:477
char * Pointer
Definition: c.h:467
unsigned char uint8
Definition: c.h:488
#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 696 of file multirangetypes.c.

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

550 {
551  TypeCacheEntry *typcache = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
552 
553  if (typcache == NULL ||
554  typcache->type_id != mltrngtypid)
555  {
556  typcache = lookup_type_cache(mltrngtypid, TYPECACHE_MULTIRANGE_INFO);
557  if (typcache->rngtype == NULL)
558  elog(ERROR, "type %u is not a multirange type", mltrngtypid);
559  fcinfo->flinfo->fn_extra = (void *) typcache;
560  }
561 
562  return typcache;
563 }
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: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 803 of file multirangetypes.c.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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