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/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 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_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 2675 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 Assert(condition)
Definition: c.h:812
#define OidIsValid(objectId)
Definition: c.h:729
RangeType * make_range(TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper, bool empty, struct Node *escontext)
Definition: rangetypes.c:1952
int range_cmp_bound_values(TypeCacheEntry *typcache, const RangeBound *b1, const RangeBound *b2)
Definition: rangetypes.c:2090
#define RangeIsEmpty(r)
Definition: rangetypes.h:55
static int cmp(const chr *x, const chr *y, size_t len)
Definition: regc_locale.c:743
Oid fn_oid
Definition: fmgr.h:59
bool lower
Definition: rangetypes.h:66
bool inclusive
Definition: rangetypes.h:65
FmgrInfo rng_canonical_finfo
Definition: typcache.h:102

References Assert, cmp(), FmgrInfo::fn_oid, RangeBound::inclusive, RangeBound::lower, make_range(), OidIsValid, range_cmp_bound_values(), RangeIsEmpty, and TypeCacheEntry::rng_canonical_finfo.

Referenced by adjacent_cmp_bounds(), multirange_adjacent_multirange(), range_adjacent_internal(), and range_adjacent_multirange_internal().

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

2912 {
2913  Oid elemType = typeCache->type_id;
2914  int16 elemTypeLen = typeCache->typlen;
2915  bool elemByValue = typeCache->typbyval;
2916  Oid elemCollation = typeCache->typcollation;
2917  int16 strategy;
2918  Oid oproid;
2919  Expr *constExpr;
2920 
2921  /* Identify the comparison operator to use */
2922  if (isLowerBound)
2923  strategy = isInclusive ? BTGreaterEqualStrategyNumber : BTGreaterStrategyNumber;
2924  else
2925  strategy = isInclusive ? BTLessEqualStrategyNumber : BTLessStrategyNumber;
2926 
2927  /*
2928  * We could use exprType(elemExpr) here, if it ever becomes possible that
2929  * elemExpr is not the exact same type as the range elements.
2930  */
2931  oproid = get_opfamily_member(opfamily, elemType, elemType, strategy);
2932 
2933  /* We don't really expect failure here, but just in case ... */
2934  if (!OidIsValid(oproid))
2935  return NULL;
2936 
2937  /* OK, convert "val" to a full-fledged Const node, and make the OpExpr */
2938  constExpr = (Expr *) makeConst(elemType,
2939  -1,
2940  elemCollation,
2941  elemTypeLen,
2942  val,
2943  false,
2944  elemByValue);
2945 
2946  return make_opclause(oproid,
2947  BOOLOID,
2948  false,
2949  elemExpr,
2950  constExpr,
2951  InvalidOid,
2952  rng_collation);
2953 }
int16_t int16
Definition: c.h:480
long val
Definition: informix.c:689
Oid get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype, int16 strategy)
Definition: lsyscache.c:166
Expr * make_opclause(Oid opno, Oid opresulttype, bool opretset, Expr *leftop, Expr *rightop, Oid opcollid, Oid inputcollid)
Definition: makefuncs.c:651
Const * makeConst(Oid consttype, int32 consttypmod, Oid constcollid, int constlen, Datum constvalue, bool constisnull, bool constbyval)
Definition: makefuncs.c:301
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
#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:47

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

1559 {
1560  RangeType *r = PG_GETARG_RANGE_P(0);
1561  Node *escontext = fcinfo->context;
1562  TypeCacheEntry *typcache;
1563  RangeBound lower;
1564  RangeBound upper;
1565  bool empty;
1566 
1567  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1568 
1569  range_deserialize(typcache, r, &lower, &upper, &empty);
1570 
1571  if (empty)
1572  PG_RETURN_RANGE_P(r);
1573 
1574  if (!lower.infinite && !DATE_NOT_FINITE(DatumGetDateADT(lower.val)) &&
1575  !lower.inclusive)
1576  {
1577  DateADT bnd = DatumGetDateADT(lower.val);
1578 
1579  /* Check for overflow -- note we already eliminated PG_INT32_MAX */
1580  bnd++;
1581  if (unlikely(!IS_VALID_DATE(bnd)))
1582  ereturn(escontext, (Datum) 0,
1583  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1584  errmsg("date out of range")));
1585  lower.val = DateADTGetDatum(bnd);
1586  lower.inclusive = true;
1587  }
1588 
1589  if (!upper.infinite && !DATE_NOT_FINITE(DatumGetDateADT(upper.val)) &&
1590  upper.inclusive)
1591  {
1592  DateADT bnd = DatumGetDateADT(upper.val);
1593 
1594  /* Check for overflow -- note we already eliminated PG_INT32_MAX */
1595  bnd++;
1596  if (unlikely(!IS_VALID_DATE(bnd)))
1597  ereturn(escontext, (Datum) 0,
1598  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1599  errmsg("date out of range")));
1600  upper.val = DateADTGetDatum(bnd);
1601  upper.inclusive = false;
1602  }
1603 
1605  false, escontext));
1606 }
#define unlikely(x)
Definition: c.h:330
#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:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ereturn(context, dummy_value,...)
Definition: elog.h:277
Datum lower(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:49
Datum upper(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:80
uintptr_t Datum
Definition: postgres.h:64
void range_deserialize(TypeCacheEntry *typcache, const RangeType *range, RangeBound *lower, RangeBound *upper, bool *empty)
Definition: rangetypes.c:1856
TypeCacheEntry * range_get_typcache(FunctionCallInfo fcinfo, Oid rngtypid)
Definition: rangetypes.c:1703
RangeType * range_serialize(TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper, bool empty, struct Node *escontext)
Definition: rangetypes.c:1727
#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:129

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

1656 {
1657  int32 v1 = PG_GETARG_INT32(0);
1658  int32 v2 = PG_GETARG_INT32(1);
1659 
1660  PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
1661 }
double float8
Definition: c.h:584
int32_t int32
Definition: c.h:481
#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 2683 of file rangetypes.c.

2685 {
2686  if (TYPE_IS_PACKABLE(typlen, typstorage) &&
2688  {
2689  /*
2690  * we're anticipating converting to a short varlena header, so adjust
2691  * length and don't count any alignment
2692  */
2694  }
2695  else
2696  {
2697  data_length = att_align_datum(data_length, typalign, typlen, val);
2698  data_length = att_addlength_datum(data_length, typlen, val);
2699  }
2700 
2701  return data_length;
2702 }
char typalign
Definition: pg_type.h:176
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:312
#define TYPE_IS_PACKABLE(typlen, typstorage)
Definition: rangetypes.c:2675
#define att_align_datum(cur_offset, attalign, attlen, attdatum)
Definition: tupmacs.h:86
#define att_addlength_datum(cur_offset, attlen, attdatum)
Definition: tupmacs.h:145
#define VARATT_CAN_MAKE_SHORT(PTR)
Definition: varatt.h:258
#define VARATT_CONVERTED_SHORT_SIZE(PTR)
Definition: varatt.h:261

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

2711 {
2712  Size data_length;
2713 
2714  if (typbyval)
2715  {
2716  /* pass-by-value */
2717  ptr = (char *) att_align_nominal(ptr, typalign);
2718  store_att_byval(ptr, datum, typlen);
2719  data_length = typlen;
2720  }
2721  else if (typlen == -1)
2722  {
2723  /* varlena */
2724  Pointer val = DatumGetPointer(datum);
2725 
2726  if (VARATT_IS_EXTERNAL(val))
2727  {
2728  /*
2729  * Throw error, because we must never put a toast pointer inside a
2730  * range object. Caller should have detoasted it.
2731  */
2732  elog(ERROR, "cannot store a toast pointer inside a range");
2733  data_length = 0; /* keep compiler quiet */
2734  }
2735  else if (VARATT_IS_SHORT(val))
2736  {
2737  /* no alignment for short varlenas */
2738  data_length = VARSIZE_SHORT(val);
2739  memcpy(ptr, val, data_length);
2740  }
2741  else if (TYPE_IS_PACKABLE(typlen, typstorage) &&
2743  {
2744  /* convert to short varlena -- no alignment */
2745  data_length = VARATT_CONVERTED_SHORT_SIZE(val);
2746  SET_VARSIZE_SHORT(ptr, data_length);
2747  memcpy(ptr + 1, VARDATA(val), data_length - 1);
2748  }
2749  else
2750  {
2751  /* full 4-byte header varlena */
2752  ptr = (char *) att_align_nominal(ptr, typalign);
2753  data_length = VARSIZE(val);
2754  memcpy(ptr, val, data_length);
2755  }
2756  }
2757  else if (typlen == -2)
2758  {
2759  /* cstring ... never needs alignment */
2760  Assert(typalign == TYPALIGN_CHAR);
2761  data_length = strlen(DatumGetCString(datum)) + 1;
2762  memcpy(ptr, DatumGetPointer(datum), data_length);
2763  }
2764  else
2765  {
2766  /* fixed-length pass-by-reference */
2767  ptr = (char *) att_align_nominal(ptr, typalign);
2768  Assert(typlen > 0);
2769  data_length = typlen;
2770  memcpy(ptr, DatumGetPointer(datum), data_length);
2771  }
2772 
2773  ptr += data_length;
2774 
2775  return ptr;
2776 }
char * Pointer
Definition: c.h:476
size_t Size
Definition: c.h:559
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
static char * DatumGetCString(Datum X)
Definition: postgres.h:335
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:129
static void store_att_byval(void *T, Datum newdatum, int attlen)
Definition: tupmacs.h:183
#define VARSIZE_SHORT(PTR)
Definition: varatt.h:281
#define SET_VARSIZE_SHORT(PTR, len)
Definition: varatt.h:306
#define VARATT_IS_SHORT(PTR)
Definition: varatt.h:302
#define VARDATA(PTR)
Definition: varatt.h:278
#define VARSIZE(PTR)
Definition: varatt.h:279
#define VARATT_IS_EXTERNAL(PTR)
Definition: varatt.h:289

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:2627

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

2188 {
2189  Node *rawreq = (Node *) PG_GETARG_POINTER(0);
2190  Node *ret = NULL;
2191 
2192  if (IsA(rawreq, SupportRequestSimplify))
2193  {
2195  FuncExpr *fexpr = req->fcall;
2196  Expr *leftop,
2197  *rightop;
2198 
2199  Assert(list_length(fexpr->args) == 2);
2200  leftop = linitial(fexpr->args);
2201  rightop = lsecond(fexpr->args);
2202 
2203  ret = find_simplified_clause(req->root, rightop, leftop);
2204  }
2205 
2206  PG_RETURN_POINTER(ret);
2207 }
#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:158
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:2786
List * args
Definition: primnodes.h:768
struct 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 2786 of file rangetypes.c.

2787 {
2788  RangeType *range;
2789  TypeCacheEntry *rangetypcache;
2790  RangeBound lower;
2791  RangeBound upper;
2792  bool empty;
2793 
2794  /* can't do anything unless the range is a non-null constant */
2795  if (!IsA(rangeExpr, Const) || ((Const *) rangeExpr)->constisnull)
2796  return NULL;
2797  range = DatumGetRangeTypeP(((Const *) rangeExpr)->constvalue);
2798 
2799  rangetypcache = lookup_type_cache(RangeTypeGetOid(range),
2801  if (rangetypcache->rngelemtype == NULL)
2802  elog(ERROR, "type %u is not a range type", RangeTypeGetOid(range));
2803 
2804  range_deserialize(rangetypcache, range, &lower, &upper, &empty);
2805 
2806  if (empty)
2807  {
2808  /* if the range is empty, then there can be no matches */
2809  return makeBoolConst(false, false);
2810  }
2811  else if (lower.infinite && upper.infinite)
2812  {
2813  /* the range has infinite bounds, so it matches everything */
2814  return makeBoolConst(true, false);
2815  }
2816  else
2817  {
2818  /* at least one bound is available, we have something to work with */
2819  TypeCacheEntry *elemTypcache = rangetypcache->rngelemtype;
2820  Oid opfamily = rangetypcache->rng_opfamily;
2821  Oid rng_collation = rangetypcache->rng_collation;
2822  Expr *lowerExpr = NULL;
2823  Expr *upperExpr = NULL;
2824 
2825  if (!lower.infinite && !upper.infinite)
2826  {
2827  /*
2828  * When both bounds are present, we have a problem: the
2829  * "simplified" clause would need to evaluate the elemExpr twice.
2830  * That's definitely not okay if the elemExpr is volatile, and
2831  * it's also unattractive if the elemExpr is expensive.
2832  */
2833  QualCost eval_cost;
2834 
2835  if (contain_volatile_functions((Node *) elemExpr))
2836  return NULL;
2837 
2838  /*
2839  * We define "expensive" as "contains any subplan or more than 10
2840  * operators". Note that the subplan search has to be done
2841  * explicitly, since cost_qual_eval() will barf on unplanned
2842  * subselects.
2843  */
2844  if (contain_subplans((Node *) elemExpr))
2845  return NULL;
2846  cost_qual_eval_node(&eval_cost, (Node *) elemExpr, root);
2847  if (eval_cost.startup + eval_cost.per_tuple >
2848  10 * cpu_operator_cost)
2849  return NULL;
2850  }
2851 
2852  /* Okay, try to build boundary comparison expressions */
2853  if (!lower.infinite)
2854  {
2855  lowerExpr = build_bound_expr(elemExpr,
2856  lower.val,
2857  true,
2858  lower.inclusive,
2859  elemTypcache,
2860  opfamily,
2861  rng_collation);
2862  if (lowerExpr == NULL)
2863  return NULL;
2864  }
2865 
2866  if (!upper.infinite)
2867  {
2868  /* Copy the elemExpr if we need two copies */
2869  if (!lower.infinite)
2870  elemExpr = copyObject(elemExpr);
2871  upperExpr = build_bound_expr(elemExpr,
2872  upper.val,
2873  false,
2874  upper.inclusive,
2875  elemTypcache,
2876  opfamily,
2877  rng_collation);
2878  if (upperExpr == NULL)
2879  return NULL;
2880  }
2881 
2882  if (lowerExpr != NULL && upperExpr != NULL)
2883  return (Node *) make_andclause(list_make2(lowerExpr, upperExpr));
2884  else if (lowerExpr != NULL)
2885  return (Node *) lowerExpr;
2886  else if (upperExpr != NULL)
2887  return (Node *) upperExpr;
2888  else
2889  {
2890  Assert(false);
2891  return NULL;
2892  }
2893  }
2894 }
bool contain_subplans(Node *clause)
Definition: clauses.c:329
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:537
double cpu_operator_cost
Definition: costsize.c:134
void cost_qual_eval_node(QualCost *cost, Node *qual, PlannerInfo *root)
Definition: costsize.c:4758
Expr * make_andclause(List *andclauses)
Definition: makefuncs.c:677
Node * makeBoolConst(bool value, bool isnull)
Definition: makefuncs.c:359
#define copyObject(obj)
Definition: nodes.h:224
#define list_make2(x1, x2)
Definition: pg_list.h:214
tree ctl root
Definition: radixtree.h:1888
static Expr * build_bound_expr(Expr *elemExpr, Datum val, bool isLowerBound, bool isInclusive, TypeCacheEntry *typeCache, Oid opfamily, Oid rng_collation)
Definition: rangetypes.c:2908
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:100
struct TypeCacheEntry * rngelemtype
Definition: typcache.h:98
Oid rng_opfamily
Definition: typcache.h:99
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:386
#define TYPECACHE_RANGE_INFO
Definition: typcache.h:148

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));
331  cache->typcache = lookup_type_cache(rngtypid, TYPECACHE_RANGE_INFO);
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)
349  ereport(ERROR,
350  (errcode(ERRCODE_UNDEFINED_FUNCTION),
351  errmsg("no binary input function available for type %s",
353  else
354  ereport(ERROR,
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:149
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:76
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:2325
@ IOFunc_receive
Definition: lsyscache.h:37
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1181
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:52
FmgrInfo typioproc
Definition: rangetypes.c:53
Oid typioparam
Definition: rangetypes.c:54

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

1331 {
1332  RangeType *r = PG_GETARG_RANGE_P(0);
1333  uint32 result;
1334  TypeCacheEntry *typcache;
1335  TypeCacheEntry *scache;
1336  RangeBound lower;
1337  RangeBound upper;
1338  bool empty;
1339  char flags;
1340  uint32 lower_hash;
1341  uint32 upper_hash;
1342 
1343  check_stack_depth(); /* recurses when subtype is a range type */
1344 
1345  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1346 
1347  /* deserialize */
1348  range_deserialize(typcache, r, &lower, &upper, &empty);
1349  flags = range_get_flags(r);
1350 
1351  /*
1352  * Look up the element type's hash function, if not done already.
1353  */
1354  scache = typcache->rngelemtype;
1355  if (!OidIsValid(scache->hash_proc_finfo.fn_oid))
1356  {
1358  if (!OidIsValid(scache->hash_proc_finfo.fn_oid))
1359  ereport(ERROR,
1360  (errcode(ERRCODE_UNDEFINED_FUNCTION),
1361  errmsg("could not identify a hash function for type %s",
1362  format_type_be(scache->type_id))));
1363  }
1364 
1365  /*
1366  * Apply the hash function to each bound.
1367  */
1368  if (RANGE_HAS_LBOUND(flags))
1369  lower_hash = DatumGetUInt32(FunctionCall1Coll(&scache->hash_proc_finfo,
1370  typcache->rng_collation,
1371  lower.val));
1372  else
1373  lower_hash = 0;
1374 
1375  if (RANGE_HAS_UBOUND(flags))
1376  upper_hash = DatumGetUInt32(FunctionCall1Coll(&scache->hash_proc_finfo,
1377  typcache->rng_collation,
1378  upper.val));
1379  else
1380  upper_hash = 0;
1381 
1382  /* Merge hashes of flags and bounds */
1383  result = hash_uint32((uint32) flags);
1384  result ^= lower_hash;
1385  result = pg_rotate_left32(result, 1);
1386  result ^= upper_hash;
1387 
1388  PG_RETURN_INT32(result);
1389 }
uint32_t uint32
Definition: c.h:485
Datum FunctionCall1Coll(FmgrInfo *flinfo, Oid collation, Datum arg1)
Definition: fmgr.c:1129
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354
static Datum hash_uint32(uint32 k)
Definition: hashfn.h:43
static uint32 pg_rotate_left32(uint32 word, int n)
Definition: pg_bitutils.h:404
void check_stack_depth(void)
Definition: postgres.c:3572
static uint32 DatumGetUInt32(Datum X)
Definition: postgres.h:222
char range_get_flags(const RangeType *range)
Definition: rangetypes.c:1923
#define RANGE_HAS_UBOUND(flags)
Definition: rangetypes.h:51
#define RANGE_HAS_LBOUND(flags)
Definition: rangetypes.h:47
FmgrInfo hash_proc_finfo
Definition: typcache.h:77
#define TYPECACHE_HASH_PROC_FINFO
Definition: typcache.h:144

References check_stack_depth(), DatumGetUInt32(), ereport, errcode(), errmsg(), ERROR, FmgrInfo::fn_oid, format_type_be(), FunctionCall1Coll(), TypeCacheEntry::hash_proc_finfo, hash_uint32(), 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 1396 of file rangetypes.c.

1397 {
1398  RangeType *r = PG_GETARG_RANGE_P(0);
1399  Datum seed = PG_GETARG_DATUM(1);
1400  uint64 result;
1401  TypeCacheEntry *typcache;
1402  TypeCacheEntry *scache;
1403  RangeBound lower;
1404  RangeBound upper;
1405  bool empty;
1406  char flags;
1407  uint64 lower_hash;
1408  uint64 upper_hash;
1409 
1411 
1412  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1413 
1414  range_deserialize(typcache, r, &lower, &upper, &empty);
1415  flags = range_get_flags(r);
1416 
1417  scache = typcache->rngelemtype;
1419  {
1420  scache = lookup_type_cache(scache->type_id,
1423  ereport(ERROR,
1424  (errcode(ERRCODE_UNDEFINED_FUNCTION),
1425  errmsg("could not identify a hash function for type %s",
1426  format_type_be(scache->type_id))));
1427  }
1428 
1429  if (RANGE_HAS_LBOUND(flags))
1431  typcache->rng_collation,
1432  lower.val,
1433  seed));
1434  else
1435  lower_hash = 0;
1436 
1437  if (RANGE_HAS_UBOUND(flags))
1439  typcache->rng_collation,
1440  upper.val,
1441  seed));
1442  else
1443  upper_hash = 0;
1444 
1445  /* Merge hashes of flags and bounds */
1446  result = DatumGetUInt64(hash_uint32_extended((uint32) flags,
1447  DatumGetInt64(seed)));
1448  result ^= lower_hash;
1449  result = ROTATE_HIGH_AND_LOW_32BITS(result);
1450  result ^= upper_hash;
1451 
1452  PG_RETURN_UINT64(result);
1453 }
uint64_t uint64
Definition: c.h:486
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:419
static int64 DatumGetInt64(Datum X)
Definition: postgres.h:385
FmgrInfo hash_extended_proc_finfo
Definition: typcache.h:78
#define TYPECACHE_HASH_EXTENDED_PROC_FINFO
Definition: typcache.h:152

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

1465 {
1466  RangeType *r = PG_GETARG_RANGE_P(0);
1467  Node *escontext = fcinfo->context;
1468  TypeCacheEntry *typcache;
1469  RangeBound lower;
1470  RangeBound upper;
1471  bool empty;
1472 
1473  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1474 
1475  range_deserialize(typcache, r, &lower, &upper, &empty);
1476 
1477  if (empty)
1478  PG_RETURN_RANGE_P(r);
1479 
1480  if (!lower.infinite && !lower.inclusive)
1481  {
1482  int32 bnd = DatumGetInt32(lower.val);
1483 
1484  /* Handle possible overflow manually */
1485  if (unlikely(bnd == PG_INT32_MAX))
1486  ereturn(escontext, (Datum) 0,
1487  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1488  errmsg("integer out of range")));
1489  lower.val = Int32GetDatum(bnd + 1);
1490  lower.inclusive = true;
1491  }
1492 
1493  if (!upper.infinite && upper.inclusive)
1494  {
1495  int32 bnd = DatumGetInt32(upper.val);
1496 
1497  /* Handle possible overflow manually */
1498  if (unlikely(bnd == PG_INT32_MAX))
1499  ereturn(escontext, (Datum) 0,
1500  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1501  errmsg("integer out of range")));
1502  upper.val = Int32GetDatum(bnd + 1);
1503  upper.inclusive = false;
1504  }
1505 
1507  false, escontext));
1508 }
#define PG_INT32_MAX
Definition: c.h:543
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:212
static int32 DatumGetInt32(Datum X)
Definition: postgres.h:202

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

1622 {
1623  int32 v1 = PG_GETARG_INT32(0);
1624  int32 v2 = PG_GETARG_INT32(1);
1625 
1626  PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
1627 }

References PG_GETARG_INT32, and PG_RETURN_FLOAT8.

◆ int8range_canonical()

Datum int8range_canonical ( PG_FUNCTION_ARGS  )

Definition at line 1511 of file rangetypes.c.

1512 {
1513  RangeType *r = PG_GETARG_RANGE_P(0);
1514  Node *escontext = fcinfo->context;
1515  TypeCacheEntry *typcache;
1516  RangeBound lower;
1517  RangeBound upper;
1518  bool empty;
1519 
1520  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1521 
1522  range_deserialize(typcache, r, &lower, &upper, &empty);
1523 
1524  if (empty)
1525  PG_RETURN_RANGE_P(r);
1526 
1527  if (!lower.infinite && !lower.inclusive)
1528  {
1529  int64 bnd = DatumGetInt64(lower.val);
1530 
1531  /* Handle possible overflow manually */
1532  if (unlikely(bnd == PG_INT64_MAX))
1533  ereturn(escontext, (Datum) 0,
1534  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1535  errmsg("bigint out of range")));
1536  lower.val = Int64GetDatum(bnd + 1);
1537  lower.inclusive = true;
1538  }
1539 
1540  if (!upper.infinite && upper.inclusive)
1541  {
1542  int64 bnd = DatumGetInt64(upper.val);
1543 
1544  /* Handle possible overflow manually */
1545  if (unlikely(bnd == PG_INT64_MAX))
1546  ereturn(escontext, (Datum) 0,
1547  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1548  errmsg("bigint out of range")));
1549  upper.val = Int64GetDatum(bnd + 1);
1550  upper.inclusive = false;
1551  }
1552 
1554  false, escontext));
1555 }
int64_t int64
Definition: c.h:482
#define PG_INT64_MAX
Definition: c.h:546
Datum Int64GetDatum(int64 X)
Definition: fmgr.c:1807

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

1631 {
1632  int64 v1 = PG_GETARG_INT64(0);
1633  int64 v2 = PG_GETARG_INT64(1);
1634 
1635  PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
1636 }
#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 2165 of file rangetypes.c.

2166 {
2167  RangeBound lower;
2168  RangeBound upper;
2169 
2170  lower.val = (Datum) 0;
2171  lower.infinite = false;
2172  lower.inclusive = false;
2173  lower.lower = true;
2174 
2175  upper.val = (Datum) 0;
2176  upper.infinite = false;
2177  upper.inclusive = false;
2178  upper.lower = false;
2179 
2180  return make_range(typcache, &lower, &upper, true, NULL);
2181 }

References lower(), make_range(), and upper().

Referenced by multirange_agg_transfn(), multirange_get_union_range(), range_intersect_internal(), range_merge_from_multirange(), and range_minus_internal().

◆ make_range()

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

Definition at line 1952 of file rangetypes.c.

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

1640 {
1641  Datum v1 = PG_GETARG_DATUM(0);
1642  Datum v2 = PG_GETARG_DATUM(1);
1643  Datum numresult;
1644  float8 floatresult;
1645 
1646  numresult = DirectFunctionCall2(numeric_sub, v1, v2);
1647 
1649  numresult));
1650 
1651  PG_RETURN_FLOAT8(floatresult);
1652 }
Datum numeric_sub(PG_FUNCTION_ARGS)
Definition: numeric.c:3043
Datum numeric_float8(PG_FUNCTION_ARGS)
Definition: numeric.c:4746
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:643
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:641
static float8 DatumGetFloat8(Datum X)
Definition: postgres.h:494

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 {
830  RangeType *r1 = PG_GETARG_RANGE_P(0);
831  RangeType *r2 = PG_GETARG_RANGE_P(1);
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 {
729  RangeType *r1 = PG_GETARG_RANGE_P(0);
730  RangeType *r2 = PG_GETARG_RANGE_P(1);
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:2016

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

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

◆ range_before()

Datum range_before ( PG_FUNCTION_ARGS  )

Definition at line 689 of file rangetypes.c.

690 {
691  RangeType *r1 = PG_GETARG_RANGE_P(0);
692  RangeType *r2 = PG_GETARG_RANGE_P(1);
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 2537 of file rangetypes.c.

2538 {
2539  bool nq;
2540  const char *ptr;
2542 
2543  initStringInfo(&buf);
2544 
2545  /* Detect whether we need double quotes for this value */
2546  nq = (value[0] == '\0'); /* force quotes for empty string */
2547  for (ptr = value; *ptr; ptr++)
2548  {
2549  char ch = *ptr;
2550 
2551  if (ch == '"' || ch == '\\' ||
2552  ch == '(' || ch == ')' ||
2553  ch == '[' || ch == ']' ||
2554  ch == ',' ||
2555  isspace((unsigned char) ch))
2556  {
2557  nq = true;
2558  break;
2559  }
2560  }
2561 
2562  /* And emit the string */
2563  if (nq)
2564  appendStringInfoChar(&buf, '"');
2565  for (ptr = value; *ptr; ptr++)
2566  {
2567  char ch = *ptr;
2568 
2569  if (ch == '"' || ch == '\\')
2570  appendStringInfoChar(&buf, ch);
2571  appendStringInfoChar(&buf, ch);
2572  }
2573  if (nq)
2574  appendStringInfoChar(&buf, '"');
2575 
2576  return buf.data;
2577 }
static struct @160 value
static char * buf
Definition: pg_test_fsync.c:72
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:191
void initStringInfo(StringInfo str)
Definition: stringinfo.c:56

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 {
1251  RangeType *r1 = PG_GETARG_RANGE_P(0);
1252  RangeType *r2 = PG_GETARG_RANGE_P(1);
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 2090 of file rangetypes.c.

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

References DatumGetInt32(), FunctionCall2Coll(), RangeBound::infinite, RangeBound::lower, TypeCacheEntry::rng_cmp_proc_finfo, TypeCacheEntry::rng_collation, and RangeBound::val.

Referenced by bounds_adjacent(), and range_serialize().

◆ range_cmp_bounds()

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

Definition at line 2016 of file rangetypes.c.

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

References DatumGetInt32(), FunctionCall2Coll(), RangeBound::inclusive, RangeBound::infinite, RangeBound::lower, TypeCacheEntry::rng_cmp_proc_finfo, TypeCacheEntry::rng_collation, and RangeBound::val.

Referenced by adjacent_cmp_bounds(), adjacent_inner_consistent(), bound_cmp(), calc_hist_selectivity_contained(), getQuadrant(), interval_cmp_lower(), interval_cmp_upper(), multirange_before_multirange_internal(), multirange_cmp(), multirange_contains_multirange_internal(), multirange_eq_internal(), multirange_overlaps_multirange_internal(), multirange_overleft_multirange(), multirange_overleft_range(), multirange_overright_multirange(), multirange_overright_range(), multirange_range_contains_bsearch_comparison(), multirange_range_overlaps_bsearch_comparison(), multirange_union_range_equal(), range_after_internal(), range_after_multirange_internal(), range_before_internal(), range_before_multirange_internal(), range_bound_qsort_cmp(), range_bounds_contains(), range_bounds_overlaps(), range_cmp(), range_compare(), range_contains_internal(), range_eq_internal(), range_gist_double_sorting_split(), range_gist_penalty(), range_intersect_internal(), range_minus_internal(), range_overlaps_internal(), range_overleft_internal(), range_overleft_multirange_internal(), range_overright_internal(), range_overright_multirange_internal(), range_split_internal(), range_super_union(), range_union_internal(), rbound_bsearch(), single_bound_cmp(), and spg_range_quad_inner_consistent().

◆ range_compare()

int range_compare ( const void *  key1,
const void *  key2,
void *  arg 
)

Definition at line 2129 of file rangetypes.c.

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

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

Referenced by multirange_canonicalize().

◆ range_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);
382  RangeType *range;
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:1888
#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);
411  RangeType *range;
412  TypeCacheEntry *typcache;
415  char flags;
416 
417  typcache = range_get_typcache(fcinfo, rngtypid);
418 
419  if (PG_ARGISNULL(2))
420  ereport(ERROR,
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:2247
#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:217

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 {
653  RangeType *r1 = PG_GETARG_RANGE_P(0);
654  RangeType *r2 = PG_GETARG_RANGE_P(1);
655  TypeCacheEntry *typcache;
656 
657  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
658 
659  PG_RETURN_BOOL(range_contained_by_internal(typcache, r1, r2));
660 }
bool range_contained_by_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:2618

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

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

References range_contains_internal().

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

◆ range_contains()

Datum range_contains ( PG_FUNCTION_ARGS  )

Definition at line 638 of file rangetypes.c.

639 {
640  RangeType *r1 = PG_GETARG_RANGE_P(0);
641  RangeType *r2 = PG_GETARG_RANGE_P(1);
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  )

Definition at line 544 of file rangetypes.c.

545 {
548  TypeCacheEntry *typcache;
549 
550  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
551 
553 }

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

◆ range_contains_elem_internal()

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

Definition at line 2627 of file rangetypes.c.

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

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

2214 {
2215  Node *rawreq = (Node *) PG_GETARG_POINTER(0);
2216  Node *ret = NULL;
2217 
2218  if (IsA(rawreq, SupportRequestSimplify))
2219  {
2221  FuncExpr *fexpr = req->fcall;
2222  Expr *leftop,
2223  *rightop;
2224 
2225  Assert(list_length(fexpr->args) == 2);
2226  leftop = linitial(fexpr->args);
2227  rightop = lsecond(fexpr->args);
2228 
2229  ret = find_simplified_clause(req->root, leftop, rightop);
2230  }
2231 
2232  PG_RETURN_POINTER(ret);
2233 }

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

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

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

Referenced by range_contained_by_internal(), range_contains(), range_gist_consistent_int_range(), range_gist_consistent_leaf_range(), and spg_range_quad_leaf_consistent().

◆ range_deparse()

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

Definition at line 2507 of file rangetypes.c.

2508 {
2510 
2511  if (flags & RANGE_EMPTY)
2512  return pstrdup(RANGE_EMPTY_LITERAL);
2513 
2514  initStringInfo(&buf);
2515 
2516  appendStringInfoChar(&buf, (flags & RANGE_LB_INC) ? '[' : '(');
2517 
2518  if (RANGE_HAS_LBOUND(flags))
2520 
2521  appendStringInfoChar(&buf, ',');
2522 
2523  if (RANGE_HAS_UBOUND(flags))
2525 
2526  appendStringInfoChar(&buf, (flags & RANGE_UB_INC) ? ']' : ')');
2527 
2528  return buf.data;
2529 }
char * pstrdup(const char *in)
Definition: mcxt.c:1696
static char * range_bound_escape(const char *value)
Definition: rangetypes.c:2537
#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:179

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

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

References Assert, att_addlength_pointer, att_align_pointer, fetch_att(), lower(), range(), RANGE_EMPTY, RANGE_HAS_LBOUND, RANGE_HAS_UBOUND, RANGE_LB_INC, RANGE_LB_INF, RANGE_UB_INC, RANGE_UB_INF, RangeTypeGetOid, TypeCacheEntry::rngelemtype, typalign, TypeCacheEntry::typalign, TypeCacheEntry::typbyval, TypeCacheEntry::type_id, TypeCacheEntry::typlen, upper(), and VARSIZE.

Referenced by calc_hist_selectivity(), compute_range_stats(), daterange_canonical(), find_simplified_clause(), getQuadrant(), hash_range(), hash_range_extended(), int4range_canonical(), int8range_canonical(), multirange_contains_range_internal(), multirange_overleft_range(), multirange_overright_range(), multirange_union_range_equal(), range_adjacent_internal(), range_adjacent_multirange_internal(), range_after_internal(), range_after_multirange_internal(), range_before_internal(), range_before_multirange_internal(), range_cmp(), range_compare(), range_contains_elem_internal(), range_contains_internal(), range_contains_multirange_internal(), range_eq_internal(), range_gist_double_sorting_split(), range_gist_penalty(), range_gist_single_sorting_split(), range_intersect_internal(), range_lower(), range_minus_internal(), range_out(), range_overlaps_internal(), range_overlaps_multirange_internal(), range_overleft_internal(), range_overleft_multirange_internal(), range_overright_internal(), range_overright_multirange_internal(), range_send(), range_split_internal(), range_super_union(), range_union_internal(), range_upper(), spg_range_quad_inner_consistent(), and spg_range_quad_picksplit().

◆ range_empty()

Datum range_empty ( PG_FUNCTION_ARGS  )

Definition at line 491 of file rangetypes.c.

492 {
493  RangeType *r1 = PG_GETARG_RANGE_P(0);
494  char flags = range_get_flags(r1);
495 
496  PG_RETURN_BOOL(flags & RANGE_EMPTY);
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 {
607  RangeType *r1 = PG_GETARG_RANGE_P(0);
608  RangeType *r2 = PG_GETARG_RANGE_P(1);
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_ge()

Datum range_ge ( PG_FUNCTION_ARGS  )

Definition at line 1311 of file rangetypes.c.

1312 {
1313  int cmp = range_cmp(fcinfo);
1314 
1315  PG_RETURN_BOOL(cmp >= 0);
1316 }
Datum range_cmp(PG_FUNCTION_ARGS)
Definition: rangetypes.c:1249

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

◆ range_get_flags()

char range_get_flags ( const RangeType range)

Definition at line 1923 of file rangetypes.c.

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

References range(), and VARSIZE.

Referenced by get_gist_range_class(), hash_range(), hash_range_extended(), range_empty(), range_gist_same(), range_lower_inc(), range_lower_inf(), range_out(), range_send(), range_super_union(), range_upper_inc(), and range_upper_inf().

◆ range_get_typcache()

TypeCacheEntry* range_get_typcache ( FunctionCallInfo  fcinfo,
Oid  rngtypid 
)

◆ range_gt()

Datum range_gt ( PG_FUNCTION_ARGS  )

Definition at line 1319 of file rangetypes.c.

1320 {
1321  int cmp = range_cmp(fcinfo);
1322 
1323  PG_RETURN_BOOL(cmp > 0);
1324 }

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

◆ range_in()

Datum range_in ( PG_FUNCTION_ARGS  )

Definition at line 88 of file rangetypes.c.

89 {
90  char *input_str = PG_GETARG_CSTRING(0);
91  Oid rngtypoid = PG_GETARG_OID(1);
92  Oid typmod = PG_GETARG_INT32(2);
93  Node *escontext = fcinfo->context;
95  RangeIOData *cache;
96  char flags;
97  char *lbound_str;
98  char *ubound_str;
101 
102  check_stack_depth(); /* recurses when subtype is a range type */
103 
104  cache = get_range_io_data(fcinfo, rngtypoid, IOFunc_input);
105 
106  /* parse */
107  if (!range_parse(input_str, &flags, &lbound_str, &ubound_str, escontext))
108  PG_RETURN_NULL();
109 
110  /* call element type's input function */
111  if (RANGE_HAS_LBOUND(flags))
112  if (!InputFunctionCallSafe(&cache->typioproc, lbound_str,
113  cache->typioparam, typmod,
114  escontext, &lower.val))
115  PG_RETURN_NULL();
116  if (RANGE_HAS_UBOUND(flags))
117  if (!InputFunctionCallSafe(&cache->typioproc, ubound_str,
118  cache->typioparam, typmod,
119  escontext, &upper.val))
120  PG_RETURN_NULL();
121 
122  lower.infinite = (flags & RANGE_LB_INF) != 0;
123  lower.inclusive = (flags & RANGE_LB_INC) != 0;
124  lower.lower = true;
125  upper.infinite = (flags & RANGE_UB_INF) != 0;
126  upper.inclusive = (flags & RANGE_UB_INC) != 0;
127  upper.lower = false;
128 
129  /* serialize and canonicalize */
130  range = make_range(cache->typcache, &lower, &upper,
131  flags & RANGE_EMPTY, escontext);
132 
134 }
bool InputFunctionCallSafe(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod, fmNodePtr escontext, Datum *result)
Definition: fmgr.c:1585
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:277
#define PG_RETURN_NULL()
Definition: fmgr.h:345
@ IOFunc_input
Definition: lsyscache.h:35
static bool range_parse(const char *string, char *flags, char **lbound_str, char **ubound_str, Node *escontext)
Definition: rangetypes.c:2322
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 {
1129  RangeType *r1 = PG_GETARG_RANGE_P(0);
1130  RangeType *r2 = PG_GETARG_RANGE_P(1);
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 
1139  PG_RETURN_RANGE_P(range_intersect_internal(typcache, r1, r2));
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:1910
bool type_is_range(Oid typid)
Definition: lsyscache.c:2688
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4510

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:2165

References make_empty_range(), make_range(), range_cmp_bounds(), range_deserialize(), and range_overlaps_internal().

Referenced by multirange_intersect_internal(), range_intersect(), and range_intersect_agg_transfn().

◆ range_le()

Datum range_le ( PG_FUNCTION_ARGS  )

Definition at line 1303 of file rangetypes.c.

1304 {
1305  int cmp = range_cmp(fcinfo);
1306 
1307  PG_RETURN_BOOL(cmp <= 0);
1308 }

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

◆ range_lower()

Datum range_lower ( PG_FUNCTION_ARGS  )

Definition at line 446 of file rangetypes.c.

447 {
448  RangeType *r1 = PG_GETARG_RANGE_P(0);
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)
460  PG_RETURN_NULL();
461 
462  PG_RETURN_DATUM(lower.val);
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 {
503  RangeType *r1 = PG_GETARG_RANGE_P(0);
504  char flags = range_get_flags(r1);
505 
506  PG_RETURN_BOOL(flags & RANGE_LB_INC);
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 {
523  RangeType *r1 = PG_GETARG_RANGE_P(0);
524  char flags = range_get_flags(r1);
525 
526  PG_RETURN_BOOL(flags & RANGE_LB_INF);
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 1295 of file rangetypes.c.

1296 {
1297  int cmp = range_cmp(fcinfo);
1298 
1299  PG_RETURN_BOOL(cmp < 0);
1300 }

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

◆ range_merge()

Datum range_merge ( PG_FUNCTION_ARGS  )

Definition at line 1114 of file rangetypes.c.

1115 {
1116  RangeType *r1 = PG_GETARG_RANGE_P(0);
1117  RangeType *r2 = PG_GETARG_RANGE_P(1);
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 {
974  RangeType *r1 = PG_GETARG_RANGE_P(0);
975  RangeType *r2 = PG_GETARG_RANGE_P(1);
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)
987  PG_RETURN_RANGE_P(ret);
988  else
989  PG_RETURN_NULL();
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 {
627  RangeType *r1 = PG_GETARG_RANGE_P(0);
628  RangeType *r2 = PG_GETARG_RANGE_P(1);
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 137 of file rangetypes.c.

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

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 {
876  RangeType *r1 = PG_GETARG_RANGE_P(0);
877  RangeType *r2 = PG_GETARG_RANGE_P(1);
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 {
917  RangeType *r1 = PG_GETARG_RANGE_P(0);
918  RangeType *r2 = PG_GETARG_RANGE_P(1);
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 {
958  RangeType *r1 = PG_GETARG_RANGE_P(0);
959  RangeType *r2 = PG_GETARG_RANGE_P(1);
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 2322 of file rangetypes.c.

2324 {
2325  const char *ptr = string;
2326  bool infinite;
2327 
2328  *flags = 0;
2329 
2330  /* consume whitespace */
2331  while (*ptr != '\0' && isspace((unsigned char) *ptr))
2332  ptr++;
2333 
2334  /* check for empty range */
2336  strlen(RANGE_EMPTY_LITERAL)) == 0)
2337  {
2338  *flags = RANGE_EMPTY;
2339  *lbound_str = NULL;
2340  *ubound_str = NULL;
2341 
2342  ptr += strlen(RANGE_EMPTY_LITERAL);
2343 
2344  /* the rest should be whitespace */
2345  while (*ptr != '\0' && isspace((unsigned char) *ptr))
2346  ptr++;
2347 
2348  /* should have consumed everything */
2349  if (*ptr != '\0')
2350  ereturn(escontext, false,
2351  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2352  errmsg("malformed range literal: \"%s\"",
2353  string),
2354  errdetail("Junk after \"empty\" key word.")));
2355 
2356  return true;
2357  }
2358 
2359  if (*ptr == '[')
2360  {
2361  *flags |= RANGE_LB_INC;
2362  ptr++;
2363  }
2364  else if (*ptr == '(')
2365  ptr++;
2366  else
2367  ereturn(escontext, false,
2368  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2369  errmsg("malformed range literal: \"%s\"",
2370  string),
2371  errdetail("Missing left parenthesis or bracket.")));
2372 
2373  ptr = range_parse_bound(string, ptr, lbound_str, &infinite, escontext);
2374  if (ptr == NULL)
2375  return false;
2376  if (infinite)
2377  *flags |= RANGE_LB_INF;
2378 
2379  if (*ptr == ',')
2380  ptr++;
2381  else
2382  ereturn(escontext, false,
2383  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2384  errmsg("malformed range literal: \"%s\"",
2385  string),
2386  errdetail("Missing comma after lower bound.")));
2387 
2388  ptr = range_parse_bound(string, ptr, ubound_str, &infinite, escontext);
2389  if (ptr == NULL)
2390  return false;
2391  if (infinite)
2392  *flags |= RANGE_UB_INF;
2393 
2394  if (*ptr == ']')
2395  {
2396  *flags |= RANGE_UB_INC;
2397  ptr++;
2398  }
2399  else if (*ptr == ')')
2400  ptr++;
2401  else /* must be a comma */
2402  ereturn(escontext, false,
2403  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2404  errmsg("malformed range literal: \"%s\"",
2405  string),
2406  errdetail("Too many commas.")));
2407 
2408  /* consume whitespace */
2409  while (*ptr != '\0' && isspace((unsigned char) *ptr))
2410  ptr++;
2411 
2412  if (*ptr != '\0')
2413  ereturn(escontext, false,
2414  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2415  errmsg("malformed range literal: \"%s\"",
2416  string),
2417  errdetail("Junk after right parenthesis or bracket.")));
2418 
2419  return true;
2420 }
int errdetail(const char *fmt,...)
Definition: elog.c:1203
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:2438

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

2440 {
2442 
2443  /* Check for null: completely empty input means null */
2444  if (*ptr == ',' || *ptr == ')' || *ptr == ']')
2445  {
2446  *bound_str = NULL;
2447  *infinite = true;
2448  }
2449  else
2450  {
2451  /* Extract string for this bound */
2452  bool inquote = false;
2453 
2454  initStringInfo(&buf);
2455  while (inquote || !(*ptr == ',' || *ptr == ')' || *ptr == ']'))
2456  {
2457  char ch = *ptr++;
2458 
2459  if (ch == '\0')
2460  ereturn(escontext, NULL,
2461  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2462  errmsg("malformed range literal: \"%s\"",
2463  string),
2464  errdetail("Unexpected end of input.")));
2465  if (ch == '\\')
2466  {
2467  if (*ptr == '\0')
2468  ereturn(escontext, NULL,
2469  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2470  errmsg("malformed range literal: \"%s\"",
2471  string),
2472  errdetail("Unexpected end of input.")));
2473  appendStringInfoChar(&buf, *ptr++);
2474  }
2475  else if (ch == '"')
2476  {
2477  if (!inquote)
2478  inquote = true;
2479  else if (*ptr == '"')
2480  {
2481  /* doubled quote within quote sequence */
2482  appendStringInfoChar(&buf, *ptr++);
2483  }
2484  else
2485  inquote = false;
2486  }
2487  else
2488  appendStringInfoChar(&buf, ch);
2489  }
2490 
2491  *bound_str = buf.data;
2492  *infinite = false;
2493  }
2494 
2495  return ptr;
2496 }

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

2248 {
2249  char flags = 0;
2250 
2251  if (flags_str[0] == '\0' ||
2252  flags_str[1] == '\0' ||
2253  flags_str[2] != '\0')
2254  ereport(ERROR,
2255  (errcode(ERRCODE_SYNTAX_ERROR),
2256  errmsg("invalid range bound flags"),
2257  errhint("Valid values are \"[]\", \"[)\", \"(]\", and \"()\".")));
2258 
2259  switch (flags_str[0])
2260  {
2261  case '[':
2262  flags |= RANGE_LB_INC;
2263  break;
2264  case '(':
2265  break;
2266  default:
2267  ereport(ERROR,
2268  (errcode(ERRCODE_SYNTAX_ERROR),
2269  errmsg("invalid range bound flags"),
2270  errhint("Valid values are \"[]\", \"[)\", \"(]\", and \"()\".")));
2271  }
2272 
2273  switch (flags_str[1])
2274  {
2275  case ']':
2276  flags |= RANGE_UB_INC;
2277  break;
2278  case ')':
2279  break;
2280  default:
2281  ereport(ERROR,
2282  (errcode(ERRCODE_SYNTAX_ERROR),
2283  errmsg("invalid range bound flags"),
2284  errhint("Valid values are \"[]\", \"[)\", \"(]\", and \"()\".")));
2285  }
2286 
2287  return flags;
2288 }
int errhint(const char *fmt,...)
Definition: elog.c:1317

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

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

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

262 {
265  RangeIOData *cache;
266  char flags;
269  bool empty;
270 
271  check_stack_depth(); /* recurses when subtype is a range type */
272 
274 
275  /* deserialize */
276  range_deserialize(cache->typcache, range, &lower, &upper, &empty);
277  flags = range_get_flags(range);
278 
279  /* construct output */
281 
282  pq_sendbyte(buf, flags);
283 
284  if (RANGE_HAS_LBOUND(flags))
285  {
287  lower.val));
288  uint32 bound_len = VARSIZE(bound) - VARHDRSZ;
289  char *bound_data = VARDATA(bound);
290 
291  pq_sendint32(buf, bound_len);
292  pq_sendbytes(buf, bound_data, bound_len);
293  }
294 
295  if (RANGE_HAS_UBOUND(flags))
296  {
298  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:646
bytea * SendFunctionCall(FmgrInfo *flinfo, Datum val)
Definition: fmgr.c:1744
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:371
@ IOFunc_send
Definition: lsyscache.h:38
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
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:38

References buf, check_stack_depth(), get_range_io_data(), IOFunc_send, lower(), makeStringInfo(), PG_GETARG_RANGE_P, PG_RETURN_BYTEA_P, PointerGetDatum(), 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 1727 of file rangetypes.c.

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

References Assert, cmp(), datum_compute_size(), datum_write(), ereturn, errcode(), errmsg(), lower(), MAXALIGN, palloc0(), PG_DETOAST_DATUM_PACKED, PointerGetDatum(), range(), range_cmp_bound_values(), RANGE_EMPTY, RANGE_HAS_LBOUND, RANGE_HAS_UBOUND, RANGE_LB_INC, RANGE_LB_INF, RANGE_UB_INC, RANGE_UB_INF, TypeCacheEntry::rngelemtype, SET_VARSIZE, typalign, TypeCacheEntry::typalign, TypeCacheEntry::typbyval, TypeCacheEntry::type_id, TypeCacheEntry::typlen, TypeCacheEntry::typstorage, and upper().

Referenced by compute_range_stats(), daterange_canonical(), int4range_canonical(), int8range_canonical(), make_range(), multirangesel(), rangesel(), and spg_range_quad_picksplit().

◆ range_set_contain_empty()

void range_set_contain_empty ( RangeType range)

Definition at line 1937 of file rangetypes.c.

1938 {
1939  char *flagsp;
1940 
1941  /* flag byte is datum's last byte */
1942  flagsp = (char *) range + VARSIZE(range) - 1;
1943 
1944  *flagsp |= RANGE_CONTAIN_EMPTY;
1945 }
#define RANGE_CONTAIN_EMPTY
Definition: rangetypes.h:45

References range(), RANGE_CONTAIN_EMPTY, and VARSIZE.

Referenced by range_super_union().

◆ range_split_internal()

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

Definition at line 1182 of file rangetypes.c.

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

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

Referenced by multirange_minus_internal().

◆ range_union()

Datum range_union ( PG_FUNCTION_ARGS  )

Definition at line 1098 of file rangetypes.c.

1099 {
1100  RangeType *r1 = PG_GETARG_RANGE_P(0);
1101  RangeType *r2 = PG_GETARG_RANGE_P(1);
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  !DatumGetBool(range_overlaps_internal(typcache, r1, r2)) &&
1079  !DatumGetBool(range_adjacent_internal(typcache, r1, r2)))
1080  ereport(ERROR,
1081  (errcode(ERRCODE_DATA_EXCEPTION),
1082  errmsg("result of range union would not be contiguous")));
1083 
1084  if (range_cmp_bounds(typcache, &lower1, &lower2) < 0)
1085  result_lower = &lower1;
1086  else
1087  result_lower = &lower2;
1088 
1089  if (range_cmp_bounds(typcache, &upper1, &upper2) > 0)
1090  result_upper = &upper1;
1091  else
1092  result_upper = &upper2;
1093 
1094  return make_range(typcache, result_lower, result_upper, false, NULL);
1095 }
static bool DatumGetBool(Datum X)
Definition: postgres.h:90

References DatumGetBool(), elog, ereport, errcode(), errmsg(), ERROR, make_range(), range_adjacent_internal(), range_cmp_bounds(), range_deserialize(), range_overlaps_internal(), and RangeTypeGetOid.

Referenced by multirange_canonicalize(), range_merge(), and range_union().

◆ range_upper()

Datum range_upper ( PG_FUNCTION_ARGS  )

Definition at line 467 of file rangetypes.c.

468 {
469  RangeType *r1 = PG_GETARG_RANGE_P(0);
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)
481  PG_RETURN_NULL();
482 
483  PG_RETURN_DATUM(upper.val);
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 {
513  RangeType *r1 = PG_GETARG_RANGE_P(0);
514  char flags = range_get_flags(r1);
515 
516  PG_RETURN_BOOL(flags & RANGE_UB_INC);
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 {
533  RangeType *r1 = PG_GETARG_RANGE_P(0);
534  char flags = range_get_flags(r1);
535 
536  PG_RETURN_BOOL(flags & RANGE_UB_INF);
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 1664 of file rangetypes.c.

1665 {
1668  float8 result;
1669 
1670  result = ((float8) v1 - (float8) v2) / USECS_PER_SEC;
1671  PG_RETURN_FLOAT8(result);
1672 }
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 1675 of file rangetypes.c.

1676 {
1679  float8 result;
1680 
1681  result = ((float8) v1 - (float8) v2) / USECS_PER_SEC;
1682  PG_RETURN_FLOAT8(result);
1683 }

References PG_GETARG_TIMESTAMP, PG_RETURN_FLOAT8, and USECS_PER_SEC.