PostgreSQL Source Code  git master
multirangetypes.c File Reference
#include "postgres.h"
#include "access/tupmacs.h"
#include "common/hashfn.h"
#include "funcapi.h"
#include "lib/stringinfo.h"
#include "libpq/pqformat.h"
#include "miscadmin.h"
#include "port/pg_bitutils.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/rangetypes.h"
#include "utils/multirangetypes.h"
#include "utils/array.h"
#include "utils/memutils.h"
Include dependency graph for multirangetypes.c:

Go to the source code of this file.

Data Structures

struct  MultirangeIOData
 

Macros

#define MultirangeGetItemsPtr(mr)
 
#define MultirangeGetFlagsPtr(mr)
 
#define MultirangeGetBoundariesPtr(mr, align)
 
#define MULTIRANGE_ITEM_OFF_BIT   0x80000000
 
#define MULTIRANGE_ITEM_GET_OFFLEN(item)   ((item) & 0x7FFFFFFF)
 
#define MULTIRANGE_ITEM_HAS_OFF(item)   ((item) & MULTIRANGE_ITEM_OFF_BIT)
 
#define MULTIRANGE_ITEM_OFFSET_STRIDE   4
 

Typedefs

typedef struct MultirangeIOData MultirangeIOData
 
typedef int(* multirange_bsearch_comparison) (TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper, void *key, bool *match)
 

Enumerations

enum  MultirangeParseState {
  MULTIRANGE_BEFORE_RANGE , MULTIRANGE_IN_RANGE , MULTIRANGE_IN_RANGE_ESCAPED , MULTIRANGE_IN_RANGE_QUOTED ,
  MULTIRANGE_IN_RANGE_QUOTED_ESCAPED , MULTIRANGE_AFTER_RANGE , MULTIRANGE_FINISHED
}
 

Functions

static MultirangeIODataget_multirange_io_data (FunctionCallInfo fcinfo, Oid mltrngtypid, IOFuncSelector func)
 
static int32 multirange_canonicalize (TypeCacheEntry *rangetyp, int32 input_range_count, RangeType **ranges)
 
Datum multirange_in (PG_FUNCTION_ARGS)
 
Datum multirange_out (PG_FUNCTION_ARGS)
 
Datum multirange_recv (PG_FUNCTION_ARGS)
 
Datum multirange_send (PG_FUNCTION_ARGS)
 
TypeCacheEntrymultirange_get_typcache (FunctionCallInfo fcinfo, Oid mltrngtypid)
 
static Size multirange_size_estimate (TypeCacheEntry *rangetyp, int32 range_count, RangeType **ranges)
 
static void write_multirange_data (MultirangeType *multirange, TypeCacheEntry *rangetyp, int32 range_count, RangeType **ranges)
 
MultirangeTypemake_multirange (Oid mltrngtypoid, TypeCacheEntry *rangetyp, int32 range_count, RangeType **ranges)
 
static uint32 multirange_get_bounds_offset (const MultirangeType *multirange, int32 i)
 
RangeTypemultirange_get_range (TypeCacheEntry *rangetyp, const MultirangeType *multirange, int i)
 
void multirange_get_bounds (TypeCacheEntry *rangetyp, const MultirangeType *multirange, uint32 i, RangeBound *lower, RangeBound *upper)
 
RangeTypemultirange_get_union_range (TypeCacheEntry *rangetyp, const MultirangeType *mr)
 
void multirange_deserialize (TypeCacheEntry *rangetyp, const MultirangeType *multirange, int32 *range_count, RangeType ***ranges)
 
MultirangeTypemake_empty_multirange (Oid mltrngtypoid, TypeCacheEntry *rangetyp)
 
static bool range_bounds_overlaps (TypeCacheEntry *typcache, RangeBound *lower1, RangeBound *upper1, RangeBound *lower2, RangeBound *upper2)
 
static bool range_bounds_contains (TypeCacheEntry *typcache, RangeBound *lower1, RangeBound *upper1, RangeBound *lower2, RangeBound *upper2)
 
static bool multirange_bsearch_match (TypeCacheEntry *typcache, const MultirangeType *mr, void *key, multirange_bsearch_comparison cmp_func)
 
Datum multirange_constructor2 (PG_FUNCTION_ARGS)
 
Datum multirange_constructor1 (PG_FUNCTION_ARGS)
 
Datum multirange_constructor0 (PG_FUNCTION_ARGS)
 
Datum multirange_union (PG_FUNCTION_ARGS)
 
Datum multirange_minus (PG_FUNCTION_ARGS)
 
MultirangeTypemultirange_minus_internal (Oid mltrngtypoid, TypeCacheEntry *rangetyp, int32 range_count1, RangeType **ranges1, int32 range_count2, RangeType **ranges2)
 
Datum multirange_intersect (PG_FUNCTION_ARGS)
 
MultirangeTypemultirange_intersect_internal (Oid mltrngtypoid, TypeCacheEntry *rangetyp, int32 range_count1, RangeType **ranges1, int32 range_count2, RangeType **ranges2)
 
Datum range_agg_transfn (PG_FUNCTION_ARGS)
 
Datum range_agg_finalfn (PG_FUNCTION_ARGS)
 
Datum multirange_agg_transfn (PG_FUNCTION_ARGS)
 
Datum multirange_intersect_agg_transfn (PG_FUNCTION_ARGS)
 
Datum multirange_lower (PG_FUNCTION_ARGS)
 
Datum multirange_upper (PG_FUNCTION_ARGS)
 
Datum multirange_empty (PG_FUNCTION_ARGS)
 
Datum multirange_lower_inc (PG_FUNCTION_ARGS)
 
Datum multirange_upper_inc (PG_FUNCTION_ARGS)
 
Datum multirange_lower_inf (PG_FUNCTION_ARGS)
 
Datum multirange_upper_inf (PG_FUNCTION_ARGS)
 
Datum multirange_contains_elem (PG_FUNCTION_ARGS)
 
Datum elem_contained_by_multirange (PG_FUNCTION_ARGS)
 
static int multirange_elem_bsearch_comparison (TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper, void *key, bool *match)
 
bool multirange_contains_elem_internal (TypeCacheEntry *rangetyp, const MultirangeType *mr, Datum val)
 
Datum multirange_contains_range (PG_FUNCTION_ARGS)
 
Datum range_contains_multirange (PG_FUNCTION_ARGS)
 
Datum range_contained_by_multirange (PG_FUNCTION_ARGS)
 
Datum multirange_contained_by_range (PG_FUNCTION_ARGS)
 
static int multirange_range_contains_bsearch_comparison (TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper, void *key, bool *match)
 
bool multirange_contains_range_internal (TypeCacheEntry *rangetyp, const MultirangeType *mr, const RangeType *r)
 
bool range_contains_multirange_internal (TypeCacheEntry *rangetyp, const RangeType *r, const MultirangeType *mr)
 
bool multirange_eq_internal (TypeCacheEntry *rangetyp, const MultirangeType *mr1, const MultirangeType *mr2)
 
Datum multirange_eq (PG_FUNCTION_ARGS)
 
bool multirange_ne_internal (TypeCacheEntry *rangetyp, const MultirangeType *mr1, const MultirangeType *mr2)
 
Datum multirange_ne (PG_FUNCTION_ARGS)
 
Datum range_overlaps_multirange (PG_FUNCTION_ARGS)
 
Datum multirange_overlaps_range (PG_FUNCTION_ARGS)
 
Datum multirange_overlaps_multirange (PG_FUNCTION_ARGS)
 
static int multirange_range_overlaps_bsearch_comparison (TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper, void *key, bool *match)
 
bool range_overlaps_multirange_internal (TypeCacheEntry *rangetyp, const RangeType *r, const MultirangeType *mr)
 
bool multirange_overlaps_multirange_internal (TypeCacheEntry *rangetyp, const MultirangeType *mr1, const MultirangeType *mr2)
 
bool range_overleft_multirange_internal (TypeCacheEntry *rangetyp, const RangeType *r, const MultirangeType *mr)
 
Datum range_overleft_multirange (PG_FUNCTION_ARGS)
 
Datum multirange_overleft_range (PG_FUNCTION_ARGS)
 
Datum multirange_overleft_multirange (PG_FUNCTION_ARGS)
 
bool range_overright_multirange_internal (TypeCacheEntry *rangetyp, const RangeType *r, const MultirangeType *mr)
 
Datum range_overright_multirange (PG_FUNCTION_ARGS)
 
Datum multirange_overright_range (PG_FUNCTION_ARGS)
 
Datum multirange_overright_multirange (PG_FUNCTION_ARGS)
 
Datum multirange_contains_multirange (PG_FUNCTION_ARGS)
 
Datum multirange_contained_by_multirange (PG_FUNCTION_ARGS)
 
bool multirange_contains_multirange_internal (TypeCacheEntry *rangetyp, const MultirangeType *mr1, const MultirangeType *mr2)
 
Datum range_before_multirange (PG_FUNCTION_ARGS)
 
Datum multirange_before_range (PG_FUNCTION_ARGS)
 
Datum multirange_before_multirange (PG_FUNCTION_ARGS)
 
Datum range_after_multirange (PG_FUNCTION_ARGS)
 
Datum multirange_after_range (PG_FUNCTION_ARGS)
 
Datum multirange_after_multirange (PG_FUNCTION_ARGS)
 
bool range_before_multirange_internal (TypeCacheEntry *rangetyp, const RangeType *r, const MultirangeType *mr)
 
bool multirange_before_multirange_internal (TypeCacheEntry *rangetyp, const MultirangeType *mr1, const MultirangeType *mr2)
 
bool range_after_multirange_internal (TypeCacheEntry *rangetyp, const RangeType *r, const MultirangeType *mr)
 
bool range_adjacent_multirange_internal (TypeCacheEntry *rangetyp, const RangeType *r, const MultirangeType *mr)
 
Datum range_adjacent_multirange (PG_FUNCTION_ARGS)
 
Datum multirange_adjacent_range (PG_FUNCTION_ARGS)
 
Datum multirange_adjacent_multirange (PG_FUNCTION_ARGS)
 
Datum multirange_cmp (PG_FUNCTION_ARGS)
 
Datum multirange_lt (PG_FUNCTION_ARGS)
 
Datum multirange_le (PG_FUNCTION_ARGS)
 
Datum multirange_ge (PG_FUNCTION_ARGS)
 
Datum multirange_gt (PG_FUNCTION_ARGS)
 
Datum range_merge_from_multirange (PG_FUNCTION_ARGS)
 
Datum multirange_unnest (PG_FUNCTION_ARGS)
 
Datum hash_multirange (PG_FUNCTION_ARGS)
 
Datum hash_multirange_extended (PG_FUNCTION_ARGS)
 

Macro Definition Documentation

◆ MULTIRANGE_ITEM_GET_OFFLEN

#define MULTIRANGE_ITEM_GET_OFFLEN (   item)    ((item) & 0x7FFFFFFF)

Definition at line 82 of file multirangetypes.c.

◆ MULTIRANGE_ITEM_HAS_OFF

#define MULTIRANGE_ITEM_HAS_OFF (   item)    ((item) & MULTIRANGE_ITEM_OFF_BIT)

Definition at line 83 of file multirangetypes.c.

◆ MULTIRANGE_ITEM_OFF_BIT

#define MULTIRANGE_ITEM_OFF_BIT   0x80000000

Definition at line 81 of file multirangetypes.c.

◆ MULTIRANGE_ITEM_OFFSET_STRIDE

#define MULTIRANGE_ITEM_OFFSET_STRIDE   4

Definition at line 84 of file multirangetypes.c.

◆ MultirangeGetBoundariesPtr

#define MultirangeGetBoundariesPtr (   mr,
  align 
)
Value:
((Pointer) (mr) + \
att_align_nominal(sizeof(MultirangeType) + \
((mr)->rangeCount - 1) * sizeof(uint32) + \
(mr)->rangeCount * sizeof(uint8), (align)))
unsigned int uint32
Definition: c.h:441
char * Pointer
Definition: c.h:418
unsigned char uint8
Definition: c.h:439

Definition at line 76 of file multirangetypes.c.

◆ MultirangeGetFlagsPtr

#define MultirangeGetFlagsPtr (   mr)
Value:
((uint8 *) ((Pointer) (mr) + \
sizeof(MultirangeType) + ((mr)->rangeCount - 1) * sizeof(uint32)))

Definition at line 74 of file multirangetypes.c.

◆ MultirangeGetItemsPtr

#define MultirangeGetItemsPtr (   mr)
Value:
((uint32 *) ((Pointer) (mr) + \
sizeof(MultirangeType)))

Definition at line 72 of file multirangetypes.c.

Typedef Documentation

◆ multirange_bsearch_comparison

typedef int(* multirange_bsearch_comparison) (TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper, void *key, bool *match)

Definition at line 86 of file multirangetypes.c.

◆ MultirangeIOData

Enumeration Type Documentation

◆ MultirangeParseState

Enumerator
MULTIRANGE_BEFORE_RANGE 
MULTIRANGE_IN_RANGE 
MULTIRANGE_IN_RANGE_ESCAPED 
MULTIRANGE_IN_RANGE_QUOTED 
MULTIRANGE_IN_RANGE_QUOTED_ESCAPED 
MULTIRANGE_AFTER_RANGE 
MULTIRANGE_FINISHED 

Definition at line 57 of file multirangetypes.c.

58 {
MultirangeParseState
@ MULTIRANGE_BEFORE_RANGE
@ MULTIRANGE_IN_RANGE
@ MULTIRANGE_FINISHED
@ MULTIRANGE_AFTER_RANGE
@ MULTIRANGE_IN_RANGE_QUOTED_ESCAPED
@ MULTIRANGE_IN_RANGE_ESCAPED
@ MULTIRANGE_IN_RANGE_QUOTED

Function Documentation

◆ elem_contained_by_multirange()

Datum elem_contained_by_multirange ( PG_FUNCTION_ARGS  )

Definition at line 1653 of file multirangetypes.c.

1654 {
1655  Datum val = PG_GETARG_DATUM(0);
1657  TypeCacheEntry *typcache;
1658 
1659  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr));
1660 
1662 }
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:268
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
long val
Definition: informix.c:664
bool multirange_contains_elem_internal(TypeCacheEntry *rangetyp, const MultirangeType *mr, Datum val)
TypeCacheEntry * multirange_get_typcache(FunctionCallInfo fcinfo, Oid mltrngtypid)
#define PG_GETARG_MULTIRANGE_P(n)
#define MultirangeTypeGetOid(mr)
uintptr_t Datum
Definition: postgres.h:411
struct TypeCacheEntry * rngtype
Definition: typcache.h:107

References multirange_contains_elem_internal(), multirange_get_typcache(), MultirangeTypeGetOid, PG_GETARG_DATUM, PG_GETARG_MULTIRANGE_P, PG_RETURN_BOOL, TypeCacheEntry::rngtype, and val.

◆ get_multirange_io_data()

static MultirangeIOData * get_multirange_io_data ( FunctionCallInfo  fcinfo,
Oid  mltrngtypid,
IOFuncSelector  func 
)
static

Definition at line 411 of file multirangetypes.c.

412 {
413  MultirangeIOData *cache = (MultirangeIOData *) fcinfo->flinfo->fn_extra;
414 
415  if (cache == NULL || cache->typcache->type_id != mltrngtypid)
416  {
417  Oid typiofunc;
418  int16 typlen;
419  bool typbyval;
420  char typalign;
421  char typdelim;
422 
423  cache = (MultirangeIOData *) MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
424  sizeof(MultirangeIOData));
426  if (cache->typcache->rngtype == NULL)
427  elog(ERROR, "type %u is not a multirange type", mltrngtypid);
428 
429  /* get_type_io_data does more than we need, but is convenient */
431  func,
432  &typlen,
433  &typbyval,
434  &typalign,
435  &typdelim,
436  &cache->typioparam,
437  &typiofunc);
438 
439  if (!OidIsValid(typiofunc))
440  {
441  /* this could only happen for receive or send */
442  if (func == IOFunc_receive)
443  ereport(ERROR,
444  (errcode(ERRCODE_UNDEFINED_FUNCTION),
445  errmsg("no binary input function available for type %s",
446  format_type_be(cache->typcache->rngtype->type_id))));
447  else
448  ereport(ERROR,
449  (errcode(ERRCODE_UNDEFINED_FUNCTION),
450  errmsg("no binary output function available for type %s",
451  format_type_be(cache->typcache->rngtype->type_id))));
452  }
453  fmgr_info_cxt(typiofunc, &cache->typioproc,
454  fcinfo->flinfo->fn_mcxt);
455 
456  fcinfo->flinfo->fn_extra = (void *) cache;
457  }
458 
459  return cache;
460 }
signed short int16
Definition: c.h:428
#define OidIsValid(objectId)
Definition: c.h:710
int errcode(int sqlerrcode)
Definition: elog.c:693
int errmsg(const char *fmt,...)
Definition: elog.c:904
#define ERROR
Definition: elog.h:33
#define elog(elevel,...)
Definition: elog.h:218
#define ereport(elevel,...)
Definition: elog.h:143
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:136
char * format_type_be(Oid type_oid)
Definition: format_type.c:343
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:2282
@ IOFunc_receive
Definition: lsyscache.h:37
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:863
char typalign
Definition: pg_type.h:176
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
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:339
#define TYPECACHE_MULTIRANGE_INFO
Definition: typcache.h:152

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::rngtype, typalign, MultirangeIOData::typcache, TypeCacheEntry::type_id, TYPECACHE_MULTIRANGE_INFO, MultirangeIOData::typioparam, and MultirangeIOData::typioproc.

Referenced by multirange_in(), multirange_out(), multirange_recv(), and multirange_send().

◆ hash_multirange()

Datum hash_multirange ( PG_FUNCTION_ARGS  )

Definition at line 2781 of file multirangetypes.c.

2782 {
2784  uint32 result = 1;
2785  TypeCacheEntry *typcache,
2786  *scache;
2787  int32 range_count,
2788  i;
2789 
2790  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr));
2791  scache = typcache->rngtype->rngelemtype;
2792  if (!OidIsValid(scache->hash_proc_finfo.fn_oid))
2793  {
2794  scache = lookup_type_cache(scache->type_id,
2796  if (!OidIsValid(scache->hash_proc_finfo.fn_oid))
2797  ereport(ERROR,
2798  (errcode(ERRCODE_UNDEFINED_FUNCTION),
2799  errmsg("could not identify a hash function for type %s",
2800  format_type_be(scache->type_id))));
2801  }
2802 
2803  range_count = mr->rangeCount;
2804  for (i = 0; i < range_count; i++)
2805  {
2806  RangeBound lower,
2807  upper;
2808  uint8 flags = MultirangeGetFlagsPtr(mr)[i];
2809  uint32 lower_hash;
2810  uint32 upper_hash;
2811  uint32 range_hash;
2812 
2813  multirange_get_bounds(typcache->rngtype, mr, i, &lower, &upper);
2814 
2815  if (RANGE_HAS_LBOUND(flags))
2816  lower_hash = DatumGetUInt32(FunctionCall1Coll(&scache->hash_proc_finfo,
2817  typcache->rngtype->rng_collation,
2818  lower.val));
2819  else
2820  lower_hash = 0;
2821 
2822  if (RANGE_HAS_UBOUND(flags))
2823  upper_hash = DatumGetUInt32(FunctionCall1Coll(&scache->hash_proc_finfo,
2824  typcache->rngtype->rng_collation,
2825  upper.val));
2826  else
2827  upper_hash = 0;
2828 
2829  /* Merge hashes of flags and bounds */
2830  range_hash = hash_uint32((uint32) flags);
2831  range_hash ^= lower_hash;
2832  range_hash = pg_rotate_left32(range_hash, 1);
2833  range_hash ^= upper_hash;
2834 
2835  /*
2836  * Use the same approach as hash_array to combine the individual
2837  * elements' hash values:
2838  */
2839  result = (result << 5) - result + range_hash;
2840  }
2841 
2842  PG_FREE_IF_COPY(mr, 0);
2843 
2844  PG_RETURN_UINT32(result);
2845 }
signed int int32
Definition: c.h:429
Datum FunctionCall1Coll(FmgrInfo *flinfo, Oid collation, Datum arg1)
Definition: fmgr.c:1114
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:260
#define PG_RETURN_UINT32(x)
Definition: fmgr.h:355
static Datum hash_uint32(uint32 k)
Definition: hashfn.h:43
int i
Definition: isn.c:73
void multirange_get_bounds(TypeCacheEntry *rangetyp, const MultirangeType *multirange, uint32 i, RangeBound *lower, RangeBound *upper)
#define MultirangeGetFlagsPtr(mr)
Datum lower(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:48
Datum upper(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:79
static uint32 pg_rotate_left32(uint32 word, int n)
Definition: pg_bitutils.h:297
#define DatumGetUInt32(X)
Definition: postgres.h:530
#define RANGE_HAS_UBOUND(flags)
Definition: rangetypes.h:51
#define RANGE_HAS_LBOUND(flags)
Definition: rangetypes.h:47
Oid fn_oid
Definition: fmgr.h:59
FmgrInfo hash_proc_finfo
Definition: typcache.h:77
Oid rng_collation
Definition: typcache.h:99
struct TypeCacheEntry * rngelemtype
Definition: typcache.h:98
#define TYPECACHE_HASH_PROC_FINFO
Definition: typcache.h:143

References DatumGetUInt32, ereport, errcode(), errmsg(), ERROR, FmgrInfo::fn_oid, format_type_be(), FunctionCall1Coll(), TypeCacheEntry::hash_proc_finfo, hash_uint32(), i, lookup_type_cache(), lower(), multirange_get_bounds(), multirange_get_typcache(), MultirangeGetFlagsPtr, MultirangeTypeGetOid, OidIsValid, PG_FREE_IF_COPY, PG_GETARG_MULTIRANGE_P, PG_RETURN_UINT32, pg_rotate_left32(), RANGE_HAS_LBOUND, RANGE_HAS_UBOUND, MultirangeType::rangeCount, TypeCacheEntry::rng_collation, TypeCacheEntry::rngelemtype, TypeCacheEntry::rngtype, TypeCacheEntry::type_id, TYPECACHE_HASH_PROC_FINFO, and upper().

◆ hash_multirange_extended()

Datum hash_multirange_extended ( PG_FUNCTION_ARGS  )

Definition at line 2852 of file multirangetypes.c.

2853 {
2855  Datum seed = PG_GETARG_DATUM(1);
2856  uint64 result = 1;
2857  TypeCacheEntry *typcache,
2858  *scache;
2859  int32 range_count,
2860  i;
2861 
2862  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr));
2863  scache = typcache->rngtype->rngelemtype;
2865  {
2866  scache = lookup_type_cache(scache->type_id,
2869  ereport(ERROR,
2870  (errcode(ERRCODE_UNDEFINED_FUNCTION),
2871  errmsg("could not identify a hash function for type %s",
2872  format_type_be(scache->type_id))));
2873  }
2874 
2875  range_count = mr->rangeCount;
2876  for (i = 0; i < range_count; i++)
2877  {
2878  RangeBound lower,
2879  upper;
2880  uint8 flags = MultirangeGetFlagsPtr(mr)[i];
2881  uint64 lower_hash;
2882  uint64 upper_hash;
2883  uint64 range_hash;
2884 
2885  multirange_get_bounds(typcache->rngtype, mr, i, &lower, &upper);
2886 
2887  if (RANGE_HAS_LBOUND(flags))
2889  typcache->rngtype->rng_collation,
2890  lower.val,
2891  seed));
2892  else
2893  lower_hash = 0;
2894 
2895  if (RANGE_HAS_UBOUND(flags))
2897  typcache->rngtype->rng_collation,
2898  upper.val,
2899  seed));
2900  else
2901  upper_hash = 0;
2902 
2903  /* Merge hashes of flags and bounds */
2904  range_hash = DatumGetUInt64(hash_uint32_extended((uint32) flags,
2905  DatumGetInt64(seed)));
2906  range_hash ^= lower_hash;
2907  range_hash = ROTATE_HIGH_AND_LOW_32BITS(range_hash);
2908  range_hash ^= upper_hash;
2909 
2910  /*
2911  * Use the same approach as hash_array to combine the individual
2912  * elements' hash values:
2913  */
2914  result = (result << 5) - result + range_hash;
2915  }
2916 
2917  PG_FREE_IF_COPY(mr, 0);
2918 
2919  PG_RETURN_UINT64(result);
2920 }
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Definition: fmgr.c:1134
#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
#define DatumGetUInt64(X)
Definition: postgres.h:678
#define DatumGetInt64(X)
Definition: postgres.h:651
FmgrInfo hash_extended_proc_finfo
Definition: typcache.h:78
#define TYPECACHE_HASH_EXTENDED_PROC_FINFO
Definition: typcache.h:151

References DatumGetInt64, DatumGetUInt64, ereport, errcode(), errmsg(), ERROR, FmgrInfo::fn_oid, format_type_be(), FunctionCall2Coll(), TypeCacheEntry::hash_extended_proc_finfo, hash_uint32_extended(), i, lookup_type_cache(), lower(), multirange_get_bounds(), multirange_get_typcache(), MultirangeGetFlagsPtr, MultirangeTypeGetOid, OidIsValid, PG_FREE_IF_COPY, PG_GETARG_DATUM, PG_GETARG_MULTIRANGE_P, PG_RETURN_UINT64, RANGE_HAS_LBOUND, RANGE_HAS_UBOUND, MultirangeType::rangeCount, TypeCacheEntry::rng_collation, TypeCacheEntry::rngelemtype, TypeCacheEntry::rngtype, ROTATE_HIGH_AND_LOW_32BITS, TypeCacheEntry::type_id, TYPECACHE_HASH_EXTENDED_PROC_FINFO, and upper().

◆ make_empty_multirange()

MultirangeType* make_empty_multirange ( Oid  mltrngtypoid,
TypeCacheEntry rangetyp 
)

Definition at line 843 of file multirangetypes.c.

844 {
845  return make_multirange(mltrngtypoid, rangetyp, 0, NULL);
846 }
MultirangeType * make_multirange(Oid mltrngtypoid, TypeCacheEntry *rangetyp, int32 range_count, RangeType **ranges)

References make_multirange().

Referenced by multirange_intersect().

◆ make_multirange()

MultirangeType* make_multirange ( Oid  mltrngtypoid,
TypeCacheEntry rangetyp,
int32  range_count,
RangeType **  ranges 
)

Definition at line 641 of file multirangetypes.c.

643 {
644  MultirangeType *multirange;
645  Size size;
646 
647  /* Sort and merge input ranges. */
648  range_count = multirange_canonicalize(rangetyp, range_count, ranges);
649 
650  /* Note: zero-fill is required here, just as in heap tuples */
651  size = multirange_size_estimate(rangetyp, range_count, ranges);
652  multirange = palloc0(size);
653  SET_VARSIZE(multirange, size);
654 
655  /* Now fill in the datum */
656  multirange->multirangetypid = mltrngtypoid;
657  multirange->rangeCount = range_count;
658 
659  write_multirange_data(multirange, rangetyp, range_count, ranges);
660 
661  return multirange;
662 }
size_t Size
Definition: c.h:540
void * palloc0(Size size)
Definition: mcxt.c:1099
static int32 multirange_canonicalize(TypeCacheEntry *rangetyp, int32 input_range_count, RangeType **ranges)
static Size multirange_size_estimate(TypeCacheEntry *rangetyp, int32 range_count, RangeType **ranges)
static void write_multirange_data(MultirangeType *multirange, TypeCacheEntry *rangetyp, int32 range_count, RangeType **ranges)
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:342

References multirange_canonicalize(), multirange_size_estimate(), MultirangeType::multirangetypid, palloc0(), MultirangeType::rangeCount, SET_VARSIZE, and write_multirange_data().

Referenced by make_empty_multirange(), multirange_constructor0(), multirange_constructor1(), multirange_constructor2(), multirange_in(), multirange_intersect_internal(), multirange_minus_internal(), multirange_recv(), multirange_union(), multirangesel(), and range_agg_finalfn().

◆ multirange_adjacent_multirange()

Datum multirange_adjacent_multirange ( PG_FUNCTION_ARGS  )

Definition at line 2529 of file multirangetypes.c.

2530 {
2533  TypeCacheEntry *typcache;
2534  int32 range_count1;
2535  int32 range_count2;
2536  RangeBound lower1,
2537  upper1,
2538  lower2,
2539  upper2;
2540 
2541  if (MultirangeIsEmpty(mr1) || MultirangeIsEmpty(mr2))
2542  return false;
2543 
2544  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr1));
2545 
2546  range_count1 = mr1->rangeCount;
2547  range_count2 = mr2->rangeCount;
2548  multirange_get_bounds(typcache->rngtype, mr1, range_count1 - 1,
2549  &lower1, &upper1);
2550  multirange_get_bounds(typcache->rngtype, mr2, 0,
2551  &lower2, &upper2);
2552  if (bounds_adjacent(typcache->rngtype, upper1, lower2))
2553  PG_RETURN_BOOL(true);
2554 
2555  if (range_count1 > 1)
2556  multirange_get_bounds(typcache->rngtype, mr1, 0,
2557  &lower1, &upper1);
2558  if (range_count2 > 1)
2559  multirange_get_bounds(typcache->rngtype, mr2, range_count2 - 1,
2560  &lower2, &upper2);
2561  if (bounds_adjacent(typcache->rngtype, upper2, lower1))
2562  PG_RETURN_BOOL(true);
2563  PG_RETURN_BOOL(false);
2564 }
#define MultirangeIsEmpty(mr)
bool bounds_adjacent(TypeCacheEntry *typcache, RangeBound boundA, RangeBound boundB)
Definition: rangetypes.c:739

References bounds_adjacent(), multirange_get_bounds(), multirange_get_typcache(), MultirangeIsEmpty, MultirangeTypeGetOid, PG_GETARG_MULTIRANGE_P, PG_RETURN_BOOL, MultirangeType::rangeCount, and TypeCacheEntry::rngtype.

◆ multirange_adjacent_range()

Datum multirange_adjacent_range ( PG_FUNCTION_ARGS  )

Definition at line 2514 of file multirangetypes.c.

2515 {
2517  RangeType *r = PG_GETARG_RANGE_P(1);
2518  TypeCacheEntry *typcache;
2519 
2520  if (RangeIsEmpty(r) || MultirangeIsEmpty(mr))
2521  return false;
2522 
2523  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr));
2524 
2526 }
bool range_adjacent_multirange_internal(TypeCacheEntry *rangetyp, const RangeType *r, const MultirangeType *mr)
#define RangeIsEmpty(r)
Definition: rangetypes.h:55
#define PG_GETARG_RANGE_P(n)
Definition: rangetypes.h:75

References multirange_get_typcache(), MultirangeIsEmpty, MultirangeTypeGetOid, PG_GETARG_MULTIRANGE_P, PG_GETARG_RANGE_P, PG_RETURN_BOOL, range_adjacent_multirange_internal(), RangeIsEmpty, and TypeCacheEntry::rngtype.

◆ multirange_after_multirange()

Datum multirange_after_multirange ( PG_FUNCTION_ARGS  )

Definition at line 2384 of file multirangetypes.c.

2385 {
2388  TypeCacheEntry *typcache;
2389 
2390  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr1));
2391 
2393 }
bool multirange_before_multirange_internal(TypeCacheEntry *rangetyp, const MultirangeType *mr1, const MultirangeType *mr2)

References multirange_before_multirange_internal(), multirange_get_typcache(), MultirangeTypeGetOid, PG_GETARG_MULTIRANGE_P, PG_RETURN_BOOL, and TypeCacheEntry::rngtype.

◆ multirange_after_range()

Datum multirange_after_range ( PG_FUNCTION_ARGS  )

Definition at line 2372 of file multirangetypes.c.

2373 {
2375  RangeType *r = PG_GETARG_RANGE_P(1);
2376  TypeCacheEntry *typcache;
2377 
2378  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr));
2379 
2381 }
bool range_before_multirange_internal(TypeCacheEntry *rangetyp, const RangeType *r, const MultirangeType *mr)

References multirange_get_typcache(), MultirangeTypeGetOid, PG_GETARG_MULTIRANGE_P, PG_GETARG_RANGE_P, PG_RETURN_BOOL, range_before_multirange_internal(), and TypeCacheEntry::rngtype.

◆ multirange_agg_transfn()

Datum multirange_agg_transfn ( PG_FUNCTION_ARGS  )

Definition at line 1407 of file multirangetypes.c.

1408 {
1409  MemoryContext aggContext;
1410  Oid mltrngtypoid;
1411  TypeCacheEntry *typcache;
1412  TypeCacheEntry *rngtypcache;
1414 
1415  if (!AggCheckCallContext(fcinfo, &aggContext))
1416  elog(ERROR, "multirange_agg_transfn called in non-aggregate context");
1417 
1418  mltrngtypoid = get_fn_expr_argtype(fcinfo->flinfo, 1);
1419  if (!type_is_multirange(mltrngtypoid))
1420  elog(ERROR, "range_agg must be called with a multirange");
1421 
1422  typcache = multirange_get_typcache(fcinfo, mltrngtypoid);
1423  rngtypcache = typcache->rngtype;
1424 
1425  if (PG_ARGISNULL(0))
1426  state = initArrayResult(rngtypcache->type_id, aggContext, false);
1427  else
1429 
1430  /* skip NULLs */
1431  if (!PG_ARGISNULL(1))
1432  {
1433  MultirangeType *current;
1434  int32 range_count;
1435  RangeType **ranges;
1436 
1437  current = PG_GETARG_MULTIRANGE_P(1);
1438  multirange_deserialize(rngtypcache, current, &range_count, &ranges);
1439  if (range_count == 0)
1440  {
1441  /*
1442  * Add an empty range so we get an empty result (not a null
1443  * result).
1444  */
1446  RangeTypePGetDatum(make_empty_range(rngtypcache)),
1447  false, rngtypcache->type_id, aggContext);
1448  }
1449  else
1450  {
1451  for (int32 i = 0; i < range_count; i++)
1452  accumArrayResult(state, RangeTypePGetDatum(ranges[i]), false, rngtypcache->type_id, aggContext);
1453  }
1454  }
1455 
1457 }
ArrayBuildState * accumArrayResult(ArrayBuildState *astate, Datum dvalue, bool disnull, Oid element_type, MemoryContext rcontext)
Definition: arrayfuncs.c:5123
ArrayBuildState * initArrayResult(Oid element_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5084
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1786
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:361
bool type_is_multirange(Oid typid)
Definition: lsyscache.c:2655
void multirange_deserialize(TypeCacheEntry *rangetyp, const MultirangeType *multirange, int32 *range_count, RangeType ***ranges)
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4487
RangeType * make_empty_range(TypeCacheEntry *typcache)
Definition: rangetypes.c:2073
#define RangeTypePGetDatum(X)
Definition: rangetypes.h:74
Definition: regguts.h:318

References accumArrayResult(), AggCheckCallContext(), elog, ERROR, get_fn_expr_argtype(), i, initArrayResult(), make_empty_range(), multirange_deserialize(), multirange_get_typcache(), PG_ARGISNULL, PG_GETARG_MULTIRANGE_P, PG_GETARG_POINTER, PG_RETURN_POINTER, RangeTypePGetDatum, TypeCacheEntry::rngtype, TypeCacheEntry::type_id, and type_is_multirange().

◆ multirange_before_multirange()

Datum multirange_before_multirange ( PG_FUNCTION_ARGS  )

◆ multirange_before_multirange_internal()

bool multirange_before_multirange_internal ( TypeCacheEntry rangetyp,
const MultirangeType mr1,
const MultirangeType mr2 
)

Definition at line 2419 of file multirangetypes.c.

2422 {
2423  RangeBound lower1,
2424  upper1,
2425  lower2,
2426  upper2;
2427 
2428  if (MultirangeIsEmpty(mr1) || MultirangeIsEmpty(mr2))
2429  return false;
2430 
2431  multirange_get_bounds(rangetyp, mr1, mr1->rangeCount - 1,
2432  &lower1, &upper1);
2433  multirange_get_bounds(rangetyp, mr2, 0,
2434  &lower2, &upper2);
2435 
2436  return (range_cmp_bounds(rangetyp, &upper1, &lower2) < 0);
2437 }
int range_cmp_bounds(TypeCacheEntry *typcache, const RangeBound *b1, const RangeBound *b2)
Definition: rangetypes.c:1924

References multirange_get_bounds(), MultirangeIsEmpty, range_cmp_bounds(), and MultirangeType::rangeCount.

Referenced by multirange_after_multirange(), and multirange_before_multirange().

◆ multirange_before_range()

Datum multirange_before_range ( PG_FUNCTION_ARGS  )

Definition at line 2335 of file multirangetypes.c.

2336 {
2338  RangeType *r = PG_GETARG_RANGE_P(1);
2339  TypeCacheEntry *typcache;
2340 
2341  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr));
2342 
2344 }
bool range_after_multirange_internal(TypeCacheEntry *rangetyp, const RangeType *r, const MultirangeType *mr)

References multirange_get_typcache(), MultirangeTypeGetOid, PG_GETARG_MULTIRANGE_P, PG_GETARG_RANGE_P, PG_RETURN_BOOL, range_after_multirange_internal(), and TypeCacheEntry::rngtype.

◆ multirange_bsearch_match()

static bool multirange_bsearch_match ( TypeCacheEntry typcache,
const MultirangeType mr,
void *  key,
multirange_bsearch_comparison  cmp_func 
)
static

Definition at line 893 of file multirangetypes.c.

895 {
896  uint32 l,
897  u,
898  idx;
899  int comparison;
900  bool match = false;
901 
902  l = 0;
903  u = mr->rangeCount;
904  while (l < u)
905  {
907  upper;
908 
909  idx = (l + u) / 2;
910  multirange_get_bounds(typcache, mr, idx, &lower, &upper);
911  comparison = (*cmp_func) (typcache, &lower, &upper, key, &match);
912 
913  if (comparison < 0)
914  u = idx;
915  else if (comparison > 0)
916  l = idx + 1;
917  else
918  return match;
919  }
920 
921  return false;
922 }
Datum idx(PG_FUNCTION_ARGS)
Definition: _int_op.c:259

References idx(), sort-test::key, lower(), multirange_get_bounds(), MultirangeType::rangeCount, and upper().

Referenced by multirange_contains_elem_internal(), multirange_contains_range_internal(), and range_overlaps_multirange_internal().

◆ multirange_canonicalize()

static int32 multirange_canonicalize ( TypeCacheEntry rangetyp,
int32  input_range_count,
RangeType **  ranges 
)
static

Definition at line 472 of file multirangetypes.c.

474 {
475  RangeType *lastRange = NULL;
476  RangeType *currentRange;
477  int32 i;
478  int32 output_range_count = 0;
479 
480  /* Sort the ranges so we can find the ones that overlap/meet. */
481  qsort_arg(ranges, input_range_count, sizeof(RangeType *), range_compare,
482  rangetyp);
483 
484  /* Now merge where possible: */
485  for (i = 0; i < input_range_count; i++)
486  {
487  currentRange = ranges[i];
488  if (RangeIsEmpty(currentRange))
489  continue;
490 
491  if (lastRange == NULL)
492  {
493  ranges[output_range_count++] = lastRange = currentRange;
494  continue;
495  }
496 
497  /*
498  * range_adjacent_internal gives true if *either* A meets B or B meets
499  * A, which is not quite want we want, but we rely on the sorting
500  * above to rule out B meets A ever happening.
501  */
502  if (range_adjacent_internal(rangetyp, lastRange, currentRange))
503  {
504  /* The two ranges touch (without overlap), so merge them: */
505  ranges[output_range_count - 1] = lastRange =
506  range_union_internal(rangetyp, lastRange, currentRange, false);
507  }
508  else if (range_before_internal(rangetyp, lastRange, currentRange))
509  {
510  /* There's a gap, so make a new entry: */
511  lastRange = ranges[output_range_count] = currentRange;
512  output_range_count++;
513  }
514  else
515  {
516  /* They must overlap, so merge them: */
517  ranges[output_range_count - 1] = lastRange =
518  range_union_internal(rangetyp, lastRange, currentRange, true);
519  }
520  }
521 
522  return output_range_count;
523 }
void qsort_arg(void *base, size_t nel, size_t elsize, qsort_arg_comparator cmp, void *arg)
bool range_before_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:646
bool range_adjacent_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:780
int range_compare(const void *key1, const void *key2, void *arg)
Definition: rangetypes.c:2037
RangeType * range_union_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2, bool strict)
Definition: rangetypes.c:1034

References i, qsort_arg(), range_adjacent_internal(), range_before_internal(), range_compare(), range_union_internal(), and RangeIsEmpty.

Referenced by make_multirange().

◆ multirange_cmp()

Datum multirange_cmp ( PG_FUNCTION_ARGS  )

Definition at line 2570 of file multirangetypes.c.

2571 {
2574  int32 range_count_1;
2575  int32 range_count_2;
2576  int32 range_count_max;
2577  int32 i;
2578  TypeCacheEntry *typcache;
2579  int cmp = 0; /* If both are empty we'll use this. */
2580 
2581  /* Different types should be prevented by ANYMULTIRANGE matching rules */
2582  if (MultirangeTypeGetOid(mr1) != MultirangeTypeGetOid(mr2))
2583  elog(ERROR, "multirange types do not match");
2584 
2585  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr1));
2586 
2587  range_count_1 = mr1->rangeCount;
2588  range_count_2 = mr2->rangeCount;
2589 
2590  /* Loop over source data */
2591  range_count_max = Max(range_count_1, range_count_2);
2592  for (i = 0; i < range_count_max; i++)
2593  {
2594  RangeBound lower1,
2595  upper1,
2596  lower2,
2597  upper2;
2598 
2599  /*
2600  * If one multirange is shorter, it's as if it had empty ranges at the
2601  * end to extend its length. An empty range compares earlier than any
2602  * other range, so the shorter multirange comes before the longer.
2603  * This is the same behavior as in other types, e.g. in strings 'aaa'
2604  * < 'aaaaaa'.
2605  */
2606  if (i >= range_count_1)
2607  {
2608  cmp = -1;
2609  break;
2610  }
2611  if (i >= range_count_2)
2612  {
2613  cmp = 1;
2614  break;
2615  }
2616 
2617  multirange_get_bounds(typcache->rngtype, mr1, i, &lower1, &upper1);
2618  multirange_get_bounds(typcache->rngtype, mr2, i, &lower2, &upper2);
2619 
2620  cmp = range_cmp_bounds(typcache->rngtype, &lower1, &lower2);
2621  if (cmp == 0)
2622  cmp = range_cmp_bounds(typcache->rngtype, &upper1, &upper2);
2623  if (cmp != 0)
2624  break;
2625  }
2626 
2627  PG_FREE_IF_COPY(mr1, 0);
2628  PG_FREE_IF_COPY(mr2, 1);
2629 
2631 }
#define Max(x, y)
Definition: c.h:980
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354
static int cmp(const chr *x, const chr *y, size_t len)
Definition: regc_locale.c:747

References cmp(), elog, ERROR, i, Max, multirange_get_bounds(), multirange_get_typcache(), MultirangeTypeGetOid, PG_FREE_IF_COPY, PG_GETARG_MULTIRANGE_P, PG_RETURN_INT32, range_cmp_bounds(), MultirangeType::rangeCount, and TypeCacheEntry::rngtype.

Referenced by multirange_ge(), multirange_gt(), multirange_le(), and multirange_lt().

◆ multirange_constructor0()

Datum multirange_constructor0 ( PG_FUNCTION_ARGS  )

Definition at line 1054 of file multirangetypes.c.

1055 {
1056  Oid mltrngtypid;
1057  TypeCacheEntry *typcache;
1058  TypeCacheEntry *rangetyp;
1059 
1060  /* This should always be called without arguments */
1061  if (PG_NARGS() != 0)
1062  elog(ERROR,
1063  "niladic multirange constructor must not receive arguments");
1064 
1065  mltrngtypid = get_fn_expr_rettype(fcinfo->flinfo);
1066  typcache = multirange_get_typcache(fcinfo, mltrngtypid);
1067  rangetyp = typcache->rngtype;
1068 
1069  PG_RETURN_MULTIRANGE_P(make_multirange(mltrngtypid, rangetyp, 0, NULL));
1070 }
Oid get_fn_expr_rettype(FmgrInfo *flinfo)
Definition: fmgr.c:1764
#define PG_NARGS()
Definition: fmgr.h:203
#define PG_RETURN_MULTIRANGE_P(x)

References elog, ERROR, get_fn_expr_rettype(), make_multirange(), multirange_get_typcache(), PG_NARGS, PG_RETURN_MULTIRANGE_P, and TypeCacheEntry::rngtype.

◆ multirange_constructor1()

Datum multirange_constructor1 ( PG_FUNCTION_ARGS  )

Definition at line 1018 of file multirangetypes.c.

1019 {
1020  Oid mltrngtypid = get_fn_expr_rettype(fcinfo->flinfo);
1021  Oid rngtypid;
1022  TypeCacheEntry *typcache;
1023  TypeCacheEntry *rangetyp;
1024  RangeType *range;
1025 
1026  typcache = multirange_get_typcache(fcinfo, mltrngtypid);
1027  rangetyp = typcache->rngtype;
1028 
1029  /*
1030  * This check should be guaranteed by our signature, but let's do it just
1031  * in case.
1032  */
1033 
1034  if (PG_ARGISNULL(0))
1035  elog(ERROR,
1036  "multirange values cannot contain null members");
1037 
1038  range = PG_GETARG_RANGE_P(0);
1039 
1040  /* Make sure the range type matches. */
1041  rngtypid = RangeTypeGetOid(range);
1042  if (rngtypid != rangetyp->type_id)
1043  elog(ERROR, "type %u does not match constructor type", rngtypid);
1044 
1045  PG_RETURN_MULTIRANGE_P(make_multirange(mltrngtypid, rangetyp, 1, &range));
1046 }
#define RangeTypeGetOid(r)
Definition: rangetypes.h:35
static struct cvec * range(struct vars *v, chr a, chr b, int cases)
Definition: regc_locale.c:412

References elog, ERROR, get_fn_expr_rettype(), make_multirange(), multirange_get_typcache(), PG_ARGISNULL, PG_GETARG_RANGE_P, PG_RETURN_MULTIRANGE_P, range(), RangeTypeGetOid, TypeCacheEntry::rngtype, and TypeCacheEntry::type_id.

◆ multirange_constructor2()

Datum multirange_constructor2 ( PG_FUNCTION_ARGS  )

Definition at line 936 of file multirangetypes.c.

937 {
938  Oid mltrngtypid = get_fn_expr_rettype(fcinfo->flinfo);
939  Oid rngtypid;
940  TypeCacheEntry *typcache;
941  TypeCacheEntry *rangetyp;
942  ArrayType *rangeArray;
943  int range_count;
944  Datum *elements;
945  bool *nulls;
946  RangeType **ranges;
947  int dims;
948  int i;
949 
950  typcache = multirange_get_typcache(fcinfo, mltrngtypid);
951  rangetyp = typcache->rngtype;
952 
953  /*
954  * A no-arg invocation should call multirange_constructor0 instead, but
955  * returning an empty range is what that does.
956  */
957 
958  if (PG_NARGS() == 0)
959  PG_RETURN_MULTIRANGE_P(make_multirange(mltrngtypid, rangetyp, 0, NULL));
960 
961  /*
962  * This check should be guaranteed by our signature, but let's do it just
963  * in case.
964  */
965 
966  if (PG_ARGISNULL(0))
967  elog(ERROR,
968  "multirange values cannot contain null members");
969 
970  rangeArray = PG_GETARG_ARRAYTYPE_P(0);
971 
972  dims = ARR_NDIM(rangeArray);
973  if (dims > 1)
974  ereport(ERROR,
975  (errcode(ERRCODE_CARDINALITY_VIOLATION),
976  errmsg("multiranges cannot be constructed from multidimensional arrays")));
977 
978  rngtypid = ARR_ELEMTYPE(rangeArray);
979  if (rngtypid != rangetyp->type_id)
980  elog(ERROR, "type %u does not match constructor type", rngtypid);
981 
982  /*
983  * Be careful: we can still be called with zero ranges, like this:
984  * `int4multirange(variadic '{}'::int4range[])
985  */
986  if (dims == 0)
987  {
988  range_count = 0;
989  ranges = NULL;
990  }
991  else
992  {
993  deconstruct_array(rangeArray, rngtypid, rangetyp->typlen, rangetyp->typbyval,
994  rangetyp->typalign, &elements, &nulls, &range_count);
995 
996  ranges = palloc0(range_count * sizeof(RangeType *));
997  for (i = 0; i < range_count; i++)
998  {
999  if (nulls[i])
1000  ereport(ERROR,
1001  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1002  errmsg("multirange values cannot contain null members")));
1003 
1004  /* make_multirange will do its own copy */
1005  ranges[i] = DatumGetRangeTypeP(elements[i]);
1006  }
1007  }
1008 
1009  PG_RETURN_MULTIRANGE_P(make_multirange(mltrngtypid, rangetyp, range_count, ranges));
1010 }
#define ARR_NDIM(a)
Definition: array.h:283
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:256
#define ARR_ELEMTYPE(a)
Definition: array.h:285
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3491
#define DatumGetRangeTypeP(X)
Definition: rangetypes.h:72
char typalign
Definition: typcache.h:41
bool typbyval
Definition: typcache.h:40
int16 typlen
Definition: typcache.h:39

References ARR_ELEMTYPE, ARR_NDIM, DatumGetRangeTypeP, deconstruct_array(), elog, ereport, errcode(), errmsg(), ERROR, get_fn_expr_rettype(), i, make_multirange(), multirange_get_typcache(), palloc0(), PG_ARGISNULL, PG_GETARG_ARRAYTYPE_P, PG_NARGS, PG_RETURN_MULTIRANGE_P, TypeCacheEntry::rngtype, TypeCacheEntry::typalign, TypeCacheEntry::typbyval, TypeCacheEntry::type_id, and TypeCacheEntry::typlen.

◆ multirange_contained_by_multirange()

Datum multirange_contained_by_multirange ( PG_FUNCTION_ARGS  )

Definition at line 2246 of file multirangetypes.c.

2247 {
2250  TypeCacheEntry *typcache;
2251 
2252  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr1));
2253 
2255 }
bool multirange_contains_multirange_internal(TypeCacheEntry *rangetyp, const MultirangeType *mr1, const MultirangeType *mr2)

References multirange_contains_multirange_internal(), multirange_get_typcache(), MultirangeTypeGetOid, PG_GETARG_MULTIRANGE_P, PG_RETURN_BOOL, and TypeCacheEntry::rngtype.

◆ multirange_contained_by_range()

Datum multirange_contained_by_range ( PG_FUNCTION_ARGS  )

Definition at line 1753 of file multirangetypes.c.

1754 {
1756  RangeType *r = PG_GETARG_RANGE_P(1);
1757  TypeCacheEntry *typcache;
1758 
1759  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr));
1760 
1762 }
bool range_contains_multirange_internal(TypeCacheEntry *rangetyp, const RangeType *r, const MultirangeType *mr)

References multirange_get_typcache(), MultirangeTypeGetOid, PG_GETARG_MULTIRANGE_P, PG_GETARG_RANGE_P, PG_RETURN_BOOL, range_contains_multirange_internal(), and TypeCacheEntry::rngtype.

◆ multirange_contains_elem()

◆ multirange_contains_elem_internal()

bool multirange_contains_elem_internal ( TypeCacheEntry rangetyp,
const MultirangeType mr,
Datum  val 
)

Definition at line 1702 of file multirangetypes.c.

1704 {
1705  if (MultirangeIsEmpty(mr))
1706  return false;
1707 
1708  return multirange_bsearch_match(rangetyp, mr, &val,
1710 }
static bool multirange_bsearch_match(TypeCacheEntry *typcache, const MultirangeType *mr, void *key, multirange_bsearch_comparison cmp_func)
static int multirange_elem_bsearch_comparison(TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper, void *key, bool *match)

References multirange_bsearch_match(), multirange_elem_bsearch_comparison(), MultirangeIsEmpty, and val.

Referenced by elem_contained_by_multirange(), and multirange_contains_elem().

◆ multirange_contains_multirange()

Datum multirange_contains_multirange ( PG_FUNCTION_ARGS  )

◆ multirange_contains_multirange_internal()

bool multirange_contains_multirange_internal ( TypeCacheEntry rangetyp,
const MultirangeType mr1,
const MultirangeType mr2 
)

Definition at line 2261 of file multirangetypes.c.

2264 {
2265  int32 range_count1 = mr1->rangeCount;
2266  int32 range_count2 = mr2->rangeCount;
2267  int i1,
2268  i2;
2269  RangeBound lower1,
2270  upper1,
2271  lower2,
2272  upper2;
2273 
2274  /*
2275  * We follow the same logic for empties as ranges: - an empty multirange
2276  * contains an empty range/multirange. - an empty multirange can't contain
2277  * any other range/multirange. - an empty multirange is contained by any
2278  * other range/multirange.
2279  */
2280 
2281  if (range_count2 == 0)
2282  return true;
2283  if (range_count1 == 0)
2284  return false;
2285 
2286  /*
2287  * Every range in mr2 must be contained by some range in mr1. To avoid
2288  * O(n^2) we walk through both ranges in tandem.
2289  */
2290  i1 = 0;
2291  multirange_get_bounds(rangetyp, mr1, i1, &lower1, &upper1);
2292  for (i2 = 0; i2 < range_count2; i2++)
2293  {
2294  multirange_get_bounds(rangetyp, mr2, i2, &lower2, &upper2);
2295 
2296  /* Discard r1s while r1 << r2 */
2297  while (range_cmp_bounds(rangetyp, &upper1, &lower2) < 0)
2298  {
2299  if (++i1 >= range_count1)
2300  return false;
2301  multirange_get_bounds(rangetyp, mr1, i1, &lower1, &upper1);
2302  }
2303 
2304  /*
2305  * If r1 @> r2, go to the next r2, otherwise return false (since every
2306  * r1[n] and r1[n+1] must have a gap). Note this will give weird
2307  * answers if you don't canonicalize, e.g. with a custom
2308  * int2multirange {[1,1], [2,2]} there is a "gap". But that is
2309  * consistent with other range operators, e.g. '[1,1]'::int2range -|-
2310  * '[2,2]'::int2range is false.
2311  */
2312  if (!range_bounds_contains(rangetyp, &lower1, &upper1,
2313  &lower2, &upper2))
2314  return false;
2315  }
2316 
2317  /* All ranges in mr2 are satisfied */
2318  return true;
2319 }
static bool range_bounds_contains(TypeCacheEntry *typcache, RangeBound *lower1, RangeBound *upper1, RangeBound *lower2, RangeBound *upper2)

References multirange_get_bounds(), range_bounds_contains(), range_cmp_bounds(), and MultirangeType::rangeCount.

Referenced by multirange_contained_by_multirange(), and multirange_contains_multirange().

◆ multirange_contains_range()

Datum multirange_contains_range ( PG_FUNCTION_ARGS  )

Definition at line 1716 of file multirangetypes.c.

1717 {
1719  RangeType *r = PG_GETARG_RANGE_P(1);
1720  TypeCacheEntry *typcache;
1721 
1722  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr));
1723 
1725 }
bool multirange_contains_range_internal(TypeCacheEntry *rangetyp, const MultirangeType *mr, const RangeType *r)

References multirange_contains_range_internal(), multirange_get_typcache(), MultirangeTypeGetOid, PG_GETARG_MULTIRANGE_P, PG_GETARG_RANGE_P, PG_RETURN_BOOL, and TypeCacheEntry::rngtype.

◆ multirange_contains_range_internal()

bool multirange_contains_range_internal ( TypeCacheEntry rangetyp,
const MultirangeType mr,
const RangeType r 
)

Definition at line 1796 of file multirangetypes.c.

1799 {
1800  RangeBound bounds[2];
1801  bool empty;
1802 
1803  /*
1804  * Every multirange contains an infinite number of empty ranges, even an
1805  * empty one.
1806  */
1807  if (RangeIsEmpty(r))
1808  return true;
1809 
1810  if (MultirangeIsEmpty(mr))
1811  return false;
1812 
1813  range_deserialize(rangetyp, r, &bounds[0], &bounds[1], &empty);
1814  Assert(!empty);
1815 
1816  return multirange_bsearch_match(rangetyp, mr, bounds,
1818 }
Assert(fmt[strlen(fmt) - 1] !='\n')
static int multirange_range_contains_bsearch_comparison(TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper, void *key, bool *match)
void range_deserialize(TypeCacheEntry *typcache, const RangeType *range, RangeBound *lower, RangeBound *upper, bool *empty)
Definition: rangetypes.c:1788

References Assert(), multirange_bsearch_match(), multirange_range_contains_bsearch_comparison(), MultirangeIsEmpty, range_deserialize(), and RangeIsEmpty.

Referenced by multirange_contains_range(), range_contained_by_multirange(), and range_gist_consistent_leaf_multirange().

◆ multirange_deserialize()

void multirange_deserialize ( TypeCacheEntry rangetyp,
const MultirangeType multirange,
int32 range_count,
RangeType ***  ranges 
)

Definition at line 821 of file multirangetypes.c.

824 {
825  *range_count = multirange->rangeCount;
826 
827  /* Convert each ShortRangeType into a RangeType */
828  if (*range_count > 0)
829  {
830  int i;
831 
832  *ranges = palloc(*range_count * sizeof(RangeType *));
833  for (i = 0; i < *range_count; i++)
834  (*ranges)[i] = multirange_get_range(rangetyp, multirange, i);
835  }
836  else
837  {
838  *ranges = NULL;
839  }
840 }
void * palloc(Size size)
Definition: mcxt.c:1068
RangeType * multirange_get_range(TypeCacheEntry *rangetyp, const MultirangeType *multirange, int i)

References i, multirange_get_range(), palloc(), and MultirangeType::rangeCount.

Referenced by multirange_agg_transfn(), multirange_intersect(), multirange_intersect_agg_transfn(), multirange_minus(), multirange_out(), multirange_send(), and multirange_union().

◆ multirange_elem_bsearch_comparison()

static int multirange_elem_bsearch_comparison ( TypeCacheEntry typcache,
RangeBound lower,
RangeBound upper,
void *  key,
bool match 
)
static

Definition at line 1669 of file multirangetypes.c.

1672 {
1673  Datum val = *((Datum *) key);
1674  int cmp;
1675 
1676  if (!lower->infinite)
1677  {
1679  typcache->rng_collation,
1680  lower->val, val));
1681  if (cmp > 0 || (cmp == 0 && !lower->inclusive))
1682  return -1;
1683  }
1684 
1685  if (!upper->infinite)
1686  {
1688  typcache->rng_collation,
1689  upper->val, val));
1690  if (cmp < 0 || (cmp == 0 && !upper->inclusive))
1691  return 1;
1692  }
1693 
1694  *match = true;
1695  return 0;
1696 }
#define DatumGetInt32(X)
Definition: postgres.h:516
FmgrInfo rng_cmp_proc_finfo
Definition: typcache.h:100

References cmp(), DatumGetInt32, FunctionCall2Coll(), sort-test::key, lower(), TypeCacheEntry::rng_cmp_proc_finfo, TypeCacheEntry::rng_collation, upper(), and val.

Referenced by multirange_contains_elem_internal().

◆ multirange_empty()

Datum multirange_empty ( PG_FUNCTION_ARGS  )

Definition at line 1551 of file multirangetypes.c.

1552 {
1554 
1556 }

References MultirangeIsEmpty, PG_GETARG_MULTIRANGE_P, and PG_RETURN_BOOL.

◆ multirange_eq()

Datum multirange_eq ( PG_FUNCTION_ARGS  )

Definition at line 1896 of file multirangetypes.c.

1897 {
1900  TypeCacheEntry *typcache;
1901 
1902  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr1));
1903 
1904  PG_RETURN_BOOL(multirange_eq_internal(typcache->rngtype, mr1, mr2));
1905 }
bool multirange_eq_internal(TypeCacheEntry *rangetyp, const MultirangeType *mr1, const MultirangeType *mr2)

References multirange_eq_internal(), multirange_get_typcache(), MultirangeTypeGetOid, PG_GETARG_MULTIRANGE_P, PG_RETURN_BOOL, and TypeCacheEntry::rngtype.

◆ multirange_eq_internal()

bool multirange_eq_internal ( TypeCacheEntry rangetyp,
const MultirangeType mr1,
const MultirangeType mr2 
)

Definition at line 1859 of file multirangetypes.c.

1862 {
1863  int32 range_count_1;
1864  int32 range_count_2;
1865  int32 i;
1866  RangeBound lower1,
1867  upper1,
1868  lower2,
1869  upper2;
1870 
1871  /* Different types should be prevented by ANYMULTIRANGE matching rules */
1872  if (MultirangeTypeGetOid(mr1) != MultirangeTypeGetOid(mr2))
1873  elog(ERROR, "multirange types do not match");
1874 
1875  range_count_1 = mr1->rangeCount;
1876  range_count_2 = mr2->rangeCount;
1877 
1878  if (range_count_1 != range_count_2)
1879  return false;
1880 
1881  for (i = 0; i < range_count_1; i++)
1882  {
1883  multirange_get_bounds(rangetyp, mr1, i, &lower1, &upper1);
1884  multirange_get_bounds(rangetyp, mr2, i, &lower2, &upper2);
1885 
1886  if (range_cmp_bounds(rangetyp, &lower1, &lower2) != 0 ||
1887  range_cmp_bounds(rangetyp, &upper1, &upper2) != 0)
1888  return false;
1889  }
1890 
1891  return true;
1892 }

References elog, ERROR, i, multirange_get_bounds(), MultirangeTypeGetOid, range_cmp_bounds(), and MultirangeType::rangeCount.

Referenced by multirange_eq(), and multirange_ne_internal().

◆ multirange_ge()

Datum multirange_ge ( PG_FUNCTION_ARGS  )

Definition at line 2651 of file multirangetypes.c.

2652 {
2653  int cmp = multirange_cmp(fcinfo);
2654 
2655  PG_RETURN_BOOL(cmp >= 0);
2656 }
Datum multirange_cmp(PG_FUNCTION_ARGS)

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

◆ multirange_get_bounds()

void multirange_get_bounds ( TypeCacheEntry rangetyp,
const MultirangeType multirange,
uint32  i,
RangeBound lower,
RangeBound upper 
)

Definition at line 739 of file multirangetypes.c.

742 {
743  uint32 offset;
744  uint8 flags;
745  Pointer ptr;
746  int16 typlen = rangetyp->rngelemtype->typlen;
747  char typalign = rangetyp->rngelemtype->typalign;
748  bool typbyval = rangetyp->rngelemtype->typbyval;
749  Datum lbound;
750  Datum ubound;
751 
752  Assert(i < multirange->rangeCount);
753 
754  offset = multirange_get_bounds_offset(multirange, i);
755  flags = MultirangeGetFlagsPtr(multirange)[i];
756  ptr = MultirangeGetBoundariesPtr(multirange, typalign) + offset;
757 
758  /* multirange can't contain empty ranges */
759  Assert((flags & RANGE_EMPTY) == 0);
760 
761  /* fetch lower bound, if any */
762  if (RANGE_HAS_LBOUND(flags))
763  {
764  /* att_align_pointer cannot be necessary here */
765  lbound = fetch_att(ptr, typbyval, typlen);
766  ptr = (Pointer) att_addlength_pointer(ptr, typlen, ptr);
767  }
768  else
769  lbound = (Datum) 0;
770 
771  /* fetch upper bound, if any */
772  if (RANGE_HAS_UBOUND(flags))
773  {
774  ptr = (Pointer) att_align_pointer(ptr, typalign, typlen, ptr);
775  ubound = fetch_att(ptr, typbyval, typlen);
776  /* no need for att_addlength_pointer */
777  }
778  else
779  ubound = (Datum) 0;
780 
781  /* emit results */
782  lower->val = lbound;
783  lower->infinite = (flags & RANGE_LB_INF) != 0;
784  lower->inclusive = (flags & RANGE_LB_INC) != 0;
785  lower->lower = true;
786 
787  upper->val = ubound;
788  upper->infinite = (flags & RANGE_UB_INF) != 0;
789  upper->inclusive = (flags & RANGE_UB_INC) != 0;
790  upper->lower = false;
791 }
static uint32 multirange_get_bounds_offset(const MultirangeType *multirange, int32 i)
#define MultirangeGetBoundariesPtr(mr, align)
#define RANGE_UB_INC
Definition: rangetypes.h:40
#define RANGE_LB_INC
Definition: rangetypes.h:39
#define RANGE_UB_INF
Definition: rangetypes.h:42
#define RANGE_EMPTY
Definition: rangetypes.h:38
#define RANGE_LB_INF
Definition: rangetypes.h:41
#define att_align_pointer(cur_offset, attalign, attlen, attptr)
Definition: tupmacs.h:126
#define att_addlength_pointer(cur_offset, attlen, attptr)
Definition: tupmacs.h:176
#define fetch_att(T, attbyval, attlen)
Definition: tupmacs.h:75

References Assert(), att_addlength_pointer, att_align_pointer, fetch_att, i, lower(), multirange_get_bounds_offset(), MultirangeGetBoundariesPtr, MultirangeGetFlagsPtr, RANGE_EMPTY, RANGE_HAS_LBOUND, RANGE_HAS_UBOUND, RANGE_LB_INC, RANGE_LB_INF, RANGE_UB_INC, RANGE_UB_INF, TypeCacheEntry::rngelemtype, typalign, TypeCacheEntry::typalign, TypeCacheEntry::typbyval, TypeCacheEntry::typlen, and upper().

Referenced by calc_hist_selectivity(), compute_range_stats(), hash_multirange(), hash_multirange_extended(), multirange_adjacent_multirange(), multirange_before_multirange_internal(), multirange_bsearch_match(), multirange_cmp(), multirange_contains_multirange_internal(), multirange_eq_internal(), multirange_get_union_range(), multirange_lower(), multirange_lower_inc(), multirange_lower_inf(), multirange_overlaps_multirange_internal(), multirange_overleft_multirange(), multirange_overleft_range(), multirange_overright_multirange(), multirange_overright_range(), multirange_union_range_equal(), multirange_upper(), multirange_upper_inc(), multirange_upper_inf(), range_adjacent_multirange_internal(), range_after_multirange_internal(), range_before_multirange_internal(), range_contains_multirange_internal(), range_merge_from_multirange(), range_overleft_multirange_internal(), and range_overright_multirange_internal().

◆ multirange_get_bounds_offset()

static uint32 multirange_get_bounds_offset ( const MultirangeType multirange,
int32  i 
)
static

Definition at line 668 of file multirangetypes.c.

669 {
670  uint32 *items = MultirangeGetItemsPtr(multirange);
671  uint32 offset = 0;
672 
673  /*
674  * Summarize lengths till we meet an offset.
675  */
676  while (i > 0)
677  {
678  offset += MULTIRANGE_ITEM_GET_OFFLEN(items[i - 1]);
679  if (MULTIRANGE_ITEM_HAS_OFF(items[i - 1]))
680  break;
681  i--;
682  }
683  return offset;
684 }
#define MULTIRANGE_ITEM_GET_OFFLEN(item)
#define MULTIRANGE_ITEM_HAS_OFF(item)
#define MultirangeGetItemsPtr(mr)

References i, MULTIRANGE_ITEM_GET_OFFLEN, MULTIRANGE_ITEM_HAS_OFF, and MultirangeGetItemsPtr.

Referenced by multirange_get_bounds(), and multirange_get_range().

◆ multirange_get_range()

RangeType* multirange_get_range ( TypeCacheEntry rangetyp,
const MultirangeType multirange,
int  i 
)

Definition at line 690 of file multirangetypes.c.

692 {
693  uint32 offset;
694  uint8 flags;
695  Pointer begin,
696  ptr;
697  int16 typlen = rangetyp->rngelemtype->typlen;
698  char typalign = rangetyp->rngelemtype->typalign;
699  uint32 len;
700  RangeType *range;
701 
702  Assert(i < multirange->rangeCount);
703 
704  offset = multirange_get_bounds_offset(multirange, i);
705  flags = MultirangeGetFlagsPtr(multirange)[i];
706  ptr = begin = MultirangeGetBoundariesPtr(multirange, typalign) + offset;
707 
708  /*
709  * Calculate the size of bound values. In principle, we could get offset
710  * of the next range bound values and calculate accordingly. But range
711  * bound values are aligned, so we have to walk the values to get the
712  * exact size.
713  */
714  if (RANGE_HAS_LBOUND(flags))
715  ptr = (Pointer) att_addlength_pointer(ptr, typlen, ptr);
716  if (RANGE_HAS_UBOUND(flags))
717  {
718  ptr = (Pointer) att_align_pointer(ptr, typalign, typlen, ptr);
719  ptr = (Pointer) att_addlength_pointer(ptr, typlen, ptr);
720  }
721  len = (ptr - begin) + sizeof(RangeType) + sizeof(uint8);
722 
723  range = palloc0(len);
725  range->rangetypid = rangetyp->type_id;
726 
727  memcpy(range + 1, begin, ptr - begin);
728  *((uint8 *) (range + 1) + (ptr - begin)) = flags;
729 
730  return range;
731 }
const void size_t len

References Assert(), att_addlength_pointer, att_align_pointer, i, len, multirange_get_bounds_offset(), MultirangeGetBoundariesPtr, MultirangeGetFlagsPtr, palloc0(), range(), RANGE_HAS_LBOUND, RANGE_HAS_UBOUND, TypeCacheEntry::rngelemtype, SET_VARSIZE, typalign, TypeCacheEntry::typalign, TypeCacheEntry::type_id, and TypeCacheEntry::typlen.

Referenced by multirange_deserialize(), multirange_unnest(), and range_merge_from_multirange().

◆ multirange_get_typcache()

TypeCacheEntry* multirange_get_typcache ( FunctionCallInfo  fcinfo,
Oid  mltrngtypid 
)

Definition at line 543 of file multirangetypes.c.

544 {
545  TypeCacheEntry *typcache = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
546 
547  if (typcache == NULL ||
548  typcache->type_id != mltrngtypid)
549  {
550  typcache = lookup_type_cache(mltrngtypid, TYPECACHE_MULTIRANGE_INFO);
551  if (typcache->rngtype == NULL)
552  elog(ERROR, "type %u is not a multirange type", mltrngtypid);
553  fcinfo->flinfo->fn_extra = (void *) typcache;
554  }
555 
556  return typcache;
557 }

References elog, ERROR, FunctionCallInfoBaseData::flinfo, FmgrInfo::fn_extra, if(), lookup_type_cache(), TypeCacheEntry::rngtype, TypeCacheEntry::type_id, and TYPECACHE_MULTIRANGE_INFO.

Referenced by elem_contained_by_multirange(), hash_multirange(), hash_multirange_extended(), multirange_adjacent_multirange(), multirange_adjacent_range(), multirange_after_multirange(), multirange_after_range(), multirange_agg_transfn(), multirange_before_multirange(), multirange_before_range(), multirange_cmp(), multirange_constructor0(), multirange_constructor1(), multirange_constructor2(), multirange_contained_by_multirange(), multirange_contained_by_range(), multirange_contains_elem(), multirange_contains_multirange(), multirange_contains_range(), multirange_eq(), multirange_gist_compress(), multirange_intersect(), multirange_intersect_agg_transfn(), multirange_lower(), multirange_lower_inc(), multirange_lower_inf(), multirange_minus(), multirange_ne(), multirange_overlaps_multirange(), multirange_overlaps_range(), multirange_overleft_multirange(), multirange_overleft_range(), multirange_overright_multirange(), multirange_overright_range(), multirange_typanalyze(), multirange_union(), multirange_upper(), multirange_upper_inc(), multirange_upper_inf(), multirangesel(), range_adjacent_multirange(), range_after_multirange(), range_agg_finalfn(), range_before_multirange(), range_contained_by_multirange(), range_contains_multirange(), range_merge_from_multirange(), range_overlaps_multirange(), range_overleft_multirange(), and range_overright_multirange().

◆ multirange_get_union_range()

RangeType* multirange_get_union_range ( TypeCacheEntry rangetyp,
const MultirangeType mr 
)

Definition at line 797 of file multirangetypes.c.

799 {
801  upper,
802  tmp;
803 
804  if (MultirangeIsEmpty(mr))
805  return make_empty_range(rangetyp);
806 
807  multirange_get_bounds(rangetyp, mr, 0, &lower, &tmp);
808  multirange_get_bounds(rangetyp, mr, mr->rangeCount - 1, &tmp, &upper);
809 
810  return make_range(rangetyp, &lower, &upper, false);
811 }
RangeType * make_range(TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper, bool empty)
Definition: rangetypes.c:1884

References lower(), make_empty_range(), make_range(), multirange_get_bounds(), MultirangeIsEmpty, MultirangeType::rangeCount, and upper().

Referenced by multirange_gist_compress().

◆ multirange_gt()

Datum multirange_gt ( PG_FUNCTION_ARGS  )

Definition at line 2659 of file multirangetypes.c.

2660 {
2661  int cmp = multirange_cmp(fcinfo);
2662 
2663  PG_RETURN_BOOL(cmp > 0);
2664 }

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

◆ multirange_in()

Datum multirange_in ( PG_FUNCTION_ARGS  )

Definition at line 118 of file multirangetypes.c.

119 {
120  char *input_str = PG_GETARG_CSTRING(0);
121  Oid mltrngtypoid = PG_GETARG_OID(1);
122  Oid typmod = PG_GETARG_INT32(2);
123  TypeCacheEntry *rangetyp;
124  int32 ranges_seen = 0;
125  int32 range_count = 0;
126  int32 range_capacity = 8;
127  RangeType *range;
128  RangeType **ranges = palloc(range_capacity * sizeof(RangeType *));
129  MultirangeIOData *cache;
130  MultirangeType *ret;
131  MultirangeParseState parse_state;
132  const char *ptr = input_str;
133  const char *range_str_begin = NULL;
134  int32 range_str_len;
135  char *range_str;
136 
137  cache = get_multirange_io_data(fcinfo, mltrngtypoid, IOFunc_input);
138  rangetyp = cache->typcache->rngtype;
139 
140  /* consume whitespace */
141  while (*ptr != '\0' && isspace((unsigned char) *ptr))
142  ptr++;
143 
144  if (*ptr == '{')
145  ptr++;
146  else
147  ereport(ERROR,
148  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
149  errmsg("malformed multirange literal: \"%s\"",
150  input_str),
151  errdetail("Missing left brace.")));
152 
153  /* consume ranges */
154  parse_state = MULTIRANGE_BEFORE_RANGE;
155  for (; parse_state != MULTIRANGE_FINISHED; ptr++)
156  {
157  char ch = *ptr;
158 
159  if (ch == '\0')
160  ereport(ERROR,
161  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
162  errmsg("malformed multirange literal: \"%s\"",
163  input_str),
164  errdetail("Unexpected end of input.")));
165 
166  /* skip whitespace */
167  if (isspace((unsigned char) ch))
168  continue;
169 
170  switch (parse_state)
171  {
173  if (ch == '[' || ch == '(')
174  {
175  range_str_begin = ptr;
176  parse_state = MULTIRANGE_IN_RANGE;
177  }
178  else if (ch == '}' && ranges_seen == 0)
179  parse_state = MULTIRANGE_FINISHED;
180  else if (pg_strncasecmp(ptr, RANGE_EMPTY_LITERAL,
181  strlen(RANGE_EMPTY_LITERAL)) == 0)
182  {
183  ranges_seen++;
184  /* nothing to do with an empty range */
185  ptr += strlen(RANGE_EMPTY_LITERAL) - 1;
186  parse_state = MULTIRANGE_AFTER_RANGE;
187  }
188  else
189  ereport(ERROR,
190  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
191  errmsg("malformed multirange literal: \"%s\"",
192  input_str),
193  errdetail("Expected range start.")));
194  break;
195  case MULTIRANGE_IN_RANGE:
196  if (ch == ']' || ch == ')')
197  {
198  range_str_len = ptr - range_str_begin + 1;
199  range_str = pnstrdup(range_str_begin, range_str_len);
200  if (range_capacity == range_count)
201  {
202  range_capacity *= 2;
203  ranges = (RangeType **)
204  repalloc(ranges, range_capacity * sizeof(RangeType *));
205  }
206  ranges_seen++;
208  range_str,
209  cache->typioparam,
210  typmod));
211  if (!RangeIsEmpty(range))
212  ranges[range_count++] = range;
213  parse_state = MULTIRANGE_AFTER_RANGE;
214  }
215  else
216  {
217  if (ch == '"')
218  parse_state = MULTIRANGE_IN_RANGE_QUOTED;
219  else if (ch == '\\')
220  parse_state = MULTIRANGE_IN_RANGE_ESCAPED;
221 
222  /*
223  * We will include this character into range_str once we
224  * find the end of the range value.
225  */
226  }
227  break;
229 
230  /*
231  * We will include this character into range_str once we find
232  * the end of the range value.
233  */
234  parse_state = MULTIRANGE_IN_RANGE;
235  break;
237  if (ch == '"')
238  if (*(ptr + 1) == '"')
239  {
240  /* two quote marks means an escaped quote mark */
241  ptr++;
242  }
243  else
244  parse_state = MULTIRANGE_IN_RANGE;
245  else if (ch == '\\')
247 
248  /*
249  * We will include this character into range_str once we find
250  * the end of the range value.
251  */
252  break;
254  if (ch == ',')
255  parse_state = MULTIRANGE_BEFORE_RANGE;
256  else if (ch == '}')
257  parse_state = MULTIRANGE_FINISHED;
258  else
259  ereport(ERROR,
260  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
261  errmsg("malformed multirange literal: \"%s\"",
262  input_str),
263  errdetail("Expected comma or end of multirange.")));
264  break;
266 
267  /*
268  * We will include this character into range_str once we find
269  * the end of the range value.
270  */
271  parse_state = MULTIRANGE_IN_RANGE_QUOTED;
272  break;
273  default:
274  elog(ERROR, "unknown parse state: %d", parse_state);
275  }
276  }
277 
278  /* consume whitespace */
279  while (*ptr != '\0' && isspace((unsigned char) *ptr))
280  ptr++;
281 
282  if (*ptr != '\0')
283  ereport(ERROR,
284  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
285  errmsg("malformed multirange literal: \"%s\"",
286  input_str),
287  errdetail("Junk after closing right brace.")));
288 
289  ret = make_multirange(mltrngtypoid, rangetyp, range_count, ranges);
291 }
int errdetail(const char *fmt,...)
Definition: elog.c:1037
Datum InputFunctionCall(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod)
Definition: fmgr.c:1515
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:277
#define PG_GETARG_INT32(n)
Definition: fmgr.h:269
@ IOFunc_input
Definition: lsyscache.h:35
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1316
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1188
static MultirangeIOData * get_multirange_io_data(FunctionCallInfo fcinfo, Oid mltrngtypid, IOFuncSelector func)
int pg_strncasecmp(const char *s1, const char *s2, size_t n)
Definition: pgstrcasecmp.c:69
#define RANGE_EMPTY_LITERAL
Definition: rangetypes.h:32

References DatumGetRangeTypeP, elog, ereport, errcode(), errdetail(), errmsg(), ERROR, get_multirange_io_data(), InputFunctionCall(), IOFunc_input, make_multirange(), MULTIRANGE_AFTER_RANGE, MULTIRANGE_BEFORE_RANGE, MULTIRANGE_FINISHED, MULTIRANGE_IN_RANGE, MULTIRANGE_IN_RANGE_ESCAPED, MULTIRANGE_IN_RANGE_QUOTED, MULTIRANGE_IN_RANGE_QUOTED_ESCAPED, palloc(), PG_GETARG_CSTRING, PG_GETARG_INT32, PG_GETARG_OID, PG_RETURN_MULTIRANGE_P, pg_strncasecmp(), pnstrdup(), range(), RANGE_EMPTY_LITERAL, RangeIsEmpty, repalloc(), TypeCacheEntry::rngtype, MultirangeIOData::typcache, MultirangeIOData::typioparam, and MultirangeIOData::typioproc.

◆ multirange_intersect()

Datum multirange_intersect ( PG_FUNCTION_ARGS  )

Definition at line 1225 of file multirangetypes.c.

1226 {
1229  Oid mltrngtypoid = MultirangeTypeGetOid(mr1);
1230  TypeCacheEntry *typcache;
1231  TypeCacheEntry *rangetyp;
1232  int32 range_count1;
1233  int32 range_count2;
1234  RangeType **ranges1;
1235  RangeType **ranges2;
1236 
1237  typcache = multirange_get_typcache(fcinfo, mltrngtypoid);
1238  rangetyp = typcache->rngtype;
1239 
1240  if (MultirangeIsEmpty(mr1) || MultirangeIsEmpty(mr2))
1241  PG_RETURN_MULTIRANGE_P(make_empty_multirange(mltrngtypoid, rangetyp));
1242 
1243  multirange_deserialize(rangetyp, mr1, &range_count1, &ranges1);
1244  multirange_deserialize(rangetyp, mr2, &range_count2, &ranges2);
1245 
1247  rangetyp,
1248  range_count1,
1249  ranges1,
1250  range_count2,
1251  ranges2));
1252 }
MultirangeType * multirange_intersect_internal(Oid mltrngtypoid, TypeCacheEntry *rangetyp, int32 range_count1, RangeType **ranges1, int32 range_count2, RangeType **ranges2)
MultirangeType * make_empty_multirange(Oid mltrngtypoid, TypeCacheEntry *rangetyp)

References make_empty_multirange(), multirange_deserialize(), multirange_get_typcache(), multirange_intersect_internal(), MultirangeIsEmpty, MultirangeTypeGetOid, PG_GETARG_MULTIRANGE_P, PG_RETURN_MULTIRANGE_P, and TypeCacheEntry::rngtype.

◆ multirange_intersect_agg_transfn()

Datum multirange_intersect_agg_transfn ( PG_FUNCTION_ARGS  )

Definition at line 1460 of file multirangetypes.c.

1461 {
1462  MemoryContext aggContext;
1463  Oid mltrngtypoid;
1464  TypeCacheEntry *typcache;
1465  MultirangeType *result;
1466  MultirangeType *current;
1467  int32 range_count1;
1468  int32 range_count2;
1469  RangeType **ranges1;
1470  RangeType **ranges2;
1471 
1472  if (!AggCheckCallContext(fcinfo, &aggContext))
1473  elog(ERROR, "multirange_intersect_agg_transfn called in non-aggregate context");
1474 
1475  mltrngtypoid = get_fn_expr_argtype(fcinfo->flinfo, 1);
1476  if (!type_is_multirange(mltrngtypoid))
1477  elog(ERROR, "range_intersect_agg must be called with a multirange");
1478 
1479  typcache = multirange_get_typcache(fcinfo, mltrngtypoid);
1480 
1481  /* strictness ensures these are non-null */
1482  result = PG_GETARG_MULTIRANGE_P(0);
1483  current = PG_GETARG_MULTIRANGE_P(1);
1484 
1485  multirange_deserialize(typcache->rngtype, result, &range_count1, &ranges1);
1486  multirange_deserialize(typcache->rngtype, current, &range_count2, &ranges2);
1487 
1488  result = multirange_intersect_internal(mltrngtypoid,
1489  typcache->rngtype,
1490  range_count1,
1491  ranges1,
1492  range_count2,
1493  ranges2);
1494  PG_RETURN_RANGE_P(result);
1495 }
#define PG_RETURN_RANGE_P(x)
Definition: rangetypes.h:77

References AggCheckCallContext(), elog, ERROR, get_fn_expr_argtype(), multirange_deserialize(), multirange_get_typcache(), multirange_intersect_internal(), PG_GETARG_MULTIRANGE_P, PG_RETURN_RANGE_P, TypeCacheEntry::rngtype, and type_is_multirange().

◆ multirange_intersect_internal()

MultirangeType* multirange_intersect_internal ( Oid  mltrngtypoid,
TypeCacheEntry rangetyp,
int32  range_count1,
RangeType **  ranges1,
int32  range_count2,
RangeType **  ranges2 
)

Definition at line 1255 of file multirangetypes.c.

1258 {
1259  RangeType *r1;
1260  RangeType *r2;
1261  RangeType **ranges3;
1262  int32 range_count3;
1263  int32 i1;
1264  int32 i2;
1265 
1266  if (range_count1 == 0 || range_count2 == 0)
1267  return make_multirange(mltrngtypoid, rangetyp, 0, NULL);
1268 
1269  /*-----------------------------------------------
1270  * Worst case is a stitching pattern like this:
1271  *
1272  * mr1: --- --- --- ---
1273  * mr2: --- --- ---
1274  * mr3: - - - - - -
1275  *
1276  * That seems to be range_count1 + range_count2 - 1,
1277  * but one extra won't hurt.
1278  *-----------------------------------------------
1279  */
1280  ranges3 = palloc0((range_count1 + range_count2) * sizeof(RangeType *));
1281  range_count3 = 0;
1282 
1283  /*
1284  * For each range in mr1, keep intersecting until the ranges in mr2 have
1285  * passed it. The parallel progress through mr1 and mr2 is similar to
1286  * multirange_minus_multirange_internal, but we don't have to assign back
1287  * to r1.
1288  */
1289  r2 = ranges2[0];
1290  for (i1 = 0, i2 = 0; i1 < range_count1; i1++)
1291  {
1292  r1 = ranges1[i1];
1293 
1294  /* Discard r2s while r2 << r1 */
1295  while (r2 != NULL && range_before_internal(rangetyp, r2, r1))
1296  {
1297  r2 = ++i2 >= range_count2 ? NULL : ranges2[i2];
1298  }
1299 
1300  while (r2 != NULL)
1301  {
1302  if (range_overlaps_internal(rangetyp, r1, r2))
1303  {
1304  /* Keep the overlapping part */
1305  ranges3[range_count3++] = range_intersect_internal(rangetyp, r1, r2);
1306 
1307  /* If we "used up" all of r2, go to the next one... */
1308  if (range_overleft_internal(rangetyp, r2, r1))
1309  r2 = ++i2 >= range_count2 ? NULL : ranges2[i2];
1310 
1311  /* ...otherwise go to the next r1 */
1312  else
1313  break;
1314  }
1315  else
1316  /* We're past r1, so move to the next one */
1317  break;
1318  }
1319 
1320  /* If we're out of r2s, there can be no more intersections */
1321  if (r2 == NULL)
1322  break;
1323  }
1324 
1325  return make_multirange(mltrngtypoid, rangetyp, range_count3, ranges3);
1326 }
bool range_overlaps_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:823
bool range_overleft_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:869
RangeType * range_intersect_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:1125

References make_multirange(), palloc0(), range_before_internal(), range_intersect_internal(), range_overlaps_internal(), and range_overleft_internal().

Referenced by multirange_intersect(), and multirange_intersect_agg_transfn().

◆ multirange_le()

Datum multirange_le ( PG_FUNCTION_ARGS  )

Definition at line 2643 of file multirangetypes.c.

2644 {
2645  int cmp = multirange_cmp(fcinfo);
2646 
2647  PG_RETURN_BOOL(cmp <= 0);
2648 }

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

◆ multirange_lower()

Datum multirange_lower ( PG_FUNCTION_ARGS  )

Definition at line 1502 of file multirangetypes.c.

1503 {
1505  TypeCacheEntry *typcache;
1506  RangeBound lower;
1507  RangeBound upper;
1508 
1509  if (MultirangeIsEmpty(mr))
1510  PG_RETURN_NULL();
1511 
1512  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr));
1513 
1514  multirange_get_bounds(typcache->rngtype, mr, 0,
1515  &lower, &upper);
1516 
1517  if (!lower.infinite)
1518  PG_RETURN_DATUM(lower.val);
1519  else
1520  PG_RETURN_NULL();
1521 }
#define PG_RETURN_NULL()
Definition: fmgr.h:345
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:353

References lower(), multirange_get_bounds(), multirange_get_typcache(), MultirangeIsEmpty, MultirangeTypeGetOid, PG_GETARG_MULTIRANGE_P, PG_RETURN_DATUM, PG_RETURN_NULL, TypeCacheEntry::rngtype, and upper().

◆ multirange_lower_inc()

Datum multirange_lower_inc ( PG_FUNCTION_ARGS  )

Definition at line 1560 of file multirangetypes.c.

1561 {
1563  TypeCacheEntry *typcache;
1564  RangeBound lower;
1565  RangeBound upper;
1566 
1567  if (MultirangeIsEmpty(mr))
1568  PG_RETURN_BOOL(false);
1569 
1570  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr));
1571  multirange_get_bounds(typcache->rngtype, mr, 0,
1572  &lower, &upper);
1573 
1574  PG_RETURN_BOOL(lower.inclusive);
1575 }

References lower(), multirange_get_bounds(), multirange_get_typcache(), MultirangeIsEmpty, MultirangeTypeGetOid, PG_GETARG_MULTIRANGE_P, PG_RETURN_BOOL, TypeCacheEntry::rngtype, and upper().

◆ multirange_lower_inf()

Datum multirange_lower_inf ( PG_FUNCTION_ARGS  )

Definition at line 1598 of file multirangetypes.c.

1599 {
1601  TypeCacheEntry *typcache;
1602  RangeBound lower;
1603  RangeBound upper;
1604 
1605  if (MultirangeIsEmpty(mr))
1606  PG_RETURN_BOOL(false);
1607 
1608  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr));
1609  multirange_get_bounds(typcache->rngtype, mr, 0,
1610  &lower, &upper);
1611 
1612  PG_RETURN_BOOL(lower.infinite);
1613 }

References lower(), multirange_get_bounds(), multirange_get_typcache(), MultirangeIsEmpty, MultirangeTypeGetOid, PG_GETARG_MULTIRANGE_P, PG_RETURN_BOOL, TypeCacheEntry::rngtype, and upper().

◆ multirange_lt()

Datum multirange_lt ( PG_FUNCTION_ARGS  )

Definition at line 2635 of file multirangetypes.c.

2636 {
2637  int cmp = multirange_cmp(fcinfo);
2638 
2639  PG_RETURN_BOOL(cmp < 0);
2640 }

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

◆ multirange_minus()

Datum multirange_minus ( PG_FUNCTION_ARGS  )

Definition at line 1109 of file multirangetypes.c.

1110 {
1113  Oid mltrngtypoid = MultirangeTypeGetOid(mr1);
1114  TypeCacheEntry *typcache;
1115  TypeCacheEntry *rangetyp;
1116  int32 range_count1;
1117  int32 range_count2;
1118  RangeType **ranges1;
1119  RangeType **ranges2;
1120 
1121  typcache = multirange_get_typcache(fcinfo, mltrngtypoid);
1122  rangetyp = typcache->rngtype;
1123 
1124  if (MultirangeIsEmpty(mr1) || MultirangeIsEmpty(mr2))
1126 
1127  multirange_deserialize(typcache->rngtype, mr1, &range_count1, &ranges1);
1128  multirange_deserialize(typcache->rngtype, mr2, &range_count2, &ranges2);
1129 
1131  rangetyp,
1132  range_count1,
1133  ranges1,
1134  range_count2,
1135  ranges2));
1136 }
MultirangeType * multirange_minus_internal(Oid mltrngtypoid, TypeCacheEntry *rangetyp, int32 range_count1, RangeType **ranges1, int32 range_count2, RangeType **ranges2)

References multirange_deserialize(), multirange_get_typcache(), multirange_minus_internal(), MultirangeIsEmpty, MultirangeTypeGetOid, PG_GETARG_MULTIRANGE_P, PG_RETURN_MULTIRANGE_P, and TypeCacheEntry::rngtype.

◆ multirange_minus_internal()

MultirangeType* multirange_minus_internal ( Oid  mltrngtypoid,
TypeCacheEntry rangetyp,
int32  range_count1,
RangeType **  ranges1,
int32  range_count2,
RangeType **  ranges2 
)

Definition at line 1139 of file multirangetypes.c.

1142 {
1143  RangeType *r1;
1144  RangeType *r2;
1145  RangeType **ranges3;
1146  int32 range_count3;
1147  int32 i1;
1148  int32 i2;
1149 
1150  /*
1151  * Worst case: every range in ranges1 makes a different cut to some range
1152  * in ranges2.
1153  */
1154  ranges3 = palloc0((range_count1 + range_count2) * sizeof(RangeType *));
1155  range_count3 = 0;
1156 
1157  /*
1158  * For each range in mr1, keep subtracting until it's gone or the ranges
1159  * in mr2 have passed it. After a subtraction we assign what's left back
1160  * to r1. The parallel progress through mr1 and mr2 is similar to
1161  * multirange_overlaps_multirange_internal.
1162  */
1163  r2 = ranges2[0];
1164  for (i1 = 0, i2 = 0; i1 < range_count1; i1++)
1165  {
1166  r1 = ranges1[i1];
1167 
1168  /* Discard r2s while r2 << r1 */
1169  while (r2 != NULL && range_before_internal(rangetyp, r2, r1))
1170  {
1171  r2 = ++i2 >= range_count2 ? NULL : ranges2[i2];
1172  }
1173 
1174  while (r2 != NULL)
1175  {
1176  if (range_split_internal(rangetyp, r1, r2, &ranges3[range_count3], &r1))
1177  {
1178  /*
1179  * If r2 takes a bite out of the middle of r1, we need two
1180  * outputs
1181  */
1182  range_count3++;
1183  r2 = ++i2 >= range_count2 ? NULL : ranges2[i2];
1184  }
1185  else if (range_overlaps_internal(rangetyp, r1, r2))
1186  {
1187  /*
1188  * If r2 overlaps r1, replace r1 with r1 - r2.
1189  */
1190  r1 = range_minus_internal(rangetyp, r1, r2);
1191 
1192  /*
1193  * If r2 goes past r1, then we need to stay with it, in case
1194  * it hits future r1s. Otherwise we need to keep r1, in case
1195  * future r2s hit it. Since we already subtracted, there's no
1196  * point in using the overright/overleft calls.
1197  */
1198  if (RangeIsEmpty(r1) || range_before_internal(rangetyp, r1, r2))
1199  break;
1200  else
1201  r2 = ++i2 >= range_count2 ? NULL : ranges2[i2];
1202  }
1203  else
1204  {
1205  /*
1206  * This and all future r2s are past r1, so keep them. Also
1207  * assign whatever is left of r1 to the result.
1208  */
1209  break;
1210  }
1211  }
1212 
1213  /*
1214  * Nothing else can remove anything from r1, so keep it. Even if r1 is
1215  * empty here, make_multirange will remove it.
1216  */
1217  ranges3[range_count3++] = r1;
1218  }
1219 
1220  return make_multirange(mltrngtypoid, rangetyp, range_count3, ranges3);
1221 }
bool range_split_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2, RangeType **output1, RangeType **output2)
Definition: rangetypes.c:1164
RangeType * range_minus_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
Definition: rangetypes.c:975

References make_multirange(), palloc0(), range_before_internal(), range_minus_internal(), range_overlaps_internal(), range_split_internal(), and RangeIsEmpty.

Referenced by multirange_minus().

◆ multirange_ne()

Datum multirange_ne ( PG_FUNCTION_ARGS  )

Definition at line 1918 of file multirangetypes.c.

1919 {
1922  TypeCacheEntry *typcache;
1923 
1924  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr1));
1925 
1926  PG_RETURN_BOOL(multirange_ne_internal(typcache->rngtype, mr1, mr2));
1927 }
bool multirange_ne_internal(TypeCacheEntry *rangetyp, const MultirangeType *mr1, const MultirangeType *mr2)

References multirange_get_typcache(), multirange_ne_internal(), MultirangeTypeGetOid, PG_GETARG_MULTIRANGE_P, PG_RETURN_BOOL, and TypeCacheEntry::rngtype.

◆ multirange_ne_internal()

bool multirange_ne_internal ( TypeCacheEntry rangetyp,
const MultirangeType mr1,
const MultirangeType mr2 
)

Definition at line 1909 of file multirangetypes.c.

1912 {
1913  return (!multirange_eq_internal(rangetyp, mr1, mr2));
1914 }

References multirange_eq_internal().

Referenced by multirange_ne().

◆ multirange_out()

Datum multirange_out ( PG_FUNCTION_ARGS  )

Definition at line 294 of file multirangetypes.c.

295 {
296  MultirangeType *multirange = PG_GETARG_MULTIRANGE_P(0);
297  Oid mltrngtypoid = MultirangeTypeGetOid(multirange);
298  MultirangeIOData *cache;
300  RangeType *range;
301  char *rangeStr;
302  int32 range_count;
303  int32 i;
304  RangeType **ranges;
305 
306  cache = get_multirange_io_data(fcinfo, mltrngtypoid, IOFunc_output);
307 
309 
310  appendStringInfoChar(&buf, '{');
311 
312  multirange_deserialize(cache->typcache->rngtype, multirange, &range_count, &ranges);
313  for (i = 0; i < range_count; i++)
314  {
315  if (i > 0)
316  appendStringInfoChar(&buf, ',');
317  range = ranges[i];
319  appendStringInfoString(&buf, rangeStr);
320  }
321 
322  appendStringInfoChar(&buf, '}');
323 
324  PG_RETURN_CSTRING(buf.data);
325 }
char * OutputFunctionCall(FmgrInfo *flinfo, Datum val)
Definition: fmgr.c:1559
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:362
@ IOFunc_output
Definition: lsyscache.h:36
static char * buf
Definition: pg_test_fsync.c:67
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59

References appendStringInfoChar(), appendStringInfoString(), buf, get_multirange_io_data(), i, initStringInfo(), IOFunc_output, multirange_deserialize(), MultirangeTypeGetOid, OutputFunctionCall(), PG_GETARG_MULTIRANGE_P, PG_RETURN_CSTRING, range(), RangeTypePGetDatum, TypeCacheEntry::rngtype, MultirangeIOData::typcache, and MultirangeIOData::typioproc.

Referenced by anycompatiblemultirange_out(), and anymultirange_out().

◆ multirange_overlaps_multirange()

Datum multirange_overlaps_multirange ( PG_FUNCTION_ARGS  )

Definition at line 1955 of file multirangetypes.c.

1956 {
1959  TypeCacheEntry *typcache;
1960 
1961  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr1));
1962 
1964 }
bool multirange_overlaps_multirange_internal(TypeCacheEntry *rangetyp, const MultirangeType *mr1, const MultirangeType *mr2)

References multirange_get_typcache(), multirange_overlaps_multirange_internal(), MultirangeTypeGetOid, PG_GETARG_MULTIRANGE_P, PG_RETURN_BOOL, and TypeCacheEntry::rngtype.

◆ multirange_overlaps_multirange_internal()

bool multirange_overlaps_multirange_internal ( TypeCacheEntry rangetyp,
const MultirangeType mr1,
const MultirangeType mr2 
)

Definition at line 2010 of file multirangetypes.c.

2013 {
2014  int32 range_count1;
2015  int32 range_count2;
2016  int32 i1;
2017  int32 i2;
2018  RangeBound lower1,
2019  upper1,
2020  lower2,
2021  upper2;
2022 
2023  /*
2024  * Empties never overlap, even with empties. (This seems strange since
2025  * they *do* contain each other, but we want to follow how ranges work.)
2026  */
2027  if (MultirangeIsEmpty(mr1) || MultirangeIsEmpty(mr2))
2028  return false;
2029 
2030  range_count1 = mr1->rangeCount;
2031  range_count2 = mr2->rangeCount;
2032 
2033  /*
2034  * Every range in mr1 gets a chance to overlap with the ranges in mr2, but
2035  * we can use their ordering to avoid O(n^2). This is similar to
2036  * range_overlaps_multirange where r1 : r2 :: mrr : r, but there if we
2037  * don't find an overlap with r we're done, and here if we don't find an
2038  * overlap with r2 we try the next r2.
2039  */
2040  i1 = 0;
2041  multirange_get_bounds(rangetyp, mr1, i1, &lower1, &upper1);
2042  for (i1 = 0, i2 = 0; i2 < range_count2; i2++)
2043  {
2044  multirange_get_bounds(rangetyp, mr2, i2, &lower2, &upper2);
2045 
2046  /* Discard r1s while r1 << r2 */
2047  while (range_cmp_bounds(rangetyp, &upper1, &lower2) < 0)
2048  {
2049  if (++i1 >= range_count1)
2050  return false;
2051  multirange_get_bounds(rangetyp, mr1, i1, &lower1, &upper1);
2052  }
2053 
2054  /*
2055  * If r1 && r2, we're done, otherwise we failed to find an overlap for
2056  * r2, so go to the next one.
2057  */
2058  if (range_bounds_overlaps(rangetyp, &lower1, &upper1, &lower2, &upper2))
2059  return true;
2060  }
2061 
2062  /* We looked through all of mr2 without finding an overlap */
2063  return false;
2064 }
static bool range_bounds_overlaps(TypeCacheEntry *typcache, RangeBound *lower1, RangeBound *upper1, RangeBound *lower2, RangeBound *upper2)

References multirange_get_bounds(), MultirangeIsEmpty, range_bounds_overlaps(), range_cmp_bounds(), and MultirangeType::rangeCount.

Referenced by multirange_overlaps_multirange().

◆ multirange_overlaps_range()

Datum multirange_overlaps_range ( PG_FUNCTION_ARGS  )

Definition at line 1943 of file multirangetypes.c.

1944 {
1946  RangeType *r = PG_GETARG_RANGE_P(1);
1947  TypeCacheEntry *typcache;
1948 
1949  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr));
1950 
1952 }
bool range_overlaps_multirange_internal(TypeCacheEntry *rangetyp, const RangeType *r, const MultirangeType *mr)

References multirange_get_typcache(), MultirangeTypeGetOid, PG_GETARG_MULTIRANGE_P, PG_GETARG_RANGE_P, PG_RETURN_BOOL, range_overlaps_multirange_internal(), and TypeCacheEntry::rngtype.

◆ multirange_overleft_multirange()

Datum multirange_overleft_multirange ( PG_FUNCTION_ARGS  )

Definition at line 2128 of file multirangetypes.c.

2129 {
2132  TypeCacheEntry *typcache;
2133  RangeBound lower1,
2134  upper1,
2135  lower2,
2136  upper2;
2137 
2138  if (MultirangeIsEmpty(mr1) || MultirangeIsEmpty(mr2))
2139  PG_RETURN_BOOL(false);
2140 
2141  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr1));
2142 
2143  multirange_get_bounds(typcache->rngtype, mr1, mr1->rangeCount - 1,
2144  &lower1, &upper1);
2145  multirange_get_bounds(typcache->rngtype, mr2, mr2->rangeCount - 1,
2146  &lower2, &upper2);
2147 
2148  PG_RETURN_BOOL(range_cmp_bounds(typcache->rngtype, &upper1, &upper2) <= 0);
2149 }

References multirange_get_bounds(), multirange_get_typcache(), MultirangeIsEmpty, MultirangeTypeGetOid, PG_GETARG_MULTIRANGE_P, PG_RETURN_BOOL, range_cmp_bounds(), MultirangeType::rangeCount, and TypeCacheEntry::rngtype.

◆ multirange_overleft_range()

Datum multirange_overleft_range ( PG_FUNCTION_ARGS  )

Definition at line 2103 of file multirangetypes.c.

2104 {
2106  RangeType *r = PG_GETARG_RANGE_P(1);
2107  TypeCacheEntry *typcache;
2108  RangeBound lower1,
2109  upper1,
2110  lower2,
2111  upper2;
2112  bool empty;
2113 
2114  if (MultirangeIsEmpty(mr) || RangeIsEmpty(r))
2115  PG_RETURN_BOOL(false);
2116 
2117  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr));
2118 
2119  multirange_get_bounds(typcache->rngtype, mr, mr->rangeCount - 1,
2120  &lower1, &upper1);
2121  range_deserialize(typcache->rngtype, r, &lower2, &upper2, &empty);
2122  Assert(!empty);
2123 
2124  PG_RETURN_BOOL(range_cmp_bounds(typcache->rngtype, &upper1, &upper2) <= 0);
2125 }

References Assert(), multirange_get_bounds(), multirange_get_typcache(), MultirangeIsEmpty, MultirangeTypeGetOid, PG_GETARG_MULTIRANGE_P, PG_GETARG_RANGE_P, PG_RETURN_BOOL, range_cmp_bounds(), range_deserialize(), MultirangeType::rangeCount, RangeIsEmpty, and TypeCacheEntry::rngtype.

◆ multirange_overright_multirange()

Datum multirange_overright_multirange ( PG_FUNCTION_ARGS  )

Definition at line 2210 of file multirangetypes.c.

2211 {
2214  TypeCacheEntry *typcache;
2215  RangeBound lower1,
2216  upper1,
2217  lower2,
2218  upper2;
2219 
2220  if (MultirangeIsEmpty(mr1) || MultirangeIsEmpty(mr2))
2221  PG_RETURN_BOOL(false);
2222 
2223  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr1));
2224 
2225  multirange_get_bounds(typcache->rngtype, mr1, 0, &lower1, &upper1);
2226  multirange_get_bounds(typcache->rngtype, mr2, 0, &lower2, &upper2);
2227 
2228  PG_RETURN_BOOL(range_cmp_bounds(typcache->rngtype, &lower1, &lower2) >= 0);
2229 }

References multirange_get_bounds(), multirange_get_typcache(), MultirangeIsEmpty, MultirangeTypeGetOid, PG_GETARG_MULTIRANGE_P, PG_RETURN_BOOL, range_cmp_bounds(), and TypeCacheEntry::rngtype.

◆ multirange_overright_range()

Datum multirange_overright_range ( PG_FUNCTION_ARGS  )

Definition at line 2186 of file multirangetypes.c.

2187 {
2189  RangeType *r = PG_GETARG_RANGE_P(1);
2190  TypeCacheEntry *typcache;
2191  RangeBound lower1,
2192  upper1,
2193  lower2,
2194  upper2;
2195  bool empty;
2196 
2197  if (MultirangeIsEmpty(mr) || RangeIsEmpty(r))
2198  PG_RETURN_BOOL(false);
2199 
2200  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr));
2201 
2202  multirange_get_bounds(typcache->rngtype, mr, 0, &lower1, &upper1);
2203  range_deserialize(typcache->rngtype, r, &lower2, &upper2, &empty);
2204  Assert(!empty);
2205 
2206  PG_RETURN_BOOL(range_cmp_bounds(typcache->rngtype, &lower1, &lower2) >= 0);
2207 }

References Assert(), multirange_get_bounds(), multirange_get_typcache(), MultirangeIsEmpty, MultirangeTypeGetOid, PG_GETARG_MULTIRANGE_P, PG_GETARG_RANGE_P, PG_RETURN_BOOL, range_cmp_bounds(), range_deserialize(), RangeIsEmpty, and TypeCacheEntry::rngtype.

◆ multirange_range_contains_bsearch_comparison()

static int multirange_range_contains_bsearch_comparison ( TypeCacheEntry typcache,
RangeBound lower,
RangeBound upper,
void *  key,
bool match 
)
static

Definition at line 1769 of file multirangetypes.c.

1772 {
1773  RangeBound *keyLower = (RangeBound *) key;
1774  RangeBound *keyUpper = (RangeBound *) key + 1;
1775 
1776  /* Check if key range is strictly in the left or in the right */
1777  if (range_cmp_bounds(typcache, keyUpper, lower) < 0)
1778  return -1;
1779  if (range_cmp_bounds(typcache, keyLower, upper) > 0)
1780  return 1;
1781 
1782  /*
1783  * At this point we found overlapping range. But we have to check if it
1784  * really contains the key range. Anyway, we have to stop our search
1785  * here, because multirange contains only non-overlapping ranges.
1786  */
1787  *match = range_bounds_contains(typcache, lower, upper, keyLower, keyUpper);
1788 
1789  return 0;
1790 }

References sort-test::key, lower(), range_bounds_contains(), range_cmp_bounds(), and upper().

Referenced by multirange_contains_range_internal().

◆ multirange_range_overlaps_bsearch_comparison()

static int multirange_range_overlaps_bsearch_comparison ( TypeCacheEntry typcache,
RangeBound lower,
RangeBound upper,
void *  key,
bool match 
)
static

Definition at line 1971 of file multirangetypes.c.

1974 {
1975  RangeBound *keyLower = (RangeBound *) key;
1976  RangeBound *keyUpper = (RangeBound *) key + 1;
1977 
1978  if (range_cmp_bounds(typcache, keyUpper, lower) < 0)
1979  return -1;
1980  if (range_cmp_bounds(typcache, keyLower, upper) > 0)
1981  return 1;
1982 
1983  *match = true;
1984  return 0;
1985 }

References sort-test::key, lower(), range_cmp_bounds(), and upper().

Referenced by range_overlaps_multirange_internal().

◆ multirange_recv()

Datum multirange_recv ( PG_FUNCTION_ARGS  )

Definition at line 332 of file multirangetypes.c.

333 {
335  Oid mltrngtypoid = PG_GETARG_OID(1);
336  int32 typmod = PG_GETARG_INT32(2);
337  MultirangeIOData *cache;
338  uint32 range_count;
339  RangeType **ranges;
340  MultirangeType *ret;
342 
343  cache = get_multirange_io_data(fcinfo, mltrngtypoid, IOFunc_receive);
344 
345  range_count = pq_getmsgint(buf, 4);
346  ranges = palloc(range_count * sizeof(RangeType *));
347 
349  for (int i = 0; i < range_count; i++)
350  {
351  uint32 range_len = pq_getmsgint(buf, 4);
352  const char *range_data = pq_getmsgbytes(buf, range_len);
353 
355  appendBinaryStringInfo(&tmpbuf, range_data, range_len);
356 
358  &tmpbuf,
359  cache->typioparam,
360  typmod));
361  }
362  pfree(tmpbuf.data);
363 
364  pq_getmsgend(buf);
365 
366  ret = make_multirange(mltrngtypoid, cache->typcache->rngtype,
367  range_count, ranges);
369 }
Datum ReceiveFunctionCall(FmgrInfo *flinfo, StringInfo buf, Oid typioparam, int32 typmod)
Definition: fmgr.c:1573
void pfree(void *pointer)
Definition: mcxt.c:1175
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition: pqformat.c:417
void pq_getmsgend(StringInfo msg)
Definition: pqformat.c:637
const char * pq_getmsgbytes(StringInfo msg, int datalen)
Definition: pqformat.c:510
void resetStringInfo(StringInfo str)
Definition: stringinfo.c:75
void appendBinaryStringInfo(StringInfo str, const char *data, int datalen)
Definition: stringinfo.c:227
StringInfoData * StringInfo
Definition: stringinfo.h:44
static StringInfoData tmpbuf
Definition: walsender.c:160

References appendBinaryStringInfo(), buf, StringInfoData::data, DatumGetRangeTypeP, get_multirange_io_data(), i, initStringInfo(), IOFunc_receive, make_multirange(), palloc(), pfree(), PG_GETARG_INT32, PG_GETARG_OID, PG_GETARG_POINTER, PG_RETURN_MULTIRANGE_P, pq_getmsgbytes(), pq_getmsgend(), pq_getmsgint(), ReceiveFunctionCall(), resetStringInfo(), TypeCacheEntry::rngtype, tmpbuf, MultirangeIOData::typcache, MultirangeIOData::typioparam, and MultirangeIOData::typioproc.

◆ multirange_send()

Datum multirange_send ( PG_FUNCTION_ARGS  )

Definition at line 372 of file multirangetypes.c.

373 {
374  MultirangeType *multirange = PG_GETARG_MULTIRANGE_P(0);
375  Oid mltrngtypoid = MultirangeTypeGetOid(multirange);
377  RangeType **ranges;
378  int32 range_count;
379  MultirangeIOData *cache;
380 
381  cache = get_multirange_io_data(fcinfo, mltrngtypoid, IOFunc_send);
382 
383  /* construct output */
385 
386  pq_sendint32(buf, multirange->rangeCount);
387 
388  multirange_deserialize(cache->typcache->rngtype, multirange, &range_count, &ranges);
389  for (int i = 0; i < range_count; i++)
390  {
391  Datum range;
392 
393  range = RangeTypePGetDatum(ranges[i]);
395 
398  }
399 
401 }
#define VARHDRSZ
Definition: c.h:627
bytea * SendFunctionCall(FmgrInfo *flinfo, Datum val)
Definition: fmgr.c:1620
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:371
@ IOFunc_send
Definition: lsyscache.h:38
#define VARDATA(PTR)
Definition: postgres.h:315
#define VARSIZE(PTR)
Definition: postgres.h:316
#define PointerGetDatum(X)
Definition: postgres.h:600
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:328
void pq_sendbytes(StringInfo buf, const char *data, int datalen)
Definition: pqformat.c:125
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:348
static void pq_sendint32(StringInfo buf, uint32 i)
Definition: pqformat.h:145
StringInfo makeStringInfo(void)
Definition: stringinfo.c:41

References buf, get_multirange_io_data(), i, IOFunc_send, makeStringInfo(), multirange_deserialize(), MultirangeTypeGetOid, PG_GETARG_MULTIRANGE_P, PG_RETURN_BYTEA_P, PointerGetDatum, pq_begintypsend(), pq_endtypsend(), pq_sendbytes(), pq_sendint32(), range(), MultirangeType::rangeCount, RangeTypePGetDatum, TypeCacheEntry::rngtype, SendFunctionCall(), MultirangeIOData::typcache, MultirangeIOData::typioproc, VARDATA, VARHDRSZ, and VARSIZE.

◆ multirange_size_estimate()

static Size multirange_size_estimate ( TypeCacheEntry rangetyp,
int32  range_count,
RangeType **  ranges 
)
static

Definition at line 564 of file multirangetypes.c.

566 {
567  char elemalign = rangetyp->rngelemtype->typalign;
568  Size size;
569  int32 i;
570 
571  /*
572  * Count space for MultirangeType struct, items and flags.
573  */
574  size = att_align_nominal(sizeof(MultirangeType) +
575  Max(range_count - 1, 0) * sizeof(uint32) +
576  range_count * sizeof(uint8), elemalign);
577 
578  /* Count space for range bounds */
579  for (i = 0; i < range_count; i++)
580  size += att_align_nominal(VARSIZE(ranges[i]) -
581  sizeof(RangeType) -
582  sizeof(char), elemalign);
583 
584  return size;
585 }
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:148

References att_align_nominal, i, Max, TypeCacheEntry::rngelemtype, TypeCacheEntry::typalign, and VARSIZE.

Referenced by make_multirange().

◆ multirange_union()

Datum multirange_union ( PG_FUNCTION_ARGS  )

Definition at line 1077 of file multirangetypes.c.

1078 {
1081  TypeCacheEntry *typcache;
1082  int32 range_count1;
1083  int32 range_count2;
1084  int32 range_count3;
1085  RangeType **ranges1;
1086  RangeType **ranges2;
1087  RangeType **ranges3;
1088 
1089  if (MultirangeIsEmpty(mr1))
1091  if (MultirangeIsEmpty(mr2))
1093 
1094  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr1));
1095 
1096  multirange_deserialize(typcache->rngtype, mr1, &range_count1, &ranges1);
1097  multirange_deserialize(typcache->rngtype, mr2, &range_count2, &ranges2);
1098 
1099  range_count3 = range_count1 + range_count2;
1100  ranges3 = palloc0(range_count3 * sizeof(RangeType *));
1101  memcpy(ranges3, ranges1, range_count1 * sizeof(RangeType *));
1102  memcpy(ranges3 + range_count1, ranges2, range_count2 * sizeof(RangeType *));
1104  range_count3, ranges3));
1105 }

References make_multirange(), multirange_deserialize(), multirange_get_typcache(), MultirangeIsEmpty, MultirangeTypeGetOid, palloc0(), PG_GETARG_MULTIRANGE_P, PG_RETURN_MULTIRANGE_P, TypeCacheEntry::rngtype, and TypeCacheEntry::type_id.

◆ multirange_unnest()

Datum multirange_unnest ( PG_FUNCTION_ARGS  )

Definition at line 2707 of file multirangetypes.c.

2708 {
2709  typedef struct
2710  {
2711  MultirangeType *mr;
2712  TypeCacheEntry *typcache;
2713  int index;
2714  } multirange_unnest_fctx;
2715 
2716  FuncCallContext *funcctx;
2717  multirange_unnest_fctx *fctx;
2718  MemoryContext oldcontext;
2719 
2720  /* stuff done only on the first call of the function */
2721  if (SRF_IS_FIRSTCALL())
2722  {
2723  MultirangeType *mr;
2724 
2725  /* create a function context for cross-call persistence */
2726  funcctx = SRF_FIRSTCALL_INIT();
2727 
2728  /*
2729  * switch to memory context appropriate for multiple function calls
2730  */
2731  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
2732 
2733  /*
2734  * Get the multirange value and detoast if needed. We can't do this
2735  * earlier because if we have to detoast, we want the detoasted copy
2736  * to be in multi_call_memory_ctx, so it will go away when we're done
2737  * and not before. (If no detoast happens, we assume the originally
2738  * passed multirange will stick around till then.)
2739  */
2740  mr = PG_GETARG_MULTIRANGE_P(0);
2741 
2742  /* allocate memory for user context */
2743  fctx = (multirange_unnest_fctx *) palloc(sizeof(multirange_unnest_fctx));
2744 
2745  /* initialize state */
2746  fctx->mr = mr;
2747  fctx->index = 0;
2748  fctx->typcache = lookup_type_cache(MultirangeTypeGetOid(mr),
2750 
2751  funcctx->user_fctx = fctx;
2752  MemoryContextSwitchTo(oldcontext);
2753  }
2754 
2755  /* stuff done on every call of the function */
2756  funcctx = SRF_PERCALL_SETUP();
2757  fctx = funcctx->user_fctx;
2758 
2759  if (fctx->index < fctx->mr->rangeCount)
2760  {
2761  RangeType *range;
2762 
2763  range = multirange_get_range(fctx->typcache->rngtype,
2764  fctx->mr,
2765  fctx->index);
2766  fctx->index++;
2767 
2769  }
2770  else
2771  {
2772  /* do when there is no more left */
2773  SRF_RETURN_DONE(funcctx);
2774  }
2775 }
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:299
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:303
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:305
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:301
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:323
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
void * user_fctx
Definition: funcapi.h:82
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:101
Definition: type.h:90

References lookup_type_cache(), MemoryContextSwitchTo(), FuncCallContext::multi_call_memory_ctx, multirange_get_range(), MultirangeTypeGetOid, palloc(), PG_GETARG_MULTIRANGE_P, range(), RangeTypePGetDatum, SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, SRF_RETURN_NEXT, TYPECACHE_MULTIRANGE_INFO, and FuncCallContext::user_fctx.

◆ multirange_upper()

Datum multirange_upper ( PG_FUNCTION_ARGS  )

Definition at line 1525 of file multirangetypes.c.

1526 {
1528  TypeCacheEntry *typcache;
1529  RangeBound lower;
1530  RangeBound upper;
1531 
1532  if (MultirangeIsEmpty(mr))
1533  PG_RETURN_NULL();
1534 
1535  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr));
1536 
1537  multirange_get_bounds(typcache->rngtype, mr, mr->rangeCount - 1,
1538  &lower, &upper);
1539 
1540  if (!upper.infinite)
1541  PG_RETURN_DATUM(upper.val);
1542  else
1543  PG_RETURN_NULL();
1544 }

References lower(), multirange_get_bounds(), multirange_get_typcache(), MultirangeIsEmpty, MultirangeTypeGetOid, PG_GETARG_MULTIRANGE_P, PG_RETURN_DATUM, PG_RETURN_NULL, MultirangeType::rangeCount, TypeCacheEntry::rngtype, and upper().

◆ multirange_upper_inc()

Datum multirange_upper_inc ( PG_FUNCTION_ARGS  )

Definition at line 1579 of file multirangetypes.c.

1580 {
1582  TypeCacheEntry *typcache;
1583  RangeBound lower;
1584  RangeBound upper;
1585 
1586  if (MultirangeIsEmpty(mr))
1587  PG_RETURN_BOOL(false);
1588 
1589  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr));
1590  multirange_get_bounds(typcache->rngtype, mr, mr->rangeCount - 1,
1591  &lower, &upper);
1592 
1593  PG_RETURN_BOOL(upper.inclusive);
1594 }

References lower(), multirange_get_bounds(), multirange_get_typcache(), MultirangeIsEmpty, MultirangeTypeGetOid, PG_GETARG_MULTIRANGE_P, PG_RETURN_BOOL, MultirangeType::rangeCount, TypeCacheEntry::rngtype, and upper().

◆ multirange_upper_inf()

Datum multirange_upper_inf ( PG_FUNCTION_ARGS  )

Definition at line 1617 of file multirangetypes.c.

1618 {
1620  TypeCacheEntry *typcache;
1621  RangeBound lower;
1622  RangeBound upper;
1623 
1624  if (MultirangeIsEmpty(mr))
1625  PG_RETURN_BOOL(false);
1626 
1627  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr));
1628  multirange_get_bounds(typcache->rngtype, mr, mr->rangeCount - 1,
1629  &lower, &upper);
1630 
1631  PG_RETURN_BOOL(upper.infinite);
1632 }

References lower(), multirange_get_bounds(), multirange_get_typcache(), MultirangeIsEmpty, MultirangeTypeGetOid, PG_GETARG_MULTIRANGE_P, PG_RETURN_BOOL, MultirangeType::rangeCount, TypeCacheEntry::rngtype, and upper().

◆ range_adjacent_multirange()

◆ range_adjacent_multirange_internal()

bool range_adjacent_multirange_internal ( TypeCacheEntry rangetyp,
const RangeType r,
const MultirangeType mr 
)

Definition at line 2466 of file multirangetypes.c.

2469 {
2470  RangeBound lower1,
2471  upper1,
2472  lower2,
2473  upper2;
2474  bool empty;
2475  int32 range_count;
2476 
2477  if (RangeIsEmpty(r) || MultirangeIsEmpty(mr))
2478  return false;
2479 
2480  range_deserialize(rangetyp, r, &lower1, &upper1, &empty);
2481  Assert(!empty);
2482 
2483  range_count = mr->rangeCount;
2484  multirange_get_bounds(rangetyp, mr, 0,
2485  &lower2, &upper2);
2486 
2487  if (bounds_adjacent(rangetyp, upper1, lower2))
2488  return true;
2489 
2490  if (range_count > 1)
2491  multirange_get_bounds(rangetyp, mr, range_count - 1,
2492  &lower2, &upper2);
2493 
2494  if (bounds_adjacent(rangetyp, upper2, lower1))
2495  return true;
2496 
2497  return false;
2498 }

References Assert(), bounds_adjacent(), multirange_get_bounds(), MultirangeIsEmpty, range_deserialize(), MultirangeType::rangeCount, and RangeIsEmpty.

Referenced by multirange_adjacent_range(), range_adjacent_multirange(), range_gist_consistent_int_multirange(), and range_gist_consistent_leaf_multirange().

◆ range_after_multirange()

◆ range_after_multirange_internal()

bool range_after_multirange_internal ( TypeCacheEntry rangetyp,
const RangeType r,
const MultirangeType mr 
)

Definition at line 2441 of file multirangetypes.c.

2444 {
2445  RangeBound lower1,
2446  upper1,
2447  lower2,
2448  upper2;
2449  bool empty;
2450  int32 range_count;
2451 
2452  if (RangeIsEmpty(r) || MultirangeIsEmpty(mr))
2453  return false;
2454 
2455  range_deserialize(rangetyp, r, &lower1, &upper1, &empty);
2456  Assert(!empty);
2457 
2458  range_count = mr->rangeCount;
2459  multirange_get_bounds(rangetyp, mr, range_count - 1,
2460  &lower2, &upper2);
2461 
2462  return (range_cmp_bounds(rangetyp, &lower1, &upper2) > 0);
2463 }

References Assert(), multirange_get_bounds(), MultirangeIsEmpty, range_cmp_bounds(), range_deserialize(), MultirangeType::rangeCount, and RangeIsEmpty.

Referenced by multirange_before_range(), range_after_multirange(), range_gist_consistent_int_multirange(), and range_gist_consistent_leaf_multirange().

◆ range_agg_finalfn()

Datum range_agg_finalfn ( PG_FUNCTION_ARGS  )

Definition at line 1367 of file multirangetypes.c.

1368 {
1369  MemoryContext aggContext;
1370  Oid mltrngtypoid;
1371  TypeCacheEntry *typcache;
1373  int32 range_count;
1374  RangeType **ranges;
1375  int i;
1376 
1377  if (!AggCheckCallContext(fcinfo, &aggContext))
1378  elog(ERROR, "range_agg_finalfn called in non-aggregate context");
1379 
1380  state = PG_ARGISNULL(0) ? NULL : (ArrayBuildState *) PG_GETARG_POINTER(0);
1381  if (state == NULL)
1382  /* This shouldn't be possible, but just in case.... */
1383  PG_RETURN_NULL();
1384 
1385  /* Also return NULL if we had zero inputs, like other aggregates */
1386  range_count = state->nelems;
1387  if (range_count == 0)
1388  PG_RETURN_NULL();
1389 
1390  mltrngtypoid = get_fn_expr_rettype(fcinfo->flinfo);
1391  typcache = multirange_get_typcache(fcinfo, mltrngtypoid);
1392 
1393  ranges = palloc0(range_count * sizeof(RangeType *));
1394  for (i = 0; i < range_count; i++)
1395  ranges[i] = DatumGetRangeTypeP(state->dvalues[i]);
1396 
1397  PG_RETURN_MULTIRANGE_P(make_multirange(mltrngtypoid, typcache->rngtype, range_count, ranges));
1398 }

References AggCheckCallContext(), DatumGetRangeTypeP, elog, ERROR, get_fn_expr_rettype(), i, make_multirange(), multirange_get_typcache(), palloc0(), PG_ARGISNULL, PG_GETARG_POINTER, PG_RETURN_MULTIRANGE_P, PG_RETURN_NULL, and TypeCacheEntry::rngtype.

◆ range_agg_transfn()

Datum range_agg_transfn ( PG_FUNCTION_ARGS  )

Definition at line 1335 of file multirangetypes.c.

1336 {
1337  MemoryContext aggContext;
1338  Oid rngtypoid;
1340 
1341  if (!AggCheckCallContext(fcinfo, &aggContext))
1342  elog(ERROR, "range_agg_transfn called in non-aggregate context");
1343 
1344  rngtypoid = get_fn_expr_argtype(fcinfo->flinfo, 1);
1345  if (!type_is_range(rngtypoid))
1346  elog(ERROR, "range_agg must be called with a range");
1347 
1348  if (PG_ARGISNULL(0))
1349  state = initArrayResult(rngtypoid, aggContext, false);
1350  else
1352 
1353  /* skip NULLs */
1354  if (!PG_ARGISNULL(1))
1355  accumArrayResult(state, PG_GETARG_DATUM(1), false, rngtypoid, aggContext);
1356 
1358 }
bool type_is_range(Oid typid)
Definition: lsyscache.c:2645

References accumArrayResult(), AggCheckCallContext(), elog, ERROR, get_fn_expr_argtype(), initArrayResult(), PG_ARGISNULL, PG_GETARG_DATUM, PG_GETARG_POINTER, PG_RETURN_POINTER, and type_is_range().

◆ range_before_multirange()

◆ range_before_multirange_internal()

bool range_before_multirange_internal ( TypeCacheEntry rangetyp,
const RangeType r,
const MultirangeType mr 
)

Definition at line 2397 of file multirangetypes.c.

2400 {
2401  RangeBound lower1,
2402  upper1,
2403  lower2,
2404  upper2;
2405  bool empty;
2406 
2407  if (RangeIsEmpty(r) || MultirangeIsEmpty(mr))
2408  return false;
2409 
2410  range_deserialize(rangetyp, r, &lower1, &upper1, &empty);
2411  Assert(!empty);
2412 
2413  multirange_get_bounds(rangetyp, mr, 0, &lower2, &upper2);
2414 
2415  return (range_cmp_bounds(rangetyp, &upper1, &lower2) < 0);
2416 }

References Assert(), multirange_get_bounds(), MultirangeIsEmpty, range_cmp_bounds(), range_deserialize(), and RangeIsEmpty.

Referenced by multirange_after_range(), range_before_multirange(), range_gist_consistent_int_multirange(), and range_gist_consistent_leaf_multirange().

◆ range_bounds_contains()

static bool range_bounds_contains ( TypeCacheEntry typcache,
RangeBound lower1,
RangeBound upper1,
RangeBound lower2,
RangeBound upper2 
)
static

Definition at line 873 of file multirangetypes.c.

876 {
877  if (range_cmp_bounds(typcache, lower1, lower2) <= 0 &&
878  range_cmp_bounds(typcache, upper1, upper2) >= 0)
879  return true;
880 
881  return false;
882 }

References range_cmp_bounds().

Referenced by multirange_contains_multirange_internal(), multirange_range_contains_bsearch_comparison(), and range_contains_multirange_internal().

◆ range_bounds_overlaps()

static bool range_bounds_overlaps ( TypeCacheEntry typcache,
RangeBound lower1,
RangeBound upper1,
RangeBound lower2,
RangeBound upper2 
)
static

Definition at line 853 of file multirangetypes.c.

856 {
857  if (range_cmp_bounds(typcache, lower1, lower2) >= 0 &&
858  range_cmp_bounds(typcache, lower1, upper2) <= 0)
859  return true;
860 
861  if (range_cmp_bounds(typcache, lower2, lower1) >= 0 &&
862  range_cmp_bounds(typcache, lower2, upper1) <= 0)
863  return true;
864 
865  return false;
866 }

References range_cmp_bounds().

Referenced by multirange_overlaps_multirange_internal().

◆ range_contained_by_multirange()

◆ range_contains_multirange()

◆ range_contains_multirange_internal()

bool range_contains_multirange_internal ( TypeCacheEntry rangetyp,
const RangeType r,
const MultirangeType mr 
)

Definition at line 1824 of file multirangetypes.c.

1827 {
1828  RangeBound lower1,
1829  upper1,
1830  lower2,
1831  upper2,
1832  tmp;
1833  bool empty;
1834 
1835  /*
1836  * Every range contains an infinite number of empty multiranges, even an
1837  * empty one.
1838  */
1839  if (MultirangeIsEmpty(mr))
1840  return true;
1841 
1842  if (RangeIsEmpty(r))
1843  return false;
1844 
1845  /* Range contains multirange iff it contains its union range. */
1846  range_deserialize(rangetyp, r, &lower1, &upper1, &empty);
1847  Assert(!empty);
1848  multirange_get_bounds(rangetyp, mr, 0, &lower2, &tmp);
1849  multirange_get_bounds(rangetyp, mr, mr->rangeCount - 1, &tmp, &upper2);
1850 
1851  return range_bounds_contains(rangetyp, &lower1, &upper1, &lower2, &upper2);
1852 }

References Assert(), multirange_get_bounds(), MultirangeIsEmpty, range_bounds_contains(), range_deserialize(), MultirangeType::rangeCount, and RangeIsEmpty.

Referenced by multirange_contained_by_range(), range_contains_multirange(), range_gist_consistent_int_multirange(), and range_gist_consistent_leaf_multirange().

◆ range_merge_from_multirange()

Datum range_merge_from_multirange ( PG_FUNCTION_ARGS  )

Definition at line 2670 of file multirangetypes.c.

2671 {
2673  Oid mltrngtypoid = MultirangeTypeGetOid(mr);
2674  TypeCacheEntry *typcache;
2675  RangeType *result;
2676 
2677  typcache = multirange_get_typcache(fcinfo, mltrngtypoid);
2678 
2679  if (MultirangeIsEmpty(mr))
2680  {
2681  result = make_empty_range(typcache->rngtype);
2682  }
2683  else if (mr->rangeCount == 1)
2684  {
2685  result = multirange_get_range(typcache->rngtype, mr, 0);
2686  }
2687  else
2688  {
2689  RangeBound firstLower,
2690  firstUpper,
2691  lastLower,
2692  lastUpper;
2693 
2694  multirange_get_bounds(typcache->rngtype, mr, 0,
2695  &firstLower, &firstUpper);
2696  multirange_get_bounds(typcache->rngtype, mr, mr->rangeCount - 1,
2697  &lastLower, &lastUpper);
2698 
2699  result = make_range(typcache->rngtype, &firstLower, &lastUpper, false);
2700  }
2701 
2702  PG_RETURN_RANGE_P(result);
2703 }

References make_empty_range(), make_range(), multirange_get_bounds(), multirange_get_range(), multirange_get_typcache(), MultirangeIsEmpty, MultirangeTypeGetOid, PG_GETARG_MULTIRANGE_P, PG_RETURN_RANGE_P, MultirangeType::rangeCount, and TypeCacheEntry::rngtype.

◆ range_overlaps_multirange()

◆ range_overlaps_multirange_internal()

bool range_overlaps_multirange_internal ( TypeCacheEntry rangetyp,
const RangeType r,
const MultirangeType mr 
)

Definition at line 1988 of file multirangetypes.c.

1991 {
1992  RangeBound bounds[2];
1993  bool empty;
1994 
1995  /*
1996  * Empties never overlap, even with empties. (This seems strange since
1997  * they *do* contain each other, but we want to follow how ranges work.)
1998  */
1999  if (RangeIsEmpty(r) || MultirangeIsEmpty(mr))
2000  return false;
2001 
2002  range_deserialize(rangetyp, r, &bounds[0], &bounds[1], &empty);
2003  Assert(!empty);
2004 
2005  return multirange_bsearch_match(rangetyp, mr, bounds,
2007 }
static int multirange_range_overlaps_bsearch_comparison(TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper, void *key, bool *match)

References Assert(), multirange_bsearch_match(), multirange_range_overlaps_bsearch_comparison(), MultirangeIsEmpty, range_deserialize(), and RangeIsEmpty.

Referenced by multirange_overlaps_range(), range_gist_consistent_int_multirange(), range_gist_consistent_leaf_multirange(), and range_overlaps_multirange().

◆ range_overleft_multirange()

Datum range_overleft_multirange ( PG_FUNCTION_ARGS  )

Definition at line 2091 of file multirangetypes.c.

2092 {
2093  RangeType *r = PG_GETARG_RANGE_P(0);
2095  TypeCacheEntry *typcache;
2096 
2097  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr));
2098 
2100 }
bool range_overleft_multirange_internal(TypeCacheEntry *rangetyp, const RangeType *r, const MultirangeType *mr)

References multirange_get_typcache(), MultirangeTypeGetOid, PG_GETARG_MULTIRANGE_P, PG_GETARG_RANGE_P, PG_RETURN_BOOL, range_overleft_multirange_internal(), and TypeCacheEntry::rngtype.

◆ range_overleft_multirange_internal()

bool range_overleft_multirange_internal ( TypeCacheEntry rangetyp,
const RangeType r,
const MultirangeType mr 
)

Definition at line 2068 of file multirangetypes.c.

2071 {
2072  RangeBound lower1,
2073  upper1,
2074  lower2,
2075  upper2;
2076  bool empty;
2077 
2078  if (RangeIsEmpty(r) || MultirangeIsEmpty(mr))
2079  PG_RETURN_BOOL(false);
2080 
2081 
2082  range_deserialize(rangetyp, r, &lower1, &upper1, &empty);
2083  Assert(!empty);
2084  multirange_get_bounds(rangetyp, mr, mr->rangeCount - 1,
2085  &lower2, &upper2);
2086 
2087  PG_RETURN_BOOL(range_cmp_bounds(rangetyp, &upper1, &upper2) <= 0);
2088 }

References Assert(), multirange_get_bounds(), MultirangeIsEmpty, PG_RETURN_BOOL, range_cmp_bounds(), range_deserialize(), MultirangeType::rangeCount, and RangeIsEmpty.

Referenced by range_gist_consistent_int_multirange(), range_gist_consistent_leaf_multirange(), and range_overleft_multirange().

◆ range_overright_multirange()

Datum range_overright_multirange ( PG_FUNCTION_ARGS  )

Definition at line 2174 of file multirangetypes.c.

2175 {
2176  RangeType *r = PG_GETARG_RANGE_P(0);
2178  TypeCacheEntry *typcache;
2179 
2180  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr));
2181 
2183 }
bool range_overright_multirange_internal(TypeCacheEntry *rangetyp, const RangeType *r, const MultirangeType *mr)

References multirange_get_typcache(), MultirangeTypeGetOid, PG_GETARG_MULTIRANGE_P, PG_GETARG_RANGE_P, PG_RETURN_BOOL, range_overright_multirange_internal(), and TypeCacheEntry::rngtype.

◆ range_overright_multirange_internal()

bool range_overright_multirange_internal ( TypeCacheEntry rangetyp,
const RangeType r,
const MultirangeType mr 
)

Definition at line 2153 of file multirangetypes.c.

2156 {
2157  RangeBound lower1,
2158  upper1,
2159  lower2,
2160  upper2;
2161  bool empty;
2162 
2163  if (RangeIsEmpty(r) || MultirangeIsEmpty(mr))
2164  PG_RETURN_BOOL(false);
2165 
2166  range_deserialize(rangetyp, r, &lower1, &upper1, &empty);
2167  Assert(!empty);
2168  multirange_get_bounds(rangetyp, mr, 0, &lower2, &upper2);
2169 
2170  return (range_cmp_bounds(rangetyp, &lower1, &lower2) >= 0);
2171 }

References Assert(), multirange_get_bounds(), MultirangeIsEmpty, PG_RETURN_BOOL, range_cmp_bounds(), range_deserialize(), and RangeIsEmpty.

Referenced by range_gist_consistent_int_multirange(), range_gist_consistent_leaf_multirange(), and range_overright_multirange().

◆ write_multirange_data()

static void write_multirange_data ( MultirangeType multirange,
TypeCacheEntry rangetyp,
int32  range_count,
RangeType **  ranges 
)
static

Definition at line 591 of file multirangetypes.c.

593 {
594  uint32 *items;
595  uint32 prev_offset = 0;
596  uint8 *flags;
597  int32 i;
598  Pointer begin,
599  ptr;
600  char elemalign = rangetyp->rngelemtype->typalign;
601 
602  items = MultirangeGetItemsPtr(multirange);
603  flags = MultirangeGetFlagsPtr(multirange);
604  ptr = begin = MultirangeGetBoundariesPtr(multirange, elemalign);
605  for (i = 0; i < range_count; i++)
606  {
607  uint32 len;
608 
609  if (i > 0)
610  {
611  /*
612  * Every range, except the first one, has an item. Every
613  * MULTIRANGE_ITEM_OFFSET_STRIDE item contains an offset, others
614  * contain lengths.
615  */
616  items[i - 1] = ptr - begin;
617  if ((i % MULTIRANGE_ITEM_OFFSET_STRIDE) != 0)
618  items[i - 1] -= prev_offset;
619  else
620  items[i - 1] |= MULTIRANGE_ITEM_OFF_BIT;
621  prev_offset = ptr - begin;
622  }
623  flags[i] = *((Pointer) ranges[i] + VARSIZE(ranges[i]) - sizeof(char));
624  len = VARSIZE(ranges[i]) - sizeof(RangeType) - sizeof(char);
625  memcpy(ptr, (Pointer) (ranges[i] + 1), len);
626  ptr += att_align_nominal(len, elemalign);
627  }
628 }
#define MULTIRANGE_ITEM_OFFSET_STRIDE
#define MULTIRANGE_ITEM_OFF_BIT

References att_align_nominal, i, len, MULTIRANGE_ITEM_OFF_BIT, MULTIRANGE_ITEM_OFFSET_STRIDE, MultirangeGetBoundariesPtr, MultirangeGetFlagsPtr, MultirangeGetItemsPtr, TypeCacheEntry::rngelemtype, TypeCacheEntry::typalign, and VARSIZE.

Referenced by make_multirange().