PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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

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

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

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

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

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

1711{
1712 if (MultirangeIsEmpty(mr))
1713 return false;
1714
1715 return multirange_bsearch_match(rangetyp, mr, &val,
1717}
long val
Definition: informix.c:689
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}
int32_t int32
Definition: c.h:538
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 1803 of file multirangetypes.c.

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

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

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

749{
750 uint32 offset;
751 uint8 flags;
752 Pointer ptr;
753 int16 typlen = rangetyp->rngelemtype->typlen;
754 char typalign = rangetyp->rngelemtype->typalign;
755 bool typbyval = rangetyp->rngelemtype->typbyval;
756 Datum lbound;
757 Datum ubound;
758
759 Assert(i < multirange->rangeCount);
760
761 offset = multirange_get_bounds_offset(multirange, i);
762 flags = MultirangeGetFlagsPtr(multirange)[i];
763 ptr = MultirangeGetBoundariesPtr(multirange, typalign) + offset;
764
765 /* multirange can't contain empty ranges */
766 Assert((flags & RANGE_EMPTY) == 0);
767
768 /* fetch lower bound, if any */
769 if (RANGE_HAS_LBOUND(flags))
770 {
771 /* att_align_pointer cannot be necessary here */
772 lbound = fetch_att(ptr, typbyval, typlen);
773 ptr = (Pointer) att_addlength_pointer(ptr, typlen, ptr);
774 }
775 else
776 lbound = (Datum) 0;
777
778 /* fetch upper bound, if any */
779 if (RANGE_HAS_UBOUND(flags))
780 {
781 ptr = (Pointer) att_align_pointer(ptr, typalign, typlen, ptr);
782 ubound = fetch_att(ptr, typbyval, typlen);
783 /* no need for att_addlength_pointer */
784 }
785 else
786 ubound = (Datum) 0;
787
788 /* emit results */
789 lower->val = lbound;
790 lower->infinite = (flags & RANGE_LB_INF) != 0;
791 lower->inclusive = (flags & RANGE_LB_INC) != 0;
792 lower->lower = true;
793
794 upper->val = ubound;
795 upper->infinite = (flags & RANGE_UB_INF) != 0;
796 upper->inclusive = (flags & RANGE_UB_INC) != 0;
797 upper->lower = false;
798}
uint8_t uint8
Definition: c.h:540
char * Pointer
Definition: c.h:533
int16_t int16
Definition: c.h:537
uint32_t uint32
Definition: c.h:542
#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
uint64_t Datum
Definition: postgres.h:70
#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:99
bool typbyval
Definition: typcache.h:40
int16 typlen
Definition: typcache.h:39
#define att_align_pointer(cur_offset, attalign, attlen, attptr)
Definition: tupmacs.h:113
#define att_addlength_pointer(cur_offset, attlen, attptr)
Definition: tupmacs.h:180
static Datum fetch_att(const void *T, bool attbyval, int attlen)
Definition: tupmacs.h:50

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2078{
2079 RangeBound lower1,
2080 upper1,
2081 lower2,
2082 upper2;
2083 bool empty;
2084
2085 if (RangeIsEmpty(r) || MultirangeIsEmpty(mr))
2086 return false;
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 return (range_cmp_bounds(rangetyp, &upper1, &upper2) <= 0);
2094}

References Assert(), multirange_get_bounds(), MultirangeIsEmpty, 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 return 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, range_cmp_bounds(), range_deserialize(), and RangeIsEmpty.

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