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

Go to the source code of this file.

Data Structures

struct  RangeType
 
struct  RangeBound
 

Macros

#define RANGE_EMPTY_LITERAL   "empty"
 
#define RangeTypeGetOid(r)   ((r)->rangetypid)
 
#define RANGE_EMPTY   0x01 /* range is empty */
 
#define RANGE_LB_INC   0x02 /* lower bound is inclusive */
 
#define RANGE_UB_INC   0x04 /* upper bound is inclusive */
 
#define RANGE_LB_INF   0x08 /* lower bound is -infinity */
 
#define RANGE_UB_INF   0x10 /* upper bound is +infinity */
 
#define RANGE_LB_NULL   0x20 /* lower bound is null (NOT USED) */
 
#define RANGE_UB_NULL   0x40 /* upper bound is null (NOT USED) */
 
#define RANGE_CONTAIN_EMPTY
 
#define RANGE_HAS_LBOUND(flags)
 
#define RANGE_HAS_UBOUND(flags)
 
#define RangeIsEmpty(r)   ((range_get_flags(r) & RANGE_EMPTY) != 0)
 
#define RangeIsOrContainsEmpty(r)    ((range_get_flags(r) & (RANGE_EMPTY | RANGE_CONTAIN_EMPTY)) != 0)
 
#define PG_GETARG_RANGE_P(n)   DatumGetRangeTypeP(PG_GETARG_DATUM(n))
 
#define PG_GETARG_RANGE_P_COPY(n)   DatumGetRangeTypePCopy(PG_GETARG_DATUM(n))
 
#define PG_RETURN_RANGE_P(x)   return RangeTypePGetDatum(x)
 
#define RANGESTRAT_BEFORE   RTLeftStrategyNumber
 
#define RANGESTRAT_OVERLEFT   RTOverLeftStrategyNumber
 
#define RANGESTRAT_OVERLAPS   RTOverlapStrategyNumber
 
#define RANGESTRAT_OVERRIGHT   RTOverRightStrategyNumber
 
#define RANGESTRAT_AFTER   RTRightStrategyNumber
 
#define RANGESTRAT_ADJACENT   RTSameStrategyNumber
 
#define RANGESTRAT_CONTAINS   RTContainsStrategyNumber
 
#define RANGESTRAT_CONTAINED_BY   RTContainedByStrategyNumber
 
#define RANGESTRAT_CONTAINS_ELEM   RTContainsElemStrategyNumber
 
#define RANGESTRAT_EQ   RTEqualStrategyNumber
 

Functions

static RangeTypeDatumGetRangeTypeP (Datum X)
 
static RangeTypeDatumGetRangeTypePCopy (Datum X)
 
static Datum RangeTypePGetDatum (const RangeType *X)
 
bool range_contains_elem_internal (TypeCacheEntry *typcache, const RangeType *r, Datum val)
 
bool range_eq_internal (TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
 
bool range_ne_internal (TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
 
bool range_contains_internal (TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
 
bool range_contained_by_internal (TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
 
bool range_before_internal (TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
 
bool range_after_internal (TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
 
bool range_adjacent_internal (TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
 
bool range_overlaps_internal (TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
 
bool range_overleft_internal (TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
 
bool range_overright_internal (TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
 
RangeTyperange_union_internal (TypeCacheEntry *typcache, RangeType *r1, RangeType *r2, bool strict)
 
RangeTyperange_minus_internal (TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
 
RangeTyperange_intersect_internal (TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
 
TypeCacheEntryrange_get_typcache (FunctionCallInfo fcinfo, Oid rngtypid)
 
RangeTyperange_serialize (TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper, bool empty, struct Node *escontext)
 
void range_deserialize (TypeCacheEntry *typcache, const RangeType *range, RangeBound *lower, RangeBound *upper, bool *empty)
 
char range_get_flags (const RangeType *range)
 
void range_set_contain_empty (RangeType *range)
 
RangeTypemake_range (TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper, bool empty, struct Node *escontext)
 
int range_cmp_bounds (TypeCacheEntry *typcache, const RangeBound *b1, const RangeBound *b2)
 
int range_cmp_bound_values (TypeCacheEntry *typcache, const RangeBound *b1, const RangeBound *b2)
 
int range_compare (const void *key1, const void *key2, void *arg)
 
bool bounds_adjacent (TypeCacheEntry *typcache, RangeBound boundA, RangeBound boundB)
 
RangeTypemake_empty_range (TypeCacheEntry *typcache)
 
bool range_split_internal (TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2, RangeType **output1, RangeType **output2)
 

Macro Definition Documentation

◆ PG_GETARG_RANGE_P

#define PG_GETARG_RANGE_P (   n)    DatumGetRangeTypeP(PG_GETARG_DATUM(n))

Definition at line 90 of file rangetypes.h.

◆ PG_GETARG_RANGE_P_COPY

#define PG_GETARG_RANGE_P_COPY (   n)    DatumGetRangeTypePCopy(PG_GETARG_DATUM(n))

Definition at line 91 of file rangetypes.h.

◆ PG_RETURN_RANGE_P

#define PG_RETURN_RANGE_P (   x)    return RangeTypePGetDatum(x)

Definition at line 92 of file rangetypes.h.

◆ RANGE_CONTAIN_EMPTY

#define RANGE_CONTAIN_EMPTY
Value:
0x80 /* marks a GiST internal-page entry whose
* subtree contains some empty ranges */

Definition at line 45 of file rangetypes.h.

◆ RANGE_EMPTY

#define RANGE_EMPTY   0x01 /* range is empty */

Definition at line 38 of file rangetypes.h.

◆ RANGE_EMPTY_LITERAL

#define RANGE_EMPTY_LITERAL   "empty"

Definition at line 32 of file rangetypes.h.

◆ RANGE_HAS_LBOUND

#define RANGE_HAS_LBOUND (   flags)
Value:
(!((flags) & (RANGE_EMPTY | \
#define RANGE_EMPTY
Definition: rangetypes.h:38
#define RANGE_LB_NULL
Definition: rangetypes.h:43
#define RANGE_LB_INF
Definition: rangetypes.h:41

Definition at line 47 of file rangetypes.h.

◆ RANGE_HAS_UBOUND

#define RANGE_HAS_UBOUND (   flags)
Value:
(!((flags) & (RANGE_EMPTY | \
#define RANGE_UB_INF
Definition: rangetypes.h:42
#define RANGE_UB_NULL
Definition: rangetypes.h:44

Definition at line 51 of file rangetypes.h.

◆ RANGE_LB_INC

#define RANGE_LB_INC   0x02 /* lower bound is inclusive */

Definition at line 39 of file rangetypes.h.

◆ RANGE_LB_INF

#define RANGE_LB_INF   0x08 /* lower bound is -infinity */

Definition at line 41 of file rangetypes.h.

◆ RANGE_LB_NULL

#define RANGE_LB_NULL   0x20 /* lower bound is null (NOT USED) */

Definition at line 43 of file rangetypes.h.

◆ RANGE_UB_INC

#define RANGE_UB_INC   0x04 /* upper bound is inclusive */

Definition at line 40 of file rangetypes.h.

◆ RANGE_UB_INF

#define RANGE_UB_INF   0x10 /* upper bound is +infinity */

Definition at line 42 of file rangetypes.h.

◆ RANGE_UB_NULL

#define RANGE_UB_NULL   0x40 /* upper bound is null (NOT USED) */

Definition at line 44 of file rangetypes.h.

◆ RangeIsEmpty

#define RangeIsEmpty (   r)    ((range_get_flags(r) & RANGE_EMPTY) != 0)

Definition at line 55 of file rangetypes.h.

◆ RangeIsOrContainsEmpty

#define RangeIsOrContainsEmpty (   r)     ((range_get_flags(r) & (RANGE_EMPTY | RANGE_CONTAIN_EMPTY)) != 0)

Definition at line 56 of file rangetypes.h.

◆ RANGESTRAT_ADJACENT

#define RANGESTRAT_ADJACENT   RTSameStrategyNumber

Definition at line 101 of file rangetypes.h.

◆ RANGESTRAT_AFTER

#define RANGESTRAT_AFTER   RTRightStrategyNumber

Definition at line 100 of file rangetypes.h.

◆ RANGESTRAT_BEFORE

#define RANGESTRAT_BEFORE   RTLeftStrategyNumber

Definition at line 96 of file rangetypes.h.

◆ RANGESTRAT_CONTAINED_BY

#define RANGESTRAT_CONTAINED_BY   RTContainedByStrategyNumber

Definition at line 103 of file rangetypes.h.

◆ RANGESTRAT_CONTAINS

#define RANGESTRAT_CONTAINS   RTContainsStrategyNumber

Definition at line 102 of file rangetypes.h.

◆ RANGESTRAT_CONTAINS_ELEM

#define RANGESTRAT_CONTAINS_ELEM   RTContainsElemStrategyNumber

Definition at line 104 of file rangetypes.h.

◆ RANGESTRAT_EQ

#define RANGESTRAT_EQ   RTEqualStrategyNumber

Definition at line 105 of file rangetypes.h.

◆ RANGESTRAT_OVERLAPS

#define RANGESTRAT_OVERLAPS   RTOverlapStrategyNumber

Definition at line 98 of file rangetypes.h.

◆ RANGESTRAT_OVERLEFT

#define RANGESTRAT_OVERLEFT   RTOverLeftStrategyNumber

Definition at line 97 of file rangetypes.h.

◆ RANGESTRAT_OVERRIGHT

#define RANGESTRAT_OVERRIGHT   RTOverRightStrategyNumber

Definition at line 99 of file rangetypes.h.

◆ RangeTypeGetOid

#define RangeTypeGetOid (   r)    ((r)->rangetypid)

Definition at line 35 of file rangetypes.h.

Function Documentation

◆ bounds_adjacent()

bool bounds_adjacent ( TypeCacheEntry typcache,
RangeBound  boundA,
RangeBound  boundB 
)

Definition at line 750 of file rangetypes.c.

751 {
752  int cmp;
753 
754  Assert(!boundA.lower && boundB.lower);
755 
756  cmp = range_cmp_bound_values(typcache, &boundA, &boundB);
757  if (cmp < 0)
758  {
759  RangeType *r;
760 
761  /*
762  * Bounds do not overlap; see if there are points in between.
763  */
764 
765  /* in a continuous subtype, there are assumed to be points between */
766  if (!OidIsValid(typcache->rng_canonical_finfo.fn_oid))
767  return false;
768 
769  /*
770  * The bounds are of a discrete range type; so make a range A..B and
771  * see if it's empty.
772  */
773 
774  /* flip the inclusion flags */
775  boundA.inclusive = !boundA.inclusive;
776  boundB.inclusive = !boundB.inclusive;
777  /* change upper/lower labels to avoid Assert failures */
778  boundA.lower = true;
779  boundB.lower = false;
780  r = make_range(typcache, &boundA, &boundB, false, NULL);
781  return RangeIsEmpty(r);
782  }
783  else if (cmp == 0)
784  return boundA.inclusive != boundB.inclusive;
785  else
786  return false; /* bounds overlap */
787 }
#define OidIsValid(objectId)
Definition: c.h:764
Assert(fmt[strlen(fmt) - 1] !='\n')
RangeType * make_range(TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper, bool empty, struct Node *escontext)
Definition: rangetypes.c:1945
int range_cmp_bound_values(TypeCacheEntry *typcache, const RangeBound *b1, const RangeBound *b2)
Definition: rangetypes.c:2083
#define RangeIsEmpty(r)
Definition: rangetypes.h:55
static int cmp(const chr *x, const chr *y, size_t len)
Definition: regc_locale.c:743
Oid fn_oid
Definition: fmgr.h:59
bool lower
Definition: rangetypes.h:66
bool inclusive
Definition: rangetypes.h:65
FmgrInfo rng_canonical_finfo
Definition: typcache.h:101

References Assert(), cmp(), FmgrInfo::fn_oid, RangeBound::inclusive, RangeBound::lower, make_range(), OidIsValid, range_cmp_bound_values(), RangeIsEmpty, and TypeCacheEntry::rng_canonical_finfo.

Referenced by adjacent_cmp_bounds(), multirange_adjacent_multirange(), range_adjacent_internal(), and range_adjacent_multirange_internal().

◆ DatumGetRangeTypeP()

◆ DatumGetRangeTypePCopy()

static RangeType* DatumGetRangeTypePCopy ( Datum  X)
inlinestatic

Definition at line 79 of file rangetypes.h.

81 {
82  return (RangeType *) PG_DETOAST_DATUM_COPY(X);
#define PG_DETOAST_DATUM_COPY(datum)
Definition: fmgr.h:242

References PG_DETOAST_DATUM_COPY.

◆ make_empty_range()

RangeType* make_empty_range ( TypeCacheEntry typcache)

Definition at line 2158 of file rangetypes.c.

2159 {
2160  RangeBound lower;
2161  RangeBound upper;
2162 
2163  lower.val = (Datum) 0;
2164  lower.infinite = false;
2165  lower.inclusive = false;
2166  lower.lower = true;
2167 
2168  upper.val = (Datum) 0;
2169  upper.infinite = false;
2170  upper.inclusive = false;
2171  upper.lower = false;
2172 
2173  return make_range(typcache, &lower, &upper, true, NULL);
2174 }
Datum lower(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:49
Datum upper(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:80
uintptr_t Datum
Definition: postgres.h:64

References lower(), make_range(), and upper().

Referenced by multirange_agg_transfn(), multirange_get_union_range(), range_intersect_internal(), range_merge_from_multirange(), and range_minus_internal().

◆ make_range()

RangeType* make_range ( TypeCacheEntry typcache,
RangeBound lower,
RangeBound upper,
bool  empty,
struct Node escontext 
)

Definition at line 1945 of file rangetypes.c.

1947 {
1948  RangeType *range;
1949 
1950  range = range_serialize(typcache, lower, upper, empty, escontext);
1951 
1952  if (SOFT_ERROR_OCCURRED(escontext))
1953  return NULL;
1954 
1955  /* no need to call canonical on empty ranges ... */
1956  if (OidIsValid(typcache->rng_canonical_finfo.fn_oid) &&
1957  !RangeIsEmpty(range))
1958  {
1959  /* Do this the hard way so that we can pass escontext */
1960  LOCAL_FCINFO(fcinfo, 1);
1961  Datum result;
1962 
1963  InitFunctionCallInfoData(*fcinfo, &typcache->rng_canonical_finfo, 1,
1964  InvalidOid, escontext, NULL);
1965 
1966  fcinfo->args[0].value = RangeTypePGetDatum(range);
1967  fcinfo->args[0].isnull = false;
1968 
1969  result = FunctionCallInvoke(fcinfo);
1970 
1971  if (SOFT_ERROR_OCCURRED(escontext))
1972  return NULL;
1973 
1974  /* Should not get a null result if there was no error */
1975  if (fcinfo->isnull)
1976  elog(ERROR, "function %u returned NULL",
1977  typcache->rng_canonical_finfo.fn_oid);
1978 
1979  range = DatumGetRangeTypeP(result);
1980  }
1981 
1982  return range;
1983 }
#define ERROR
Definition: elog.h:39
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition: fmgr.h:150
#define LOCAL_FCINFO(name, nargs)
Definition: fmgr.h:110
#define FunctionCallInvoke(fcinfo)
Definition: fmgr.h:172
#define SOFT_ERROR_OCCURRED(escontext)
Definition: miscnodes.h:52
#define InvalidOid
Definition: postgres_ext.h:36
RangeType * range_serialize(TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper, bool empty, struct Node *escontext)
Definition: rangetypes.c:1720
static Datum RangeTypePGetDatum(const RangeType *X)
Definition: rangetypes.h:85
static RangeType * DatumGetRangeTypeP(Datum X)
Definition: rangetypes.h:73
static struct cvec * range(struct vars *v, chr a, chr b, int cases)
Definition: regc_locale.c:412

References DatumGetRangeTypeP(), elog(), ERROR, FmgrInfo::fn_oid, FunctionCallInvoke, InitFunctionCallInfoData, InvalidOid, LOCAL_FCINFO, lower(), OidIsValid, range(), range_serialize(), RangeIsEmpty, RangeTypePGetDatum(), TypeCacheEntry::rng_canonical_finfo, SOFT_ERROR_OCCURRED, and upper().

Referenced by bounds_adjacent(), make_empty_range(), multirange_get_union_range(), range_constructor2(), range_constructor3(), range_in(), range_intersect_internal(), range_merge_from_multirange(), range_minus_internal(), range_recv(), range_split_internal(), range_super_union(), and range_union_internal().

◆ range_adjacent_internal()

bool range_adjacent_internal ( TypeCacheEntry typcache,
const RangeType r1,
const RangeType r2 
)

Definition at line 791 of file rangetypes.c.

792 {
793  RangeBound lower1,
794  lower2;
795  RangeBound upper1,
796  upper2;
797  bool empty1,
798  empty2;
799 
800  /* Different types should be prevented by ANYRANGE matching rules */
801  if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
802  elog(ERROR, "range types do not match");
803 
804  range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
805  range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
806 
807  /* An empty range is not adjacent to any other range */
808  if (empty1 || empty2)
809  return false;
810 
811  /*
812  * Given two ranges A..B and C..D, the ranges are adjacent if and only if
813  * B is adjacent to C, or D is adjacent to A.
814  */
815  return (bounds_adjacent(typcache, upper1, lower2) ||
816  bounds_adjacent(typcache, upper2, lower1));
817 }
bool bounds_adjacent(TypeCacheEntry *typcache, RangeBound boundA, RangeBound boundB)
Definition: rangetypes.c:750
void range_deserialize(TypeCacheEntry *typcache, const RangeType *range, RangeBound *lower, RangeBound *upper, bool *empty)
Definition: rangetypes.c:1849
#define RangeTypeGetOid(r)
Definition: rangetypes.h:35

References bounds_adjacent(), elog(), ERROR, range_deserialize(), and RangeTypeGetOid.

Referenced by multirange_canonicalize(), range_adjacent(), range_gist_consistent_int_range(), range_gist_consistent_leaf_range(), range_union_internal(), and spg_range_quad_leaf_consistent().

◆ range_after_internal()

bool range_after_internal ( TypeCacheEntry typcache,
const RangeType r1,
const RangeType r2 
)

Definition at line 695 of file rangetypes.c.

696 {
697  RangeBound lower1,
698  lower2;
699  RangeBound upper1,
700  upper2;
701  bool empty1,
702  empty2;
703 
704  /* Different types should be prevented by ANYRANGE matching rules */
705  if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
706  elog(ERROR, "range types do not match");
707 
708  range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
709  range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
710 
711  /* An empty range is neither before nor after any other range */
712  if (empty1 || empty2)
713  return false;
714 
715  return (range_cmp_bounds(typcache, &lower1, &upper2) > 0);
716 }
int range_cmp_bounds(TypeCacheEntry *typcache, const RangeBound *b1, const RangeBound *b2)
Definition: rangetypes.c:2009

References elog(), ERROR, range_cmp_bounds(), range_deserialize(), and RangeTypeGetOid.

Referenced by range_after(), range_gist_consistent_int_range(), range_gist_consistent_leaf_range(), and spg_range_quad_leaf_consistent().

◆ range_before_internal()

bool range_before_internal ( TypeCacheEntry typcache,
const RangeType r1,
const RangeType r2 
)

Definition at line 657 of file rangetypes.c.

658 {
659  RangeBound lower1,
660  lower2;
661  RangeBound upper1,
662  upper2;
663  bool empty1,
664  empty2;
665 
666  /* Different types should be prevented by ANYRANGE matching rules */
667  if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
668  elog(ERROR, "range types do not match");
669 
670  range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
671  range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
672 
673  /* An empty range is neither before nor after any other range */
674  if (empty1 || empty2)
675  return false;
676 
677  return (range_cmp_bounds(typcache, &upper1, &lower2) < 0);
678 }

References elog(), ERROR, range_cmp_bounds(), range_deserialize(), and RangeTypeGetOid.

Referenced by multirange_canonicalize(), multirange_intersect_internal(), multirange_minus_internal(), range_before(), range_gist_consistent_int_range(), range_gist_consistent_leaf_range(), and spg_range_quad_leaf_consistent().

◆ range_cmp_bound_values()

int range_cmp_bound_values ( TypeCacheEntry typcache,
const RangeBound b1,
const RangeBound b2 
)

Definition at line 2083 of file rangetypes.c.

2085 {
2086  /*
2087  * First, handle cases involving infinity, which don't require invoking
2088  * the comparison proc.
2089  */
2090  if (b1->infinite && b2->infinite)
2091  {
2092  /*
2093  * Both are infinity, so they are equal unless one is lower and the
2094  * other not.
2095  */
2096  if (b1->lower == b2->lower)
2097  return 0;
2098  else
2099  return b1->lower ? -1 : 1;
2100  }
2101  else if (b1->infinite)
2102  return b1->lower ? -1 : 1;
2103  else if (b2->infinite)
2104  return b2->lower ? 1 : -1;
2105 
2106  /*
2107  * Both boundaries are finite, so compare the held values.
2108  */
2110  typcache->rng_collation,
2111  b1->val, b2->val));
2112 }
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Definition: fmgr.c:1132
static int32 DatumGetInt32(Datum X)
Definition: postgres.h:202
bool infinite
Definition: rangetypes.h:64
Datum val
Definition: rangetypes.h:63
FmgrInfo rng_cmp_proc_finfo
Definition: typcache.h:100
Oid rng_collation
Definition: typcache.h:99

References DatumGetInt32(), FunctionCall2Coll(), RangeBound::infinite, RangeBound::lower, TypeCacheEntry::rng_cmp_proc_finfo, TypeCacheEntry::rng_collation, and RangeBound::val.

Referenced by bounds_adjacent(), and range_serialize().

◆ range_cmp_bounds()

int range_cmp_bounds ( TypeCacheEntry typcache,
const RangeBound b1,
const RangeBound b2 
)

Definition at line 2009 of file rangetypes.c.

2010 {
2011  int32 result;
2012 
2013  /*
2014  * First, handle cases involving infinity, which don't require invoking
2015  * the comparison proc.
2016  */
2017  if (b1->infinite && b2->infinite)
2018  {
2019  /*
2020  * Both are infinity, so they are equal unless one is lower and the
2021  * other not.
2022  */
2023  if (b1->lower == b2->lower)
2024  return 0;
2025  else
2026  return b1->lower ? -1 : 1;
2027  }
2028  else if (b1->infinite)
2029  return b1->lower ? -1 : 1;
2030  else if (b2->infinite)
2031  return b2->lower ? 1 : -1;
2032 
2033  /*
2034  * Both boundaries are finite, so compare the held values.
2035  */
2037  typcache->rng_collation,
2038  b1->val, b2->val));
2039 
2040  /*
2041  * If the comparison is anything other than equal, we're done. If they
2042  * compare equal though, we still have to consider whether the boundaries
2043  * are inclusive or exclusive.
2044  */
2045  if (result == 0)
2046  {
2047  if (!b1->inclusive && !b2->inclusive)
2048  {
2049  /* both are exclusive */
2050  if (b1->lower == b2->lower)
2051  return 0;
2052  else
2053  return b1->lower ? 1 : -1;
2054  }
2055  else if (!b1->inclusive)
2056  return b1->lower ? 1 : -1;
2057  else if (!b2->inclusive)
2058  return b2->lower ? -1 : 1;
2059  else
2060  {
2061  /*
2062  * Both are inclusive and the values held are equal, so they are
2063  * equal regardless of whether they are upper or lower boundaries,
2064  * or a mix.
2065  */
2066  return 0;
2067  }
2068  }
2069 
2070  return result;
2071 }
signed int int32
Definition: c.h:483

References DatumGetInt32(), FunctionCall2Coll(), RangeBound::inclusive, RangeBound::infinite, RangeBound::lower, TypeCacheEntry::rng_cmp_proc_finfo, TypeCacheEntry::rng_collation, and RangeBound::val.

Referenced by adjacent_cmp_bounds(), adjacent_inner_consistent(), bound_cmp(), calc_hist_selectivity_contained(), getQuadrant(), interval_cmp_lower(), interval_cmp_upper(), multirange_before_multirange_internal(), multirange_cmp(), multirange_contains_multirange_internal(), multirange_eq_internal(), multirange_overlaps_multirange_internal(), multirange_overleft_multirange(), multirange_overleft_range(), multirange_overright_multirange(), multirange_overright_range(), multirange_range_contains_bsearch_comparison(), multirange_range_overlaps_bsearch_comparison(), multirange_union_range_equal(), range_after_internal(), range_after_multirange_internal(), range_before_internal(), range_before_multirange_internal(), range_bound_qsort_cmp(), range_bounds_contains(), range_bounds_overlaps(), range_cmp(), range_compare(), range_contains_internal(), range_eq_internal(), range_gist_double_sorting_split(), range_gist_penalty(), range_intersect_internal(), range_minus_internal(), range_overlaps_internal(), range_overleft_internal(), range_overleft_multirange_internal(), range_overright_internal(), range_overright_multirange_internal(), range_split_internal(), range_super_union(), range_union_internal(), rbound_bsearch(), single_bound_cmp(), and spg_range_quad_inner_consistent().

◆ range_compare()

int range_compare ( const void *  key1,
const void *  key2,
void *  arg 
)

Definition at line 2122 of file rangetypes.c.

2123 {
2124  RangeType *r1 = *(RangeType **) key1;
2125  RangeType *r2 = *(RangeType **) key2;
2126  TypeCacheEntry *typcache = (TypeCacheEntry *) arg;
2127  RangeBound lower1;
2128  RangeBound upper1;
2129  RangeBound lower2;
2130  RangeBound upper2;
2131  bool empty1;
2132  bool empty2;
2133  int cmp;
2134 
2135  range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
2136  range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
2137 
2138  if (empty1 && empty2)
2139  cmp = 0;
2140  else if (empty1)
2141  cmp = -1;
2142  else if (empty2)
2143  cmp = 1;
2144  else
2145  {
2146  cmp = range_cmp_bounds(typcache, &lower1, &lower2);
2147  if (cmp == 0)
2148  cmp = range_cmp_bounds(typcache, &upper1, &upper2);
2149  }
2150 
2151  return cmp;
2152 }
void * arg

References arg, cmp(), range_cmp_bounds(), and range_deserialize().

Referenced by multirange_canonicalize().

◆ range_contained_by_internal()

bool range_contained_by_internal ( TypeCacheEntry typcache,
const RangeType r1,
const RangeType r2 
)

Definition at line 2559 of file rangetypes.c.

2560 {
2561  return range_contains_internal(typcache, r2, r1);
2562 }
bool range_contains_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:2527

References range_contains_internal().

Referenced by range_contained_by(), range_gist_consistent_leaf_range(), and spg_range_quad_leaf_consistent().

◆ range_contains_elem_internal()

bool range_contains_elem_internal ( TypeCacheEntry typcache,
const RangeType r,
Datum  val 
)

Definition at line 2568 of file rangetypes.c.

2569 {
2570  RangeBound lower;
2571  RangeBound upper;
2572  bool empty;
2573  int32 cmp;
2574 
2575  range_deserialize(typcache, r, &lower, &upper, &empty);
2576 
2577  if (empty)
2578  return false;
2579 
2580  if (!lower.infinite)
2581  {
2583  typcache->rng_collation,
2584  lower.val, val));
2585  if (cmp > 0)
2586  return false;
2587  if (cmp == 0 && !lower.inclusive)
2588  return false;
2589  }
2590 
2591  if (!upper.infinite)
2592  {
2594  typcache->rng_collation,
2595  upper.val, val));
2596  if (cmp < 0)
2597  return false;
2598  if (cmp == 0 && !upper.inclusive)
2599  return false;
2600  }
2601 
2602  return true;
2603 }
long val
Definition: informix.c:664

References cmp(), DatumGetInt32(), FunctionCall2Coll(), lower(), range_deserialize(), TypeCacheEntry::rng_cmp_proc_finfo, TypeCacheEntry::rng_collation, upper(), and val.

Referenced by elem_contained_by_range(), range_contains_elem(), range_gist_consistent_int_element(), range_gist_consistent_leaf_element(), and spg_range_quad_leaf_consistent().

◆ range_contains_internal()

bool range_contains_internal ( TypeCacheEntry typcache,
const RangeType r1,
const RangeType r2 
)

Definition at line 2527 of file rangetypes.c.

2528 {
2529  RangeBound lower1;
2530  RangeBound upper1;
2531  bool empty1;
2532  RangeBound lower2;
2533  RangeBound upper2;
2534  bool empty2;
2535 
2536  /* Different types should be prevented by ANYRANGE matching rules */
2537  if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
2538  elog(ERROR, "range types do not match");
2539 
2540  range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
2541  range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
2542 
2543  /* If either range is empty, the answer is easy */
2544  if (empty2)
2545  return true;
2546  else if (empty1)
2547  return false;
2548 
2549  /* Else we must have lower1 <= lower2 and upper1 >= upper2 */
2550  if (range_cmp_bounds(typcache, &lower1, &lower2) > 0)
2551  return false;
2552  if (range_cmp_bounds(typcache, &upper1, &upper2) < 0)
2553  return false;
2554 
2555  return true;
2556 }

References elog(), ERROR, range_cmp_bounds(), range_deserialize(), and RangeTypeGetOid.

Referenced by range_contained_by_internal(), range_contains(), range_gist_consistent_int_range(), range_gist_consistent_leaf_range(), and spg_range_quad_leaf_consistent().

◆ range_deserialize()

void range_deserialize ( TypeCacheEntry typcache,
const RangeType range,
RangeBound lower,
RangeBound upper,
bool empty 
)

Definition at line 1849 of file rangetypes.c.

1851 {
1852  char flags;
1853  int16 typlen;
1854  bool typbyval;
1855  char typalign;
1856  Pointer ptr;
1857  Datum lbound;
1858  Datum ubound;
1859 
1860  /* assert caller passed the right typcache entry */
1861  Assert(RangeTypeGetOid(range) == typcache->type_id);
1862 
1863  /* fetch the flag byte from datum's last byte */
1864  flags = *((const char *) range + VARSIZE(range) - 1);
1865 
1866  /* fetch information about range's element type */
1867  typlen = typcache->rngelemtype->typlen;
1868  typbyval = typcache->rngelemtype->typbyval;
1869  typalign = typcache->rngelemtype->typalign;
1870 
1871  /* initialize data pointer just after the range OID */
1872  ptr = (Pointer) (range + 1);
1873 
1874  /* fetch lower bound, if any */
1875  if (RANGE_HAS_LBOUND(flags))
1876  {
1877  /* att_align_pointer cannot be necessary here */
1878  lbound = fetch_att(ptr, typbyval, typlen);
1879  ptr = (Pointer) att_addlength_pointer(ptr, typlen, ptr);
1880  }
1881  else
1882  lbound = (Datum) 0;
1883 
1884  /* fetch upper bound, if any */
1885  if (RANGE_HAS_UBOUND(flags))
1886  {
1887  ptr = (Pointer) att_align_pointer(ptr, typalign, typlen, ptr);
1888  ubound = fetch_att(ptr, typbyval, typlen);
1889  /* no need for att_addlength_pointer */
1890  }
1891  else
1892  ubound = (Datum) 0;
1893 
1894  /* emit results */
1895 
1896  *empty = (flags & RANGE_EMPTY) != 0;
1897 
1898  lower->val = lbound;
1899  lower->infinite = (flags & RANGE_LB_INF) != 0;
1900  lower->inclusive = (flags & RANGE_LB_INC) != 0;
1901  lower->lower = true;
1902 
1903  upper->val = ubound;
1904  upper->infinite = (flags & RANGE_UB_INF) != 0;
1905  upper->inclusive = (flags & RANGE_UB_INC) != 0;
1906  upper->lower = false;
1907 }
signed short int16
Definition: c.h:482
char * Pointer
Definition: c.h:472
char typalign
Definition: pg_type.h:176
#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_HAS_LBOUND(flags)
Definition: rangetypes.h:47
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
#define VARSIZE(PTR)
Definition: varatt.h:279

References Assert(), att_addlength_pointer, att_align_pointer, fetch_att(), lower(), range(), RANGE_EMPTY, RANGE_HAS_LBOUND, RANGE_HAS_UBOUND, RANGE_LB_INC, RANGE_LB_INF, RANGE_UB_INC, RANGE_UB_INF, RangeTypeGetOid, TypeCacheEntry::rngelemtype, typalign, TypeCacheEntry::typalign, TypeCacheEntry::typbyval, TypeCacheEntry::type_id, TypeCacheEntry::typlen, upper(), and VARSIZE.

Referenced by calc_hist_selectivity(), compute_range_stats(), daterange_canonical(), getQuadrant(), hash_range(), hash_range_extended(), int4range_canonical(), int8range_canonical(), multirange_contains_range_internal(), multirange_overleft_range(), multirange_overright_range(), multirange_union_range_equal(), range_adjacent_internal(), range_adjacent_multirange_internal(), range_after_internal(), range_after_multirange_internal(), range_before_internal(), range_before_multirange_internal(), range_cmp(), range_compare(), range_contains_elem_internal(), range_contains_internal(), range_contains_multirange_internal(), range_eq_internal(), range_gist_double_sorting_split(), range_gist_penalty(), range_gist_single_sorting_split(), range_intersect_internal(), range_lower(), range_minus_internal(), range_out(), range_overlaps_internal(), range_overlaps_multirange_internal(), range_overleft_internal(), range_overleft_multirange_internal(), range_overright_internal(), range_overright_multirange_internal(), range_send(), range_split_internal(), range_super_union(), range_union_internal(), range_upper(), spg_range_quad_inner_consistent(), and spg_range_quad_picksplit().

◆ range_eq_internal()

bool range_eq_internal ( TypeCacheEntry typcache,
const RangeType r1,
const RangeType r2 
)

Definition at line 566 of file rangetypes.c.

567 {
568  RangeBound lower1,
569  lower2;
570  RangeBound upper1,
571  upper2;
572  bool empty1,
573  empty2;
574 
575  /* Different types should be prevented by ANYRANGE matching rules */
576  if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
577  elog(ERROR, "range types do not match");
578 
579  range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
580  range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
581 
582  if (empty1 && empty2)
583  return true;
584  if (empty1 != empty2)
585  return false;
586 
587  if (range_cmp_bounds(typcache, &lower1, &lower2) != 0)
588  return false;
589 
590  if (range_cmp_bounds(typcache, &upper1, &upper2) != 0)
591  return false;
592 
593  return true;
594 }

References elog(), ERROR, range_cmp_bounds(), range_deserialize(), and RangeTypeGetOid.

Referenced by range_eq(), range_gist_consistent_leaf_range(), range_gist_same(), range_ne_internal(), and spg_range_quad_leaf_consistent().

◆ range_get_flags()

char range_get_flags ( const RangeType range)

Definition at line 1916 of file rangetypes.c.

1917 {
1918  /* fetch the flag byte from datum's last byte */
1919  return *((char *) range + VARSIZE(range) - 1);
1920 }

References range(), and VARSIZE.

Referenced by get_gist_range_class(), hash_range(), hash_range_extended(), range_empty(), range_gist_same(), range_lower_inc(), range_lower_inf(), range_out(), range_send(), range_super_union(), range_upper_inc(), and range_upper_inf().

◆ range_get_typcache()

TypeCacheEntry* range_get_typcache ( FunctionCallInfo  fcinfo,
Oid  rngtypid 
)

Definition at line 1696 of file rangetypes.c.

1697 {
1698  TypeCacheEntry *typcache = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
1699 
1700  if (typcache == NULL ||
1701  typcache->type_id != rngtypid)
1702  {
1703  typcache = lookup_type_cache(rngtypid, TYPECACHE_RANGE_INFO);
1704  if (typcache->rngelemtype == NULL)
1705  elog(ERROR, "type %u is not a range type", rngtypid);
1706  fcinfo->flinfo->fn_extra = (void *) typcache;
1707  }
1708 
1709  return typcache;
1710 }
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
void * fn_extra
Definition: fmgr.h:64
FmgrInfo * flinfo
Definition: fmgr.h:87
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:344
#define TYPECACHE_RANGE_INFO
Definition: typcache.h:147

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

Referenced by daterange_canonical(), elem_contained_by_range(), hash_range(), hash_range_extended(), int4range_canonical(), int8range_canonical(), multirange_gist_consistent(), range_adjacent(), range_after(), range_before(), range_cmp(), range_constructor2(), range_constructor3(), range_contained_by(), range_contains(), range_contains_elem(), range_eq(), range_gist_consistent(), range_gist_penalty(), range_gist_picksplit(), range_gist_same(), range_gist_union(), range_intersect(), range_intersect_agg_transfn(), range_lower(), range_merge(), range_minus(), range_ne(), range_overlaps(), range_overleft(), range_overright(), range_typanalyze(), range_union(), range_upper(), rangesel(), spg_range_quad_choose(), spg_range_quad_inner_consistent(), spg_range_quad_leaf_consistent(), and spg_range_quad_picksplit().

◆ range_intersect_internal()

RangeType* range_intersect_internal ( TypeCacheEntry typcache,
const RangeType r1,
const RangeType r2 
)

Definition at line 1136 of file rangetypes.c.

1137 {
1138  RangeBound lower1,
1139  lower2;
1140  RangeBound upper1,
1141  upper2;
1142  bool empty1,
1143  empty2;
1144  RangeBound *result_lower;
1145  RangeBound *result_upper;
1146 
1147  range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
1148  range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
1149 
1150  if (empty1 || empty2 || !range_overlaps_internal(typcache, r1, r2))
1151  return make_empty_range(typcache);
1152 
1153  if (range_cmp_bounds(typcache, &lower1, &lower2) >= 0)
1154  result_lower = &lower1;
1155  else
1156  result_lower = &lower2;
1157 
1158  if (range_cmp_bounds(typcache, &upper1, &upper2) <= 0)
1159  result_upper = &upper1;
1160  else
1161  result_upper = &upper2;
1162 
1163  return make_range(typcache, result_lower, result_upper, false, NULL);
1164 }
bool range_overlaps_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:834
RangeType * make_empty_range(TypeCacheEntry *typcache)
Definition: rangetypes.c:2158

References make_empty_range(), make_range(), range_cmp_bounds(), range_deserialize(), and range_overlaps_internal().

Referenced by multirange_intersect_internal(), range_intersect(), and range_intersect_agg_transfn().

◆ range_minus_internal()

RangeType* range_minus_internal ( TypeCacheEntry typcache,
RangeType r1,
RangeType r2 
)

Definition at line 986 of file rangetypes.c.

987 {
988  RangeBound lower1,
989  lower2;
990  RangeBound upper1,
991  upper2;
992  bool empty1,
993  empty2;
994  int cmp_l1l2,
995  cmp_l1u2,
996  cmp_u1l2,
997  cmp_u1u2;
998 
999  range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
1000  range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
1001 
1002  /* if either is empty, r1 is the correct answer */
1003  if (empty1 || empty2)
1004  return r1;
1005 
1006  cmp_l1l2 = range_cmp_bounds(typcache, &lower1, &lower2);
1007  cmp_l1u2 = range_cmp_bounds(typcache, &lower1, &upper2);
1008  cmp_u1l2 = range_cmp_bounds(typcache, &upper1, &lower2);
1009  cmp_u1u2 = range_cmp_bounds(typcache, &upper1, &upper2);
1010 
1011  if (cmp_l1l2 < 0 && cmp_u1u2 > 0)
1012  ereport(ERROR,
1013  (errcode(ERRCODE_DATA_EXCEPTION),
1014  errmsg("result of range difference would not be contiguous")));
1015 
1016  if (cmp_l1u2 > 0 || cmp_u1l2 < 0)
1017  return r1;
1018 
1019  if (cmp_l1l2 >= 0 && cmp_u1u2 <= 0)
1020  return make_empty_range(typcache);
1021 
1022  if (cmp_l1l2 <= 0 && cmp_u1l2 >= 0 && cmp_u1u2 <= 0)
1023  {
1024  lower2.inclusive = !lower2.inclusive;
1025  lower2.lower = false; /* it will become the upper bound */
1026  return make_range(typcache, &lower1, &lower2, false, NULL);
1027  }
1028 
1029  if (cmp_l1l2 >= 0 && cmp_u1u2 >= 0 && cmp_l1u2 <= 0)
1030  {
1031  upper2.inclusive = !upper2.inclusive;
1032  upper2.lower = true; /* it will become the lower bound */
1033  return make_range(typcache, &upper2, &upper1, false, NULL);
1034  }
1035 
1036  elog(ERROR, "unexpected case in range_minus");
1037  return NULL;
1038 }
int errcode(int sqlerrcode)
Definition: elog.c:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define ereport(elevel,...)
Definition: elog.h:149

References elog(), ereport, errcode(), errmsg(), ERROR, RangeBound::inclusive, RangeBound::lower, make_empty_range(), make_range(), range_cmp_bounds(), and range_deserialize().

Referenced by multirange_minus_internal(), and range_minus().

◆ range_ne_internal()

bool range_ne_internal ( TypeCacheEntry typcache,
const RangeType r1,
const RangeType r2 
)

Definition at line 611 of file rangetypes.c.

612 {
613  return (!range_eq_internal(typcache, r1, r2));
614 }
bool range_eq_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:566

References range_eq_internal().

Referenced by range_ne().

◆ range_overlaps_internal()

bool range_overlaps_internal ( TypeCacheEntry typcache,
const RangeType r1,
const RangeType r2 
)

Definition at line 834 of file rangetypes.c.

835 {
836  RangeBound lower1,
837  lower2;
838  RangeBound upper1,
839  upper2;
840  bool empty1,
841  empty2;
842 
843  /* Different types should be prevented by ANYRANGE matching rules */
844  if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
845  elog(ERROR, "range types do not match");
846 
847  range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
848  range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
849 
850  /* An empty range does not overlap any other range */
851  if (empty1 || empty2)
852  return false;
853 
854  if (range_cmp_bounds(typcache, &lower1, &lower2) >= 0 &&
855  range_cmp_bounds(typcache, &lower1, &upper2) <= 0)
856  return true;
857 
858  if (range_cmp_bounds(typcache, &lower2, &lower1) >= 0 &&
859  range_cmp_bounds(typcache, &lower2, &upper1) <= 0)
860  return true;
861 
862  return false;
863 }

References elog(), ERROR, range_cmp_bounds(), range_deserialize(), and RangeTypeGetOid.

Referenced by multirange_intersect_internal(), multirange_minus_internal(), range_gist_consistent_int_range(), range_gist_consistent_leaf_range(), range_intersect_internal(), range_overlaps(), range_union_internal(), and spg_range_quad_leaf_consistent().

◆ range_overleft_internal()

bool range_overleft_internal ( TypeCacheEntry typcache,
const RangeType r1,
const RangeType r2 
)

Definition at line 880 of file rangetypes.c.

881 {
882  RangeBound lower1,
883  lower2;
884  RangeBound upper1,
885  upper2;
886  bool empty1,
887  empty2;
888 
889  /* Different types should be prevented by ANYRANGE matching rules */
890  if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
891  elog(ERROR, "range types do not match");
892 
893  range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
894  range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
895 
896  /* An empty range is neither before nor after any other range */
897  if (empty1 || empty2)
898  return false;
899 
900  if (range_cmp_bounds(typcache, &upper1, &upper2) <= 0)
901  return true;
902 
903  return false;
904 }

References elog(), ERROR, range_cmp_bounds(), range_deserialize(), and RangeTypeGetOid.

Referenced by multirange_intersect_internal(), range_gist_consistent_int_range(), range_gist_consistent_leaf_range(), range_overleft(), and spg_range_quad_leaf_consistent().

◆ range_overright_internal()

bool range_overright_internal ( TypeCacheEntry typcache,
const RangeType r1,
const RangeType r2 
)

Definition at line 921 of file rangetypes.c.

922 {
923  RangeBound lower1,
924  lower2;
925  RangeBound upper1,
926  upper2;
927  bool empty1,
928  empty2;
929 
930  /* Different types should be prevented by ANYRANGE matching rules */
931  if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
932  elog(ERROR, "range types do not match");
933 
934  range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
935  range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
936 
937  /* An empty range is neither before nor after any other range */
938  if (empty1 || empty2)
939  return false;
940 
941  if (range_cmp_bounds(typcache, &lower1, &lower2) >= 0)
942  return true;
943 
944  return false;
945 }

References elog(), ERROR, range_cmp_bounds(), range_deserialize(), and RangeTypeGetOid.

Referenced by range_gist_consistent_int_range(), range_gist_consistent_leaf_range(), range_overright(), and spg_range_quad_leaf_consistent().

◆ range_serialize()

RangeType* range_serialize ( TypeCacheEntry typcache,
RangeBound lower,
RangeBound upper,
bool  empty,
struct Node escontext 
)

Definition at line 1720 of file rangetypes.c.

1722 {
1723  RangeType *range;
1724  int cmp;
1725  Size msize;
1726  Pointer ptr;
1727  int16 typlen;
1728  bool typbyval;
1729  char typalign;
1730  char typstorage;
1731  char flags = 0;
1732 
1733  /*
1734  * Verify range is not invalid on its face, and construct flags value,
1735  * preventing any non-canonical combinations such as infinite+inclusive.
1736  */
1737  Assert(lower->lower);
1738  Assert(!upper->lower);
1739 
1740  if (empty)
1741  flags |= RANGE_EMPTY;
1742  else
1743  {
1744  cmp = range_cmp_bound_values(typcache, lower, upper);
1745 
1746  /* error check: if lower bound value is above upper, it's wrong */
1747  if (cmp > 0)
1748  ereturn(escontext, NULL,
1749  (errcode(ERRCODE_DATA_EXCEPTION),
1750  errmsg("range lower bound must be less than or equal to range upper bound")));
1751 
1752  /* if bounds are equal, and not both inclusive, range is empty */
1753  if (cmp == 0 && !(lower->inclusive && upper->inclusive))
1754  flags |= RANGE_EMPTY;
1755  else
1756  {
1757  /* infinite boundaries are never inclusive */
1758  if (lower->infinite)
1759  flags |= RANGE_LB_INF;
1760  else if (lower->inclusive)
1761  flags |= RANGE_LB_INC;
1762  if (upper->infinite)
1763  flags |= RANGE_UB_INF;
1764  else if (upper->inclusive)
1765  flags |= RANGE_UB_INC;
1766  }
1767  }
1768 
1769  /* Fetch information about range's element type */
1770  typlen = typcache->rngelemtype->typlen;
1771  typbyval = typcache->rngelemtype->typbyval;
1772  typalign = typcache->rngelemtype->typalign;
1773  typstorage = typcache->rngelemtype->typstorage;
1774 
1775  /* Count space for varlena header and range type's OID */
1776  msize = sizeof(RangeType);
1777  Assert(msize == MAXALIGN(msize));
1778 
1779  /* Count space for bounds */
1780  if (RANGE_HAS_LBOUND(flags))
1781  {
1782  /*
1783  * Make sure item to be inserted is not toasted. It is essential that
1784  * we not insert an out-of-line toast value pointer into a range
1785  * object, for the same reasons that arrays and records can't contain
1786  * them. It would work to store a compressed-in-line value, but we
1787  * prefer to decompress and then let compression be applied to the
1788  * whole range object if necessary. But, unlike arrays, we do allow
1789  * short-header varlena objects to stay as-is.
1790  */
1791  if (typlen == -1)
1793 
1794  msize = datum_compute_size(msize, lower->val, typbyval, typalign,
1795  typlen, typstorage);
1796  }
1797 
1798  if (RANGE_HAS_UBOUND(flags))
1799  {
1800  /* Make sure item to be inserted is not toasted */
1801  if (typlen == -1)
1803 
1804  msize = datum_compute_size(msize, upper->val, typbyval, typalign,
1805  typlen, typstorage);
1806  }
1807 
1808  /* Add space for flag byte */
1809  msize += sizeof(char);
1810 
1811  /* Note: zero-fill is required here, just as in heap tuples */
1812  range = (RangeType *) palloc0(msize);
1813  SET_VARSIZE(range, msize);
1814 
1815  /* Now fill in the datum */
1816  range->rangetypid = typcache->type_id;
1817 
1818  ptr = (char *) (range + 1);
1819 
1820  if (RANGE_HAS_LBOUND(flags))
1821  {
1822  Assert(lower->lower);
1823  ptr = datum_write(ptr, lower->val, typbyval, typalign, typlen,
1824  typstorage);
1825  }
1826 
1827  if (RANGE_HAS_UBOUND(flags))
1828  {
1829  Assert(!upper->lower);
1830  ptr = datum_write(ptr, upper->val, typbyval, typalign, typlen,
1831  typstorage);
1832  }
1833 
1834  *((char *) ptr) = flags;
1835 
1836  return range;
1837 }
#define MAXALIGN(LEN)
Definition: c.h:800
size_t Size
Definition: c.h:594
#define ereturn(context, dummy_value,...)
Definition: elog.h:276
#define PG_DETOAST_DATUM_PACKED(datum)
Definition: fmgr.h:248
void * palloc0(Size size)
Definition: mcxt.c:1257
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
static Pointer datum_write(Pointer ptr, Datum datum, bool typbyval, char typalign, int16 typlen, char typstorage)
Definition: rangetypes.c:2650
static Size datum_compute_size(Size data_length, Datum val, bool typbyval, char typalign, int16 typlen, char typstorage)
Definition: rangetypes.c:2624
char typstorage
Definition: typcache.h:42
#define SET_VARSIZE(PTR, len)
Definition: varatt.h:305

References Assert(), cmp(), datum_compute_size(), datum_write(), ereturn, errcode(), errmsg(), lower(), MAXALIGN, palloc0(), PG_DETOAST_DATUM_PACKED, PointerGetDatum(), range(), range_cmp_bound_values(), RANGE_EMPTY, RANGE_HAS_LBOUND, RANGE_HAS_UBOUND, RANGE_LB_INC, RANGE_LB_INF, RANGE_UB_INC, RANGE_UB_INF, TypeCacheEntry::rngelemtype, SET_VARSIZE, typalign, TypeCacheEntry::typalign, TypeCacheEntry::typbyval, TypeCacheEntry::type_id, TypeCacheEntry::typlen, TypeCacheEntry::typstorage, and upper().

Referenced by compute_range_stats(), daterange_canonical(), int4range_canonical(), int8range_canonical(), make_range(), multirangesel(), rangesel(), and spg_range_quad_picksplit().

◆ range_set_contain_empty()

void range_set_contain_empty ( RangeType range)

Definition at line 1930 of file rangetypes.c.

1931 {
1932  char *flagsp;
1933 
1934  /* flag byte is datum's last byte */
1935  flagsp = (char *) range + VARSIZE(range) - 1;
1936 
1937  *flagsp |= RANGE_CONTAIN_EMPTY;
1938 }
#define RANGE_CONTAIN_EMPTY
Definition: rangetypes.h:45

References range(), RANGE_CONTAIN_EMPTY, and VARSIZE.

Referenced by range_super_union().

◆ range_split_internal()

bool range_split_internal ( TypeCacheEntry typcache,
const RangeType r1,
const RangeType r2,
RangeType **  output1,
RangeType **  output2 
)

Definition at line 1175 of file rangetypes.c.

1177 {
1178  RangeBound lower1,
1179  lower2;
1180  RangeBound upper1,
1181  upper2;
1182  bool empty1,
1183  empty2;
1184 
1185  range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
1186  range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
1187 
1188  if (range_cmp_bounds(typcache, &lower1, &lower2) < 0 &&
1189  range_cmp_bounds(typcache, &upper1, &upper2) > 0)
1190  {
1191  /*
1192  * Need to invert inclusive/exclusive for the lower2 and upper2
1193  * points. They can't be infinite though. We're allowed to overwrite
1194  * these RangeBounds since they only exist locally.
1195  */
1196  lower2.inclusive = !lower2.inclusive;
1197  lower2.lower = false;
1198  upper2.inclusive = !upper2.inclusive;
1199  upper2.lower = true;
1200 
1201  *output1 = make_range(typcache, &lower1, &lower2, false, NULL);
1202  *output2 = make_range(typcache, &upper2, &upper1, false, NULL);
1203  return true;
1204  }
1205 
1206  return false;
1207 }

References RangeBound::inclusive, RangeBound::lower, make_range(), range_cmp_bounds(), and range_deserialize().

Referenced by multirange_minus_internal().

◆ range_union_internal()

RangeType* range_union_internal ( TypeCacheEntry typcache,
RangeType r1,
RangeType r2,
bool  strict 
)

Definition at line 1045 of file rangetypes.c.

1047 {
1048  RangeBound lower1,
1049  lower2;
1050  RangeBound upper1,
1051  upper2;
1052  bool empty1,
1053  empty2;
1054  RangeBound *result_lower;
1055  RangeBound *result_upper;
1056 
1057  /* Different types should be prevented by ANYRANGE matching rules */
1058  if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
1059  elog(ERROR, "range types do not match");
1060 
1061  range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
1062  range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
1063 
1064  /* if either is empty, the other is the correct answer */
1065  if (empty1)
1066  return r2;
1067  if (empty2)
1068  return r1;
1069 
1070  if (strict &&
1071  !DatumGetBool(range_overlaps_internal(typcache, r1, r2)) &&
1072  !DatumGetBool(range_adjacent_internal(typcache, r1, r2)))
1073  ereport(ERROR,
1074  (errcode(ERRCODE_DATA_EXCEPTION),
1075  errmsg("result of range union would not be contiguous")));
1076 
1077  if (range_cmp_bounds(typcache, &lower1, &lower2) < 0)
1078  result_lower = &lower1;
1079  else
1080  result_lower = &lower2;
1081 
1082  if (range_cmp_bounds(typcache, &upper1, &upper2) > 0)
1083  result_upper = &upper1;
1084  else
1085  result_upper = &upper2;
1086 
1087  return make_range(typcache, result_lower, result_upper, false, NULL);
1088 }
static bool DatumGetBool(Datum X)
Definition: postgres.h:90
bool range_adjacent_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:791

References DatumGetBool(), elog(), ereport, errcode(), errmsg(), ERROR, make_range(), range_adjacent_internal(), range_cmp_bounds(), range_deserialize(), range_overlaps_internal(), and RangeTypeGetOid.

Referenced by multirange_canonicalize(), range_merge(), and range_union().

◆ RangeTypePGetDatum()