PostgreSQL Source Code  git master
rangetypes.c File Reference
#include "postgres.h"
#include "access/tupmacs.h"
#include "common/hashfn.h"
#include "lib/stringinfo.h"
#include "libpq/pqformat.h"
#include "miscadmin.h"
#include "nodes/miscnodes.h"
#include "port/pg_bitutils.h"
#include "utils/builtins.h"
#include "utils/date.h"
#include "utils/lsyscache.h"
#include "utils/rangetypes.h"
#include "utils/timestamp.h"
#include "varatt.h"
Include dependency graph for rangetypes.c:

Go to the source code of this file.

Data Structures

struct  RangeIOData
 

Macros

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

Typedefs

typedef struct RangeIOData RangeIOData
 

Functions

static RangeIODataget_range_io_data (FunctionCallInfo fcinfo, Oid rngtypid, IOFuncSelector func)
 
static 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)
 
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)
 
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 2615 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 750 of file rangetypes.c.

751 {
752  int cmp;
753 
754  Assert(!boundA.lower && boundB.lower);
755 
756  cmp = range_cmp_bound_values(typcache, &boundA, &boundB);
757  if (cmp < 0)
758  {
759  RangeType *r;
760 
761  /*
762  * Bounds do not overlap; see if there are points in between.
763  */
764 
765  /* in a continuous subtype, there are assumed to be points between */
766  if (!OidIsValid(typcache->rng_canonical_finfo.fn_oid))
767  return false;
768 
769  /*
770  * The bounds are of a discrete range type; so make a range A..B and
771  * see if it's empty.
772  */
773 
774  /* flip the inclusion flags */
775  boundA.inclusive = !boundA.inclusive;
776  boundB.inclusive = !boundB.inclusive;
777  /* change upper/lower labels to avoid Assert failures */
778  boundA.lower = true;
779  boundB.lower = false;
780  r = make_range(typcache, &boundA, &boundB, false, NULL);
781  return RangeIsEmpty(r);
782  }
783  else if (cmp == 0)
784  return boundA.inclusive != boundB.inclusive;
785  else
786  return false; /* bounds overlap */
787 }
#define OidIsValid(objectId)
Definition: c.h:759
Assert(fmt[strlen(fmt) - 1] !='\n')
RangeType * make_range(TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper, bool empty, struct Node *escontext)
Definition: rangetypes.c:1945
int range_cmp_bound_values(TypeCacheEntry *typcache, const RangeBound *b1, const RangeBound *b2)
Definition: rangetypes.c:2083
#define RangeIsEmpty(r)
Definition: rangetypes.h:55
static int cmp(const chr *x, const chr *y, size_t len)
Definition: regc_locale.c:747
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:101

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

◆ daterange_canonical()

Datum daterange_canonical ( PG_FUNCTION_ARGS  )

Definition at line 1551 of file rangetypes.c.

1552 {
1553  RangeType *r = PG_GETARG_RANGE_P(0);
1554  Node *escontext = fcinfo->context;
1555  TypeCacheEntry *typcache;
1556  RangeBound lower;
1557  RangeBound upper;
1558  bool empty;
1559 
1560  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1561 
1562  range_deserialize(typcache, r, &lower, &upper, &empty);
1563 
1564  if (empty)
1565  PG_RETURN_RANGE_P(r);
1566 
1567  if (!lower.infinite && !DATE_NOT_FINITE(DatumGetDateADT(lower.val)) &&
1568  !lower.inclusive)
1569  {
1570  DateADT bnd = DatumGetDateADT(lower.val);
1571 
1572  /* Check for overflow -- note we already eliminated PG_INT32_MAX */
1573  bnd++;
1574  if (unlikely(!IS_VALID_DATE(bnd)))
1575  ereturn(escontext, (Datum) 0,
1576  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1577  errmsg("date out of range")));
1578  lower.val = DateADTGetDatum(bnd);
1579  lower.inclusive = true;
1580  }
1581 
1582  if (!upper.infinite && !DATE_NOT_FINITE(DatumGetDateADT(upper.val)) &&
1583  upper.inclusive)
1584  {
1585  DateADT bnd = DatumGetDateADT(upper.val);
1586 
1587  /* Check for overflow -- note we already eliminated PG_INT32_MAX */
1588  bnd++;
1589  if (unlikely(!IS_VALID_DATE(bnd)))
1590  ereturn(escontext, (Datum) 0,
1591  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1592  errmsg("date out of range")));
1593  upper.val = DateADTGetDatum(bnd);
1594  upper.inclusive = false;
1595  }
1596 
1598  false, escontext));
1599 }
#define unlikely(x)
Definition: c.h:295
#define IS_VALID_DATE(d)
Definition: timestamp.h:236
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:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define ereturn(context, dummy_value,...)
Definition: elog.h:276
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:1849
TypeCacheEntry * range_get_typcache(FunctionCallInfo fcinfo, Oid rngtypid)
Definition: rangetypes.c:1696
RangeType * range_serialize(TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper, bool empty, struct Node *escontext)
Definition: rangetypes.c:1720
#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:118

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

1649 {
1650  int32 v1 = PG_GETARG_INT32(0);
1651  int32 v2 = PG_GETARG_INT32(1);
1652 
1653  PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
1654 }
signed int int32
Definition: c.h:478
double float8
Definition: c.h:614
#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 2623 of file rangetypes.c.

2625 {
2626  if (TYPE_IS_PACKABLE(typlen, typstorage) &&
2628  {
2629  /*
2630  * we're anticipating converting to a short varlena header, so adjust
2631  * length and don't count any alignment
2632  */
2634  }
2635  else
2636  {
2637  data_length = att_align_datum(data_length, typalign, typlen, val);
2638  data_length = att_addlength_datum(data_length, typlen, val);
2639  }
2640 
2641  return data_length;
2642 }
long val
Definition: informix.c:664
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:2615
#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 2649 of file rangetypes.c.

2651 {
2652  Size data_length;
2653 
2654  if (typbyval)
2655  {
2656  /* pass-by-value */
2657  ptr = (char *) att_align_nominal(ptr, typalign);
2658  store_att_byval(ptr, datum, typlen);
2659  data_length = typlen;
2660  }
2661  else if (typlen == -1)
2662  {
2663  /* varlena */
2664  Pointer val = DatumGetPointer(datum);
2665 
2666  if (VARATT_IS_EXTERNAL(val))
2667  {
2668  /*
2669  * Throw error, because we must never put a toast pointer inside a
2670  * range object. Caller should have detoasted it.
2671  */
2672  elog(ERROR, "cannot store a toast pointer inside a range");
2673  data_length = 0; /* keep compiler quiet */
2674  }
2675  else if (VARATT_IS_SHORT(val))
2676  {
2677  /* no alignment for short varlenas */
2678  data_length = VARSIZE_SHORT(val);
2679  memcpy(ptr, val, data_length);
2680  }
2681  else if (TYPE_IS_PACKABLE(typlen, typstorage) &&
2683  {
2684  /* convert to short varlena -- no alignment */
2685  data_length = VARATT_CONVERTED_SHORT_SIZE(val);
2686  SET_VARSIZE_SHORT(ptr, data_length);
2687  memcpy(ptr + 1, VARDATA(val), data_length - 1);
2688  }
2689  else
2690  {
2691  /* full 4-byte header varlena */
2692  ptr = (char *) att_align_nominal(ptr, typalign);
2693  data_length = VARSIZE(val);
2694  memcpy(ptr, val, data_length);
2695  }
2696  }
2697  else if (typlen == -2)
2698  {
2699  /* cstring ... never needs alignment */
2700  Assert(typalign == TYPALIGN_CHAR);
2701  data_length = strlen(DatumGetCString(datum)) + 1;
2702  memcpy(ptr, DatumGetPointer(datum), data_length);
2703  }
2704  else
2705  {
2706  /* fixed-length pass-by-reference */
2707  ptr = (char *) att_align_nominal(ptr, typalign);
2708  Assert(typlen > 0);
2709  data_length = typlen;
2710  memcpy(ptr, DatumGetPointer(datum), data_length);
2711  }
2712 
2713  ptr += data_length;
2714 
2715  return ptr;
2716 }
char * Pointer
Definition: c.h:467
size_t Size
Definition: c.h:589
#define ERROR
Definition: elog.h:39
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 550 of file rangetypes.c.

551 {
554  TypeCacheEntry *typcache;
555 
556  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
557 
559 }
#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:2568

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

◆ get_range_io_data()

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

Definition at line 310 of file rangetypes.c.

311 {
312  RangeIOData *cache = (RangeIOData *) fcinfo->flinfo->fn_extra;
313 
314  if (cache == NULL || cache->typcache->type_id != rngtypid)
315  {
316  int16 typlen;
317  bool typbyval;
318  char typalign;
319  char typdelim;
320  Oid typiofunc;
321 
322  cache = (RangeIOData *) MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
323  sizeof(RangeIOData));
324  cache->typcache = lookup_type_cache(rngtypid, TYPECACHE_RANGE_INFO);
325  if (cache->typcache->rngelemtype == NULL)
326  elog(ERROR, "type %u is not a range type", rngtypid);
327 
328  /* get_type_io_data does more than we need, but is convenient */
330  func,
331  &typlen,
332  &typbyval,
333  &typalign,
334  &typdelim,
335  &cache->typioparam,
336  &typiofunc);
337 
338  if (!OidIsValid(typiofunc))
339  {
340  /* this could only happen for receive or send */
341  if (func == IOFunc_receive)
342  ereport(ERROR,
343  (errcode(ERRCODE_UNDEFINED_FUNCTION),
344  errmsg("no binary input function available for type %s",
346  else
347  ereport(ERROR,
348  (errcode(ERRCODE_UNDEFINED_FUNCTION),
349  errmsg("no binary output function available for type %s",
351  }
352  fmgr_info_cxt(typiofunc, &cache->typioproc,
353  fcinfo->flinfo->fn_mcxt);
354 
355  fcinfo->flinfo->fn_extra = (void *) cache;
356  }
357 
358  return cache;
359 }
signed short int16
Definition: c.h:477
#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:339
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
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:2283
@ IOFunc_receive
Definition: lsyscache.h:37
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1005
unsigned int Oid
Definition: postgres_ext.h:31
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:51
FmgrInfo typioproc
Definition: rangetypes.c:52
Oid typioparam
Definition: rangetypes.c:53
struct TypeCacheEntry * rngelemtype
Definition: typcache.h:98
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:339
#define TYPECACHE_RANGE_INFO
Definition: typcache.h:147

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

1324 {
1325  RangeType *r = PG_GETARG_RANGE_P(0);
1326  uint32 result;
1327  TypeCacheEntry *typcache;
1328  TypeCacheEntry *scache;
1329  RangeBound lower;
1330  RangeBound upper;
1331  bool empty;
1332  char flags;
1333  uint32 lower_hash;
1334  uint32 upper_hash;
1335 
1336  check_stack_depth(); /* recurses when subtype is a range type */
1337 
1338  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1339 
1340  /* deserialize */
1341  range_deserialize(typcache, r, &lower, &upper, &empty);
1342  flags = range_get_flags(r);
1343 
1344  /*
1345  * Look up the element type's hash function, if not done already.
1346  */
1347  scache = typcache->rngelemtype;
1348  if (!OidIsValid(scache->hash_proc_finfo.fn_oid))
1349  {
1351  if (!OidIsValid(scache->hash_proc_finfo.fn_oid))
1352  ereport(ERROR,
1353  (errcode(ERRCODE_UNDEFINED_FUNCTION),
1354  errmsg("could not identify a hash function for type %s",
1355  format_type_be(scache->type_id))));
1356  }
1357 
1358  /*
1359  * Apply the hash function to each bound.
1360  */
1361  if (RANGE_HAS_LBOUND(flags))
1362  lower_hash = DatumGetUInt32(FunctionCall1Coll(&scache->hash_proc_finfo,
1363  typcache->rng_collation,
1364  lower.val));
1365  else
1366  lower_hash = 0;
1367 
1368  if (RANGE_HAS_UBOUND(flags))
1369  upper_hash = DatumGetUInt32(FunctionCall1Coll(&scache->hash_proc_finfo,
1370  typcache->rng_collation,
1371  upper.val));
1372  else
1373  upper_hash = 0;
1374 
1375  /* Merge hashes of flags and bounds */
1376  result = hash_uint32((uint32) flags);
1377  result ^= lower_hash;
1378  result = pg_rotate_left32(result, 1);
1379  result ^= upper_hash;
1380 
1381  PG_RETURN_INT32(result);
1382 }
unsigned int uint32
Definition: c.h:490
Datum FunctionCall1Coll(FmgrInfo *flinfo, Oid collation, Datum arg1)
Definition: fmgr.c:1116
#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:277
void check_stack_depth(void)
Definition: postgres.c:3454
static uint32 DatumGetUInt32(Datum X)
Definition: postgres.h:222
char range_get_flags(const RangeType *range)
Definition: rangetypes.c:1916
#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
Oid rng_collation
Definition: typcache.h:99
#define TYPECACHE_HASH_PROC_FINFO
Definition: typcache.h:143

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

1390 {
1391  RangeType *r = PG_GETARG_RANGE_P(0);
1392  Datum seed = PG_GETARG_DATUM(1);
1393  uint64 result;
1394  TypeCacheEntry *typcache;
1395  TypeCacheEntry *scache;
1396  RangeBound lower;
1397  RangeBound upper;
1398  bool empty;
1399  char flags;
1400  uint64 lower_hash;
1401  uint64 upper_hash;
1402 
1404 
1405  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1406 
1407  range_deserialize(typcache, r, &lower, &upper, &empty);
1408  flags = range_get_flags(r);
1409 
1410  scache = typcache->rngelemtype;
1412  {
1413  scache = lookup_type_cache(scache->type_id,
1416  ereport(ERROR,
1417  (errcode(ERRCODE_UNDEFINED_FUNCTION),
1418  errmsg("could not identify a hash function for type %s",
1419  format_type_be(scache->type_id))));
1420  }
1421 
1422  if (RANGE_HAS_LBOUND(flags))
1424  typcache->rng_collation,
1425  lower.val,
1426  seed));
1427  else
1428  lower_hash = 0;
1429 
1430  if (RANGE_HAS_UBOUND(flags))
1432  typcache->rng_collation,
1433  upper.val,
1434  seed));
1435  else
1436  upper_hash = 0;
1437 
1438  /* Merge hashes of flags and bounds */
1439  result = DatumGetUInt64(hash_uint32_extended((uint32) flags,
1440  DatumGetInt64(seed)));
1441  result ^= lower_hash;
1442  result = ROTATE_HIGH_AND_LOW_32BITS(result);
1443  result ^= upper_hash;
1444 
1445  PG_RETURN_UINT64(result);
1446 }
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Definition: fmgr.c:1136
#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:151

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

1458 {
1459  RangeType *r = PG_GETARG_RANGE_P(0);
1460  Node *escontext = fcinfo->context;
1461  TypeCacheEntry *typcache;
1462  RangeBound lower;
1463  RangeBound upper;
1464  bool empty;
1465 
1466  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1467 
1468  range_deserialize(typcache, r, &lower, &upper, &empty);
1469 
1470  if (empty)
1471  PG_RETURN_RANGE_P(r);
1472 
1473  if (!lower.infinite && !lower.inclusive)
1474  {
1475  int32 bnd = DatumGetInt32(lower.val);
1476 
1477  /* Handle possible overflow manually */
1478  if (unlikely(bnd == PG_INT32_MAX))
1479  ereturn(escontext, (Datum) 0,
1480  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1481  errmsg("integer out of range")));
1482  lower.val = Int32GetDatum(bnd + 1);
1483  lower.inclusive = true;
1484  }
1485 
1486  if (!upper.infinite && upper.inclusive)
1487  {
1488  int32 bnd = DatumGetInt32(upper.val);
1489 
1490  /* Handle possible overflow manually */
1491  if (unlikely(bnd == PG_INT32_MAX))
1492  ereturn(escontext, (Datum) 0,
1493  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1494  errmsg("integer out of range")));
1495  upper.val = Int32GetDatum(bnd + 1);
1496  upper.inclusive = false;
1497  }
1498 
1500  false, escontext));
1501 }
#define PG_INT32_MAX
Definition: c.h:573
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 1614 of file rangetypes.c.

1615 {
1616  int32 v1 = PG_GETARG_INT32(0);
1617  int32 v2 = PG_GETARG_INT32(1);
1618 
1619  PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
1620 }

References PG_GETARG_INT32, and PG_RETURN_FLOAT8.

◆ int8range_canonical()

Datum int8range_canonical ( PG_FUNCTION_ARGS  )

Definition at line 1504 of file rangetypes.c.

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

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

1624 {
1625  int64 v1 = PG_GETARG_INT64(0);
1626  int64 v2 = PG_GETARG_INT64(1);
1627 
1628  PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
1629 }
#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 2158 of file rangetypes.c.

2159 {
2160  RangeBound lower;
2161  RangeBound upper;
2162 
2163  lower.val = (Datum) 0;
2164  lower.infinite = false;
2165  lower.inclusive = false;
2166  lower.lower = true;
2167 
2168  upper.val = (Datum) 0;
2169  upper.infinite = false;
2170  upper.inclusive = false;
2171  upper.lower = false;
2172 
2173  return make_range(typcache, &lower, &upper, true, NULL);
2174 }

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

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

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

1633 {
1634  Datum v1 = PG_GETARG_DATUM(0);
1635  Datum v2 = PG_GETARG_DATUM(1);
1636  Datum numresult;
1637  float8 floatresult;
1638 
1639  numresult = DirectFunctionCall2(numeric_sub, v1, v2);
1640 
1642  numresult));
1643 
1644  PG_RETURN_FLOAT8(floatresult);
1645 }
Datum numeric_sub(PG_FUNCTION_ARGS)
Definition: numeric.c:2913
Datum numeric_float8(PG_FUNCTION_ARGS)
Definition: numeric.c:4499
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:644
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:642
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 821 of file rangetypes.c.

822 {
823  RangeType *r1 = PG_GETARG_RANGE_P(0);
824  RangeType *r2 = PG_GETARG_RANGE_P(1);
825  TypeCacheEntry *typcache;
826 
827  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
828 
829  PG_RETURN_BOOL(range_adjacent_internal(typcache, r1, r2));
830 }
bool range_adjacent_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:791

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

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

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

721 {
722  RangeType *r1 = PG_GETARG_RANGE_P(0);
723  RangeType *r2 = PG_GETARG_RANGE_P(1);
724  TypeCacheEntry *typcache;
725 
726  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
727 
728  PG_RETURN_BOOL(range_after_internal(typcache, r1, r2));
729 }
bool range_after_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:695

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

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

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

683 {
684  RangeType *r1 = PG_GETARG_RANGE_P(0);
685  RangeType *r2 = PG_GETARG_RANGE_P(1);
686  TypeCacheEntry *typcache;
687 
688  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
689 
690  PG_RETURN_BOOL(range_before_internal(typcache, r1, r2));
691 }
bool range_before_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:657

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

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

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

2479 {
2480  bool nq;
2481  const char *ptr;
2483 
2484  initStringInfo(&buf);
2485 
2486  /* Detect whether we need double quotes for this value */
2487  nq = (value[0] == '\0'); /* force quotes for empty string */
2488  for (ptr = value; *ptr; ptr++)
2489  {
2490  char ch = *ptr;
2491 
2492  if (ch == '"' || ch == '\\' ||
2493  ch == '(' || ch == ')' ||
2494  ch == '[' || ch == ']' ||
2495  ch == ',' ||
2496  isspace((unsigned char) ch))
2497  {
2498  nq = true;
2499  break;
2500  }
2501  }
2502 
2503  /* And emit the string */
2504  if (nq)
2505  appendStringInfoChar(&buf, '"');
2506  for (ptr = value; *ptr; ptr++)
2507  {
2508  char ch = *ptr;
2509 
2510  if (ch == '"' || ch == '\\')
2511  appendStringInfoChar(&buf, ch);
2512  appendStringInfoChar(&buf, ch);
2513  }
2514  if (nq)
2515  appendStringInfoChar(&buf, '"');
2516 
2517  return buf.data;
2518 }
static struct @143 value
static char * buf
Definition: pg_test_fsync.c:67
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59

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

Referenced by range_deparse().

◆ range_cmp()

Datum range_cmp ( PG_FUNCTION_ARGS  )

Definition at line 1242 of file rangetypes.c.

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

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

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

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

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

2123 {
2124  RangeType *r1 = *(RangeType **) key1;
2125  RangeType *r2 = *(RangeType **) key2;
2126  TypeCacheEntry *typcache = (TypeCacheEntry *) arg;
2127  RangeBound lower1;
2128  RangeBound upper1;
2129  RangeBound lower2;
2130  RangeBound upper2;
2131  bool empty1;
2132  bool empty2;
2133  int cmp;
2134 
2135  range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
2136  range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
2137 
2138  if (empty1 && empty2)
2139  cmp = 0;
2140  else if (empty1)
2141  cmp = -1;
2142  else if (empty2)
2143  cmp = 1;
2144  else
2145  {
2146  cmp = range_cmp_bounds(typcache, &lower1, &lower2);
2147  if (cmp == 0)
2148  cmp = range_cmp_bounds(typcache, &upper1, &upper2);
2149  }
2150 
2151  return cmp;
2152 }
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 370 of file rangetypes.c.

371 {
372  Datum arg1 = PG_GETARG_DATUM(0);
373  Datum arg2 = PG_GETARG_DATUM(1);
374  Oid rngtypid = get_fn_expr_rettype(fcinfo->flinfo);
375  RangeType *range;
376  TypeCacheEntry *typcache;
379 
380  typcache = range_get_typcache(fcinfo, rngtypid);
381 
382  lower.val = PG_ARGISNULL(0) ? (Datum) 0 : arg1;
383  lower.infinite = PG_ARGISNULL(0);
384  lower.inclusive = true;
385  lower.lower = true;
386 
387  upper.val = PG_ARGISNULL(1) ? (Datum) 0 : arg2;
388  upper.infinite = PG_ARGISNULL(1);
389  upper.inclusive = false;
390  upper.lower = false;
391 
392  range = make_range(typcache, &lower, &upper, false, NULL);
393 
395 }
Oid get_fn_expr_rettype(FmgrInfo *flinfo)
Definition: fmgr.c:1875
#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 399 of file rangetypes.c.

400 {
401  Datum arg1 = PG_GETARG_DATUM(0);
402  Datum arg2 = PG_GETARG_DATUM(1);
403  Oid rngtypid = get_fn_expr_rettype(fcinfo->flinfo);
404  RangeType *range;
405  TypeCacheEntry *typcache;
408  char flags;
409 
410  typcache = range_get_typcache(fcinfo, rngtypid);
411 
412  if (PG_ARGISNULL(2))
413  ereport(ERROR,
414  (errcode(ERRCODE_DATA_EXCEPTION),
415  errmsg("range constructor flags argument must not be null")));
416 
418 
419  lower.val = PG_ARGISNULL(0) ? (Datum) 0 : arg1;
420  lower.infinite = PG_ARGISNULL(0);
421  lower.inclusive = (flags & RANGE_LB_INC) != 0;
422  lower.lower = true;
423 
424  upper.val = PG_ARGISNULL(1) ? (Datum) 0 : arg2;
425  upper.infinite = PG_ARGISNULL(1);
426  upper.inclusive = (flags & RANGE_UB_INC) != 0;
427  upper.lower = false;
428 
429  range = make_range(typcache, &lower, &upper, false, NULL);
430 
432 }
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
static char range_parse_flags(const char *flags_str)
Definition: rangetypes.c:2188
#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:222

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

645 {
646  RangeType *r1 = PG_GETARG_RANGE_P(0);
647  RangeType *r2 = PG_GETARG_RANGE_P(1);
648  TypeCacheEntry *typcache;
649 
650  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
651 
652  PG_RETURN_BOOL(range_contained_by_internal(typcache, r1, r2));
653 }
bool range_contained_by_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:2559

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

2560 {
2561  return range_contains_internal(typcache, r2, r1);
2562 }
bool range_contains_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:2527

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

632 {
633  RangeType *r1 = PG_GETARG_RANGE_P(0);
634  RangeType *r2 = PG_GETARG_RANGE_P(1);
635  TypeCacheEntry *typcache;
636 
637  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
638 
639  PG_RETURN_BOOL(range_contains_internal(typcache, r1, r2));
640 }

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

538 {
541  TypeCacheEntry *typcache;
542 
543  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
544 
546 }

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

2569 {
2570  RangeBound lower;
2571  RangeBound upper;
2572  bool empty;
2573  int32 cmp;
2574 
2575  range_deserialize(typcache, r, &lower, &upper, &empty);
2576 
2577  if (empty)
2578  return false;
2579 
2580  if (!lower.infinite)
2581  {
2583  typcache->rng_collation,
2584  lower.val, val));
2585  if (cmp > 0)
2586  return false;
2587  if (cmp == 0 && !lower.inclusive)
2588  return false;
2589  }
2590 
2591  if (!upper.infinite)
2592  {
2594  typcache->rng_collation,
2595  upper.val, val));
2596  if (cmp < 0)
2597  return false;
2598  if (cmp == 0 && !upper.inclusive)
2599  return false;
2600  }
2601 
2602  return true;
2603 }

References cmp(), DatumGetInt32(), FunctionCall2Coll(), lower(), range_deserialize(), TypeCacheEntry::rng_cmp_proc_finfo, TypeCacheEntry::rng_collation, upper(), and val.

Referenced by elem_contained_by_range(), range_contains_elem(), range_gist_consistent_int_element(), range_gist_consistent_leaf_element(), and spg_range_quad_leaf_consistent().

◆ range_contains_internal()

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

Definition at line 2527 of file rangetypes.c.

2528 {
2529  RangeBound lower1;
2530  RangeBound upper1;
2531  bool empty1;
2532  RangeBound lower2;
2533  RangeBound upper2;
2534  bool empty2;
2535 
2536  /* Different types should be prevented by ANYRANGE matching rules */
2537  if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
2538  elog(ERROR, "range types do not match");
2539 
2540  range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
2541  range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
2542 
2543  /* If either range is empty, the answer is easy */
2544  if (empty2)
2545  return true;
2546  else if (empty1)
2547  return false;
2548 
2549  /* Else we must have lower1 <= lower2 and upper1 >= upper2 */
2550  if (range_cmp_bounds(typcache, &lower1, &lower2) > 0)
2551  return false;
2552  if (range_cmp_bounds(typcache, &upper1, &upper2) < 0)
2553  return false;
2554 
2555  return true;
2556 }

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

2449 {
2451 
2452  if (flags & RANGE_EMPTY)
2453  return pstrdup(RANGE_EMPTY_LITERAL);
2454 
2455  initStringInfo(&buf);
2456 
2457  appendStringInfoChar(&buf, (flags & RANGE_LB_INC) ? '[' : '(');
2458 
2459  if (RANGE_HAS_LBOUND(flags))
2461 
2462  appendStringInfoChar(&buf, ',');
2463 
2464  if (RANGE_HAS_UBOUND(flags))
2466 
2467  appendStringInfoChar(&buf, (flags & RANGE_UB_INC) ? ']' : ')');
2468 
2469  return buf.data;
2470 }
char * pstrdup(const char *in)
Definition: mcxt.c:1624
static char * range_bound_escape(const char *value)
Definition: rangetypes.c:2478
#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:176

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

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

485 {
486  RangeType *r1 = PG_GETARG_RANGE_P(0);
487  char flags = range_get_flags(r1);
488 
489  PG_RETURN_BOOL(flags & RANGE_EMPTY);
490 }

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

599 {
600  RangeType *r1 = PG_GETARG_RANGE_P(0);
601  RangeType *r2 = PG_GETARG_RANGE_P(1);
602  TypeCacheEntry *typcache;
603 
604  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
605 
606  PG_RETURN_BOOL(range_eq_internal(typcache, r1, r2));
607 }
bool range_eq_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:566

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

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

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

1305 {
1306  int cmp = range_cmp(fcinfo);
1307 
1308  PG_RETURN_BOOL(cmp >= 0);
1309 }
Datum range_cmp(PG_FUNCTION_ARGS)
Definition: rangetypes.c:1242

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

◆ range_get_flags()

char range_get_flags ( const RangeType range)

Definition at line 1916 of file rangetypes.c.

1917 {
1918  /* fetch the flag byte from datum's last byte */
1919  return *((char *) range + VARSIZE(range) - 1);
1920 }

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

1313 {
1314  int cmp = range_cmp(fcinfo);
1315 
1316  PG_RETURN_BOOL(cmp > 0);
1317 }

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

◆ range_in()

Datum range_in ( PG_FUNCTION_ARGS  )

Definition at line 81 of file rangetypes.c.

82 {
83  char *input_str = PG_GETARG_CSTRING(0);
84  Oid rngtypoid = PG_GETARG_OID(1);
85  Oid typmod = PG_GETARG_INT32(2);
86  Node *escontext = fcinfo->context;
88  RangeIOData *cache;
89  char flags;
90  char *lbound_str;
91  char *ubound_str;
94 
95  check_stack_depth(); /* recurses when subtype is a range type */
96 
97  cache = get_range_io_data(fcinfo, rngtypoid, IOFunc_input);
98 
99  /* parse */
100  if (!range_parse(input_str, &flags, &lbound_str, &ubound_str, escontext))
101  PG_RETURN_NULL();
102 
103  /* call element type's input function */
104  if (RANGE_HAS_LBOUND(flags))
105  if (!InputFunctionCallSafe(&cache->typioproc, lbound_str,
106  cache->typioparam, typmod,
107  escontext, &lower.val))
108  PG_RETURN_NULL();
109  if (RANGE_HAS_UBOUND(flags))
110  if (!InputFunctionCallSafe(&cache->typioproc, ubound_str,
111  cache->typioparam, typmod,
112  escontext, &upper.val))
113  PG_RETURN_NULL();
114 
115  lower.infinite = (flags & RANGE_LB_INF) != 0;
116  lower.inclusive = (flags & RANGE_LB_INC) != 0;
117  lower.lower = true;
118  upper.infinite = (flags & RANGE_UB_INF) != 0;
119  upper.inclusive = (flags & RANGE_UB_INC) != 0;
120  upper.lower = false;
121 
122  /* serialize and canonicalize */
123  range = make_range(cache->typcache, &lower, &upper,
124  flags & RANGE_EMPTY, escontext);
125 
127 }
bool InputFunctionCallSafe(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod, fmNodePtr escontext, Datum *result)
Definition: fmgr.c:1572
#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:2263
static RangeIOData * get_range_io_data(FunctionCallInfo fcinfo, Oid rngtypid, IOFuncSelector func)
Definition: rangetypes.c:310

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

1121 {
1122  RangeType *r1 = PG_GETARG_RANGE_P(0);
1123  RangeType *r2 = PG_GETARG_RANGE_P(1);
1124  TypeCacheEntry *typcache;
1125 
1126  /* Different types should be prevented by ANYRANGE matching rules */
1127  if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
1128  elog(ERROR, "range types do not match");
1129 
1130  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
1131 
1132  PG_RETURN_RANGE_P(range_intersect_internal(typcache, r1, r2));
1133 }
RangeType * range_intersect_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:1136

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

1213 {
1214  MemoryContext aggContext;
1215  Oid rngtypoid;
1216  TypeCacheEntry *typcache;
1217  RangeType *result;
1218  RangeType *current;
1219 
1220  if (!AggCheckCallContext(fcinfo, &aggContext))
1221  elog(ERROR, "range_intersect_agg_transfn called in non-aggregate context");
1222 
1223  rngtypoid = get_fn_expr_argtype(fcinfo->flinfo, 1);
1224  if (!type_is_range(rngtypoid))
1225  elog(ERROR, "range_intersect_agg must be called with a range");
1226 
1227  typcache = range_get_typcache(fcinfo, rngtypoid);
1228 
1229  /* strictness ensures these are non-null */
1230  result = PG_GETARG_RANGE_P(0);
1231  current = PG_GETARG_RANGE_P(1);
1232 
1233  result = range_intersect_internal(typcache, result, current);
1234  PG_RETURN_RANGE_P(result);
1235 }
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1897
bool type_is_range(Oid typid)
Definition: lsyscache.c:2646
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4513

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

1137 {
1138  RangeBound lower1,
1139  lower2;
1140  RangeBound upper1,
1141  upper2;
1142  bool empty1,
1143  empty2;
1144  RangeBound *result_lower;
1145  RangeBound *result_upper;
1146 
1147  range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
1148  range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
1149 
1150  if (empty1 || empty2 || !range_overlaps_internal(typcache, r1, r2))
1151  return make_empty_range(typcache);
1152 
1153  if (range_cmp_bounds(typcache, &lower1, &lower2) >= 0)
1154  result_lower = &lower1;
1155  else
1156  result_lower = &lower2;
1157 
1158  if (range_cmp_bounds(typcache, &upper1, &upper2) <= 0)
1159  result_upper = &upper1;
1160  else
1161  result_upper = &upper2;
1162 
1163  return make_range(typcache, result_lower, result_upper, false, NULL);
1164 }
bool range_overlaps_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:834
RangeType * make_empty_range(TypeCacheEntry *typcache)
Definition: rangetypes.c:2158

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

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

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

◆ range_lower()

Datum range_lower ( PG_FUNCTION_ARGS  )

Definition at line 439 of file rangetypes.c.

440 {
441  RangeType *r1 = PG_GETARG_RANGE_P(0);
442  TypeCacheEntry *typcache;
445  bool empty;
446 
447  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
448 
449  range_deserialize(typcache, r1, &lower, &upper, &empty);
450 
451  /* Return NULL if there's no finite lower bound */
452  if (empty || lower.infinite)
453  PG_RETURN_NULL();
454 
455  PG_RETURN_DATUM(lower.val);
456 }
#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 494 of file rangetypes.c.

495 {
496  RangeType *r1 = PG_GETARG_RANGE_P(0);
497  char flags = range_get_flags(r1);
498 
499  PG_RETURN_BOOL(flags & RANGE_LB_INC);
500 }

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

515 {
516  RangeType *r1 = PG_GETARG_RANGE_P(0);
517  char flags = range_get_flags(r1);
518 
519  PG_RETURN_BOOL(flags & RANGE_LB_INF);
520 }

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

1289 {
1290  int cmp = range_cmp(fcinfo);
1291 
1292  PG_RETURN_BOOL(cmp < 0);
1293 }

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

◆ range_merge()

Datum range_merge ( PG_FUNCTION_ARGS  )

Definition at line 1107 of file rangetypes.c.

1108 {
1109  RangeType *r1 = PG_GETARG_RANGE_P(0);
1110  RangeType *r2 = PG_GETARG_RANGE_P(1);
1111  TypeCacheEntry *typcache;
1112 
1113  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
1114 
1115  PG_RETURN_RANGE_P(range_union_internal(typcache, r1, r2, false));
1116 }
RangeType * range_union_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2, bool strict)
Definition: rangetypes.c:1045

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

966 {
967  RangeType *r1 = PG_GETARG_RANGE_P(0);
968  RangeType *r2 = PG_GETARG_RANGE_P(1);
969  RangeType *ret;
970  TypeCacheEntry *typcache;
971 
972  /* Different types should be prevented by ANYRANGE matching rules */
973  if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
974  elog(ERROR, "range types do not match");
975 
976  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
977 
978  ret = range_minus_internal(typcache, r1, r2);
979  if (ret)
980  PG_RETURN_RANGE_P(ret);
981  else
982  PG_RETURN_NULL();
983 }
RangeType * range_minus_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
Definition: rangetypes.c:986

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

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

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

619 {
620  RangeType *r1 = PG_GETARG_RANGE_P(0);
621  RangeType *r2 = PG_GETARG_RANGE_P(1);
622  TypeCacheEntry *typcache;
623 
624  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
625 
626  PG_RETURN_BOOL(range_ne_internal(typcache, r1, r2));
627 }
bool range_ne_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:611

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

612 {
613  return (!range_eq_internal(typcache, r1, r2));
614 }

References range_eq_internal().

Referenced by range_ne().

◆ range_out()

Datum range_out ( PG_FUNCTION_ARGS  )

Definition at line 130 of file rangetypes.c.

131 {
133  char *output_str;
134  RangeIOData *cache;
135  char flags;
136  char *lbound_str = NULL;
137  char *ubound_str = NULL;
140  bool empty;
141 
142  check_stack_depth(); /* recurses when subtype is a range type */
143 
145 
146  /* deserialize */
147  range_deserialize(cache->typcache, range, &lower, &upper, &empty);
148  flags = range_get_flags(range);
149 
150  /* call element type's output function */
151  if (RANGE_HAS_LBOUND(flags))
152  lbound_str = OutputFunctionCall(&cache->typioproc, lower.val);
153  if (RANGE_HAS_UBOUND(flags))
154  ubound_str = OutputFunctionCall(&cache->typioproc, upper.val);
155 
156  /* construct result string */
157  output_str = range_deparse(flags, lbound_str, ubound_str);
158 
159  PG_RETURN_CSTRING(output_str);
160 }
char * OutputFunctionCall(FmgrInfo *flinfo, Datum val)
Definition: fmgr.c:1670
#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:2448

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

868 {
869  RangeType *r1 = PG_GETARG_RANGE_P(0);
870  RangeType *r2 = PG_GETARG_RANGE_P(1);
871  TypeCacheEntry *typcache;
872 
873  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
874 
875  PG_RETURN_BOOL(range_overlaps_internal(typcache, r1, r2));
876 }

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

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

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

909 {
910  RangeType *r1 = PG_GETARG_RANGE_P(0);
911  RangeType *r2 = PG_GETARG_RANGE_P(1);
912  TypeCacheEntry *typcache;
913 
914  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
915 
916  PG_RETURN_BOOL(range_overleft_internal(typcache, r1, r2));
917 }
bool range_overleft_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:880

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

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

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

950 {
951  RangeType *r1 = PG_GETARG_RANGE_P(0);
952  RangeType *r2 = PG_GETARG_RANGE_P(1);
953  TypeCacheEntry *typcache;
954 
955  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
956 
957  PG_RETURN_BOOL(range_overright_internal(typcache, r1, r2));
958 }
bool range_overright_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:921

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

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

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

2265 {
2266  const char *ptr = string;
2267  bool infinite;
2268 
2269  *flags = 0;
2270 
2271  /* consume whitespace */
2272  while (*ptr != '\0' && isspace((unsigned char) *ptr))
2273  ptr++;
2274 
2275  /* check for empty range */
2277  strlen(RANGE_EMPTY_LITERAL)) == 0)
2278  {
2279  *flags = RANGE_EMPTY;
2280  *lbound_str = NULL;
2281  *ubound_str = NULL;
2282 
2283  ptr += strlen(RANGE_EMPTY_LITERAL);
2284 
2285  /* the rest should be whitespace */
2286  while (*ptr != '\0' && isspace((unsigned char) *ptr))
2287  ptr++;
2288 
2289  /* should have consumed everything */
2290  if (*ptr != '\0')
2291  ereturn(escontext, false,
2292  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2293  errmsg("malformed range literal: \"%s\"",
2294  string),
2295  errdetail("Junk after \"empty\" key word.")));
2296 
2297  return true;
2298  }
2299 
2300  if (*ptr == '[')
2301  {
2302  *flags |= RANGE_LB_INC;
2303  ptr++;
2304  }
2305  else if (*ptr == '(')
2306  ptr++;
2307  else
2308  ereturn(escontext, false,
2309  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2310  errmsg("malformed range literal: \"%s\"",
2311  string),
2312  errdetail("Missing left parenthesis or bracket.")));
2313 
2314  ptr = range_parse_bound(string, ptr, lbound_str, &infinite, escontext);
2315  if (ptr == NULL)
2316  return false;
2317  if (infinite)
2318  *flags |= RANGE_LB_INF;
2319 
2320  if (*ptr == ',')
2321  ptr++;
2322  else
2323  ereturn(escontext, false,
2324  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2325  errmsg("malformed range literal: \"%s\"",
2326  string),
2327  errdetail("Missing comma after lower bound.")));
2328 
2329  ptr = range_parse_bound(string, ptr, ubound_str, &infinite, escontext);
2330  if (ptr == NULL)
2331  return false;
2332  if (infinite)
2333  *flags |= RANGE_UB_INF;
2334 
2335  if (*ptr == ']')
2336  {
2337  *flags |= RANGE_UB_INC;
2338  ptr++;
2339  }
2340  else if (*ptr == ')')
2341  ptr++;
2342  else /* must be a comma */
2343  ereturn(escontext, false,
2344  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2345  errmsg("malformed range literal: \"%s\"",
2346  string),
2347  errdetail("Too many commas.")));
2348 
2349  /* consume whitespace */
2350  while (*ptr != '\0' && isspace((unsigned char) *ptr))
2351  ptr++;
2352 
2353  if (*ptr != '\0')
2354  ereturn(escontext, false,
2355  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2356  errmsg("malformed range literal: \"%s\"",
2357  string),
2358  errdetail("Junk after right parenthesis or bracket.")));
2359 
2360  return true;
2361 }
int errdetail(const char *fmt,...)
Definition: elog.c:1202
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:2379

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

2381 {
2383 
2384  /* Check for null: completely empty input means null */
2385  if (*ptr == ',' || *ptr == ')' || *ptr == ']')
2386  {
2387  *bound_str = NULL;
2388  *infinite = true;
2389  }
2390  else
2391  {
2392  /* Extract string for this bound */
2393  bool inquote = false;
2394 
2395  initStringInfo(&buf);
2396  while (inquote || !(*ptr == ',' || *ptr == ')' || *ptr == ']'))
2397  {
2398  char ch = *ptr++;
2399 
2400  if (ch == '\0')
2401  ereturn(escontext, NULL,
2402  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2403  errmsg("malformed range literal: \"%s\"",
2404  string),
2405  errdetail("Unexpected end of input.")));
2406  if (ch == '\\')
2407  {
2408  if (*ptr == '\0')
2409  ereturn(escontext, NULL,
2410  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2411  errmsg("malformed range literal: \"%s\"",
2412  string),
2413  errdetail("Unexpected end of input.")));
2414  appendStringInfoChar(&buf, *ptr++);
2415  }
2416  else if (ch == '"')
2417  {
2418  if (!inquote)
2419  inquote = true;
2420  else if (*ptr == '"')
2421  {
2422  /* doubled quote within quote sequence */
2423  appendStringInfoChar(&buf, *ptr++);
2424  }
2425  else
2426  inquote = false;
2427  }
2428  else
2429  appendStringInfoChar(&buf, ch);
2430  }
2431 
2432  *bound_str = buf.data;
2433  *infinite = false;
2434  }
2435 
2436  return ptr;
2437 }

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

2189 {
2190  char flags = 0;
2191 
2192  if (flags_str[0] == '\0' ||
2193  flags_str[1] == '\0' ||
2194  flags_str[2] != '\0')
2195  ereport(ERROR,
2196  (errcode(ERRCODE_SYNTAX_ERROR),
2197  errmsg("invalid range bound flags"),
2198  errhint("Valid values are \"[]\", \"[)\", \"(]\", and \"()\".")));
2199 
2200  switch (flags_str[0])
2201  {
2202  case '[':
2203  flags |= RANGE_LB_INC;
2204  break;
2205  case '(':
2206  break;
2207  default:
2208  ereport(ERROR,
2209  (errcode(ERRCODE_SYNTAX_ERROR),
2210  errmsg("invalid range bound flags"),
2211  errhint("Valid values are \"[]\", \"[)\", \"(]\", and \"()\".")));
2212  }
2213 
2214  switch (flags_str[1])
2215  {
2216  case ']':
2217  flags |= RANGE_UB_INC;
2218  break;
2219  case ')':
2220  break;
2221  default:
2222  ereport(ERROR,
2223  (errcode(ERRCODE_SYNTAX_ERROR),
2224  errmsg("invalid range bound flags"),
2225  errhint("Valid values are \"[]\", \"[)\", \"(]\", and \"()\".")));
2226  }
2227 
2228  return flags;
2229 }
int errhint(const char *fmt,...)
Definition: elog.c:1316

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

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

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

255 {
258  RangeIOData *cache;
259  char flags;
262  bool empty;
263 
264  check_stack_depth(); /* recurses when subtype is a range type */
265 
267 
268  /* deserialize */
269  range_deserialize(cache->typcache, range, &lower, &upper, &empty);
270  flags = range_get_flags(range);
271 
272  /* construct output */
274 
275  pq_sendbyte(buf, flags);
276 
277  if (RANGE_HAS_LBOUND(flags))
278  {
280  lower.val));
281  uint32 bound_len = VARSIZE(bound) - VARHDRSZ;
282  char *bound_data = VARDATA(bound);
283 
284  pq_sendint32(buf, bound_len);
285  pq_sendbytes(buf, bound_data, bound_len);
286  }
287 
288  if (RANGE_HAS_UBOUND(flags))
289  {
291  upper.val));
292  uint32 bound_len = VARSIZE(bound) - VARHDRSZ;
293  char *bound_data = VARDATA(bound);
294 
295  pq_sendint32(buf, bound_len);
296  pq_sendbytes(buf, bound_data, bound_len);
297  }
298 
300 }
#define VARHDRSZ
Definition: c.h:676
bytea * SendFunctionCall(FmgrInfo *flinfo, Datum val)
Definition: fmgr.c:1731
#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_begintypsend(StringInfo buf)
Definition: pqformat.c:329
void pq_sendbytes(StringInfo buf, const char *data, int datalen)
Definition: pqformat.c:126
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:349
static void pq_sendint32(StringInfo buf, uint32 i)
Definition: pqformat.h:145
static void pq_sendbyte(StringInfo buf, uint8 byt)
Definition: pqformat.h:161
StringInfo makeStringInfo(void)
Definition: stringinfo.c:41

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

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

1931 {
1932  char *flagsp;
1933 
1934  /* flag byte is datum's last byte */
1935  flagsp = (char *) range + VARSIZE(range) - 1;
1936 
1937  *flagsp |= RANGE_CONTAIN_EMPTY;
1938 }
#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 1175 of file rangetypes.c.

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

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

1092 {
1093  RangeType *r1 = PG_GETARG_RANGE_P(0);
1094  RangeType *r2 = PG_GETARG_RANGE_P(1);
1095  TypeCacheEntry *typcache;
1096 
1097  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
1098 
1099  PG_RETURN_RANGE_P(range_union_internal(typcache, r1, r2, true));
1100 }

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

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

461 {
462  RangeType *r1 = PG_GETARG_RANGE_P(0);
463  TypeCacheEntry *typcache;
466  bool empty;
467 
468  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
469 
470  range_deserialize(typcache, r1, &lower, &upper, &empty);
471 
472  /* Return NULL if there's no finite upper bound */
473  if (empty || upper.infinite)
474  PG_RETURN_NULL();
475 
476  PG_RETURN_DATUM(upper.val);
477 }

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

505 {
506  RangeType *r1 = PG_GETARG_RANGE_P(0);
507  char flags = range_get_flags(r1);
508 
509  PG_RETURN_BOOL(flags & RANGE_UB_INC);
510 }

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

525 {
526  RangeType *r1 = PG_GETARG_RANGE_P(0);
527  char flags = range_get_flags(r1);
528 
529  PG_RETURN_BOOL(flags & RANGE_UB_INF);
530 }

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

1658 {
1661  float8 result;
1662 
1663  result = ((float8) v1 - (float8) v2) / USECS_PER_SEC;
1664  PG_RETURN_FLOAT8(result);
1665 }
int64 Timestamp
Definition: timestamp.h:38
#define USECS_PER_SEC
Definition: timestamp.h:133
#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 1668 of file rangetypes.c.

1669 {
1672  float8 result;
1673 
1674  result = ((float8) v1 - (float8) v2) / USECS_PER_SEC;
1675  PG_RETURN_FLOAT8(result);
1676 }

References PG_GETARG_TIMESTAMP, PG_RETURN_FLOAT8, and USECS_PER_SEC.