Thanks to visit codestin.com
Credit goes to doxygen.postgresql.org

PostgreSQL Source Code git master
rangetypes.c File Reference
#include "postgres.h"
#include "common/hashfn.h"
#include "libpq/pqformat.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "nodes/miscnodes.h"
#include "nodes/supportnodes.h"
#include "optimizer/clauses.h"
#include "optimizer/cost.h"
#include "optimizer/optimizer.h"
#include "utils/builtins.h"
#include "utils/date.h"
#include "utils/lsyscache.h"
#include "utils/rangetypes.h"
#include "utils/sortsupport.h"
#include "utils/timestamp.h"
#include "varatt.h"
Include dependency graph for rangetypes.c:

Go to the source code of this file.

Data Structures

struct  RangeIOData
 

Macros

#define TYPE_IS_PACKABLE(typlen, typstorage)    ((typlen) == -1 && (typstorage) != TYPSTORAGE_PLAIN)
 

Typedefs

typedef struct RangeIOData RangeIOData
 

Functions

static RangeIODataget_range_io_data (FunctionCallInfo fcinfo, Oid rngtypid, IOFuncSelector func)
 
static int range_fast_cmp (Datum a, Datum b, SortSupport ssup)
 
static char range_parse_flags (const char *flags_str)
 
static bool range_parse (const char *string, char *flags, char **lbound_str, char **ubound_str, Node *escontext)
 
static const char * range_parse_bound (const char *string, const char *ptr, char **bound_str, bool *infinite, Node *escontext)
 
static char * range_deparse (char flags, const char *lbound_str, const char *ubound_str)
 
static char * range_bound_escape (const char *value)
 
static Size datum_compute_size (Size data_length, Datum val, bool typbyval, char typalign, int16 typlen, char typstorage)
 
static Pointer datum_write (Pointer ptr, Datum datum, bool typbyval, char typalign, int16 typlen, char typstorage)
 
static Nodefind_simplified_clause (PlannerInfo *root, Expr *rangeExpr, Expr *elemExpr)
 
static Exprbuild_bound_expr (Expr *elemExpr, Datum val, bool isLowerBound, bool isInclusive, TypeCacheEntry *typeCache, Oid opfamily, Oid rng_collation)
 
Datum range_in (PG_FUNCTION_ARGS)
 
Datum range_out (PG_FUNCTION_ARGS)
 
Datum range_recv (PG_FUNCTION_ARGS)
 
Datum range_send (PG_FUNCTION_ARGS)
 
Datum range_constructor2 (PG_FUNCTION_ARGS)
 
Datum range_constructor3 (PG_FUNCTION_ARGS)
 
Datum range_lower (PG_FUNCTION_ARGS)
 
Datum range_upper (PG_FUNCTION_ARGS)
 
Datum range_empty (PG_FUNCTION_ARGS)
 
Datum range_lower_inc (PG_FUNCTION_ARGS)
 
Datum range_upper_inc (PG_FUNCTION_ARGS)
 
Datum range_lower_inf (PG_FUNCTION_ARGS)
 
Datum range_upper_inf (PG_FUNCTION_ARGS)
 
Datum range_contains_elem (PG_FUNCTION_ARGS)
 
Datum elem_contained_by_range (PG_FUNCTION_ARGS)
 
bool range_eq_internal (TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
 
Datum range_eq (PG_FUNCTION_ARGS)
 
bool range_ne_internal (TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
 
Datum range_ne (PG_FUNCTION_ARGS)
 
Datum range_contains (PG_FUNCTION_ARGS)
 
Datum range_contained_by (PG_FUNCTION_ARGS)
 
bool range_before_internal (TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
 
Datum range_before (PG_FUNCTION_ARGS)
 
bool range_after_internal (TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
 
Datum range_after (PG_FUNCTION_ARGS)
 
bool bounds_adjacent (TypeCacheEntry *typcache, RangeBound boundA, RangeBound boundB)
 
bool range_adjacent_internal (TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
 
Datum range_adjacent (PG_FUNCTION_ARGS)
 
bool range_overlaps_internal (TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
 
Datum range_overlaps (PG_FUNCTION_ARGS)
 
bool range_overleft_internal (TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
 
Datum range_overleft (PG_FUNCTION_ARGS)
 
bool range_overright_internal (TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
 
Datum range_overright (PG_FUNCTION_ARGS)
 
Datum range_minus (PG_FUNCTION_ARGS)
 
RangeTyperange_minus_internal (TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
 
RangeTyperange_union_internal (TypeCacheEntry *typcache, RangeType *r1, RangeType *r2, bool strict)
 
Datum range_union (PG_FUNCTION_ARGS)
 
Datum range_merge (PG_FUNCTION_ARGS)
 
Datum range_intersect (PG_FUNCTION_ARGS)
 
RangeTyperange_intersect_internal (TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
 
bool range_split_internal (TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2, RangeType **output1, RangeType **output2)
 
Datum range_intersect_agg_transfn (PG_FUNCTION_ARGS)
 
Datum range_cmp (PG_FUNCTION_ARGS)
 
Datum range_sortsupport (PG_FUNCTION_ARGS)
 
Datum range_lt (PG_FUNCTION_ARGS)
 
Datum range_le (PG_FUNCTION_ARGS)
 
Datum range_ge (PG_FUNCTION_ARGS)
 
Datum range_gt (PG_FUNCTION_ARGS)
 
Datum hash_range (PG_FUNCTION_ARGS)
 
Datum hash_range_extended (PG_FUNCTION_ARGS)
 
Datum int4range_canonical (PG_FUNCTION_ARGS)
 
Datum int8range_canonical (PG_FUNCTION_ARGS)
 
Datum daterange_canonical (PG_FUNCTION_ARGS)
 
Datum int4range_subdiff (PG_FUNCTION_ARGS)
 
Datum int8range_subdiff (PG_FUNCTION_ARGS)
 
Datum numrange_subdiff (PG_FUNCTION_ARGS)
 
Datum daterange_subdiff (PG_FUNCTION_ARGS)
 
Datum tsrange_subdiff (PG_FUNCTION_ARGS)
 
Datum tstzrange_subdiff (PG_FUNCTION_ARGS)
 
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)
 
RangeTypemake_empty_range (TypeCacheEntry *typcache)
 
Datum elem_contained_by_range_support (PG_FUNCTION_ARGS)
 
Datum range_contains_elem_support (PG_FUNCTION_ARGS)
 
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_contains_elem_internal (TypeCacheEntry *typcache, const RangeType *r, Datum val)
 

Macro Definition Documentation

◆ TYPE_IS_PACKABLE

#define TYPE_IS_PACKABLE (   typlen,
  typstorage 
)     ((typlen) == -1 && (typstorage) != TYPSTORAGE_PLAIN)

Definition at line 2738 of file rangetypes.c.

Typedef Documentation

◆ RangeIOData

typedef struct RangeIOData RangeIOData

Function Documentation

◆ bounds_adjacent()

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

Definition at line 758 of file rangetypes.c.

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

◆ build_bound_expr()

static Expr * build_bound_expr ( Expr elemExpr,
Datum  val,
bool  isLowerBound,
bool  isInclusive,
TypeCacheEntry typeCache,
Oid  opfamily,
Oid  rng_collation 
)
static

Definition at line 2971 of file rangetypes.c.

2975{
2976 Oid elemType = typeCache->type_id;
2977 int16 elemTypeLen = typeCache->typlen;
2978 bool elemByValue = typeCache->typbyval;
2979 Oid elemCollation = typeCache->typcollation;
2980 int16 strategy;
2981 Oid oproid;
2982 Expr *constExpr;
2983
2984 /* Identify the comparison operator to use */
2985 if (isLowerBound)
2986 strategy = isInclusive ? BTGreaterEqualStrategyNumber : BTGreaterStrategyNumber;
2987 else
2988 strategy = isInclusive ? BTLessEqualStrategyNumber : BTLessStrategyNumber;
2989
2990 /*
2991 * We could use exprType(elemExpr) here, if it ever becomes possible that
2992 * elemExpr is not the exact same type as the range elements.
2993 */
2994 oproid = get_opfamily_member(opfamily, elemType, elemType, strategy);
2995
2996 /* We don't really expect failure here, but just in case ... */
2997 if (!OidIsValid(oproid))
2998 return NULL;
2999
3000 /* OK, convert "val" to a full-fledged Const node, and make the OpExpr */
3001 constExpr = (Expr *) makeConst(elemType,
3002 -1,
3003 elemCollation,
3004 elemTypeLen,
3005 val,
3006 false,
3007 elemByValue);
3008
3009 return make_opclause(oproid,
3010 BOOLOID,
3011 false,
3012 elemExpr,
3013 constExpr,
3014 InvalidOid,
3015 rng_collation);
3016}
int16_t int16
Definition: c.h:533
long val
Definition: informix.c:689
Oid get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype, int16 strategy)
Definition: lsyscache.c:168
Expr * make_opclause(Oid opno, Oid opresulttype, bool opretset, Expr *leftop, Expr *rightop, Oid opcollid, Oid inputcollid)
Definition: makefuncs.c:701
Const * makeConst(Oid consttype, int32 consttypmod, Oid constcollid, int constlen, Datum constvalue, bool constisnull, bool constbyval)
Definition: makefuncs.c:350
#define InvalidOid
Definition: postgres_ext.h:37
unsigned int Oid
Definition: postgres_ext.h:32
#define BTGreaterStrategyNumber
Definition: stratnum.h:33
#define BTLessStrategyNumber
Definition: stratnum.h:29
#define BTLessEqualStrategyNumber
Definition: stratnum.h:30
#define BTGreaterEqualStrategyNumber
Definition: stratnum.h:32
bool typbyval
Definition: typcache.h:40
int16 typlen
Definition: typcache.h:39
Oid typcollation
Definition: typcache.h:48

References BTGreaterEqualStrategyNumber, BTGreaterStrategyNumber, BTLessEqualStrategyNumber, BTLessStrategyNumber, get_opfamily_member(), InvalidOid, make_opclause(), makeConst(), OidIsValid, TypeCacheEntry::typbyval, TypeCacheEntry::typcollation, TypeCacheEntry::type_id, TypeCacheEntry::typlen, and val.

Referenced by find_simplified_clause().

◆ daterange_canonical()

Datum daterange_canonical ( PG_FUNCTION_ARGS  )

Definition at line 1621 of file rangetypes.c.

1622{
1624 Node *escontext = fcinfo->context;
1625 TypeCacheEntry *typcache;
1628 bool empty;
1629
1630 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1631
1632 range_deserialize(typcache, r, &lower, &upper, &empty);
1633
1634 if (empty)
1636
1637 if (!lower.infinite && !DATE_NOT_FINITE(DatumGetDateADT(lower.val)) &&
1638 !lower.inclusive)
1639 {
1640 DateADT bnd = DatumGetDateADT(lower.val);
1641
1642 /* Check for overflow -- note we already eliminated PG_INT32_MAX */
1643 bnd++;
1644 if (unlikely(!IS_VALID_DATE(bnd)))
1645 ereturn(escontext, (Datum) 0,
1646 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1647 errmsg("date out of range")));
1648 lower.val = DateADTGetDatum(bnd);
1649 lower.inclusive = true;
1650 }
1651
1652 if (!upper.infinite && !DATE_NOT_FINITE(DatumGetDateADT(upper.val)) &&
1653 upper.inclusive)
1654 {
1655 DateADT bnd = DatumGetDateADT(upper.val);
1656
1657 /* Check for overflow -- note we already eliminated PG_INT32_MAX */
1658 bnd++;
1659 if (unlikely(!IS_VALID_DATE(bnd)))
1660 ereturn(escontext, (Datum) 0,
1661 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1662 errmsg("date out of range")));
1663 upper.val = DateADTGetDatum(bnd);
1664 upper.inclusive = false;
1665 }
1666
1668 false, escontext));
1669}
#define unlikely(x)
Definition: c.h:402
#define IS_VALID_DATE(d)
Definition: timestamp.h:262
static Datum DateADTGetDatum(DateADT X)
Definition: date.h:72
#define DATE_NOT_FINITE(j)
Definition: date.h:43
int32 DateADT
Definition: date.h:23
static DateADT DatumGetDateADT(Datum X)
Definition: date.h:54
int errcode(int sqlerrcode)
Definition: elog.c:863
int errmsg(const char *fmt,...)
Definition: elog.c:1080
#define ereturn(context, dummy_value,...)
Definition: elog.h:278
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
RangeType * range_serialize(TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper, bool empty, struct Node *escontext)
Definition: rangetypes.c:1790
void range_deserialize(TypeCacheEntry *typcache, const RangeType *range, RangeBound *lower, RangeBound *upper, bool *empty)
Definition: rangetypes.c:1919
TypeCacheEntry * range_get_typcache(FunctionCallInfo fcinfo, Oid rngtypid)
Definition: rangetypes.c:1766
#define PG_RETURN_RANGE_P(x)
Definition: rangetypes.h:92
#define PG_GETARG_RANGE_P(n)
Definition: rangetypes.h:90
#define RangeTypeGetOid(r)
Definition: rangetypes.h:35
Definition: nodes.h:135

References DATE_NOT_FINITE, DateADTGetDatum(), DatumGetDateADT(), ereturn, errcode(), errmsg(), IS_VALID_DATE, lower(), PG_GETARG_RANGE_P, PG_RETURN_RANGE_P, range_deserialize(), range_get_typcache(), range_serialize(), RangeTypeGetOid, unlikely, and upper().

◆ daterange_subdiff()

Datum daterange_subdiff ( PG_FUNCTION_ARGS  )

Definition at line 1718 of file rangetypes.c.

1719{
1720 int32 v1 = PG_GETARG_INT32(0);
1721 int32 v2 = PG_GETARG_INT32(1);
1722
1723 PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
1724}
double float8
Definition: c.h:635
int32_t int32
Definition: c.h:534
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:367
#define PG_GETARG_INT32(n)
Definition: fmgr.h:269

References PG_GETARG_INT32, and PG_RETURN_FLOAT8.

◆ datum_compute_size()

static Size datum_compute_size ( Size  data_length,
Datum  val,
bool  typbyval,
char  typalign,
int16  typlen,
char  typstorage 
)
static

Definition at line 2746 of file rangetypes.c.

2748{
2749 if (TYPE_IS_PACKABLE(typlen, typstorage) &&
2751 {
2752 /*
2753 * we're anticipating converting to a short varlena header, so adjust
2754 * length and don't count any alignment
2755 */
2757 }
2758 else
2759 {
2760 data_length = att_align_datum(data_length, typalign, typlen, val);
2761 data_length = att_addlength_datum(data_length, typlen, val);
2762 }
2763
2764 return data_length;
2765}
char typalign
Definition: pg_type.h:176
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:322
#define TYPE_IS_PACKABLE(typlen, typstorage)
Definition: rangetypes.c:2738
#define att_align_datum(cur_offset, attalign, attlen, attdatum)
Definition: tupmacs.h:82
#define att_addlength_datum(cur_offset, attlen, attdatum)
Definition: tupmacs.h:168
static bool VARATT_CAN_MAKE_SHORT(const void *PTR)
Definition: varatt.h:417
static Size VARATT_CONVERTED_SHORT_SIZE(const void *PTR)
Definition: varatt.h:425

References att_addlength_datum, att_align_datum, DatumGetPointer(), typalign, TYPE_IS_PACKABLE, val, VARATT_CAN_MAKE_SHORT(), and VARATT_CONVERTED_SHORT_SIZE().

Referenced by range_serialize().

◆ datum_write()

static Pointer datum_write ( Pointer  ptr,
Datum  datum,
bool  typbyval,
char  typalign,
int16  typlen,
char  typstorage 
)
static

Definition at line 2772 of file rangetypes.c.

2774{
2775 Size data_length;
2776
2777 if (typbyval)
2778 {
2779 /* pass-by-value */
2780 ptr = (char *) att_align_nominal(ptr, typalign);
2781 store_att_byval(ptr, datum, typlen);
2782 data_length = typlen;
2783 }
2784 else if (typlen == -1)
2785 {
2786 /* varlena */
2787 Pointer val = DatumGetPointer(datum);
2788
2790 {
2791 /*
2792 * Throw error, because we must never put a toast pointer inside a
2793 * range object. Caller should have detoasted it.
2794 */
2795 elog(ERROR, "cannot store a toast pointer inside a range");
2796 data_length = 0; /* keep compiler quiet */
2797 }
2798 else if (VARATT_IS_SHORT(val))
2799 {
2800 /* no alignment for short varlenas */
2801 data_length = VARSIZE_SHORT(val);
2802 memcpy(ptr, val, data_length);
2803 }
2804 else if (TYPE_IS_PACKABLE(typlen, typstorage) &&
2806 {
2807 /* convert to short varlena -- no alignment */
2808 data_length = VARATT_CONVERTED_SHORT_SIZE(val);
2809 SET_VARSIZE_SHORT(ptr, data_length);
2810 memcpy(ptr + 1, VARDATA(val), data_length - 1);
2811 }
2812 else
2813 {
2814 /* full 4-byte header varlena */
2815 ptr = (char *) att_align_nominal(ptr, typalign);
2816 data_length = VARSIZE(val);
2817 memcpy(ptr, val, data_length);
2818 }
2819 }
2820 else if (typlen == -2)
2821 {
2822 /* cstring ... never needs alignment */
2823 Assert(typalign == TYPALIGN_CHAR);
2824 data_length = strlen(DatumGetCString(datum)) + 1;
2825 memcpy(ptr, DatumGetPointer(datum), data_length);
2826 }
2827 else
2828 {
2829 /* fixed-length pass-by-reference */
2830 ptr = (char *) att_align_nominal(ptr, typalign);
2831 Assert(typlen > 0);
2832 data_length = typlen;
2833 memcpy(ptr, DatumGetPointer(datum), data_length);
2834 }
2835
2836 ptr += data_length;
2837
2838 return ptr;
2839}
char * Pointer
Definition: c.h:529
size_t Size
Definition: c.h:610
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:226
static char * DatumGetCString(Datum X)
Definition: postgres.h:345
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:145
static void store_att_byval(void *T, Datum newdatum, int attlen)
Definition: tupmacs.h:206
static bool VARATT_IS_SHORT(const void *PTR)
Definition: varatt.h:403
static bool VARATT_IS_EXTERNAL(const void *PTR)
Definition: varatt.h:354
static Size VARSIZE(const void *PTR)
Definition: varatt.h:298
static char * VARDATA(const void *PTR)
Definition: varatt.h:305
static void SET_VARSIZE_SHORT(void *PTR, Size len)
Definition: varatt.h:439
static Size VARSIZE_SHORT(const void *PTR)
Definition: varatt.h:312

References Assert(), att_align_nominal, DatumGetCString(), DatumGetPointer(), elog, ERROR, SET_VARSIZE_SHORT(), store_att_byval(), typalign, TYPE_IS_PACKABLE, val, VARATT_CAN_MAKE_SHORT(), VARATT_CONVERTED_SHORT_SIZE(), VARATT_IS_EXTERNAL(), VARATT_IS_SHORT(), VARDATA(), VARSIZE(), and VARSIZE_SHORT().

Referenced by range_serialize().

◆ elem_contained_by_range()

Datum elem_contained_by_range ( PG_FUNCTION_ARGS  )

Definition at line 558 of file rangetypes.c.

559{
562 TypeCacheEntry *typcache;
563
564 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
565
567}
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:268
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
bool range_contains_elem_internal(TypeCacheEntry *typcache, const RangeType *r, Datum val)
Definition: rangetypes.c:2690

References PG_GETARG_DATUM, PG_GETARG_RANGE_P, PG_RETURN_BOOL, range_contains_elem_internal(), range_get_typcache(), RangeTypeGetOid, and val.

◆ elem_contained_by_range_support()

Datum elem_contained_by_range_support ( PG_FUNCTION_ARGS  )

Definition at line 2250 of file rangetypes.c.

2251{
2252 Node *rawreq = (Node *) PG_GETARG_POINTER(0);
2253 Node *ret = NULL;
2254
2255 if (IsA(rawreq, SupportRequestSimplify))
2256 {
2258 FuncExpr *fexpr = req->fcall;
2259 Expr *leftop,
2260 *rightop;
2261
2262 Assert(list_length(fexpr->args) == 2);
2263 leftop = linitial(fexpr->args);
2264 rightop = lsecond(fexpr->args);
2265
2266 ret = find_simplified_clause(req->root, rightop, leftop);
2267 }
2268
2269 PG_RETURN_POINTER(ret);
2270}
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:361
#define IsA(nodeptr, _type_)
Definition: nodes.h:164
static int list_length(const List *l)
Definition: pg_list.h:152
#define linitial(l)
Definition: pg_list.h:178
#define lsecond(l)
Definition: pg_list.h:183
static Node * find_simplified_clause(PlannerInfo *root, Expr *rangeExpr, Expr *elemExpr)
Definition: rangetypes.c:2849
List * args
Definition: primnodes.h:800
PlannerInfo * root
Definition: supportnodes.h:68

References FuncExpr::args, Assert(), SupportRequestSimplify::fcall, find_simplified_clause(), IsA, linitial, list_length(), lsecond, PG_GETARG_POINTER, PG_RETURN_POINTER, and SupportRequestSimplify::root.

◆ find_simplified_clause()

static Node * find_simplified_clause ( PlannerInfo root,
Expr rangeExpr,
Expr elemExpr 
)
static

Definition at line 2849 of file rangetypes.c.

2850{
2852 TypeCacheEntry *rangetypcache;
2855 bool empty;
2856
2857 /* can't do anything unless the range is a non-null constant */
2858 if (!IsA(rangeExpr, Const) || ((Const *) rangeExpr)->constisnull)
2859 return NULL;
2860 range = DatumGetRangeTypeP(((Const *) rangeExpr)->constvalue);
2861
2862 rangetypcache = lookup_type_cache(RangeTypeGetOid(range),
2864 if (rangetypcache->rngelemtype == NULL)
2865 elog(ERROR, "type %u is not a range type", RangeTypeGetOid(range));
2866
2867 range_deserialize(rangetypcache, range, &lower, &upper, &empty);
2868
2869 if (empty)
2870 {
2871 /* if the range is empty, then there can be no matches */
2872 return makeBoolConst(false, false);
2873 }
2874 else if (lower.infinite && upper.infinite)
2875 {
2876 /* the range has infinite bounds, so it matches everything */
2877 return makeBoolConst(true, false);
2878 }
2879 else
2880 {
2881 /* at least one bound is available, we have something to work with */
2882 TypeCacheEntry *elemTypcache = rangetypcache->rngelemtype;
2883 Oid opfamily = rangetypcache->rng_opfamily;
2884 Oid rng_collation = rangetypcache->rng_collation;
2885 Expr *lowerExpr = NULL;
2886 Expr *upperExpr = NULL;
2887
2888 if (!lower.infinite && !upper.infinite)
2889 {
2890 /*
2891 * When both bounds are present, we have a problem: the
2892 * "simplified" clause would need to evaluate the elemExpr twice.
2893 * That's definitely not okay if the elemExpr is volatile, and
2894 * it's also unattractive if the elemExpr is expensive.
2895 */
2896 QualCost eval_cost;
2897
2898 if (contain_volatile_functions((Node *) elemExpr))
2899 return NULL;
2900
2901 /*
2902 * We define "expensive" as "contains any subplan or more than 10
2903 * operators". Note that the subplan search has to be done
2904 * explicitly, since cost_qual_eval() will barf on unplanned
2905 * subselects.
2906 */
2907 if (contain_subplans((Node *) elemExpr))
2908 return NULL;
2909 cost_qual_eval_node(&eval_cost, (Node *) elemExpr, root);
2910 if (eval_cost.startup + eval_cost.per_tuple >
2911 10 * cpu_operator_cost)
2912 return NULL;
2913 }
2914
2915 /* Okay, try to build boundary comparison expressions */
2916 if (!lower.infinite)
2917 {
2918 lowerExpr = build_bound_expr(elemExpr,
2919 lower.val,
2920 true,
2921 lower.inclusive,
2922 elemTypcache,
2923 opfamily,
2924 rng_collation);
2925 if (lowerExpr == NULL)
2926 return NULL;
2927 }
2928
2929 if (!upper.infinite)
2930 {
2931 /* Copy the elemExpr if we need two copies */
2932 if (!lower.infinite)
2933 elemExpr = copyObject(elemExpr);
2934 upperExpr = build_bound_expr(elemExpr,
2935 upper.val,
2936 false,
2937 upper.inclusive,
2938 elemTypcache,
2939 opfamily,
2940 rng_collation);
2941 if (upperExpr == NULL)
2942 return NULL;
2943 }
2944
2945 if (lowerExpr != NULL && upperExpr != NULL)
2946 return (Node *) make_andclause(list_make2(lowerExpr, upperExpr));
2947 else if (lowerExpr != NULL)
2948 return (Node *) lowerExpr;
2949 else if (upperExpr != NULL)
2950 return (Node *) upperExpr;
2951 else
2952 {
2953 Assert(false);
2954 return NULL;
2955 }
2956 }
2957}
bool contain_subplans(Node *clause)
Definition: clauses.c:334
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:542
double cpu_operator_cost
Definition: costsize.c:134
void cost_qual_eval_node(QualCost *cost, Node *qual, PlannerInfo *root)
Definition: costsize.c:4817
Node * makeBoolConst(bool value, bool isnull)
Definition: makefuncs.c:408
Expr * make_andclause(List *andclauses)
Definition: makefuncs.c:727
#define copyObject(obj)
Definition: nodes.h:232
#define list_make2(x1, x2)
Definition: pg_list.h:214
tree ctl root
Definition: radixtree.h:1857
static Expr * build_bound_expr(Expr *elemExpr, Datum val, bool isLowerBound, bool isInclusive, TypeCacheEntry *typeCache, Oid opfamily, Oid rng_collation)
Definition: rangetypes.c:2971
static RangeType * DatumGetRangeTypeP(Datum X)
Definition: rangetypes.h:73
static struct cvec * range(struct vars *v, chr a, chr b, int cases)
Definition: regc_locale.c:412
Cost per_tuple
Definition: pathnodes.h:48
Cost startup
Definition: pathnodes.h:47
Oid rng_collation
Definition: typcache.h:101
struct TypeCacheEntry * rngelemtype
Definition: typcache.h:99
Oid rng_opfamily
Definition: typcache.h:100
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:386
#define TYPECACHE_RANGE_INFO
Definition: typcache.h:149

References Assert(), build_bound_expr(), contain_subplans(), contain_volatile_functions(), copyObject, cost_qual_eval_node(), cpu_operator_cost, DatumGetRangeTypeP(), elog, ERROR, IsA, list_make2, lookup_type_cache(), lower(), make_andclause(), makeBoolConst(), QualCost::per_tuple, range(), range_deserialize(), RangeTypeGetOid, TypeCacheEntry::rng_collation, TypeCacheEntry::rng_opfamily, TypeCacheEntry::rngelemtype, root, QualCost::startup, TYPECACHE_RANGE_INFO, and upper().

Referenced by elem_contained_by_range_support(), and range_contains_elem_support().

◆ get_range_io_data()

static RangeIOData * get_range_io_data ( FunctionCallInfo  fcinfo,
Oid  rngtypid,
IOFuncSelector  func 
)
static

Definition at line 318 of file rangetypes.c.

319{
320 RangeIOData *cache = (RangeIOData *) fcinfo->flinfo->fn_extra;
321
322 if (cache == NULL || cache->typcache->type_id != rngtypid)
323 {
324 int16 typlen;
325 bool typbyval;
326 char typalign;
327 char typdelim;
328 Oid typiofunc;
329
330 cache = (RangeIOData *) MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
331 sizeof(RangeIOData));
333 if (cache->typcache->rngelemtype == NULL)
334 elog(ERROR, "type %u is not a range type", rngtypid);
335
336 /* get_type_io_data does more than we need, but is convenient */
338 func,
339 &typlen,
340 &typbyval,
341 &typalign,
342 &typdelim,
343 &cache->typioparam,
344 &typiofunc);
345
346 if (!OidIsValid(typiofunc))
347 {
348 /* this could only happen for receive or send */
349 if (func == IOFunc_receive)
351 (errcode(ERRCODE_UNDEFINED_FUNCTION),
352 errmsg("no binary input function available for type %s",
354 else
356 (errcode(ERRCODE_UNDEFINED_FUNCTION),
357 errmsg("no binary output function available for type %s",
359 }
360 fmgr_info_cxt(typiofunc, &cache->typioproc,
361 fcinfo->flinfo->fn_mcxt);
362
363 fcinfo->flinfo->fn_extra = cache;
364 }
365
366 return cache;
367}
#define ereport(elevel,...)
Definition: elog.h:150
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:138
char * format_type_be(Oid type_oid)
Definition: format_type.c:343
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:81
void get_type_io_data(Oid typid, IOFuncSelector which_func, int16 *typlen, bool *typbyval, char *typalign, char *typdelim, Oid *typioparam, Oid *func)
Definition: lsyscache.c:2492
@ IOFunc_receive
Definition: lsyscache.h:38
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1229
void * fn_extra
Definition: fmgr.h:64
MemoryContext fn_mcxt
Definition: fmgr.h:65
FmgrInfo * flinfo
Definition: fmgr.h:87
TypeCacheEntry * typcache
Definition: rangetypes.c:54
FmgrInfo typioproc
Definition: rangetypes.c:55
Oid typioparam
Definition: rangetypes.c:56

References elog, ereport, errcode(), errmsg(), ERROR, FunctionCallInfoBaseData::flinfo, fmgr_info_cxt(), FmgrInfo::fn_extra, FmgrInfo::fn_mcxt, format_type_be(), get_type_io_data(), if(), IOFunc_receive, lookup_type_cache(), MemoryContextAlloc(), OidIsValid, TypeCacheEntry::rngelemtype, typalign, RangeIOData::typcache, TypeCacheEntry::type_id, TYPECACHE_RANGE_INFO, RangeIOData::typioparam, and RangeIOData::typioproc.

Referenced by range_in(), range_out(), range_recv(), and range_send().

◆ hash_range()

Datum hash_range ( PG_FUNCTION_ARGS  )

Definition at line 1393 of file rangetypes.c.

1394{
1396 uint32 result;
1397 TypeCacheEntry *typcache;
1398 TypeCacheEntry *scache;
1401 bool empty;
1402 char flags;
1403 uint32 lower_hash;
1404 uint32 upper_hash;
1405
1406 check_stack_depth(); /* recurses when subtype is a range type */
1407
1408 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1409
1410 /* deserialize */
1411 range_deserialize(typcache, r, &lower, &upper, &empty);
1412 flags = range_get_flags(r);
1413
1414 /*
1415 * Look up the element type's hash function, if not done already.
1416 */
1417 scache = typcache->rngelemtype;
1418 if (!OidIsValid(scache->hash_proc_finfo.fn_oid))
1419 {
1421 if (!OidIsValid(scache->hash_proc_finfo.fn_oid))
1422 ereport(ERROR,
1423 (errcode(ERRCODE_UNDEFINED_FUNCTION),
1424 errmsg("could not identify a hash function for type %s",
1425 format_type_be(scache->type_id))));
1426 }
1427
1428 /*
1429 * Apply the hash function to each bound.
1430 */
1431 if (RANGE_HAS_LBOUND(flags))
1432 lower_hash = DatumGetUInt32(FunctionCall1Coll(&scache->hash_proc_finfo,
1433 typcache->rng_collation,
1434 lower.val));
1435 else
1436 lower_hash = 0;
1437
1438 if (RANGE_HAS_UBOUND(flags))
1439 upper_hash = DatumGetUInt32(FunctionCall1Coll(&scache->hash_proc_finfo,
1440 typcache->rng_collation,
1441 upper.val));
1442 else
1443 upper_hash = 0;
1444
1445 /* Merge hashes of flags and bounds */
1446 result = hash_bytes_uint32((uint32) flags);
1447 result ^= lower_hash;
1448 result = pg_rotate_left32(result, 1);
1449 result ^= upper_hash;
1450
1451 PG_RETURN_INT32(result);
1452}
uint32_t uint32
Definition: c.h:538
Datum FunctionCall1Coll(FmgrInfo *flinfo, Oid collation, Datum arg1)
Definition: fmgr.c:1130
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354
uint32 hash_bytes_uint32(uint32 k)
Definition: hashfn.c:610
static uint32 pg_rotate_left32(uint32 word, int n)
Definition: pg_bitutils.h:428
static uint32 DatumGetUInt32(Datum X)
Definition: postgres.h:232
char range_get_flags(const RangeType *range)
Definition: rangetypes.c:1986
#define RANGE_HAS_UBOUND(flags)
Definition: rangetypes.h:51
#define RANGE_HAS_LBOUND(flags)
Definition: rangetypes.h:47
void check_stack_depth(void)
Definition: stack_depth.c:95
FmgrInfo hash_proc_finfo
Definition: typcache.h:78
#define TYPECACHE_HASH_PROC_FINFO
Definition: typcache.h:145

References check_stack_depth(), DatumGetUInt32(), ereport, errcode(), errmsg(), ERROR, FmgrInfo::fn_oid, format_type_be(), FunctionCall1Coll(), hash_bytes_uint32(), TypeCacheEntry::hash_proc_finfo, lookup_type_cache(), lower(), OidIsValid, PG_GETARG_RANGE_P, PG_RETURN_INT32, pg_rotate_left32(), range_deserialize(), range_get_flags(), range_get_typcache(), RANGE_HAS_LBOUND, RANGE_HAS_UBOUND, RangeTypeGetOid, TypeCacheEntry::rng_collation, TypeCacheEntry::rngelemtype, TypeCacheEntry::type_id, TYPECACHE_HASH_PROC_FINFO, and upper().

◆ hash_range_extended()

Datum hash_range_extended ( PG_FUNCTION_ARGS  )

Definition at line 1459 of file rangetypes.c.

1460{
1462 Datum seed = PG_GETARG_DATUM(1);
1463 uint64 result;
1464 TypeCacheEntry *typcache;
1465 TypeCacheEntry *scache;
1468 bool empty;
1469 char flags;
1470 uint64 lower_hash;
1471 uint64 upper_hash;
1472
1474
1475 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1476
1477 range_deserialize(typcache, r, &lower, &upper, &empty);
1478 flags = range_get_flags(r);
1479
1480 scache = typcache->rngelemtype;
1482 {
1483 scache = lookup_type_cache(scache->type_id,
1486 ereport(ERROR,
1487 (errcode(ERRCODE_UNDEFINED_FUNCTION),
1488 errmsg("could not identify a hash function for type %s",
1489 format_type_be(scache->type_id))));
1490 }
1491
1492 if (RANGE_HAS_LBOUND(flags))
1494 typcache->rng_collation,
1495 lower.val,
1496 seed));
1497 else
1498 lower_hash = 0;
1499
1500 if (RANGE_HAS_UBOUND(flags))
1502 typcache->rng_collation,
1503 upper.val,
1504 seed));
1505 else
1506 upper_hash = 0;
1507
1508 /* Merge hashes of flags and bounds */
1510 DatumGetInt64(seed)));
1511 result ^= lower_hash;
1512 result = ROTATE_HIGH_AND_LOW_32BITS(result);
1513 result ^= upper_hash;
1514
1515 PG_RETURN_UINT64(result);
1516}
uint64_t uint64
Definition: c.h:539
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Definition: fmgr.c:1150
#define PG_RETURN_UINT64(x)
Definition: fmgr.h:369
#define ROTATE_HIGH_AND_LOW_32BITS(v)
Definition: hashfn.h:18
static Datum hash_uint32_extended(uint32 k, uint64 seed)
Definition: hashfn.h:49
static uint64 DatumGetUInt64(Datum X)
Definition: postgres.h:413
static int64 DatumGetInt64(Datum X)
Definition: postgres.h:393
FmgrInfo hash_extended_proc_finfo
Definition: typcache.h:79
#define TYPECACHE_HASH_EXTENDED_PROC_FINFO
Definition: typcache.h:153

References check_stack_depth(), DatumGetInt64(), DatumGetUInt64(), ereport, errcode(), errmsg(), ERROR, FmgrInfo::fn_oid, format_type_be(), FunctionCall2Coll(), TypeCacheEntry::hash_extended_proc_finfo, hash_uint32_extended(), lookup_type_cache(), lower(), OidIsValid, PG_GETARG_DATUM, PG_GETARG_RANGE_P, PG_RETURN_UINT64, range_deserialize(), range_get_flags(), range_get_typcache(), RANGE_HAS_LBOUND, RANGE_HAS_UBOUND, RangeTypeGetOid, TypeCacheEntry::rng_collation, TypeCacheEntry::rngelemtype, ROTATE_HIGH_AND_LOW_32BITS, TypeCacheEntry::type_id, TYPECACHE_HASH_EXTENDED_PROC_FINFO, and upper().

◆ int4range_canonical()

Datum int4range_canonical ( PG_FUNCTION_ARGS  )

Definition at line 1527 of file rangetypes.c.

1528{
1530 Node *escontext = fcinfo->context;
1531 TypeCacheEntry *typcache;
1534 bool empty;
1535
1536 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1537
1538 range_deserialize(typcache, r, &lower, &upper, &empty);
1539
1540 if (empty)
1542
1543 if (!lower.infinite && !lower.inclusive)
1544 {
1545 int32 bnd = DatumGetInt32(lower.val);
1546
1547 /* Handle possible overflow manually */
1548 if (unlikely(bnd == PG_INT32_MAX))
1549 ereturn(escontext, (Datum) 0,
1550 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1551 errmsg("integer out of range")));
1552 lower.val = Int32GetDatum(bnd + 1);
1553 lower.inclusive = true;
1554 }
1555
1556 if (!upper.infinite && upper.inclusive)
1557 {
1558 int32 bnd = DatumGetInt32(upper.val);
1559
1560 /* Handle possible overflow manually */
1561 if (unlikely(bnd == PG_INT32_MAX))
1562 ereturn(escontext, (Datum) 0,
1563 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1564 errmsg("integer out of range")));
1565 upper.val = Int32GetDatum(bnd + 1);
1566 upper.inclusive = false;
1567 }
1568
1570 false, escontext));
1571}
#define PG_INT32_MAX
Definition: c.h:594
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:222
static int32 DatumGetInt32(Datum X)
Definition: postgres.h:212

References DatumGetInt32(), ereturn, errcode(), errmsg(), Int32GetDatum(), lower(), PG_GETARG_RANGE_P, PG_INT32_MAX, PG_RETURN_RANGE_P, range_deserialize(), range_get_typcache(), range_serialize(), RangeTypeGetOid, unlikely, and upper().

◆ int4range_subdiff()

Datum int4range_subdiff ( PG_FUNCTION_ARGS  )

Definition at line 1684 of file rangetypes.c.

1685{
1686 int32 v1 = PG_GETARG_INT32(0);
1687 int32 v2 = PG_GETARG_INT32(1);
1688
1689 PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
1690}

References PG_GETARG_INT32, and PG_RETURN_FLOAT8.

◆ int8range_canonical()

Datum int8range_canonical ( PG_FUNCTION_ARGS  )

Definition at line 1574 of file rangetypes.c.

1575{
1577 Node *escontext = fcinfo->context;
1578 TypeCacheEntry *typcache;
1581 bool empty;
1582
1583 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1584
1585 range_deserialize(typcache, r, &lower, &upper, &empty);
1586
1587 if (empty)
1589
1590 if (!lower.infinite && !lower.inclusive)
1591 {
1592 int64 bnd = DatumGetInt64(lower.val);
1593
1594 /* Handle possible overflow manually */
1595 if (unlikely(bnd == PG_INT64_MAX))
1596 ereturn(escontext, (Datum) 0,
1597 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1598 errmsg("bigint out of range")));
1599 lower.val = Int64GetDatum(bnd + 1);
1600 lower.inclusive = true;
1601 }
1602
1603 if (!upper.infinite && upper.inclusive)
1604 {
1605 int64 bnd = DatumGetInt64(upper.val);
1606
1607 /* Handle possible overflow manually */
1608 if (unlikely(bnd == PG_INT64_MAX))
1609 ereturn(escontext, (Datum) 0,
1610 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1611 errmsg("bigint out of range")));
1612 upper.val = Int64GetDatum(bnd + 1);
1613 upper.inclusive = false;
1614 }
1615
1617 false, escontext));
1618}
int64_t int64
Definition: c.h:535
#define PG_INT64_MAX
Definition: c.h:597
static Datum Int64GetDatum(int64 X)
Definition: postgres.h:403

References DatumGetInt64(), ereturn, errcode(), errmsg(), Int64GetDatum(), lower(), PG_GETARG_RANGE_P, PG_INT64_MAX, PG_RETURN_RANGE_P, range_deserialize(), range_get_typcache(), range_serialize(), RangeTypeGetOid, unlikely, and upper().

◆ int8range_subdiff()

Datum int8range_subdiff ( PG_FUNCTION_ARGS  )

Definition at line 1693 of file rangetypes.c.

1694{
1695 int64 v1 = PG_GETARG_INT64(0);
1696 int64 v2 = PG_GETARG_INT64(1);
1697
1698 PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
1699}
#define PG_GETARG_INT64(n)
Definition: fmgr.h:283

References PG_GETARG_INT64, and PG_RETURN_FLOAT8.

◆ make_empty_range()

RangeType * make_empty_range ( TypeCacheEntry typcache)

Definition at line 2228 of file rangetypes.c.

2229{
2232
2233 lower.val = (Datum) 0;
2234 lower.infinite = false;
2235 lower.inclusive = false;
2236 lower.lower = true;
2237
2238 upper.val = (Datum) 0;
2239 upper.infinite = false;
2240 upper.inclusive = false;
2241 upper.lower = false;
2242
2243 return make_range(typcache, &lower, &upper, true, NULL);
2244}

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

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

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

◆ numrange_subdiff()

Datum numrange_subdiff ( PG_FUNCTION_ARGS  )

Definition at line 1702 of file rangetypes.c.

1703{
1704 Datum v1 = PG_GETARG_DATUM(0);
1705 Datum v2 = PG_GETARG_DATUM(1);
1706 Datum numresult;
1707 float8 floatresult;
1708
1709 numresult = DirectFunctionCall2(numeric_sub, v1, v2);
1710
1712 numresult));
1713
1714 PG_RETURN_FLOAT8(floatresult);
1715}
Datum numeric_sub(PG_FUNCTION_ARGS)
Definition: numeric.c:2940
Datum numeric_float8(PG_FUNCTION_ARGS)
Definition: numeric.c:4557
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:684
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:682
static float8 DatumGetFloat8(Datum X)
Definition: postgres.h:475

References DatumGetFloat8(), DirectFunctionCall1, DirectFunctionCall2, numeric_float8(), numeric_sub(), PG_GETARG_DATUM, and PG_RETURN_FLOAT8.

◆ range_adjacent()

Datum range_adjacent ( PG_FUNCTION_ARGS  )

Definition at line 829 of file rangetypes.c.

830{
833 TypeCacheEntry *typcache;
834
835 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
836
837 PG_RETURN_BOOL(range_adjacent_internal(typcache, r1, r2));
838}
bool range_adjacent_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:799

References PG_GETARG_RANGE_P, PG_RETURN_BOOL, range_adjacent_internal(), range_get_typcache(), and RangeTypeGetOid.

◆ range_adjacent_internal()

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

Definition at line 799 of file rangetypes.c.

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

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

Datum range_after ( PG_FUNCTION_ARGS  )

Definition at line 728 of file rangetypes.c.

729{
732 TypeCacheEntry *typcache;
733
734 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
735
736 PG_RETURN_BOOL(range_after_internal(typcache, r1, r2));
737}
bool range_after_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:703

References PG_GETARG_RANGE_P, PG_RETURN_BOOL, range_after_internal(), range_get_typcache(), and RangeTypeGetOid.

◆ range_after_internal()

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

Definition at line 703 of file rangetypes.c.

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

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

Datum range_before ( PG_FUNCTION_ARGS  )

Definition at line 690 of file rangetypes.c.

691{
694 TypeCacheEntry *typcache;
695
696 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
697
698 PG_RETURN_BOOL(range_before_internal(typcache, r1, r2));
699}
bool range_before_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:665

References PG_GETARG_RANGE_P, PG_RETURN_BOOL, range_before_internal(), range_get_typcache(), and RangeTypeGetOid.

◆ range_before_internal()

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

Definition at line 665 of file rangetypes.c.

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

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

static char * range_bound_escape ( const char *  value)
static

Definition at line 2600 of file rangetypes.c.

2601{
2602 bool nq;
2603 const char *ptr;
2605
2607
2608 /* Detect whether we need double quotes for this value */
2609 nq = (value[0] == '\0'); /* force quotes for empty string */
2610 for (ptr = value; *ptr; ptr++)
2611 {
2612 char ch = *ptr;
2613
2614 if (ch == '"' || ch == '\\' ||
2615 ch == '(' || ch == ')' ||
2616 ch == '[' || ch == ']' ||
2617 ch == ',' ||
2618 isspace((unsigned char) ch))
2619 {
2620 nq = true;
2621 break;
2622 }
2623 }
2624
2625 /* And emit the string */
2626 if (nq)
2628 for (ptr = value; *ptr; ptr++)
2629 {
2630 char ch = *ptr;
2631
2632 if (ch == '"' || ch == '\\')
2635 }
2636 if (nq)
2638
2639 return buf.data;
2640}
static struct @169 value
static char * buf
Definition: pg_test_fsync.c:72
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:242
void initStringInfo(StringInfo str)
Definition: stringinfo.c:97

References appendStringInfoChar(), buf, initStringInfo(), and value.

Referenced by range_deparse().

◆ range_cmp()

Datum range_cmp ( PG_FUNCTION_ARGS  )

Definition at line 1250 of file rangetypes.c.

1251{
1254 TypeCacheEntry *typcache;
1255 RangeBound lower1,
1256 lower2;
1257 RangeBound upper1,
1258 upper2;
1259 bool empty1,
1260 empty2;
1261 int cmp;
1262
1263 check_stack_depth(); /* recurses when subtype is a range type */
1264
1265 /* Different types should be prevented by ANYRANGE matching rules */
1266 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
1267 elog(ERROR, "range types do not match");
1268
1269 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
1270
1271 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
1272 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
1273
1274 /* For b-tree use, empty ranges sort before all else */
1275 if (empty1 && empty2)
1276 cmp = 0;
1277 else if (empty1)
1278 cmp = -1;
1279 else if (empty2)
1280 cmp = 1;
1281 else
1282 {
1283 cmp = range_cmp_bounds(typcache, &lower1, &lower2);
1284 if (cmp == 0)
1285 cmp = range_cmp_bounds(typcache, &upper1, &upper2);
1286 }
1287
1288 PG_FREE_IF_COPY(r1, 0);
1289 PG_FREE_IF_COPY(r2, 1);
1290
1292}
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:260

References check_stack_depth(), cmp(), elog, ERROR, PG_FREE_IF_COPY, PG_GETARG_RANGE_P, PG_RETURN_INT32, range_cmp_bounds(), range_deserialize(), range_get_typcache(), and RangeTypeGetOid.

Referenced by range_ge(), range_gt(), range_le(), and range_lt().

◆ range_cmp_bound_values()

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

Definition at line 2153 of file rangetypes.c.

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

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

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

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

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

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

Referenced by multirange_canonicalize().

◆ range_constructor2()

Datum range_constructor2 ( PG_FUNCTION_ARGS  )

Definition at line 378 of file rangetypes.c.

379{
380 Datum arg1 = PG_GETARG_DATUM(0);
381 Datum arg2 = PG_GETARG_DATUM(1);
382 Oid rngtypid = get_fn_expr_rettype(fcinfo->flinfo);
384 TypeCacheEntry *typcache;
387
388 typcache = range_get_typcache(fcinfo, rngtypid);
389
390 lower.val = PG_ARGISNULL(0) ? (Datum) 0 : arg1;
391 lower.infinite = PG_ARGISNULL(0);
392 lower.inclusive = true;
393 lower.lower = true;
394
395 upper.val = PG_ARGISNULL(1) ? (Datum) 0 : arg2;
396 upper.infinite = PG_ARGISNULL(1);
397 upper.inclusive = false;
398 upper.lower = false;
399
400 range = make_range(typcache, &lower, &upper, false, NULL);
401
403}
Oid get_fn_expr_rettype(FmgrInfo *flinfo)
Definition: fmgr.c:1853
#define PG_ARGISNULL(n)
Definition: fmgr.h:209

References get_fn_expr_rettype(), lower(), make_range(), PG_ARGISNULL, PG_GETARG_DATUM, PG_RETURN_RANGE_P, range(), range_get_typcache(), and upper().

◆ range_constructor3()

Datum range_constructor3 ( PG_FUNCTION_ARGS  )

Definition at line 407 of file rangetypes.c.

408{
409 Datum arg1 = PG_GETARG_DATUM(0);
410 Datum arg2 = PG_GETARG_DATUM(1);
411 Oid rngtypid = get_fn_expr_rettype(fcinfo->flinfo);
413 TypeCacheEntry *typcache;
416 char flags;
417
418 typcache = range_get_typcache(fcinfo, rngtypid);
419
420 if (PG_ARGISNULL(2))
422 (errcode(ERRCODE_DATA_EXCEPTION),
423 errmsg("range constructor flags argument must not be null")));
424
426
427 lower.val = PG_ARGISNULL(0) ? (Datum) 0 : arg1;
428 lower.infinite = PG_ARGISNULL(0);
429 lower.inclusive = (flags & RANGE_LB_INC) != 0;
430 lower.lower = true;
431
432 upper.val = PG_ARGISNULL(1) ? (Datum) 0 : arg2;
433 upper.infinite = PG_ARGISNULL(1);
434 upper.inclusive = (flags & RANGE_UB_INC) != 0;
435 upper.lower = false;
436
437 range = make_range(typcache, &lower, &upper, false, NULL);
438
440}
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
static char range_parse_flags(const char *flags_str)
Definition: rangetypes.c:2310
#define RANGE_UB_INC
Definition: rangetypes.h:40
#define RANGE_LB_INC
Definition: rangetypes.h:39
char * text_to_cstring(const text *t)
Definition: varlena.c:214

References ereport, errcode(), errmsg(), ERROR, get_fn_expr_rettype(), lower(), make_range(), PG_ARGISNULL, PG_GETARG_DATUM, PG_GETARG_TEXT_PP, PG_RETURN_RANGE_P, range(), range_get_typcache(), RANGE_LB_INC, range_parse_flags(), RANGE_UB_INC, text_to_cstring(), and upper().

◆ range_contained_by()

Datum range_contained_by ( PG_FUNCTION_ARGS  )

Definition at line 652 of file rangetypes.c.

653{
656 TypeCacheEntry *typcache;
657
658 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
659
661}
bool range_contained_by_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:2681

References PG_GETARG_RANGE_P, PG_RETURN_BOOL, range_contained_by_internal(), range_get_typcache(), and RangeTypeGetOid.

◆ range_contained_by_internal()

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

Definition at line 2681 of file rangetypes.c.

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

References range_contains_internal().

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

◆ range_contains()

Datum range_contains ( PG_FUNCTION_ARGS  )

Definition at line 639 of file rangetypes.c.

640{
643 TypeCacheEntry *typcache;
644
645 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
646
647 PG_RETURN_BOOL(range_contains_internal(typcache, r1, r2));
648}

References PG_GETARG_RANGE_P, PG_RETURN_BOOL, range_contains_internal(), range_get_typcache(), and RangeTypeGetOid.

◆ range_contains_elem()

Datum range_contains_elem ( PG_FUNCTION_ARGS  )

◆ range_contains_elem_internal()

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

Definition at line 2690 of file rangetypes.c.

2691{
2694 bool empty;
2695 int32 cmp;
2696
2697 range_deserialize(typcache, r, &lower, &upper, &empty);
2698
2699 if (empty)
2700 return false;
2701
2702 if (!lower.infinite)
2703 {
2705 typcache->rng_collation,
2706 lower.val, val));
2707 if (cmp > 0)
2708 return false;
2709 if (cmp == 0 && !lower.inclusive)
2710 return false;
2711 }
2712
2713 if (!upper.infinite)
2714 {
2716 typcache->rng_collation,
2717 upper.val, val));
2718 if (cmp < 0)
2719 return false;
2720 if (cmp == 0 && !upper.inclusive)
2721 return false;
2722 }
2723
2724 return true;
2725}

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

Datum range_contains_elem_support ( PG_FUNCTION_ARGS  )

Definition at line 2276 of file rangetypes.c.

2277{
2278 Node *rawreq = (Node *) PG_GETARG_POINTER(0);
2279 Node *ret = NULL;
2280
2281 if (IsA(rawreq, SupportRequestSimplify))
2282 {
2284 FuncExpr *fexpr = req->fcall;
2285 Expr *leftop,
2286 *rightop;
2287
2288 Assert(list_length(fexpr->args) == 2);
2289 leftop = linitial(fexpr->args);
2290 rightop = lsecond(fexpr->args);
2291
2292 ret = find_simplified_clause(req->root, leftop, rightop);
2293 }
2294
2295 PG_RETURN_POINTER(ret);
2296}

References FuncExpr::args, Assert(), SupportRequestSimplify::fcall, find_simplified_clause(), IsA, linitial, list_length(), lsecond, PG_GETARG_POINTER, PG_RETURN_POINTER, and SupportRequestSimplify::root.

◆ range_contains_internal()

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

Definition at line 2649 of file rangetypes.c.

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

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

static char * range_deparse ( char  flags,
const char *  lbound_str,
const char *  ubound_str 
)
static

Definition at line 2570 of file rangetypes.c.

2571{
2573
2574 if (flags & RANGE_EMPTY)
2576
2578
2579 appendStringInfoChar(&buf, (flags & RANGE_LB_INC) ? '[' : '(');
2580
2581 if (RANGE_HAS_LBOUND(flags))
2583
2585
2586 if (RANGE_HAS_UBOUND(flags))
2588
2589 appendStringInfoChar(&buf, (flags & RANGE_UB_INC) ? ']' : ')');
2590
2591 return buf.data;
2592}
char * pstrdup(const char *in)
Definition: mcxt.c:1759
static char * range_bound_escape(const char *value)
Definition: rangetypes.c:2600
#define RANGE_EMPTY
Definition: rangetypes.h:38
#define RANGE_EMPTY_LITERAL
Definition: rangetypes.h:32
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:230

References appendStringInfoChar(), appendStringInfoString(), buf, initStringInfo(), pstrdup(), range_bound_escape(), RANGE_EMPTY, RANGE_EMPTY_LITERAL, RANGE_HAS_LBOUND, RANGE_HAS_UBOUND, RANGE_LB_INC, and RANGE_UB_INC.

Referenced by range_out().

◆ range_deserialize()

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

Definition at line 1919 of file rangetypes.c.

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

References Assert(), att_addlength_pointer, att_align_pointer, fetch_att(), 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_empty()

Datum range_empty ( PG_FUNCTION_ARGS  )

Definition at line 492 of file rangetypes.c.

493{
495 char flags = range_get_flags(r1);
496
498}

References PG_GETARG_RANGE_P, PG_RETURN_BOOL, RANGE_EMPTY, and range_get_flags().

◆ range_eq()

Datum range_eq ( PG_FUNCTION_ARGS  )

Definition at line 606 of file rangetypes.c.

607{
610 TypeCacheEntry *typcache;
611
612 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
613
614 PG_RETURN_BOOL(range_eq_internal(typcache, r1, r2));
615}
bool range_eq_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:574

References PG_GETARG_RANGE_P, PG_RETURN_BOOL, range_eq_internal(), range_get_typcache(), and RangeTypeGetOid.

◆ range_eq_internal()

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

Definition at line 574 of file rangetypes.c.

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

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

static int range_fast_cmp ( Datum  a,
Datum  b,
SortSupport  ssup 
)
static

Definition at line 1308 of file rangetypes.c.

1309{
1310 RangeType *range_a = DatumGetRangeTypeP(a);
1311 RangeType *range_b = DatumGetRangeTypeP(b);
1312 TypeCacheEntry *typcache;
1313 RangeBound lower1,
1314 lower2;
1315 RangeBound upper1,
1316 upper2;
1317 bool empty1,
1318 empty2;
1319 int cmp;
1320
1321 /* cache the range info between calls */
1322 if (ssup->ssup_extra == NULL)
1323 {
1324 Assert(RangeTypeGetOid(range_a) == RangeTypeGetOid(range_b));
1325 ssup->ssup_extra =
1327 }
1328 typcache = ssup->ssup_extra;
1329
1330 range_deserialize(typcache, range_a, &lower1, &upper1, &empty1);
1331 range_deserialize(typcache, range_b, &lower2, &upper2, &empty2);
1332
1333 /* For b-tree use, empty ranges sort before all else */
1334 if (empty1 && empty2)
1335 cmp = 0;
1336 else if (empty1)
1337 cmp = -1;
1338 else if (empty2)
1339 cmp = 1;
1340 else
1341 {
1342 cmp = range_cmp_bounds(typcache, &lower1, &lower2);
1343 if (cmp == 0)
1344 cmp = range_cmp_bounds(typcache, &upper1, &upper2);
1345 }
1346
1347 if ((Pointer) range_a != DatumGetPointer(a))
1348 pfree(range_a);
1349 if ((Pointer) range_b != DatumGetPointer(b))
1350 pfree(range_b);
1351
1352 return cmp;
1353}
int b
Definition: isn.c:74
int a
Definition: isn.c:73
void pfree(void *pointer)
Definition: mcxt.c:1594
void * ssup_extra
Definition: sortsupport.h:87

References a, Assert(), b, cmp(), DatumGetPointer(), DatumGetRangeTypeP(), lookup_type_cache(), pfree(), range_cmp_bounds(), range_deserialize(), RangeTypeGetOid, SortSupportData::ssup_extra, and TYPECACHE_RANGE_INFO.

Referenced by range_sortsupport().

◆ range_ge()

Datum range_ge ( PG_FUNCTION_ARGS  )

Definition at line 1374 of file rangetypes.c.

1375{
1376 int cmp = DatumGetInt32(range_cmp(fcinfo));
1377
1378 PG_RETURN_BOOL(cmp >= 0);
1379}
Datum range_cmp(PG_FUNCTION_ARGS)
Definition: rangetypes.c:1250

References cmp(), DatumGetInt32(), PG_RETURN_BOOL, and range_cmp().

◆ range_get_flags()

char range_get_flags ( const RangeType range)

Definition at line 1986 of file rangetypes.c.

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

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 
)

◆ range_gt()

Datum range_gt ( PG_FUNCTION_ARGS  )

Definition at line 1382 of file rangetypes.c.

1383{
1384 int cmp = DatumGetInt32(range_cmp(fcinfo));
1385
1386 PG_RETURN_BOOL(cmp > 0);
1387}

References cmp(), DatumGetInt32(), PG_RETURN_BOOL, and range_cmp().

◆ range_in()

Datum range_in ( PG_FUNCTION_ARGS  )

Definition at line 91 of file rangetypes.c.

92{
93 char *input_str = PG_GETARG_CSTRING(0);
94 Oid rngtypoid = PG_GETARG_OID(1);
95 Oid typmod = PG_GETARG_INT32(2);
96 Node *escontext = fcinfo->context;
98 RangeIOData *cache;
99 char flags;
100 char *lbound_str;
101 char *ubound_str;
104
105 check_stack_depth(); /* recurses when subtype is a range type */
106
107 cache = get_range_io_data(fcinfo, rngtypoid, IOFunc_input);
108
109 /* parse */
110 if (!range_parse(input_str, &flags, &lbound_str, &ubound_str, escontext))
112
113 /* call element type's input function */
114 if (RANGE_HAS_LBOUND(flags))
115 if (!InputFunctionCallSafe(&cache->typioproc, lbound_str,
116 cache->typioparam, typmod,
117 escontext, &lower.val))
119 if (RANGE_HAS_UBOUND(flags))
120 if (!InputFunctionCallSafe(&cache->typioproc, ubound_str,
121 cache->typioparam, typmod,
122 escontext, &upper.val))
124
125 lower.infinite = (flags & RANGE_LB_INF) != 0;
126 lower.inclusive = (flags & RANGE_LB_INC) != 0;
127 lower.lower = true;
128 upper.infinite = (flags & RANGE_UB_INF) != 0;
129 upper.inclusive = (flags & RANGE_UB_INC) != 0;
130 upper.lower = false;
131
132 /* serialize and canonicalize */
133 range = make_range(cache->typcache, &lower, &upper,
134 flags & RANGE_EMPTY, escontext);
135
137}
bool InputFunctionCallSafe(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod, Node *escontext, Datum *result)
Definition: fmgr.c:1585
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:277
#define PG_RETURN_NULL()
Definition: fmgr.h:345
@ IOFunc_input
Definition: lsyscache.h:36
static bool range_parse(const char *string, char *flags, char **lbound_str, char **ubound_str, Node *escontext)
Definition: rangetypes.c:2385
static RangeIOData * get_range_io_data(FunctionCallInfo fcinfo, Oid rngtypid, IOFuncSelector func)
Definition: rangetypes.c:318

References check_stack_depth(), get_range_io_data(), InputFunctionCallSafe(), IOFunc_input, lower(), make_range(), PG_GETARG_CSTRING, PG_GETARG_INT32, PG_GETARG_OID, PG_RETURN_NULL, PG_RETURN_RANGE_P, range(), RANGE_EMPTY, RANGE_HAS_LBOUND, RANGE_HAS_UBOUND, RANGE_LB_INC, RANGE_LB_INF, range_parse(), RANGE_UB_INC, RANGE_UB_INF, RangeIOData::typcache, RangeIOData::typioparam, RangeIOData::typioproc, and upper().

◆ range_intersect()

Datum range_intersect ( PG_FUNCTION_ARGS  )

Definition at line 1128 of file rangetypes.c.

1129{
1132 TypeCacheEntry *typcache;
1133
1134 /* Different types should be prevented by ANYRANGE matching rules */
1135 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
1136 elog(ERROR, "range types do not match");
1137
1138 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
1139
1141}
RangeType * range_intersect_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:1144

References elog, ERROR, PG_GETARG_RANGE_P, PG_RETURN_RANGE_P, range_get_typcache(), range_intersect_internal(), and RangeTypeGetOid.

◆ range_intersect_agg_transfn()

Datum range_intersect_agg_transfn ( PG_FUNCTION_ARGS  )

Definition at line 1220 of file rangetypes.c.

1221{
1222 MemoryContext aggContext;
1223 Oid rngtypoid;
1224 TypeCacheEntry *typcache;
1225 RangeType *result;
1226 RangeType *current;
1227
1228 if (!AggCheckCallContext(fcinfo, &aggContext))
1229 elog(ERROR, "range_intersect_agg_transfn called in non-aggregate context");
1230
1231 rngtypoid = get_fn_expr_argtype(fcinfo->flinfo, 1);
1232 if (!type_is_range(rngtypoid))
1233 elog(ERROR, "range_intersect_agg must be called with a range");
1234
1235 typcache = range_get_typcache(fcinfo, rngtypoid);
1236
1237 /* strictness ensures these are non-null */
1238 result = PG_GETARG_RANGE_P(0);
1239 current = PG_GETARG_RANGE_P(1);
1240
1241 result = range_intersect_internal(typcache, result, current);
1242 PG_RETURN_RANGE_P(result);
1243}
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1875
bool type_is_range(Oid typid)
Definition: lsyscache.c:2855
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4613

References AggCheckCallContext(), elog, ERROR, get_fn_expr_argtype(), PG_GETARG_RANGE_P, PG_RETURN_RANGE_P, range_get_typcache(), range_intersect_internal(), and type_is_range().

◆ range_intersect_internal()

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

Definition at line 1144 of file rangetypes.c.

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

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

Datum range_le ( PG_FUNCTION_ARGS  )

Definition at line 1366 of file rangetypes.c.

1367{
1368 int cmp = DatumGetInt32(range_cmp(fcinfo));
1369
1370 PG_RETURN_BOOL(cmp <= 0);
1371}

References cmp(), DatumGetInt32(), PG_RETURN_BOOL, and range_cmp().

◆ range_lower()

Datum range_lower ( PG_FUNCTION_ARGS  )

Definition at line 447 of file rangetypes.c.

448{
450 TypeCacheEntry *typcache;
453 bool empty;
454
455 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
456
457 range_deserialize(typcache, r1, &lower, &upper, &empty);
458
459 /* Return NULL if there's no finite lower bound */
460 if (empty || lower.infinite)
462
464}
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:353

References lower(), PG_GETARG_RANGE_P, PG_RETURN_DATUM, PG_RETURN_NULL, range_deserialize(), range_get_typcache(), RangeTypeGetOid, and upper().

◆ range_lower_inc()

Datum range_lower_inc ( PG_FUNCTION_ARGS  )

Definition at line 502 of file rangetypes.c.

503{
505 char flags = range_get_flags(r1);
506
508}

References PG_GETARG_RANGE_P, PG_RETURN_BOOL, range_get_flags(), and RANGE_LB_INC.

◆ range_lower_inf()

Datum range_lower_inf ( PG_FUNCTION_ARGS  )

Definition at line 522 of file rangetypes.c.

523{
525 char flags = range_get_flags(r1);
526
528}

References PG_GETARG_RANGE_P, PG_RETURN_BOOL, range_get_flags(), and RANGE_LB_INF.

◆ range_lt()

Datum range_lt ( PG_FUNCTION_ARGS  )

Definition at line 1358 of file rangetypes.c.

1359{
1360 int cmp = DatumGetInt32(range_cmp(fcinfo));
1361
1362 PG_RETURN_BOOL(cmp < 0);
1363}

References cmp(), DatumGetInt32(), PG_RETURN_BOOL, and range_cmp().

◆ range_merge()

Datum range_merge ( PG_FUNCTION_ARGS  )

Definition at line 1115 of file rangetypes.c.

1116{
1119 TypeCacheEntry *typcache;
1120
1121 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
1122
1123 PG_RETURN_RANGE_P(range_union_internal(typcache, r1, r2, false));
1124}
RangeType * range_union_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2, bool strict)
Definition: rangetypes.c:1053

References PG_GETARG_RANGE_P, PG_RETURN_RANGE_P, range_get_typcache(), range_union_internal(), and RangeTypeGetOid.

◆ range_minus()

Datum range_minus ( PG_FUNCTION_ARGS  )

Definition at line 973 of file rangetypes.c.

974{
977 RangeType *ret;
978 TypeCacheEntry *typcache;
979
980 /* Different types should be prevented by ANYRANGE matching rules */
981 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
982 elog(ERROR, "range types do not match");
983
984 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
985
986 ret = range_minus_internal(typcache, r1, r2);
987 if (ret)
989 else
991}
RangeType * range_minus_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
Definition: rangetypes.c:994

References elog, ERROR, PG_GETARG_RANGE_P, PG_RETURN_NULL, PG_RETURN_RANGE_P, range_get_typcache(), range_minus_internal(), and RangeTypeGetOid.

◆ range_minus_internal()

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

Definition at line 994 of file rangetypes.c.

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

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

Datum range_ne ( PG_FUNCTION_ARGS  )

Definition at line 626 of file rangetypes.c.

627{
630 TypeCacheEntry *typcache;
631
632 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
633
634 PG_RETURN_BOOL(range_ne_internal(typcache, r1, r2));
635}
bool range_ne_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:619

References PG_GETARG_RANGE_P, PG_RETURN_BOOL, range_get_typcache(), range_ne_internal(), and RangeTypeGetOid.

◆ range_ne_internal()

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

Definition at line 619 of file rangetypes.c.

620{
621 return (!range_eq_internal(typcache, r1, r2));
622}

References range_eq_internal().

Referenced by range_ne().

◆ range_out()

Datum range_out ( PG_FUNCTION_ARGS  )

Definition at line 140 of file rangetypes.c.

141{
143 char *output_str;
144 RangeIOData *cache;
145 char flags;
146 char *lbound_str = NULL;
147 char *ubound_str = NULL;
150 bool empty;
151
152 check_stack_depth(); /* recurses when subtype is a range type */
153
155
156 /* deserialize */
157 range_deserialize(cache->typcache, range, &lower, &upper, &empty);
158 flags = range_get_flags(range);
159
160 /* call element type's output function */
161 if (RANGE_HAS_LBOUND(flags))
162 lbound_str = OutputFunctionCall(&cache->typioproc, lower.val);
163 if (RANGE_HAS_UBOUND(flags))
164 ubound_str = OutputFunctionCall(&cache->typioproc, upper.val);
165
166 /* construct result string */
167 output_str = range_deparse(flags, lbound_str, ubound_str);
168
169 PG_RETURN_CSTRING(output_str);
170}
char * OutputFunctionCall(FmgrInfo *flinfo, Datum val)
Definition: fmgr.c:1683
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:362
@ IOFunc_output
Definition: lsyscache.h:37
static char * range_deparse(char flags, const char *lbound_str, const char *ubound_str)
Definition: rangetypes.c:2570

References check_stack_depth(), get_range_io_data(), IOFunc_output, lower(), OutputFunctionCall(), PG_GETARG_RANGE_P, PG_RETURN_CSTRING, range(), range_deparse(), range_deserialize(), range_get_flags(), RANGE_HAS_LBOUND, RANGE_HAS_UBOUND, RangeTypeGetOid, RangeIOData::typcache, RangeIOData::typioproc, and upper().

Referenced by anycompatiblerange_out(), and anyrange_out().

◆ range_overlaps()

Datum range_overlaps ( PG_FUNCTION_ARGS  )

Definition at line 875 of file rangetypes.c.

876{
879 TypeCacheEntry *typcache;
880
881 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
882
883 PG_RETURN_BOOL(range_overlaps_internal(typcache, r1, r2));
884}

References PG_GETARG_RANGE_P, PG_RETURN_BOOL, range_get_typcache(), range_overlaps_internal(), and RangeTypeGetOid.

◆ range_overlaps_internal()

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

Definition at line 842 of file rangetypes.c.

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

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

Datum range_overleft ( PG_FUNCTION_ARGS  )

Definition at line 916 of file rangetypes.c.

917{
920 TypeCacheEntry *typcache;
921
922 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
923
924 PG_RETURN_BOOL(range_overleft_internal(typcache, r1, r2));
925}
bool range_overleft_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:888

References PG_GETARG_RANGE_P, PG_RETURN_BOOL, range_get_typcache(), range_overleft_internal(), and RangeTypeGetOid.

◆ range_overleft_internal()

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

Definition at line 888 of file rangetypes.c.

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

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

Datum range_overright ( PG_FUNCTION_ARGS  )

Definition at line 957 of file rangetypes.c.

958{
961 TypeCacheEntry *typcache;
962
963 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
964
965 PG_RETURN_BOOL(range_overright_internal(typcache, r1, r2));
966}
bool range_overright_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:929

References PG_GETARG_RANGE_P, PG_RETURN_BOOL, range_get_typcache(), range_overright_internal(), and RangeTypeGetOid.

◆ range_overright_internal()

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

Definition at line 929 of file rangetypes.c.

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

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

static bool range_parse ( const char *  string,
char *  flags,
char **  lbound_str,
char **  ubound_str,
Node escontext 
)
static

Definition at line 2385 of file rangetypes.c.

2387{
2388 const char *ptr = string;
2389 bool infinite;
2390
2391 *flags = 0;
2392
2393 /* consume whitespace */
2394 while (*ptr != '\0' && isspace((unsigned char) *ptr))
2395 ptr++;
2396
2397 /* check for empty range */
2399 strlen(RANGE_EMPTY_LITERAL)) == 0)
2400 {
2401 *flags = RANGE_EMPTY;
2402 *lbound_str = NULL;
2403 *ubound_str = NULL;
2404
2405 ptr += strlen(RANGE_EMPTY_LITERAL);
2406
2407 /* the rest should be whitespace */
2408 while (*ptr != '\0' && isspace((unsigned char) *ptr))
2409 ptr++;
2410
2411 /* should have consumed everything */
2412 if (*ptr != '\0')
2413 ereturn(escontext, false,
2414 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2415 errmsg("malformed range literal: \"%s\"",
2416 string),
2417 errdetail("Junk after \"empty\" key word.")));
2418
2419 return true;
2420 }
2421
2422 if (*ptr == '[')
2423 {
2424 *flags |= RANGE_LB_INC;
2425 ptr++;
2426 }
2427 else if (*ptr == '(')
2428 ptr++;
2429 else
2430 ereturn(escontext, false,
2431 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2432 errmsg("malformed range literal: \"%s\"",
2433 string),
2434 errdetail("Missing left parenthesis or bracket.")));
2435
2436 ptr = range_parse_bound(string, ptr, lbound_str, &infinite, escontext);
2437 if (ptr == NULL)
2438 return false;
2439 if (infinite)
2440 *flags |= RANGE_LB_INF;
2441
2442 if (*ptr == ',')
2443 ptr++;
2444 else
2445 ereturn(escontext, false,
2446 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2447 errmsg("malformed range literal: \"%s\"",
2448 string),
2449 errdetail("Missing comma after lower bound.")));
2450
2451 ptr = range_parse_bound(string, ptr, ubound_str, &infinite, escontext);
2452 if (ptr == NULL)
2453 return false;
2454 if (infinite)
2455 *flags |= RANGE_UB_INF;
2456
2457 if (*ptr == ']')
2458 {
2459 *flags |= RANGE_UB_INC;
2460 ptr++;
2461 }
2462 else if (*ptr == ')')
2463 ptr++;
2464 else /* must be a comma */
2465 ereturn(escontext, false,
2466 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2467 errmsg("malformed range literal: \"%s\"",
2468 string),
2469 errdetail("Too many commas.")));
2470
2471 /* consume whitespace */
2472 while (*ptr != '\0' && isspace((unsigned char) *ptr))
2473 ptr++;
2474
2475 if (*ptr != '\0')
2476 ereturn(escontext, false,
2477 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2478 errmsg("malformed range literal: \"%s\"",
2479 string),
2480 errdetail("Junk after right parenthesis or bracket.")));
2481
2482 return true;
2483}
int errdetail(const char *fmt,...)
Definition: elog.c:1216
int pg_strncasecmp(const char *s1, const char *s2, size_t n)
Definition: pgstrcasecmp.c:69
char string[11]
Definition: preproc-type.c:52
static const char * range_parse_bound(const char *string, const char *ptr, char **bound_str, bool *infinite, Node *escontext)
Definition: rangetypes.c:2501

References ereturn, errcode(), errdetail(), errmsg(), pg_strncasecmp(), RANGE_EMPTY, RANGE_EMPTY_LITERAL, RANGE_LB_INC, RANGE_LB_INF, range_parse_bound(), RANGE_UB_INC, and RANGE_UB_INF.

Referenced by range_in().

◆ range_parse_bound()

static const char * range_parse_bound ( const char *  string,
const char *  ptr,
char **  bound_str,
bool *  infinite,
Node escontext 
)
static

Definition at line 2501 of file rangetypes.c.

2503{
2505
2506 /* Check for null: completely empty input means null */
2507 if (*ptr == ',' || *ptr == ')' || *ptr == ']')
2508 {
2509 *bound_str = NULL;
2510 *infinite = true;
2511 }
2512 else
2513 {
2514 /* Extract string for this bound */
2515 bool inquote = false;
2516
2518 while (inquote || !(*ptr == ',' || *ptr == ')' || *ptr == ']'))
2519 {
2520 char ch = *ptr++;
2521
2522 if (ch == '\0')
2523 ereturn(escontext, NULL,
2524 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2525 errmsg("malformed range literal: \"%s\"",
2526 string),
2527 errdetail("Unexpected end of input.")));
2528 if (ch == '\\')
2529 {
2530 if (*ptr == '\0')
2531 ereturn(escontext, NULL,
2532 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2533 errmsg("malformed range literal: \"%s\"",
2534 string),
2535 errdetail("Unexpected end of input.")));
2536 appendStringInfoChar(&buf, *ptr++);
2537 }
2538 else if (ch == '"')
2539 {
2540 if (!inquote)
2541 inquote = true;
2542 else if (*ptr == '"')
2543 {
2544 /* doubled quote within quote sequence */
2545 appendStringInfoChar(&buf, *ptr++);
2546 }
2547 else
2548 inquote = false;
2549 }
2550 else
2552 }
2553
2554 *bound_str = buf.data;
2555 *infinite = false;
2556 }
2557
2558 return ptr;
2559}

References appendStringInfoChar(), buf, ereturn, errcode(), errdetail(), errmsg(), and initStringInfo().

Referenced by range_parse().

◆ range_parse_flags()

static char range_parse_flags ( const char *  flags_str)
static

Definition at line 2310 of file rangetypes.c.

2311{
2312 char flags = 0;
2313
2314 if (flags_str[0] == '\0' ||
2315 flags_str[1] == '\0' ||
2316 flags_str[2] != '\0')
2317 ereport(ERROR,
2318 (errcode(ERRCODE_SYNTAX_ERROR),
2319 errmsg("invalid range bound flags"),
2320 errhint("Valid values are \"[]\", \"[)\", \"(]\", and \"()\".")));
2321
2322 switch (flags_str[0])
2323 {
2324 case '[':
2325 flags |= RANGE_LB_INC;
2326 break;
2327 case '(':
2328 break;
2329 default:
2330 ereport(ERROR,
2331 (errcode(ERRCODE_SYNTAX_ERROR),
2332 errmsg("invalid range bound flags"),
2333 errhint("Valid values are \"[]\", \"[)\", \"(]\", and \"()\".")));
2334 }
2335
2336 switch (flags_str[1])
2337 {
2338 case ']':
2339 flags |= RANGE_UB_INC;
2340 break;
2341 case ')':
2342 break;
2343 default:
2344 ereport(ERROR,
2345 (errcode(ERRCODE_SYNTAX_ERROR),
2346 errmsg("invalid range bound flags"),
2347 errhint("Valid values are \"[]\", \"[)\", \"(]\", and \"()\".")));
2348 }
2349
2350 return flags;
2351}
int errhint(const char *fmt,...)
Definition: elog.c:1330

References ereport, errcode(), errhint(), errmsg(), ERROR, RANGE_LB_INC, and RANGE_UB_INC.

Referenced by range_constructor3().

◆ range_recv()

Datum range_recv ( PG_FUNCTION_ARGS  )

Definition at line 180 of file rangetypes.c.

181{
183 Oid rngtypoid = PG_GETARG_OID(1);
184 int32 typmod = PG_GETARG_INT32(2);
186 RangeIOData *cache;
187 char flags;
190
191 check_stack_depth(); /* recurses when subtype is a range type */
192
193 cache = get_range_io_data(fcinfo, rngtypoid, IOFunc_receive);
194
195 /* receive the flags... */
196 flags = (unsigned char) pq_getmsgbyte(buf);
197
198 /*
199 * Mask out any unsupported flags, particularly RANGE_xB_NULL which would
200 * confuse following tests. Note that range_serialize will take care of
201 * cleaning up any inconsistencies in the remaining flags.
202 */
203 flags &= (RANGE_EMPTY |
208
209 /* receive the bounds ... */
210 if (RANGE_HAS_LBOUND(flags))
211 {
212 uint32 bound_len = pq_getmsgint(buf, 4);
213 const char *bound_data = pq_getmsgbytes(buf, bound_len);
214 StringInfoData bound_buf;
215
216 initStringInfo(&bound_buf);
217 appendBinaryStringInfo(&bound_buf, bound_data, bound_len);
218
219 lower.val = ReceiveFunctionCall(&cache->typioproc,
220 &bound_buf,
221 cache->typioparam,
222 typmod);
223 pfree(bound_buf.data);
224 }
225 else
226 lower.val = (Datum) 0;
227
228 if (RANGE_HAS_UBOUND(flags))
229 {
230 uint32 bound_len = pq_getmsgint(buf, 4);
231 const char *bound_data = pq_getmsgbytes(buf, bound_len);
232 StringInfoData bound_buf;
233
234 initStringInfo(&bound_buf);
235 appendBinaryStringInfo(&bound_buf, bound_data, bound_len);
236
237 upper.val = ReceiveFunctionCall(&cache->typioproc,
238 &bound_buf,
239 cache->typioparam,
240 typmod);
241 pfree(bound_buf.data);
242 }
243 else
244 upper.val = (Datum) 0;
245
247
248 /* finish constructing RangeBound representation */
249 lower.infinite = (flags & RANGE_LB_INF) != 0;
250 lower.inclusive = (flags & RANGE_LB_INC) != 0;
251 lower.lower = true;
252 upper.infinite = (flags & RANGE_UB_INF) != 0;
253 upper.inclusive = (flags & RANGE_UB_INC) != 0;
254 upper.lower = false;
255
256 /* serialize and canonicalize */
257 range = make_range(cache->typcache, &lower, &upper,
258 flags & RANGE_EMPTY, NULL);
259
261}
Datum ReceiveFunctionCall(FmgrInfo *flinfo, StringInfo buf, Oid typioparam, int32 typmod)
Definition: fmgr.c:1697
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition: pqformat.c:415
void pq_getmsgend(StringInfo msg)
Definition: pqformat.c:635
int pq_getmsgbyte(StringInfo msg)
Definition: pqformat.c:399
const char * pq_getmsgbytes(StringInfo msg, int datalen)
Definition: pqformat.c:508
struct StringInfoData * StringInfo
Definition: string.h:15
void appendBinaryStringInfo(StringInfo str, const void *data, int datalen)
Definition: stringinfo.c:281

References appendBinaryStringInfo(), buf, check_stack_depth(), StringInfoData::data, get_range_io_data(), initStringInfo(), IOFunc_receive, lower(), make_range(), pfree(), PG_GETARG_INT32, PG_GETARG_OID, PG_GETARG_POINTER, PG_RETURN_RANGE_P, pq_getmsgbyte(), pq_getmsgbytes(), pq_getmsgend(), pq_getmsgint(), range(), RANGE_EMPTY, RANGE_HAS_LBOUND, RANGE_HAS_UBOUND, RANGE_LB_INC, RANGE_LB_INF, RANGE_UB_INC, RANGE_UB_INF, ReceiveFunctionCall(), RangeIOData::typcache, RangeIOData::typioparam, RangeIOData::typioproc, and upper().

◆ range_send()

Datum range_send ( PG_FUNCTION_ARGS  )

Definition at line 264 of file rangetypes.c.

265{
268 RangeIOData *cache;
269 char flags;
272 bool empty;
273
274 check_stack_depth(); /* recurses when subtype is a range type */
275
277
278 /* deserialize */
279 range_deserialize(cache->typcache, range, &lower, &upper, &empty);
280 flags = range_get_flags(range);
281
282 /* construct output */
284
285 pq_sendbyte(buf, flags);
286
287 if (RANGE_HAS_LBOUND(flags))
288 {
289 bytea *bound = SendFunctionCall(&cache->typioproc, lower.val);
290 uint32 bound_len = VARSIZE(bound) - VARHDRSZ;
291 char *bound_data = VARDATA(bound);
292
293 pq_sendint32(buf, bound_len);
294 pq_sendbytes(buf, bound_data, bound_len);
295 }
296
297 if (RANGE_HAS_UBOUND(flags))
298 {
299 bytea *bound = SendFunctionCall(&cache->typioproc, upper.val);
300 uint32 bound_len = VARSIZE(bound) - VARHDRSZ;
301 char *bound_data = VARDATA(bound);
302
303 pq_sendint32(buf, bound_len);
304 pq_sendbytes(buf, bound_data, bound_len);
305 }
306
308}
#define VARHDRSZ
Definition: c.h:697
bytea * SendFunctionCall(FmgrInfo *flinfo, Datum val)
Definition: fmgr.c:1744
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:371
@ IOFunc_send
Definition: lsyscache.h:39
void pq_sendbytes(StringInfo buf, const void *data, int datalen)
Definition: pqformat.c:126
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:326
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:346
static void pq_sendint32(StringInfo buf, uint32 i)
Definition: pqformat.h:144
static void pq_sendbyte(StringInfo buf, uint8 byt)
Definition: pqformat.h:160
StringInfo makeStringInfo(void)
Definition: stringinfo.c:72
Definition: c.h:692

References buf, check_stack_depth(), get_range_io_data(), IOFunc_send, lower(), makeStringInfo(), PG_GETARG_RANGE_P, PG_RETURN_BYTEA_P, pq_begintypsend(), pq_endtypsend(), pq_sendbyte(), pq_sendbytes(), pq_sendint32(), range(), range_deserialize(), range_get_flags(), RANGE_HAS_LBOUND, RANGE_HAS_UBOUND, RangeTypeGetOid, SendFunctionCall(), RangeIOData::typcache, RangeIOData::typioproc, upper(), VARDATA(), VARHDRSZ, and VARSIZE().

◆ range_serialize()

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

Definition at line 1790 of file rangetypes.c.

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

2001{
2002 char *flagsp;
2003
2004 /* flag byte is datum's last byte */
2005 flagsp = (char *) range + VARSIZE(range) - 1;
2006
2007 *flagsp |= RANGE_CONTAIN_EMPTY;
2008}
#define RANGE_CONTAIN_EMPTY
Definition: rangetypes.h:45

References range(), RANGE_CONTAIN_EMPTY, and VARSIZE().

Referenced by range_super_union().

◆ range_sortsupport()

Datum range_sortsupport ( PG_FUNCTION_ARGS  )

Definition at line 1296 of file rangetypes.c.

1297{
1299
1300 ssup->comparator = range_fast_cmp;
1301 ssup->ssup_extra = NULL;
1302
1304}
#define PG_RETURN_VOID()
Definition: fmgr.h:349
static int range_fast_cmp(Datum a, Datum b, SortSupport ssup)
Definition: rangetypes.c:1308
struct SortSupportData * SortSupport
Definition: sortsupport.h:58
int(* comparator)(Datum x, Datum y, SortSupport ssup)
Definition: sortsupport.h:106

References SortSupportData::comparator, PG_GETARG_POINTER, PG_RETURN_VOID, range_fast_cmp(), and SortSupportData::ssup_extra.

◆ range_split_internal()

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

Definition at line 1183 of file rangetypes.c.

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

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

Referenced by multirange_minus_internal().

◆ range_union()

Datum range_union ( PG_FUNCTION_ARGS  )

Definition at line 1099 of file rangetypes.c.

1100{
1103 TypeCacheEntry *typcache;
1104
1105 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
1106
1107 PG_RETURN_RANGE_P(range_union_internal(typcache, r1, r2, true));
1108}

References PG_GETARG_RANGE_P, PG_RETURN_RANGE_P, range_get_typcache(), range_union_internal(), and RangeTypeGetOid.

◆ range_union_internal()

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

Definition at line 1053 of file rangetypes.c.

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

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

◆ range_upper()

Datum range_upper ( PG_FUNCTION_ARGS  )

Definition at line 468 of file rangetypes.c.

469{
471 TypeCacheEntry *typcache;
474 bool empty;
475
476 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
477
478 range_deserialize(typcache, r1, &lower, &upper, &empty);
479
480 /* Return NULL if there's no finite upper bound */
481 if (empty || upper.infinite)
483
485}

References lower(), PG_GETARG_RANGE_P, PG_RETURN_DATUM, PG_RETURN_NULL, range_deserialize(), range_get_typcache(), RangeTypeGetOid, and upper().

◆ range_upper_inc()

Datum range_upper_inc ( PG_FUNCTION_ARGS  )

Definition at line 512 of file rangetypes.c.

513{
515 char flags = range_get_flags(r1);
516
518}

References PG_GETARG_RANGE_P, PG_RETURN_BOOL, range_get_flags(), and RANGE_UB_INC.

◆ range_upper_inf()

Datum range_upper_inf ( PG_FUNCTION_ARGS  )

Definition at line 532 of file rangetypes.c.

533{
535 char flags = range_get_flags(r1);
536
538}

References PG_GETARG_RANGE_P, PG_RETURN_BOOL, range_get_flags(), and RANGE_UB_INF.

◆ tsrange_subdiff()

Datum tsrange_subdiff ( PG_FUNCTION_ARGS  )

Definition at line 1727 of file rangetypes.c.

1728{
1731 float8 result;
1732
1733 result = ((float8) v1 - (float8) v2) / USECS_PER_SEC;
1734 PG_RETURN_FLOAT8(result);
1735}
int64 Timestamp
Definition: timestamp.h:38
#define USECS_PER_SEC
Definition: timestamp.h:134
#define PG_GETARG_TIMESTAMP(n)
Definition: timestamp.h:63

References PG_GETARG_TIMESTAMP, PG_RETURN_FLOAT8, and USECS_PER_SEC.

◆ tstzrange_subdiff()

Datum tstzrange_subdiff ( PG_FUNCTION_ARGS  )

Definition at line 1738 of file rangetypes.c.

1739{
1742 float8 result;
1743
1744 result = ((float8) v1 - (float8) v2) / USECS_PER_SEC;
1745 PG_RETURN_FLOAT8(result);
1746}

References PG_GETARG_TIMESTAMP, PG_RETURN_FLOAT8, and USECS_PER_SEC.