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

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

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

2230{
2233
2234 lower.val = (Datum) 0;
2235 lower.infinite = false;
2236 lower.inclusive = false;
2237 lower.lower = true;
2238
2239 upper.val = (Datum) 0;
2240 upper.infinite = false;
2241 upper.inclusive = false;
2242 upper.lower = false;
2243
2244 return make_range(typcache, &lower, &upper, true, NULL);
2245}
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:69

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

2018{
2020
2021 range = range_serialize(typcache, lower, upper, empty, escontext);
2022
2023 if (SOFT_ERROR_OCCURRED(escontext))
2024 return NULL;
2025
2026 /* no need to call canonical on empty ranges ... */
2027 if (OidIsValid(typcache->rng_canonical_finfo.fn_oid) &&
2029 {
2030 /* Do this the hard way so that we can pass escontext */
2031 LOCAL_FCINFO(fcinfo, 1);
2032 Datum result;
2033
2034 InitFunctionCallInfoData(*fcinfo, &typcache->rng_canonical_finfo, 1,
2035 InvalidOid, escontext, NULL);
2036
2037 fcinfo->args[0].value = RangeTypePGetDatum(range);
2038 fcinfo->args[0].isnull = false;
2039
2040 result = FunctionCallInvoke(fcinfo);
2041
2042 if (SOFT_ERROR_OCCURRED(escontext))
2043 return NULL;
2044
2045 /* Should not get a null result if there was no error */
2046 if (fcinfo->isnull)
2047 elog(ERROR, "function %u returned NULL",
2048 typcache->rng_canonical_finfo.fn_oid);
2049
2050 range = DatumGetRangeTypeP(result);
2051 }
2052
2053 return range;
2054}
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:226
#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:35
RangeType * range_serialize(TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper, bool empty, struct Node *escontext)
Definition: rangetypes.c:1791
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 800 of file rangetypes.c.

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

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

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

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

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

2156{
2157 /*
2158 * First, handle cases involving infinity, which don't require invoking
2159 * the comparison proc.
2160 */
2161 if (b1->infinite && b2->infinite)
2162 {
2163 /*
2164 * Both are infinity, so they are equal unless one is lower and the
2165 * other not.
2166 */
2167 if (b1->lower == b2->lower)
2168 return 0;
2169 else
2170 return b1->lower ? -1 : 1;
2171 }
2172 else if (b1->infinite)
2173 return b1->lower ? -1 : 1;
2174 else if (b2->infinite)
2175 return b2->lower ? 1 : -1;
2176
2177 /*
2178 * Both boundaries are finite, so compare the held values.
2179 */
2181 typcache->rng_collation,
2182 b1->val, b2->val));
2183}
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Definition: fmgr.c:1149
static int32 DatumGetInt32(Datum X)
Definition: postgres.h:207
bool infinite
Definition: rangetypes.h:64
Datum val
Definition: rangetypes.h:63
FmgrInfo rng_cmp_proc_finfo
Definition: typcache.h:102
Oid rng_collation
Definition: typcache.h:101

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

2081{
2082 int32 result;
2083
2084 /*
2085 * First, handle cases involving infinity, which don't require invoking
2086 * the comparison proc.
2087 */
2088 if (b1->infinite && b2->infinite)
2089 {
2090 /*
2091 * Both are infinity, so they are equal unless one is lower and the
2092 * other not.
2093 */
2094 if (b1->lower == b2->lower)
2095 return 0;
2096 else
2097 return b1->lower ? -1 : 1;
2098 }
2099 else if (b1->infinite)
2100 return b1->lower ? -1 : 1;
2101 else if (b2->infinite)
2102 return b2->lower ? 1 : -1;
2103
2104 /*
2105 * Both boundaries are finite, so compare the held values.
2106 */
2108 typcache->rng_collation,
2109 b1->val, b2->val));
2110
2111 /*
2112 * If the comparison is anything other than equal, we're done. If they
2113 * compare equal though, we still have to consider whether the boundaries
2114 * are inclusive or exclusive.
2115 */
2116 if (result == 0)
2117 {
2118 if (!b1->inclusive && !b2->inclusive)
2119 {
2120 /* both are exclusive */
2121 if (b1->lower == b2->lower)
2122 return 0;
2123 else
2124 return b1->lower ? 1 : -1;
2125 }
2126 else if (!b1->inclusive)
2127 return b1->lower ? 1 : -1;
2128 else if (!b2->inclusive)
2129 return b2->lower ? -1 : 1;
2130 else
2131 {
2132 /*
2133 * Both are inclusive and the values held are equal, so they are
2134 * equal regardless of whether they are upper or lower boundaries,
2135 * or a mix.
2136 */
2137 return 0;
2138 }
2139 }
2140
2141 return result;
2142}
int32_t int32
Definition: c.h:498

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_fast_cmp(), 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 2193 of file rangetypes.c.

2194{
2195 RangeType *r1 = *(RangeType **) key1;
2196 RangeType *r2 = *(RangeType **) key2;
2197 TypeCacheEntry *typcache = (TypeCacheEntry *) arg;
2198 RangeBound lower1;
2199 RangeBound upper1;
2200 RangeBound lower2;
2201 RangeBound upper2;
2202 bool empty1;
2203 bool empty2;
2204 int cmp;
2205
2206 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
2207 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
2208
2209 if (empty1 && empty2)
2210 cmp = 0;
2211 else if (empty1)
2212 cmp = -1;
2213 else if (empty2)
2214 cmp = 1;
2215 else
2216 {
2217 cmp = range_cmp_bounds(typcache, &lower1, &lower2);
2218 if (cmp == 0)
2219 cmp = range_cmp_bounds(typcache, &upper1, &upper2);
2220 }
2221
2222 return cmp;
2223}
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 2682 of file rangetypes.c.

2683{
2684 return range_contains_internal(typcache, r2, r1);
2685}
bool range_contains_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:2650

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

2692{
2695 bool empty;
2696 int32 cmp;
2697
2698 range_deserialize(typcache, r, &lower, &upper, &empty);
2699
2700 if (empty)
2701 return false;
2702
2703 if (!lower.infinite)
2704 {
2706 typcache->rng_collation,
2707 lower.val, val));
2708 if (cmp > 0)
2709 return false;
2710 if (cmp == 0 && !lower.inclusive)
2711 return false;
2712 }
2713
2714 if (!upper.infinite)
2715 {
2717 typcache->rng_collation,
2718 upper.val, val));
2719 if (cmp < 0)
2720 return false;
2721 if (cmp == 0 && !upper.inclusive)
2722 return false;
2723 }
2724
2725 return true;
2726}
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 2650 of file rangetypes.c.

2651{
2652 RangeBound lower1;
2653 RangeBound upper1;
2654 bool empty1;
2655 RangeBound lower2;
2656 RangeBound upper2;
2657 bool empty2;
2658
2659 /* Different types should be prevented by ANYRANGE matching rules */
2660 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
2661 elog(ERROR, "range types do not match");
2662
2663 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
2664 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
2665
2666 /* If either range is empty, the answer is easy */
2667 if (empty2)
2668 return true;
2669 else if (empty1)
2670 return false;
2671
2672 /* Else we must have lower1 <= lower2 and upper1 >= upper2 */
2673 if (range_cmp_bounds(typcache, &lower1, &lower2) > 0)
2674 return false;
2675 if (range_cmp_bounds(typcache, &upper1, &upper2) < 0)
2676 return false;
2677
2678 return true;
2679}

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

1922{
1923 char flags;
1924 int16 typlen;
1925 bool typbyval;
1926 char typalign;
1927 Pointer ptr;
1928 Datum lbound;
1929 Datum ubound;
1930
1931 /* assert caller passed the right typcache entry */
1932 Assert(RangeTypeGetOid(range) == typcache->type_id);
1933
1934 /* fetch the flag byte from datum's last byte */
1935 flags = *((const char *) range + VARSIZE(range) - 1);
1936
1937 /* fetch information about range's element type */
1938 typlen = typcache->rngelemtype->typlen;
1939 typbyval = typcache->rngelemtype->typbyval;
1940 typalign = typcache->rngelemtype->typalign;
1941
1942 /* initialize data pointer just after the range OID */
1943 ptr = (Pointer) (range + 1);
1944
1945 /* fetch lower bound, if any */
1946 if (RANGE_HAS_LBOUND(flags))
1947 {
1948 /* att_align_pointer cannot be necessary here */
1949 lbound = fetch_att(ptr, typbyval, typlen);
1950 ptr = (Pointer) att_addlength_pointer(ptr, typlen, ptr);
1951 }
1952 else
1953 lbound = (Datum) 0;
1954
1955 /* fetch upper bound, if any */
1956 if (RANGE_HAS_UBOUND(flags))
1957 {
1958 ptr = (Pointer) att_align_pointer(ptr, typalign, typlen, ptr);
1959 ubound = fetch_att(ptr, typbyval, typlen);
1960 /* no need for att_addlength_pointer */
1961 }
1962 else
1963 ubound = (Datum) 0;
1964
1965 /* emit results */
1966
1967 *empty = (flags & RANGE_EMPTY) != 0;
1968
1969 lower->val = lbound;
1970 lower->infinite = (flags & RANGE_LB_INF) != 0;
1971 lower->inclusive = (flags & RANGE_LB_INC) != 0;
1972 lower->lower = true;
1973
1974 upper->val = ubound;
1975 upper->infinite = (flags & RANGE_UB_INF) != 0;
1976 upper->inclusive = (flags & RANGE_UB_INC) != 0;
1977 upper->lower = false;
1978}
char * Pointer
Definition: c.h:493
int16_t int16
Definition: c.h:497
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:99
bool typbyval
Definition: typcache.h:40
int16 typlen
Definition: typcache.h:39
#define att_align_pointer(cur_offset, attalign, attlen, attptr)
Definition: tupmacs.h: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_fast_cmp(), 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 575 of file rangetypes.c.

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

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

1988{
1989 /* fetch the flag byte from datum's last byte */
1990 return *((char *) range + VARSIZE(range) - 1);
1991}

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

1768{
1769 TypeCacheEntry *typcache = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
1770
1771 if (typcache == NULL ||
1772 typcache->type_id != rngtypid)
1773 {
1774 typcache = lookup_type_cache(rngtypid, TYPECACHE_RANGE_INFO);
1775 if (typcache->rngelemtype == NULL)
1776 elog(ERROR, "type %u is not a range type", rngtypid);
1777 fcinfo->flinfo->fn_extra = typcache;
1778 }
1779
1780 return typcache;
1781}
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:81
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:149

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

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

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

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

621{
622 return (!range_eq_internal(typcache, r1, r2));
623}
bool range_eq_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:575

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

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

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

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

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

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

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

1793{
1795 int cmp;
1796 Size msize;
1797 Pointer ptr;
1798 int16 typlen;
1799 bool typbyval;
1800 char typalign;
1801 char typstorage;
1802 char flags = 0;
1803
1804 /*
1805 * Verify range is not invalid on its face, and construct flags value,
1806 * preventing any non-canonical combinations such as infinite+inclusive.
1807 */
1808 Assert(lower->lower);
1809 Assert(!upper->lower);
1810
1811 if (empty)
1812 flags |= RANGE_EMPTY;
1813 else
1814 {
1815 cmp = range_cmp_bound_values(typcache, lower, upper);
1816
1817 /* error check: if lower bound value is above upper, it's wrong */
1818 if (cmp > 0)
1819 ereturn(escontext, NULL,
1820 (errcode(ERRCODE_DATA_EXCEPTION),
1821 errmsg("range lower bound must be less than or equal to range upper bound")));
1822
1823 /* if bounds are equal, and not both inclusive, range is empty */
1824 if (cmp == 0 && !(lower->inclusive && upper->inclusive))
1825 flags |= RANGE_EMPTY;
1826 else
1827 {
1828 /* infinite boundaries are never inclusive */
1829 if (lower->infinite)
1830 flags |= RANGE_LB_INF;
1831 else if (lower->inclusive)
1832 flags |= RANGE_LB_INC;
1833 if (upper->infinite)
1834 flags |= RANGE_UB_INF;
1835 else if (upper->inclusive)
1836 flags |= RANGE_UB_INC;
1837 }
1838 }
1839
1840 /* Fetch information about range's element type */
1841 typlen = typcache->rngelemtype->typlen;
1842 typbyval = typcache->rngelemtype->typbyval;
1843 typalign = typcache->rngelemtype->typalign;
1844 typstorage = typcache->rngelemtype->typstorage;
1845
1846 /* Count space for varlena header and range type's OID */
1847 msize = sizeof(RangeType);
1848 Assert(msize == MAXALIGN(msize));
1849
1850 /* Count space for bounds */
1851 if (RANGE_HAS_LBOUND(flags))
1852 {
1853 /*
1854 * Make sure item to be inserted is not toasted. It is essential that
1855 * we not insert an out-of-line toast value pointer into a range
1856 * object, for the same reasons that arrays and records can't contain
1857 * them. It would work to store a compressed-in-line value, but we
1858 * prefer to decompress and then let compression be applied to the
1859 * whole range object if necessary. But, unlike arrays, we do allow
1860 * short-header varlena objects to stay as-is.
1861 */
1862 if (typlen == -1)
1864
1865 msize = datum_compute_size(msize, lower->val, typbyval, typalign,
1866 typlen, typstorage);
1867 }
1868
1869 if (RANGE_HAS_UBOUND(flags))
1870 {
1871 /* Make sure item to be inserted is not toasted */
1872 if (typlen == -1)
1874
1875 msize = datum_compute_size(msize, upper->val, typbyval, typalign,
1876 typlen, typstorage);
1877 }
1878
1879 /* Add space for flag byte */
1880 msize += sizeof(char);
1881
1882 /* Note: zero-fill is required here, just as in heap tuples */
1883 range = (RangeType *) palloc0(msize);
1884 SET_VARSIZE(range, msize);
1885
1886 /* Now fill in the datum */
1887 range->rangetypid = typcache->type_id;
1888
1889 ptr = (char *) (range + 1);
1890
1891 if (RANGE_HAS_LBOUND(flags))
1892 {
1893 Assert(lower->lower);
1894 ptr = datum_write(ptr, lower->val, typbyval, typalign, typlen,
1895 typstorage);
1896 }
1897
1898 if (RANGE_HAS_UBOUND(flags))
1899 {
1900 Assert(!upper->lower);
1901 ptr = datum_write(ptr, upper->val, typbyval, typalign, typlen,
1902 typstorage);
1903 }
1904
1905 *((char *) ptr) = flags;
1906
1907 return range;
1908}
#define MAXALIGN(LEN)
Definition: c.h:782
size_t Size
Definition: c.h:576
#define ereturn(context, dummy_value,...)
Definition: elog.h:278
#define PG_DETOAST_DATUM_PACKED(datum)
Definition: fmgr.h:248
void * palloc0(Size size)
Definition: mcxt.c:1969
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:327
static Pointer datum_write(Pointer ptr, Datum datum, bool typbyval, char typalign, int16 typlen, char typstorage)
Definition: rangetypes.c:2773
static Size datum_compute_size(Size data_length, Datum val, bool typbyval, char typalign, int16 typlen, char typstorage)
Definition: rangetypes.c:2747
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 2001 of file rangetypes.c.

2002{
2003 char *flagsp;
2004
2005 /* flag byte is datum's last byte */
2006 flagsp = (char *) range + VARSIZE(range) - 1;
2007
2008 *flagsp |= RANGE_CONTAIN_EMPTY;
2009}
#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 1184 of file rangetypes.c.

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

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

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

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