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

758{
759 int cmp;
760
761 Assert(!boundA.lower && boundB.lower);
762
763 cmp = range_cmp_bound_values(typcache, &boundA, &boundB);
764 if (cmp < 0)
765 {
766 RangeType *r;
767
768 /*
769 * Bounds do not overlap; see if there are points in between.
770 */
771
772 /* in a continuous subtype, there are assumed to be points between */
773 if (!OidIsValid(typcache->rng_canonical_finfo.fn_oid))
774 return false;
775
776 /*
777 * The bounds are of a discrete range type; so make a range A..B and
778 * see if it's empty.
779 */
780
781 /* flip the inclusion flags */
782 boundA.inclusive = !boundA.inclusive;
783 boundB.inclusive = !boundB.inclusive;
784 /* change upper/lower labels to avoid Assert failures */
785 boundA.lower = true;
786 boundB.lower = false;
787 r = make_range(typcache, &boundA, &boundB, false, NULL);
788 return RangeIsEmpty(r);
789 }
790 else if (cmp == 0)
791 return boundA.inclusive != boundB.inclusive;
792 else
793 return false; /* bounds overlap */
794}
#define Assert(condition)
Definition: c.h:812
#define OidIsValid(objectId)
Definition: c.h:729
RangeType * make_range(TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper, bool empty, struct Node *escontext)
Definition: rangetypes.c:1952
int range_cmp_bound_values(TypeCacheEntry *typcache, const RangeBound *b1, const RangeBound *b2)
Definition: rangetypes.c:2090
#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:102

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 2165 of file rangetypes.c.

2166{
2169
2170 lower.val = (Datum) 0;
2171 lower.infinite = false;
2172 lower.inclusive = false;
2173 lower.lower = true;
2174
2175 upper.val = (Datum) 0;
2176 upper.infinite = false;
2177 upper.inclusive = false;
2178 upper.lower = false;
2179
2180 return make_range(typcache, &lower, &upper, true, NULL);
2181}
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 1952 of file rangetypes.c.

1954{
1956
1957 range = range_serialize(typcache, lower, upper, empty, escontext);
1958
1959 if (SOFT_ERROR_OCCURRED(escontext))
1960 return NULL;
1961
1962 /* no need to call canonical on empty ranges ... */
1963 if (OidIsValid(typcache->rng_canonical_finfo.fn_oid) &&
1965 {
1966 /* Do this the hard way so that we can pass escontext */
1967 LOCAL_FCINFO(fcinfo, 1);
1968 Datum result;
1969
1970 InitFunctionCallInfoData(*fcinfo, &typcache->rng_canonical_finfo, 1,
1971 InvalidOid, escontext, NULL);
1972
1973 fcinfo->args[0].value = RangeTypePGetDatum(range);
1974 fcinfo->args[0].isnull = false;
1975
1976 result = FunctionCallInvoke(fcinfo);
1977
1978 if (SOFT_ERROR_OCCURRED(escontext))
1979 return NULL;
1980
1981 /* Should not get a null result if there was no error */
1982 if (fcinfo->isnull)
1983 elog(ERROR, "function %u returned NULL",
1984 typcache->rng_canonical_finfo.fn_oid);
1985
1986 range = DatumGetRangeTypeP(result);
1987 }
1988
1989 return range;
1990}
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
#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:53
#define InvalidOid
Definition: postgres_ext.h:36
RangeType * range_serialize(TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper, bool empty, struct Node *escontext)
Definition: rangetypes.c:1727
static RangeType * DatumGetRangeTypeP(Datum X)
Definition: rangetypes.h:73
static Datum RangeTypePGetDatum(const RangeType *X)
Definition: rangetypes.h:85
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 798 of file rangetypes.c.

799{
800 RangeBound lower1,
801 lower2;
802 RangeBound upper1,
803 upper2;
804 bool empty1,
805 empty2;
806
807 /* Different types should be prevented by ANYRANGE matching rules */
808 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
809 elog(ERROR, "range types do not match");
810
811 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
812 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
813
814 /* An empty range is not adjacent to any other range */
815 if (empty1 || empty2)
816 return false;
817
818 /*
819 * Given two ranges A..B and C..D, the ranges are adjacent if and only if
820 * B is adjacent to C, or D is adjacent to A.
821 */
822 return (bounds_adjacent(typcache, upper1, lower2) ||
823 bounds_adjacent(typcache, upper2, lower1));
824}
bool bounds_adjacent(TypeCacheEntry *typcache, RangeBound boundA, RangeBound boundB)
Definition: rangetypes.c:757
void range_deserialize(TypeCacheEntry *typcache, const RangeType *range, RangeBound *lower, RangeBound *upper, bool *empty)
Definition: rangetypes.c:1856
#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 702 of file rangetypes.c.

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

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 664 of file rangetypes.c.

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

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 2090 of file rangetypes.c.

2092{
2093 /*
2094 * First, handle cases involving infinity, which don't require invoking
2095 * the comparison proc.
2096 */
2097 if (b1->infinite && b2->infinite)
2098 {
2099 /*
2100 * Both are infinity, so they are equal unless one is lower and the
2101 * other not.
2102 */
2103 if (b1->lower == b2->lower)
2104 return 0;
2105 else
2106 return b1->lower ? -1 : 1;
2107 }
2108 else if (b1->infinite)
2109 return b1->lower ? -1 : 1;
2110 else if (b2->infinite)
2111 return b2->lower ? 1 : -1;
2112
2113 /*
2114 * Both boundaries are finite, so compare the held values.
2115 */
2117 typcache->rng_collation,
2118 b1->val, b2->val));
2119}
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Definition: fmgr.c:1149
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:101
Oid rng_collation
Definition: typcache.h:100

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 2016 of file rangetypes.c.

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

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 2129 of file rangetypes.c.

2130{
2131 RangeType *r1 = *(RangeType **) key1;
2132 RangeType *r2 = *(RangeType **) key2;
2133 TypeCacheEntry *typcache = (TypeCacheEntry *) arg;
2134 RangeBound lower1;
2135 RangeBound upper1;
2136 RangeBound lower2;
2137 RangeBound upper2;
2138 bool empty1;
2139 bool empty2;
2140 int cmp;
2141
2142 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
2143 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
2144
2145 if (empty1 && empty2)
2146 cmp = 0;
2147 else if (empty1)
2148 cmp = -1;
2149 else if (empty2)
2150 cmp = 1;
2151 else
2152 {
2153 cmp = range_cmp_bounds(typcache, &lower1, &lower2);
2154 if (cmp == 0)
2155 cmp = range_cmp_bounds(typcache, &upper1, &upper2);
2156 }
2157
2158 return cmp;
2159}
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 2618 of file rangetypes.c.

2619{
2620 return range_contains_internal(typcache, r2, r1);
2621}
bool range_contains_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:2586

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 2627 of file rangetypes.c.

2628{
2631 bool empty;
2632 int32 cmp;
2633
2634 range_deserialize(typcache, r, &lower, &upper, &empty);
2635
2636 if (empty)
2637 return false;
2638
2639 if (!lower.infinite)
2640 {
2642 typcache->rng_collation,
2643 lower.val, val));
2644 if (cmp > 0)
2645 return false;
2646 if (cmp == 0 && !lower.inclusive)
2647 return false;
2648 }
2649
2650 if (!upper.infinite)
2651 {
2653 typcache->rng_collation,
2654 upper.val, val));
2655 if (cmp < 0)
2656 return false;
2657 if (cmp == 0 && !upper.inclusive)
2658 return false;
2659 }
2660
2661 return true;
2662}
long val
Definition: informix.c:689

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 2586 of file rangetypes.c.

2587{
2588 RangeBound lower1;
2589 RangeBound upper1;
2590 bool empty1;
2591 RangeBound lower2;
2592 RangeBound upper2;
2593 bool empty2;
2594
2595 /* Different types should be prevented by ANYRANGE matching rules */
2596 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
2597 elog(ERROR, "range types do not match");
2598
2599 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
2600 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
2601
2602 /* If either range is empty, the answer is easy */
2603 if (empty2)
2604 return true;
2605 else if (empty1)
2606 return false;
2607
2608 /* Else we must have lower1 <= lower2 and upper1 >= upper2 */
2609 if (range_cmp_bounds(typcache, &lower1, &lower2) > 0)
2610 return false;
2611 if (range_cmp_bounds(typcache, &upper1, &upper2) < 0)
2612 return false;
2613
2614 return true;
2615}

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 1856 of file rangetypes.c.

1858{
1859 char flags;
1860 int16 typlen;
1861 bool typbyval;
1862 char typalign;
1863 Pointer ptr;
1864 Datum lbound;
1865 Datum ubound;
1866
1867 /* assert caller passed the right typcache entry */
1868 Assert(RangeTypeGetOid(range) == typcache->type_id);
1869
1870 /* fetch the flag byte from datum's last byte */
1871 flags = *((const char *) range + VARSIZE(range) - 1);
1872
1873 /* fetch information about range's element type */
1874 typlen = typcache->rngelemtype->typlen;
1875 typbyval = typcache->rngelemtype->typbyval;
1876 typalign = typcache->rngelemtype->typalign;
1877
1878 /* initialize data pointer just after the range OID */
1879 ptr = (Pointer) (range + 1);
1880
1881 /* fetch lower bound, if any */
1882 if (RANGE_HAS_LBOUND(flags))
1883 {
1884 /* att_align_pointer cannot be necessary here */
1885 lbound = fetch_att(ptr, typbyval, typlen);
1886 ptr = (Pointer) att_addlength_pointer(ptr, typlen, ptr);
1887 }
1888 else
1889 lbound = (Datum) 0;
1890
1891 /* fetch upper bound, if any */
1892 if (RANGE_HAS_UBOUND(flags))
1893 {
1894 ptr = (Pointer) att_align_pointer(ptr, typalign, typlen, ptr);
1895 ubound = fetch_att(ptr, typbyval, typlen);
1896 /* no need for att_addlength_pointer */
1897 }
1898 else
1899 ubound = (Datum) 0;
1900
1901 /* emit results */
1902
1903 *empty = (flags & RANGE_EMPTY) != 0;
1904
1905 lower->val = lbound;
1906 lower->infinite = (flags & RANGE_LB_INF) != 0;
1907 lower->inclusive = (flags & RANGE_LB_INC) != 0;
1908 lower->lower = true;
1909
1910 upper->val = ubound;
1911 upper->infinite = (flags & RANGE_UB_INF) != 0;
1912 upper->inclusive = (flags & RANGE_UB_INC) != 0;
1913 upper->lower = false;
1914}
char * Pointer
Definition: c.h:476
int16_t int16
Definition: c.h:480
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:118
#define att_addlength_pointer(cur_offset, attlen, attptr)
Definition: tupmacs.h:185
static Datum fetch_att(const void *T, bool attbyval, int attlen)
Definition: tupmacs.h:53
#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(), find_simplified_clause(), 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 573 of file rangetypes.c.

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

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 1923 of file rangetypes.c.

1924{
1925 /* fetch the flag byte from datum's last byte */
1926 return *((char *) range + VARSIZE(range) - 1);
1927}

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 1703 of file rangetypes.c.

1704{
1705 TypeCacheEntry *typcache = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
1706
1707 if (typcache == NULL ||
1708 typcache->type_id != rngtypid)
1709 {
1710 typcache = lookup_type_cache(rngtypid, TYPECACHE_RANGE_INFO);
1711 if (typcache->rngelemtype == NULL)
1712 elog(ERROR, "type %u is not a range type", rngtypid);
1713 fcinfo->flinfo->fn_extra = typcache;
1714 }
1715
1716 return typcache;
1717}
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:76
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:386
#define TYPECACHE_RANGE_INFO
Definition: typcache.h:148

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 1143 of file rangetypes.c.

1144{
1145 RangeBound lower1,
1146 lower2;
1147 RangeBound upper1,
1148 upper2;
1149 bool empty1,
1150 empty2;
1151 RangeBound *result_lower;
1152 RangeBound *result_upper;
1153
1154 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
1155 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
1156
1157 if (empty1 || empty2 || !range_overlaps_internal(typcache, r1, r2))
1158 return make_empty_range(typcache);
1159
1160 if (range_cmp_bounds(typcache, &lower1, &lower2) >= 0)
1161 result_lower = &lower1;
1162 else
1163 result_lower = &lower2;
1164
1165 if (range_cmp_bounds(typcache, &upper1, &upper2) <= 0)
1166 result_upper = &upper1;
1167 else
1168 result_upper = &upper2;
1169
1170 return make_range(typcache, result_lower, result_upper, false, NULL);
1171}
bool range_overlaps_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:841
RangeType * make_empty_range(TypeCacheEntry *typcache)
Definition: rangetypes.c:2165

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 993 of file rangetypes.c.

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

619{
620 return (!range_eq_internal(typcache, r1, r2));
621}
bool range_eq_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:573

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 841 of file rangetypes.c.

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

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 887 of file rangetypes.c.

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

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 928 of file rangetypes.c.

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

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 1727 of file rangetypes.c.

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

1938{
1939 char *flagsp;
1940
1941 /* flag byte is datum's last byte */
1942 flagsp = (char *) range + VARSIZE(range) - 1;
1943
1944 *flagsp |= RANGE_CONTAIN_EMPTY;
1945}
#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 1182 of file rangetypes.c.

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

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 1052 of file rangetypes.c.

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

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