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

Go to the source code of this file.

Data Structures

struct  RangeType
 
struct  RangeBound
 

Macros

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

Functions

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

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

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

2398{
2401
2402 lower.val = (Datum) 0;
2403 lower.infinite = false;
2404 lower.inclusive = false;
2405 lower.lower = true;
2406
2407 upper.val = (Datum) 0;
2408 upper.infinite = false;
2409 upper.inclusive = false;
2410 upper.lower = false;
2411
2412 return make_range(typcache, &lower, &upper, true, NULL);
2413}
Datum lower(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:49
Datum upper(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:80
uint64_t Datum
Definition: postgres.h:70

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

2186{
2188
2189 range = range_serialize(typcache, lower, upper, empty, escontext);
2190
2191 if (SOFT_ERROR_OCCURRED(escontext))
2192 return NULL;
2193
2194 /* no need to call canonical on empty ranges ... */
2195 if (OidIsValid(typcache->rng_canonical_finfo.fn_oid) &&
2197 {
2198 /* Do this the hard way so that we can pass escontext */
2199 LOCAL_FCINFO(fcinfo, 1);
2200 Datum result;
2201
2202 InitFunctionCallInfoData(*fcinfo, &typcache->rng_canonical_finfo, 1,
2203 InvalidOid, escontext, NULL);
2204
2205 fcinfo->args[0].value = RangeTypePGetDatum(range);
2206 fcinfo->args[0].isnull = false;
2207
2208 result = FunctionCallInvoke(fcinfo);
2209
2210 if (SOFT_ERROR_OCCURRED(escontext))
2211 return NULL;
2212
2213 /* Should not get a null result if there was no error */
2214 if (fcinfo->isnull)
2215 elog(ERROR, "function %u returned NULL",
2216 typcache->rng_canonical_finfo.fn_oid);
2217
2218 range = DatumGetRangeTypeP(result);
2219 }
2220
2221 return range;
2222}
#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:37
RangeType * range_serialize(TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper, bool empty, struct Node *escontext)
Definition: rangetypes.c:1959
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_minus_multi_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 802 of file rangetypes.c.

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

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

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

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

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

2324{
2325 /*
2326 * First, handle cases involving infinity, which don't require invoking
2327 * the comparison proc.
2328 */
2329 if (b1->infinite && b2->infinite)
2330 {
2331 /*
2332 * Both are infinity, so they are equal unless one is lower and the
2333 * other not.
2334 */
2335 if (b1->lower == b2->lower)
2336 return 0;
2337 else
2338 return b1->lower ? -1 : 1;
2339 }
2340 else if (b1->infinite)
2341 return b1->lower ? -1 : 1;
2342 else if (b2->infinite)
2343 return b2->lower ? 1 : -1;
2344
2345 /*
2346 * Both boundaries are finite, so compare the held values.
2347 */
2349 typcache->rng_collation,
2350 b1->val, b2->val));
2351}
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Definition: fmgr.c:1150
static int32 DatumGetInt32(Datum X)
Definition: postgres.h:212
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 2248 of file rangetypes.c.

2249{
2250 int32 result;
2251
2252 /*
2253 * First, handle cases involving infinity, which don't require invoking
2254 * the comparison proc.
2255 */
2256 if (b1->infinite && b2->infinite)
2257 {
2258 /*
2259 * Both are infinity, so they are equal unless one is lower and the
2260 * other not.
2261 */
2262 if (b1->lower == b2->lower)
2263 return 0;
2264 else
2265 return b1->lower ? -1 : 1;
2266 }
2267 else if (b1->infinite)
2268 return b1->lower ? -1 : 1;
2269 else if (b2->infinite)
2270 return b2->lower ? 1 : -1;
2271
2272 /*
2273 * Both boundaries are finite, so compare the held values.
2274 */
2276 typcache->rng_collation,
2277 b1->val, b2->val));
2278
2279 /*
2280 * If the comparison is anything other than equal, we're done. If they
2281 * compare equal though, we still have to consider whether the boundaries
2282 * are inclusive or exclusive.
2283 */
2284 if (result == 0)
2285 {
2286 if (!b1->inclusive && !b2->inclusive)
2287 {
2288 /* both are exclusive */
2289 if (b1->lower == b2->lower)
2290 return 0;
2291 else
2292 return b1->lower ? 1 : -1;
2293 }
2294 else if (!b1->inclusive)
2295 return b1->lower ? 1 : -1;
2296 else if (!b2->inclusive)
2297 return b2->lower ? -1 : 1;
2298 else
2299 {
2300 /*
2301 * Both are inclusive and the values held are equal, so they are
2302 * equal regardless of whether they are upper or lower boundaries,
2303 * or a mix.
2304 */
2305 return 0;
2306 }
2307 }
2308
2309 return result;
2310}
int32_t int32
Definition: c.h:537

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

2362{
2363 RangeType *r1 = *(RangeType **) key1;
2364 RangeType *r2 = *(RangeType **) key2;
2365 TypeCacheEntry *typcache = (TypeCacheEntry *) arg;
2366 RangeBound lower1;
2367 RangeBound upper1;
2368 RangeBound lower2;
2369 RangeBound upper2;
2370 bool empty1;
2371 bool empty2;
2372 int cmp;
2373
2374 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
2375 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
2376
2377 if (empty1 && empty2)
2378 cmp = 0;
2379 else if (empty1)
2380 cmp = -1;
2381 else if (empty2)
2382 cmp = 1;
2383 else
2384 {
2385 cmp = range_cmp_bounds(typcache, &lower1, &lower2);
2386 if (cmp == 0)
2387 cmp = range_cmp_bounds(typcache, &upper1, &upper2);
2388 }
2389
2390 return cmp;
2391}
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 2850 of file rangetypes.c.

2851{
2852 return range_contains_internal(typcache, r2, r1);
2853}
bool range_contains_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:2818

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

2860{
2863 bool empty;
2864 int32 cmp;
2865
2866 range_deserialize(typcache, r, &lower, &upper, &empty);
2867
2868 if (empty)
2869 return false;
2870
2871 if (!lower.infinite)
2872 {
2874 typcache->rng_collation,
2875 lower.val, val));
2876 if (cmp > 0)
2877 return false;
2878 if (cmp == 0 && !lower.inclusive)
2879 return false;
2880 }
2881
2882 if (!upper.infinite)
2883 {
2885 typcache->rng_collation,
2886 upper.val, val));
2887 if (cmp < 0)
2888 return false;
2889 if (cmp == 0 && !upper.inclusive)
2890 return false;
2891 }
2892
2893 return true;
2894}
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 2818 of file rangetypes.c.

2819{
2820 RangeBound lower1;
2821 RangeBound upper1;
2822 bool empty1;
2823 RangeBound lower2;
2824 RangeBound upper2;
2825 bool empty2;
2826
2827 /* Different types should be prevented by ANYRANGE matching rules */
2828 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
2829 elog(ERROR, "range types do not match");
2830
2831 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
2832 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
2833
2834 /* If either range is empty, the answer is easy */
2835 if (empty2)
2836 return true;
2837 else if (empty1)
2838 return false;
2839
2840 /* Else we must have lower1 <= lower2 and upper1 >= upper2 */
2841 if (range_cmp_bounds(typcache, &lower1, &lower2) > 0)
2842 return false;
2843 if (range_cmp_bounds(typcache, &upper1, &upper2) < 0)
2844 return false;
2845
2846 return true;
2847}

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

2090{
2091 char flags;
2092 int16 typlen;
2093 bool typbyval;
2094 char typalign;
2095 const char *ptr;
2096 Datum lbound;
2097 Datum ubound;
2098
2099 /* assert caller passed the right typcache entry */
2100 Assert(RangeTypeGetOid(range) == typcache->type_id);
2101
2102 /* fetch the flag byte from datum's last byte */
2103 flags = *((const char *) range + VARSIZE(range) - 1);
2104
2105 /* fetch information about range's element type */
2106 typlen = typcache->rngelemtype->typlen;
2107 typbyval = typcache->rngelemtype->typbyval;
2108 typalign = typcache->rngelemtype->typalign;
2109
2110 /* initialize data pointer just after the range OID */
2111 ptr = (char *) (range + 1);
2112
2113 /* fetch lower bound, if any */
2114 if (RANGE_HAS_LBOUND(flags))
2115 {
2116 /* att_align_pointer cannot be necessary here */
2117 lbound = fetch_att(ptr, typbyval, typlen);
2118 ptr = (char *) att_addlength_pointer(ptr, typlen, ptr);
2119 }
2120 else
2121 lbound = (Datum) 0;
2122
2123 /* fetch upper bound, if any */
2124 if (RANGE_HAS_UBOUND(flags))
2125 {
2126 ptr = (char *) att_align_pointer(ptr, typalign, typlen, ptr);
2127 ubound = fetch_att(ptr, typbyval, typlen);
2128 /* no need for att_addlength_pointer */
2129 }
2130 else
2131 ubound = (Datum) 0;
2132
2133 /* emit results */
2134
2135 *empty = (flags & RANGE_EMPTY) != 0;
2136
2137 lower->val = lbound;
2138 lower->infinite = (flags & RANGE_LB_INF) != 0;
2139 lower->inclusive = (flags & RANGE_LB_INC) != 0;
2140 lower->lower = true;
2141
2142 upper->val = ubound;
2143 upper->infinite = (flags & RANGE_UB_INF) != 0;
2144 upper->inclusive = (flags & RANGE_UB_INC) != 0;
2145 upper->lower = false;
2146}
int16_t int16
Definition: c.h:536
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:113
#define att_addlength_pointer(cur_offset, attlen, attptr)
Definition: tupmacs.h:180
static Datum fetch_att(const void *T, bool attbyval, int attlen)
Definition: tupmacs.h:50
static Size VARSIZE(const void *PTR)
Definition: varatt.h:298

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

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

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

2156{
2157 /* fetch the flag byte from datum's last byte */
2158 return *((char *) range + VARSIZE(range) - 1);
2159}

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

1936{
1937 TypeCacheEntry *typcache = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
1938
1939 if (typcache == NULL ||
1940 typcache->type_id != rngtypid)
1941 {
1942 typcache = lookup_type_cache(rngtypid, TYPECACHE_RANGE_INFO);
1943 if (typcache->rngelemtype == NULL)
1944 elog(ERROR, "type %u is not a range type", rngtypid);
1945 fcinfo->flinfo->fn_extra = typcache;
1946 }
1947
1948 return typcache;
1949}
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 1147 of file rangetypes.c.

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

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

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

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

void range_minus_multi_internal ( TypeCacheEntry typcache,
RangeType r1,
RangeType r2,
RangeType **  outputs,
int *  outputn 
)

Definition at line 1306 of file rangetypes.c.

1308{
1309 int cmp_l1l2,
1310 cmp_l1u2,
1311 cmp_u1l2,
1312 cmp_u1u2;
1313 RangeBound lower1,
1314 lower2;
1315 RangeBound upper1,
1316 upper2;
1317 bool empty1,
1318 empty2;
1319
1320 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
1321 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
1322
1323 if (empty1)
1324 {
1325 /* if r1 is empty then r1 - r2 is empty, so return zero results */
1326 *outputn = 0;
1327 return;
1328 }
1329 else if (empty2)
1330 {
1331 /* r2 is empty so the result is just r1 (which we know is not empty) */
1332 outputs[0] = r1;
1333 *outputn = 1;
1334 return;
1335 }
1336
1337 /*
1338 * Use the same logic as range_minus_internal, but support the split case
1339 */
1340 cmp_l1l2 = range_cmp_bounds(typcache, &lower1, &lower2);
1341 cmp_l1u2 = range_cmp_bounds(typcache, &lower1, &upper2);
1342 cmp_u1l2 = range_cmp_bounds(typcache, &upper1, &lower2);
1343 cmp_u1u2 = range_cmp_bounds(typcache, &upper1, &upper2);
1344
1345 if (cmp_l1l2 < 0 && cmp_u1u2 > 0)
1346 {
1347 lower2.inclusive = !lower2.inclusive;
1348 lower2.lower = false; /* it will become the upper bound */
1349 outputs[0] = make_range(typcache, &lower1, &lower2, false, NULL);
1350
1351 upper2.inclusive = !upper2.inclusive;
1352 upper2.lower = true; /* it will become the lower bound */
1353 outputs[1] = make_range(typcache, &upper2, &upper1, false, NULL);
1354
1355 *outputn = 2;
1356 }
1357 else if (cmp_l1u2 > 0 || cmp_u1l2 < 0)
1358 {
1359 outputs[0] = r1;
1360 *outputn = 1;
1361 }
1362 else if (cmp_l1l2 >= 0 && cmp_u1u2 <= 0)
1363 {
1364 *outputn = 0;
1365 }
1366 else if (cmp_l1l2 <= 0 && cmp_u1l2 >= 0 && cmp_u1u2 <= 0)
1367 {
1368 lower2.inclusive = !lower2.inclusive;
1369 lower2.lower = false; /* it will become the upper bound */
1370 outputs[0] = make_range(typcache, &lower1, &lower2, false, NULL);
1371 *outputn = 1;
1372 }
1373 else if (cmp_l1l2 >= 0 && cmp_u1u2 >= 0 && cmp_l1u2 <= 0)
1374 {
1375 upper2.inclusive = !upper2.inclusive;
1376 upper2.lower = true; /* it will become the lower bound */
1377 outputs[0] = make_range(typcache, &upper2, &upper1, false, NULL);
1378 *outputn = 1;
1379 }
1380 else
1381 {
1382 elog(ERROR, "unexpected case in range_minus_multi");
1383 }
1384}

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

Referenced by range_minus_multi().

◆ range_ne_internal()

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

Definition at line 622 of file rangetypes.c.

623{
624 return (!range_eq_internal(typcache, r1, r2));
625}
bool range_eq_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:577

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

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

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

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

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

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

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

1961{
1963 int cmp;
1964 Size msize;
1965 Pointer ptr;
1966 int16 typlen;
1967 bool typbyval;
1968 char typalign;
1969 char typstorage;
1970 char flags = 0;
1971
1972 /*
1973 * Verify range is not invalid on its face, and construct flags value,
1974 * preventing any non-canonical combinations such as infinite+inclusive.
1975 */
1976 Assert(lower->lower);
1977 Assert(!upper->lower);
1978
1979 if (empty)
1980 flags |= RANGE_EMPTY;
1981 else
1982 {
1983 cmp = range_cmp_bound_values(typcache, lower, upper);
1984
1985 /* error check: if lower bound value is above upper, it's wrong */
1986 if (cmp > 0)
1987 ereturn(escontext, NULL,
1988 (errcode(ERRCODE_DATA_EXCEPTION),
1989 errmsg("range lower bound must be less than or equal to range upper bound")));
1990
1991 /* if bounds are equal, and not both inclusive, range is empty */
1992 if (cmp == 0 && !(lower->inclusive && upper->inclusive))
1993 flags |= RANGE_EMPTY;
1994 else
1995 {
1996 /* infinite boundaries are never inclusive */
1997 if (lower->infinite)
1998 flags |= RANGE_LB_INF;
1999 else if (lower->inclusive)
2000 flags |= RANGE_LB_INC;
2001 if (upper->infinite)
2002 flags |= RANGE_UB_INF;
2003 else if (upper->inclusive)
2004 flags |= RANGE_UB_INC;
2005 }
2006 }
2007
2008 /* Fetch information about range's element type */
2009 typlen = typcache->rngelemtype->typlen;
2010 typbyval = typcache->rngelemtype->typbyval;
2011 typalign = typcache->rngelemtype->typalign;
2012 typstorage = typcache->rngelemtype->typstorage;
2013
2014 /* Count space for varlena header and range type's OID */
2015 msize = sizeof(RangeType);
2016 Assert(msize == MAXALIGN(msize));
2017
2018 /* Count space for bounds */
2019 if (RANGE_HAS_LBOUND(flags))
2020 {
2021 /*
2022 * Make sure item to be inserted is not toasted. It is essential that
2023 * we not insert an out-of-line toast value pointer into a range
2024 * object, for the same reasons that arrays and records can't contain
2025 * them. It would work to store a compressed-in-line value, but we
2026 * prefer to decompress and then let compression be applied to the
2027 * whole range object if necessary. But, unlike arrays, we do allow
2028 * short-header varlena objects to stay as-is.
2029 */
2030 if (typlen == -1)
2032
2033 msize = datum_compute_size(msize, lower->val, typbyval, typalign,
2034 typlen, typstorage);
2035 }
2036
2037 if (RANGE_HAS_UBOUND(flags))
2038 {
2039 /* Make sure item to be inserted is not toasted */
2040 if (typlen == -1)
2042
2043 msize = datum_compute_size(msize, upper->val, typbyval, typalign,
2044 typlen, typstorage);
2045 }
2046
2047 /* Add space for flag byte */
2048 msize += sizeof(char);
2049
2050 /* Note: zero-fill is required here, just as in heap tuples */
2051 range = (RangeType *) palloc0(msize);
2052 SET_VARSIZE(range, msize);
2053
2054 /* Now fill in the datum */
2055 range->rangetypid = typcache->type_id;
2056
2057 ptr = (char *) (range + 1);
2058
2059 if (RANGE_HAS_LBOUND(flags))
2060 {
2061 Assert(lower->lower);
2062 ptr = datum_write(ptr, lower->val, typbyval, typalign, typlen,
2063 typstorage);
2064 }
2065
2066 if (RANGE_HAS_UBOUND(flags))
2067 {
2068 Assert(!upper->lower);
2069 ptr = datum_write(ptr, upper->val, typbyval, typalign, typlen,
2070 typstorage);
2071 }
2072
2073 *((char *) ptr) = flags;
2074
2075 return range;
2076}
#define MAXALIGN(LEN)
Definition: c.h:813
void * Pointer
Definition: c.h:532
size_t Size
Definition: c.h:613
#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:1395
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:332
static char * datum_write(char *ptr, Datum datum, bool typbyval, char typalign, int16 typlen, char typstorage)
Definition: rangetypes.c:2941
static Size datum_compute_size(Size data_length, Datum val, bool typbyval, char typalign, int16 typlen, char typstorage)
Definition: rangetypes.c:2915
char typstorage
Definition: typcache.h:42
static void SET_VARSIZE(void *PTR, Size len)
Definition: varatt.h:432

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

2170{
2171 char *flagsp;
2172
2173 /* flag byte is datum's last byte */
2174 flagsp = (char *) range + VARSIZE(range) - 1;
2175
2176 *flagsp |= RANGE_CONTAIN_EMPTY;
2177}
#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 1186 of file rangetypes.c.

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

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

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

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