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

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

2974{
2975 Oid elemType = typeCache->type_id;
2976 int16 elemTypeLen = typeCache->typlen;
2977 bool elemByValue = typeCache->typbyval;
2978 Oid elemCollation = typeCache->typcollation;
2979 int16 strategy;
2980 Oid oproid;
2981 Expr *constExpr;
2982
2983 /* Identify the comparison operator to use */
2984 if (isLowerBound)
2985 strategy = isInclusive ? BTGreaterEqualStrategyNumber : BTGreaterStrategyNumber;
2986 else
2987 strategy = isInclusive ? BTLessEqualStrategyNumber : BTLessStrategyNumber;
2988
2989 /*
2990 * We could use exprType(elemExpr) here, if it ever becomes possible that
2991 * elemExpr is not the exact same type as the range elements.
2992 */
2993 oproid = get_opfamily_member(opfamily, elemType, elemType, strategy);
2994
2995 /* We don't really expect failure here, but just in case ... */
2996 if (!OidIsValid(oproid))
2997 return NULL;
2998
2999 /* OK, convert "val" to a full-fledged Const node, and make the OpExpr */
3000 constExpr = (Expr *) makeConst(elemType,
3001 -1,
3002 elemCollation,
3003 elemTypeLen,
3004 val,
3005 false,
3006 elemByValue);
3007
3008 return make_opclause(oproid,
3009 BOOLOID,
3010 false,
3011 elemExpr,
3012 constExpr,
3013 InvalidOid,
3014 rng_collation);
3015}
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 1620 of file rangetypes.c.

1621{
1623 Node *escontext = fcinfo->context;
1624 TypeCacheEntry *typcache;
1627 bool empty;
1628
1629 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1630
1631 range_deserialize(typcache, r, &lower, &upper, &empty);
1632
1633 if (empty)
1635
1636 if (!lower.infinite && !DATE_NOT_FINITE(DatumGetDateADT(lower.val)) &&
1637 !lower.inclusive)
1638 {
1639 DateADT bnd = DatumGetDateADT(lower.val);
1640
1641 /* Check for overflow -- note we already eliminated PG_INT32_MAX */
1642 bnd++;
1643 if (unlikely(!IS_VALID_DATE(bnd)))
1644 ereturn(escontext, (Datum) 0,
1645 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1646 errmsg("date out of range")));
1647 lower.val = DateADTGetDatum(bnd);
1648 lower.inclusive = true;
1649 }
1650
1651 if (!upper.infinite && !DATE_NOT_FINITE(DatumGetDateADT(upper.val)) &&
1652 upper.inclusive)
1653 {
1654 DateADT bnd = DatumGetDateADT(upper.val);
1655
1656 /* Check for overflow -- note we already eliminated PG_INT32_MAX */
1657 bnd++;
1658 if (unlikely(!IS_VALID_DATE(bnd)))
1659 ereturn(escontext, (Datum) 0,
1660 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1661 errmsg("date out of range")));
1662 upper.val = DateADTGetDatum(bnd);
1663 upper.inclusive = false;
1664 }
1665
1667 false, escontext));
1668}
#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:854
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#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:1789
void range_deserialize(TypeCacheEntry *typcache, const RangeType *range, RangeBound *lower, RangeBound *upper, bool *empty)
Definition: rangetypes.c:1918
TypeCacheEntry * range_get_typcache(FunctionCallInfo fcinfo, Oid rngtypid)
Definition: rangetypes.c:1765
#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 1717 of file rangetypes.c.

1718{
1719 int32 v1 = PG_GETARG_INT32(0);
1720 int32 v2 = PG_GETARG_INT32(1);
1721
1722 PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
1723}
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 2745 of file rangetypes.c.

2747{
2748 if (TYPE_IS_PACKABLE(typlen, typstorage) &&
2750 {
2751 /*
2752 * we're anticipating converting to a short varlena header, so adjust
2753 * length and don't count any alignment
2754 */
2756 }
2757 else
2758 {
2759 data_length = att_align_datum(data_length, typalign, typlen, val);
2760 data_length = att_addlength_datum(data_length, typlen, val);
2761 }
2762
2763 return data_length;
2764}
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:2737
#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 2771 of file rangetypes.c.

2773{
2774 Size data_length;
2775
2776 if (typbyval)
2777 {
2778 /* pass-by-value */
2779 ptr = (char *) att_align_nominal(ptr, typalign);
2780 store_att_byval(ptr, datum, typlen);
2781 data_length = typlen;
2782 }
2783 else if (typlen == -1)
2784 {
2785 /* varlena */
2786 Pointer val = DatumGetPointer(datum);
2787
2789 {
2790 /*
2791 * Throw error, because we must never put a toast pointer inside a
2792 * range object. Caller should have detoasted it.
2793 */
2794 elog(ERROR, "cannot store a toast pointer inside a range");
2795 data_length = 0; /* keep compiler quiet */
2796 }
2797 else if (VARATT_IS_SHORT(val))
2798 {
2799 /* no alignment for short varlenas */
2800 data_length = VARSIZE_SHORT(val);
2801 memcpy(ptr, val, data_length);
2802 }
2803 else if (TYPE_IS_PACKABLE(typlen, typstorage) &&
2805 {
2806 /* convert to short varlena -- no alignment */
2807 data_length = VARATT_CONVERTED_SHORT_SIZE(val);
2808 SET_VARSIZE_SHORT(ptr, data_length);
2809 memcpy(ptr + 1, VARDATA(val), data_length - 1);
2810 }
2811 else
2812 {
2813 /* full 4-byte header varlena */
2814 ptr = (char *) att_align_nominal(ptr, typalign);
2815 data_length = VARSIZE(val);
2816 memcpy(ptr, val, data_length);
2817 }
2818 }
2819 else if (typlen == -2)
2820 {
2821 /* cstring ... never needs alignment */
2822 Assert(typalign == TYPALIGN_CHAR);
2823 data_length = strlen(DatumGetCString(datum)) + 1;
2824 memcpy(ptr, DatumGetPointer(datum), data_length);
2825 }
2826 else
2827 {
2828 /* fixed-length pass-by-reference */
2829 ptr = (char *) att_align_nominal(ptr, typalign);
2830 Assert(typlen > 0);
2831 data_length = typlen;
2832 memcpy(ptr, DatumGetPointer(datum), data_length);
2833 }
2834
2835 ptr += data_length;
2836
2837 return ptr;
2838}
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 557 of file rangetypes.c.

558{
561 TypeCacheEntry *typcache;
562
563 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
564
566}
#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:2689

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

2250{
2251 Node *rawreq = (Node *) PG_GETARG_POINTER(0);
2252 Node *ret = NULL;
2253
2254 if (IsA(rawreq, SupportRequestSimplify))
2255 {
2257 FuncExpr *fexpr = req->fcall;
2258 Expr *leftop,
2259 *rightop;
2260
2261 Assert(list_length(fexpr->args) == 2);
2262 leftop = linitial(fexpr->args);
2263 rightop = lsecond(fexpr->args);
2264
2265 ret = find_simplified_clause(req->root, rightop, leftop);
2266 }
2267
2268 PG_RETURN_POINTER(ret);
2269}
#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:2848
List * args
Definition: primnodes.h:787
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 2848 of file rangetypes.c.

2849{
2851 TypeCacheEntry *rangetypcache;
2854 bool empty;
2855
2856 /* can't do anything unless the range is a non-null constant */
2857 if (!IsA(rangeExpr, Const) || ((Const *) rangeExpr)->constisnull)
2858 return NULL;
2859 range = DatumGetRangeTypeP(((Const *) rangeExpr)->constvalue);
2860
2861 rangetypcache = lookup_type_cache(RangeTypeGetOid(range),
2863 if (rangetypcache->rngelemtype == NULL)
2864 elog(ERROR, "type %u is not a range type", RangeTypeGetOid(range));
2865
2866 range_deserialize(rangetypcache, range, &lower, &upper, &empty);
2867
2868 if (empty)
2869 {
2870 /* if the range is empty, then there can be no matches */
2871 return makeBoolConst(false, false);
2872 }
2873 else if (lower.infinite && upper.infinite)
2874 {
2875 /* the range has infinite bounds, so it matches everything */
2876 return makeBoolConst(true, false);
2877 }
2878 else
2879 {
2880 /* at least one bound is available, we have something to work with */
2881 TypeCacheEntry *elemTypcache = rangetypcache->rngelemtype;
2882 Oid opfamily = rangetypcache->rng_opfamily;
2883 Oid rng_collation = rangetypcache->rng_collation;
2884 Expr *lowerExpr = NULL;
2885 Expr *upperExpr = NULL;
2886
2887 if (!lower.infinite && !upper.infinite)
2888 {
2889 /*
2890 * When both bounds are present, we have a problem: the
2891 * "simplified" clause would need to evaluate the elemExpr twice.
2892 * That's definitely not okay if the elemExpr is volatile, and
2893 * it's also unattractive if the elemExpr is expensive.
2894 */
2895 QualCost eval_cost;
2896
2897 if (contain_volatile_functions((Node *) elemExpr))
2898 return NULL;
2899
2900 /*
2901 * We define "expensive" as "contains any subplan or more than 10
2902 * operators". Note that the subplan search has to be done
2903 * explicitly, since cost_qual_eval() will barf on unplanned
2904 * subselects.
2905 */
2906 if (contain_subplans((Node *) elemExpr))
2907 return NULL;
2908 cost_qual_eval_node(&eval_cost, (Node *) elemExpr, root);
2909 if (eval_cost.startup + eval_cost.per_tuple >
2910 10 * cpu_operator_cost)
2911 return NULL;
2912 }
2913
2914 /* Okay, try to build boundary comparison expressions */
2915 if (!lower.infinite)
2916 {
2917 lowerExpr = build_bound_expr(elemExpr,
2918 lower.val,
2919 true,
2920 lower.inclusive,
2921 elemTypcache,
2922 opfamily,
2923 rng_collation);
2924 if (lowerExpr == NULL)
2925 return NULL;
2926 }
2927
2928 if (!upper.infinite)
2929 {
2930 /* Copy the elemExpr if we need two copies */
2931 if (!lower.infinite)
2932 elemExpr = copyObject(elemExpr);
2933 upperExpr = build_bound_expr(elemExpr,
2934 upper.val,
2935 false,
2936 upper.inclusive,
2937 elemTypcache,
2938 opfamily,
2939 rng_collation);
2940 if (upperExpr == NULL)
2941 return NULL;
2942 }
2943
2944 if (lowerExpr != NULL && upperExpr != NULL)
2945 return (Node *) make_andclause(list_make2(lowerExpr, upperExpr));
2946 else if (lowerExpr != NULL)
2947 return (Node *) lowerExpr;
2948 else if (upperExpr != NULL)
2949 return (Node *) upperExpr;
2950 else
2951 {
2952 Assert(false);
2953 return NULL;
2954 }
2955 }
2956}
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:2970
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 317 of file rangetypes.c.

318{
319 RangeIOData *cache = (RangeIOData *) fcinfo->flinfo->fn_extra;
320
321 if (cache == NULL || cache->typcache->type_id != rngtypid)
322 {
323 int16 typlen;
324 bool typbyval;
325 char typalign;
326 char typdelim;
327 Oid typiofunc;
328
329 cache = (RangeIOData *) MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
330 sizeof(RangeIOData));
332 if (cache->typcache->rngelemtype == NULL)
333 elog(ERROR, "type %u is not a range type", rngtypid);
334
335 /* get_type_io_data does more than we need, but is convenient */
337 func,
338 &typlen,
339 &typbyval,
340 &typalign,
341 &typdelim,
342 &cache->typioparam,
343 &typiofunc);
344
345 if (!OidIsValid(typiofunc))
346 {
347 /* this could only happen for receive or send */
348 if (func == IOFunc_receive)
350 (errcode(ERRCODE_UNDEFINED_FUNCTION),
351 errmsg("no binary input function available for type %s",
353 else
355 (errcode(ERRCODE_UNDEFINED_FUNCTION),
356 errmsg("no binary output function available for type %s",
358 }
359 fmgr_info_cxt(typiofunc, &cache->typioproc,
360 fcinfo->flinfo->fn_mcxt);
361
362 fcinfo->flinfo->fn_extra = cache;
363 }
364
365 return cache;
366}
#define ereport(elevel,...)
Definition: elog.h:150
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:137
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:53
FmgrInfo typioproc
Definition: rangetypes.c:54
Oid typioparam
Definition: rangetypes.c:55

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

1393{
1395 uint32 result;
1396 TypeCacheEntry *typcache;
1397 TypeCacheEntry *scache;
1400 bool empty;
1401 char flags;
1402 uint32 lower_hash;
1403 uint32 upper_hash;
1404
1405 check_stack_depth(); /* recurses when subtype is a range type */
1406
1407 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1408
1409 /* deserialize */
1410 range_deserialize(typcache, r, &lower, &upper, &empty);
1411 flags = range_get_flags(r);
1412
1413 /*
1414 * Look up the element type's hash function, if not done already.
1415 */
1416 scache = typcache->rngelemtype;
1417 if (!OidIsValid(scache->hash_proc_finfo.fn_oid))
1418 {
1420 if (!OidIsValid(scache->hash_proc_finfo.fn_oid))
1421 ereport(ERROR,
1422 (errcode(ERRCODE_UNDEFINED_FUNCTION),
1423 errmsg("could not identify a hash function for type %s",
1424 format_type_be(scache->type_id))));
1425 }
1426
1427 /*
1428 * Apply the hash function to each bound.
1429 */
1430 if (RANGE_HAS_LBOUND(flags))
1431 lower_hash = DatumGetUInt32(FunctionCall1Coll(&scache->hash_proc_finfo,
1432 typcache->rng_collation,
1433 lower.val));
1434 else
1435 lower_hash = 0;
1436
1437 if (RANGE_HAS_UBOUND(flags))
1438 upper_hash = DatumGetUInt32(FunctionCall1Coll(&scache->hash_proc_finfo,
1439 typcache->rng_collation,
1440 upper.val));
1441 else
1442 upper_hash = 0;
1443
1444 /* Merge hashes of flags and bounds */
1445 result = hash_bytes_uint32((uint32) flags);
1446 result ^= lower_hash;
1447 result = pg_rotate_left32(result, 1);
1448 result ^= upper_hash;
1449
1450 PG_RETURN_INT32(result);
1451}
uint32_t uint32
Definition: c.h:538
Datum FunctionCall1Coll(FmgrInfo *flinfo, Oid collation, Datum arg1)
Definition: fmgr.c:1129
#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:1985
#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 1458 of file rangetypes.c.

1459{
1461 Datum seed = PG_GETARG_DATUM(1);
1462 uint64 result;
1463 TypeCacheEntry *typcache;
1464 TypeCacheEntry *scache;
1467 bool empty;
1468 char flags;
1469 uint64 lower_hash;
1470 uint64 upper_hash;
1471
1473
1474 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1475
1476 range_deserialize(typcache, r, &lower, &upper, &empty);
1477 flags = range_get_flags(r);
1478
1479 scache = typcache->rngelemtype;
1481 {
1482 scache = lookup_type_cache(scache->type_id,
1485 ereport(ERROR,
1486 (errcode(ERRCODE_UNDEFINED_FUNCTION),
1487 errmsg("could not identify a hash function for type %s",
1488 format_type_be(scache->type_id))));
1489 }
1490
1491 if (RANGE_HAS_LBOUND(flags))
1493 typcache->rng_collation,
1494 lower.val,
1495 seed));
1496 else
1497 lower_hash = 0;
1498
1499 if (RANGE_HAS_UBOUND(flags))
1501 typcache->rng_collation,
1502 upper.val,
1503 seed));
1504 else
1505 upper_hash = 0;
1506
1507 /* Merge hashes of flags and bounds */
1509 DatumGetInt64(seed)));
1510 result ^= lower_hash;
1511 result = ROTATE_HIGH_AND_LOW_32BITS(result);
1512 result ^= upper_hash;
1513
1514 PG_RETURN_UINT64(result);
1515}
uint64_t uint64
Definition: c.h:539
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Definition: fmgr.c:1149
#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 1526 of file rangetypes.c.

1527{
1529 Node *escontext = fcinfo->context;
1530 TypeCacheEntry *typcache;
1533 bool empty;
1534
1535 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1536
1537 range_deserialize(typcache, r, &lower, &upper, &empty);
1538
1539 if (empty)
1541
1542 if (!lower.infinite && !lower.inclusive)
1543 {
1544 int32 bnd = DatumGetInt32(lower.val);
1545
1546 /* Handle possible overflow manually */
1547 if (unlikely(bnd == PG_INT32_MAX))
1548 ereturn(escontext, (Datum) 0,
1549 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1550 errmsg("integer out of range")));
1551 lower.val = Int32GetDatum(bnd + 1);
1552 lower.inclusive = true;
1553 }
1554
1555 if (!upper.infinite && upper.inclusive)
1556 {
1557 int32 bnd = DatumGetInt32(upper.val);
1558
1559 /* Handle possible overflow manually */
1560 if (unlikely(bnd == PG_INT32_MAX))
1561 ereturn(escontext, (Datum) 0,
1562 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1563 errmsg("integer out of range")));
1564 upper.val = Int32GetDatum(bnd + 1);
1565 upper.inclusive = false;
1566 }
1567
1569 false, escontext));
1570}
#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 1683 of file rangetypes.c.

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

References PG_GETARG_INT32, and PG_RETURN_FLOAT8.

◆ int8range_canonical()

Datum int8range_canonical ( PG_FUNCTION_ARGS  )

Definition at line 1573 of file rangetypes.c.

1574{
1576 Node *escontext = fcinfo->context;
1577 TypeCacheEntry *typcache;
1580 bool empty;
1581
1582 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1583
1584 range_deserialize(typcache, r, &lower, &upper, &empty);
1585
1586 if (empty)
1588
1589 if (!lower.infinite && !lower.inclusive)
1590 {
1591 int64 bnd = DatumGetInt64(lower.val);
1592
1593 /* Handle possible overflow manually */
1594 if (unlikely(bnd == PG_INT64_MAX))
1595 ereturn(escontext, (Datum) 0,
1596 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1597 errmsg("bigint out of range")));
1598 lower.val = Int64GetDatum(bnd + 1);
1599 lower.inclusive = true;
1600 }
1601
1602 if (!upper.infinite && upper.inclusive)
1603 {
1604 int64 bnd = DatumGetInt64(upper.val);
1605
1606 /* Handle possible overflow manually */
1607 if (unlikely(bnd == PG_INT64_MAX))
1608 ereturn(escontext, (Datum) 0,
1609 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1610 errmsg("bigint out of range")));
1611 upper.val = Int64GetDatum(bnd + 1);
1612 upper.inclusive = false;
1613 }
1614
1616 false, escontext));
1617}
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 1692 of file rangetypes.c.

1693{
1694 int64 v1 = PG_GETARG_INT64(0);
1695 int64 v2 = PG_GETARG_INT64(1);
1696
1697 PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
1698}
#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 2227 of file rangetypes.c.

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

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

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

1702{
1703 Datum v1 = PG_GETARG_DATUM(0);
1704 Datum v2 = PG_GETARG_DATUM(1);
1705 Datum numresult;
1706 float8 floatresult;
1707
1708 numresult = DirectFunctionCall2(numeric_sub, v1, v2);
1709
1711 numresult));
1712
1713 PG_RETURN_FLOAT8(floatresult);
1714}
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 828 of file rangetypes.c.

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

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

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

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

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

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

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

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

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

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

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

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

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

◆ range_bound_escape()

static char * range_bound_escape ( const char *  value)
static

Definition at line 2599 of file rangetypes.c.

2600{
2601 bool nq;
2602 const char *ptr;
2604
2606
2607 /* Detect whether we need double quotes for this value */
2608 nq = (value[0] == '\0'); /* force quotes for empty string */
2609 for (ptr = value; *ptr; ptr++)
2610 {
2611 char ch = *ptr;
2612
2613 if (ch == '"' || ch == '\\' ||
2614 ch == '(' || ch == ')' ||
2615 ch == '[' || ch == ']' ||
2616 ch == ',' ||
2617 isspace((unsigned char) ch))
2618 {
2619 nq = true;
2620 break;
2621 }
2622 }
2623
2624 /* And emit the string */
2625 if (nq)
2627 for (ptr = value; *ptr; ptr++)
2628 {
2629 char ch = *ptr;
2630
2631 if (ch == '"' || ch == '\\')
2634 }
2635 if (nq)
2637
2638 return buf.data;
2639}
static struct @168 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 1249 of file rangetypes.c.

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

2154{
2155 /*
2156 * First, handle cases involving infinity, which don't require invoking
2157 * the comparison proc.
2158 */
2159 if (b1->infinite && b2->infinite)
2160 {
2161 /*
2162 * Both are infinity, so they are equal unless one is lower and the
2163 * other not.
2164 */
2165 if (b1->lower == b2->lower)
2166 return 0;
2167 else
2168 return b1->lower ? -1 : 1;
2169 }
2170 else if (b1->infinite)
2171 return b1->lower ? -1 : 1;
2172 else if (b2->infinite)
2173 return b2->lower ? 1 : -1;
2174
2175 /*
2176 * Both boundaries are finite, so compare the held values.
2177 */
2179 typcache->rng_collation,
2180 b1->val, b2->val));
2181}
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 2078 of file rangetypes.c.

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

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

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

378{
379 Datum arg1 = PG_GETARG_DATUM(0);
380 Datum arg2 = PG_GETARG_DATUM(1);
381 Oid rngtypid = get_fn_expr_rettype(fcinfo->flinfo);
383 TypeCacheEntry *typcache;
386
387 typcache = range_get_typcache(fcinfo, rngtypid);
388
389 lower.val = PG_ARGISNULL(0) ? (Datum) 0 : arg1;
390 lower.infinite = PG_ARGISNULL(0);
391 lower.inclusive = true;
392 lower.lower = true;
393
394 upper.val = PG_ARGISNULL(1) ? (Datum) 0 : arg2;
395 upper.infinite = PG_ARGISNULL(1);
396 upper.inclusive = false;
397 upper.lower = false;
398
399 range = make_range(typcache, &lower, &upper, false, NULL);
400
402}
Oid get_fn_expr_rettype(FmgrInfo *flinfo)
Definition: fmgr.c:1852
#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 406 of file rangetypes.c.

407{
408 Datum arg1 = PG_GETARG_DATUM(0);
409 Datum arg2 = PG_GETARG_DATUM(1);
410 Oid rngtypid = get_fn_expr_rettype(fcinfo->flinfo);
412 TypeCacheEntry *typcache;
415 char flags;
416
417 typcache = range_get_typcache(fcinfo, rngtypid);
418
419 if (PG_ARGISNULL(2))
421 (errcode(ERRCODE_DATA_EXCEPTION),
422 errmsg("range constructor flags argument must not be null")));
423
425
426 lower.val = PG_ARGISNULL(0) ? (Datum) 0 : arg1;
427 lower.infinite = PG_ARGISNULL(0);
428 lower.inclusive = (flags & RANGE_LB_INC) != 0;
429 lower.lower = true;
430
431 upper.val = PG_ARGISNULL(1) ? (Datum) 0 : arg2;
432 upper.infinite = PG_ARGISNULL(1);
433 upper.inclusive = (flags & RANGE_UB_INC) != 0;
434 upper.lower = false;
435
436 range = make_range(typcache, &lower, &upper, false, NULL);
437
439}
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
static char range_parse_flags(const char *flags_str)
Definition: rangetypes.c:2309
#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 651 of file rangetypes.c.

652{
655 TypeCacheEntry *typcache;
656
657 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
658
660}
bool range_contained_by_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:2680

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

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

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

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

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

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

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

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

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

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

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

2570{
2572
2573 if (flags & RANGE_EMPTY)
2575
2577
2578 appendStringInfoChar(&buf, (flags & RANGE_LB_INC) ? '[' : '(');
2579
2580 if (RANGE_HAS_LBOUND(flags))
2582
2584
2585 if (RANGE_HAS_UBOUND(flags))
2587
2588 appendStringInfoChar(&buf, (flags & RANGE_UB_INC) ? ']' : ')');
2589
2590 return buf.data;
2591}
char * pstrdup(const char *in)
Definition: mcxt.c:1759
static char * range_bound_escape(const char *value)
Definition: rangetypes.c:2599
#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 1918 of file rangetypes.c.

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

492{
494 char flags = range_get_flags(r1);
495
497}

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

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

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

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

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

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

◆ range_fast_cmp()

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

Definition at line 1307 of file rangetypes.c.

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

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

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

◆ range_get_flags()

char range_get_flags ( const RangeType range)

Definition at line 1985 of file rangetypes.c.

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

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

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

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

◆ range_in()

Datum range_in ( PG_FUNCTION_ARGS  )

Definition at line 90 of file rangetypes.c.

91{
92 char *input_str = PG_GETARG_CSTRING(0);
93 Oid rngtypoid = PG_GETARG_OID(1);
94 Oid typmod = PG_GETARG_INT32(2);
95 Node *escontext = fcinfo->context;
97 RangeIOData *cache;
98 char flags;
99 char *lbound_str;
100 char *ubound_str;
103
104 check_stack_depth(); /* recurses when subtype is a range type */
105
106 cache = get_range_io_data(fcinfo, rngtypoid, IOFunc_input);
107
108 /* parse */
109 if (!range_parse(input_str, &flags, &lbound_str, &ubound_str, escontext))
111
112 /* call element type's input function */
113 if (RANGE_HAS_LBOUND(flags))
114 if (!InputFunctionCallSafe(&cache->typioproc, lbound_str,
115 cache->typioparam, typmod,
116 escontext, &lower.val))
118 if (RANGE_HAS_UBOUND(flags))
119 if (!InputFunctionCallSafe(&cache->typioproc, ubound_str,
120 cache->typioparam, typmod,
121 escontext, &upper.val))
123
124 lower.infinite = (flags & RANGE_LB_INF) != 0;
125 lower.inclusive = (flags & RANGE_LB_INC) != 0;
126 lower.lower = true;
127 upper.infinite = (flags & RANGE_UB_INF) != 0;
128 upper.inclusive = (flags & RANGE_UB_INC) != 0;
129 upper.lower = false;
130
131 /* serialize and canonicalize */
132 range = make_range(cache->typcache, &lower, &upper,
133 flags & RANGE_EMPTY, escontext);
134
136}
bool InputFunctionCallSafe(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod, Node *escontext, Datum *result)
Definition: fmgr.c:1584
#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:2384
static RangeIOData * get_range_io_data(FunctionCallInfo fcinfo, Oid rngtypid, IOFuncSelector func)
Definition: rangetypes.c:317

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

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

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

1220{
1221 MemoryContext aggContext;
1222 Oid rngtypoid;
1223 TypeCacheEntry *typcache;
1224 RangeType *result;
1225 RangeType *current;
1226
1227 if (!AggCheckCallContext(fcinfo, &aggContext))
1228 elog(ERROR, "range_intersect_agg_transfn called in non-aggregate context");
1229
1230 rngtypoid = get_fn_expr_argtype(fcinfo->flinfo, 1);
1231 if (!type_is_range(rngtypoid))
1232 elog(ERROR, "range_intersect_agg must be called with a range");
1233
1234 typcache = range_get_typcache(fcinfo, rngtypoid);
1235
1236 /* strictness ensures these are non-null */
1237 result = PG_GETARG_RANGE_P(0);
1238 current = PG_GETARG_RANGE_P(1);
1239
1240 result = range_intersect_internal(typcache, result, current);
1241 PG_RETURN_RANGE_P(result);
1242}
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1874
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 1143 of file rangetypes.c.

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

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

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

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

◆ range_lower()

Datum range_lower ( PG_FUNCTION_ARGS  )

Definition at line 446 of file rangetypes.c.

447{
449 TypeCacheEntry *typcache;
452 bool empty;
453
454 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
455
456 range_deserialize(typcache, r1, &lower, &upper, &empty);
457
458 /* Return NULL if there's no finite lower bound */
459 if (empty || lower.infinite)
461
463}
#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 501 of file rangetypes.c.

502{
504 char flags = range_get_flags(r1);
505
507}

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

522{
524 char flags = range_get_flags(r1);
525
527}

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

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

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

◆ range_merge()

Datum range_merge ( PG_FUNCTION_ARGS  )

Definition at line 1114 of file rangetypes.c.

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

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

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

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

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

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

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

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

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

References range_eq_internal().

Referenced by range_ne().

◆ range_out()

Datum range_out ( PG_FUNCTION_ARGS  )

Definition at line 139 of file rangetypes.c.

140{
142 char *output_str;
143 RangeIOData *cache;
144 char flags;
145 char *lbound_str = NULL;
146 char *ubound_str = NULL;
149 bool empty;
150
151 check_stack_depth(); /* recurses when subtype is a range type */
152
154
155 /* deserialize */
156 range_deserialize(cache->typcache, range, &lower, &upper, &empty);
157 flags = range_get_flags(range);
158
159 /* call element type's output function */
160 if (RANGE_HAS_LBOUND(flags))
161 lbound_str = OutputFunctionCall(&cache->typioproc, lower.val);
162 if (RANGE_HAS_UBOUND(flags))
163 ubound_str = OutputFunctionCall(&cache->typioproc, upper.val);
164
165 /* construct result string */
166 output_str = range_deparse(flags, lbound_str, ubound_str);
167
168 PG_RETURN_CSTRING(output_str);
169}
char * OutputFunctionCall(FmgrInfo *flinfo, Datum val)
Definition: fmgr.c:1682
#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:2569

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

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

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

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

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

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

◆ range_overleft()

Datum range_overleft ( PG_FUNCTION_ARGS  )

Definition at line 915 of file rangetypes.c.

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

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

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

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

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

◆ range_overright()

Datum range_overright ( PG_FUNCTION_ARGS  )

Definition at line 956 of file rangetypes.c.

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

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

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

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

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

◆ range_parse()

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

Definition at line 2384 of file rangetypes.c.

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

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

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

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

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

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

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

264{
267 RangeIOData *cache;
268 char flags;
271 bool empty;
272
273 check_stack_depth(); /* recurses when subtype is a range type */
274
276
277 /* deserialize */
278 range_deserialize(cache->typcache, range, &lower, &upper, &empty);
279 flags = range_get_flags(range);
280
281 /* construct output */
283
284 pq_sendbyte(buf, flags);
285
286 if (RANGE_HAS_LBOUND(flags))
287 {
288 bytea *bound = SendFunctionCall(&cache->typioproc, lower.val);
289 uint32 bound_len = VARSIZE(bound) - VARHDRSZ;
290 char *bound_data = VARDATA(bound);
291
292 pq_sendint32(buf, bound_len);
293 pq_sendbytes(buf, bound_data, bound_len);
294 }
295
296 if (RANGE_HAS_UBOUND(flags))
297 {
298 bytea *bound = SendFunctionCall(&cache->typioproc, upper.val);
299 uint32 bound_len = VARSIZE(bound) - VARHDRSZ;
300 char *bound_data = VARDATA(bound);
301
302 pq_sendint32(buf, bound_len);
303 pq_sendbytes(buf, bound_data, bound_len);
304 }
305
307}
#define VARHDRSZ
Definition: c.h:697
bytea * SendFunctionCall(FmgrInfo *flinfo, Datum val)
Definition: fmgr.c:1743
#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 1789 of file rangetypes.c.

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

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

1296{
1298
1299 ssup->comparator = range_fast_cmp;
1300 ssup->ssup_extra = NULL;
1301
1303}
#define PG_RETURN_VOID()
Definition: fmgr.h:349
static int range_fast_cmp(Datum a, Datum b, SortSupport ssup)
Definition: rangetypes.c:1307
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 1182 of file rangetypes.c.

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

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

Referenced by multirange_minus_internal().

◆ range_union()

Datum range_union ( PG_FUNCTION_ARGS  )

Definition at line 1098 of file rangetypes.c.

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

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

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

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

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

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

512{
514 char flags = range_get_flags(r1);
515
517}

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

532{
534 char flags = range_get_flags(r1);
535
537}

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

1727{
1730 float8 result;
1731
1732 result = ((float8) v1 - (float8) v2) / USECS_PER_SEC;
1733 PG_RETURN_FLOAT8(result);
1734}
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 1737 of file rangetypes.c.

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

References PG_GETARG_TIMESTAMP, PG_RETURN_FLOAT8, and USECS_PER_SEC.