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 "nodes/nodes.h"
#include "port/pg_bitutils.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/multirangetypes.h"
#include "utils/rangetypes.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 81 of file multirangetypes.c.

◆ MULTIRANGE_ITEM_HAS_OFF

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

Definition at line 82 of file multirangetypes.c.

◆ MULTIRANGE_ITEM_OFF_BIT

#define MULTIRANGE_ITEM_OFF_BIT   0x80000000

Definition at line 80 of file multirangetypes.c.

◆ MULTIRANGE_ITEM_OFFSET_STRIDE

#define MULTIRANGE_ITEM_OFFSET_STRIDE   4

Definition at line 83 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:506
char * Pointer
Definition: c.h:483
unsigned char uint8
Definition: c.h:504

Definition at line 75 of file multirangetypes.c.

◆ MultirangeGetFlagsPtr

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

Definition at line 73 of file multirangetypes.c.

◆ MultirangeGetItemsPtr

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

Definition at line 71 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 85 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 56 of file multirangetypes.c.

57 {
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 1658 of file multirangetypes.c.

1659 {
1660  Datum val = PG_GETARG_DATUM(0);
1662  TypeCacheEntry *typcache;
1663 
1664  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr));
1665 
1667 }
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:268
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
long val
Definition: informix.c:670
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:64
struct TypeCacheEntry * rngtype
Definition: typcache.h:108

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 416 of file multirangetypes.c.

417 {
418  MultirangeIOData *cache = (MultirangeIOData *) fcinfo->flinfo->fn_extra;
419 
420  if (cache == NULL || cache->typcache->type_id != mltrngtypid)
421  {
422  Oid typiofunc;
423  int16 typlen;
424  bool typbyval;
425  char typalign;
426  char typdelim;
427 
428  cache = (MultirangeIOData *) MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
429  sizeof(MultirangeIOData));
431  if (cache->typcache->rngtype == NULL)
432  elog(ERROR, "type %u is not a multirange type", mltrngtypid);
433 
434  /* get_type_io_data does more than we need, but is convenient */
436  func,
437  &typlen,
438  &typbyval,
439  &typalign,
440  &typdelim,
441  &cache->typioparam,
442  &typiofunc);
443 
444  if (!OidIsValid(typiofunc))
445  {
446  /* this could only happen for receive or send */
447  if (func == IOFunc_receive)
448  ereport(ERROR,
449  (errcode(ERRCODE_UNDEFINED_FUNCTION),
450  errmsg("no binary input function available for type %s",
451  format_type_be(cache->typcache->rngtype->type_id))));
452  else
453  ereport(ERROR,
454  (errcode(ERRCODE_UNDEFINED_FUNCTION),
455  errmsg("no binary output function available for type %s",
456  format_type_be(cache->typcache->rngtype->type_id))));
457  }
458  fmgr_info_cxt(typiofunc, &cache->typioproc,
459  fcinfo->flinfo->fn_mcxt);
460 
461  fcinfo->flinfo->fn_extra = (void *) cache;
462  }
463 
464  return cache;
465 }
signed short int16
Definition: c.h:493
#define OidIsValid(objectId)
Definition: c.h:775
int errcode(int sqlerrcode)
Definition: elog.c:857
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:224
#define ereport(elevel,...)
Definition: elog.h:149
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:137
char * format_type_be(Oid type_oid)
Definition: format_type.c:343
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
void get_type_io_data(Oid typid, IOFuncSelector which_func, int16 *typlen, bool *typbyval, char *typalign, char *typdelim, Oid *typioparam, Oid *func)
Definition: lsyscache.c:2325
@ IOFunc_receive
Definition: lsyscache.h:37
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1180
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:346
#define TYPECACHE_MULTIRANGE_INFO
Definition: typcache.h:153

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 2787 of file multirangetypes.c.

2788 {
2790  uint32 result = 1;
2791  TypeCacheEntry *typcache,
2792  *scache;
2793  int32 range_count,
2794  i;
2795 
2796  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr));
2797  scache = typcache->rngtype->rngelemtype;
2798  if (!OidIsValid(scache->hash_proc_finfo.fn_oid))
2799  {
2800  scache = lookup_type_cache(scache->type_id,
2802  if (!OidIsValid(scache->hash_proc_finfo.fn_oid))
2803  ereport(ERROR,
2804  (errcode(ERRCODE_UNDEFINED_FUNCTION),
2805  errmsg("could not identify a hash function for type %s",
2806  format_type_be(scache->type_id))));
2807  }
2808 
2809  range_count = mr->rangeCount;
2810  for (i = 0; i < range_count; i++)
2811  {
2812  RangeBound lower,
2813  upper;
2814  uint8 flags = MultirangeGetFlagsPtr(mr)[i];
2815  uint32 lower_hash;
2816  uint32 upper_hash;
2817  uint32 range_hash;
2818 
2819  multirange_get_bounds(typcache->rngtype, mr, i, &lower, &upper);
2820 
2821  if (RANGE_HAS_LBOUND(flags))
2822  lower_hash = DatumGetUInt32(FunctionCall1Coll(&scache->hash_proc_finfo,
2823  typcache->rngtype->rng_collation,
2824  lower.val));
2825  else
2826  lower_hash = 0;
2827 
2828  if (RANGE_HAS_UBOUND(flags))
2829  upper_hash = DatumGetUInt32(FunctionCall1Coll(&scache->hash_proc_finfo,
2830  typcache->rngtype->rng_collation,
2831  upper.val));
2832  else
2833  upper_hash = 0;
2834 
2835  /* Merge hashes of flags and bounds */
2836  range_hash = hash_uint32((uint32) flags);
2837  range_hash ^= lower_hash;
2838  range_hash = pg_rotate_left32(range_hash, 1);
2839  range_hash ^= upper_hash;
2840 
2841  /*
2842  * Use the same approach as hash_array to combine the individual
2843  * elements' hash values:
2844  */
2845  result = (result << 5) - result + range_hash;
2846  }
2847 
2848  PG_FREE_IF_COPY(mr, 0);
2849 
2850  PG_RETURN_UINT32(result);
2851 }
signed int int32
Definition: c.h:494
Datum FunctionCall1Coll(FmgrInfo *flinfo, Oid collation, Datum arg1)
Definition: fmgr.c:1129
#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:49
Datum upper(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:80
static uint32 pg_rotate_left32(uint32 word, int n)
Definition: pg_bitutils.h:404
static uint32 DatumGetUInt32(Datum X)
Definition: postgres.h:222
#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:100
struct TypeCacheEntry * rngelemtype
Definition: typcache.h:98
#define TYPECACHE_HASH_PROC_FINFO
Definition: typcache.h:144

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 2858 of file multirangetypes.c.

2859 {
2861  Datum seed = PG_GETARG_DATUM(1);
2862  uint64 result = 1;
2863  TypeCacheEntry *typcache,
2864  *scache;
2865  int32 range_count,
2866  i;
2867 
2868  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr));
2869  scache = typcache->rngtype->rngelemtype;
2871  {
2872  scache = lookup_type_cache(scache->type_id,
2875  ereport(ERROR,
2876  (errcode(ERRCODE_UNDEFINED_FUNCTION),
2877  errmsg("could not identify a hash function for type %s",
2878  format_type_be(scache->type_id))));
2879  }
2880 
2881  range_count = mr->rangeCount;
2882  for (i = 0; i < range_count; i++)
2883  {
2884  RangeBound lower,
2885  upper;
2886  uint8 flags = MultirangeGetFlagsPtr(mr)[i];
2887  uint64 lower_hash;
2888  uint64 upper_hash;
2889  uint64 range_hash;
2890 
2891  multirange_get_bounds(typcache->rngtype, mr, i, &lower, &upper);
2892 
2893  if (RANGE_HAS_LBOUND(flags))
2895  typcache->rngtype->rng_collation,
2896  lower.val,
2897  seed));
2898  else
2899  lower_hash = 0;
2900 
2901  if (RANGE_HAS_UBOUND(flags))
2903  typcache->rngtype->rng_collation,
2904  upper.val,
2905  seed));
2906  else
2907  upper_hash = 0;
2908 
2909  /* Merge hashes of flags and bounds */
2910  range_hash = DatumGetUInt64(hash_uint32_extended((uint32) flags,
2911  DatumGetInt64(seed)));
2912  range_hash ^= lower_hash;
2913  range_hash = ROTATE_HIGH_AND_LOW_32BITS(range_hash);
2914  range_hash ^= upper_hash;
2915 
2916  /*
2917  * Use the same approach as hash_array to combine the individual
2918  * elements' hash values:
2919  */
2920  result = (result << 5) - result + range_hash;
2921  }
2922 
2923  PG_FREE_IF_COPY(mr, 0);
2924 
2925  PG_RETURN_UINT64(result);
2926 }
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Definition: fmgr.c:1149
#define PG_RETURN_UINT64(x)
Definition: fmgr.h:369
#define ROTATE_HIGH_AND_LOW_32BITS(v)
Definition: hashfn.h:18
static Datum hash_uint32_extended(uint32 k, uint64 seed)
Definition: hashfn.h:49
static uint64 DatumGetUInt64(Datum X)
Definition: postgres.h:419
static int64 DatumGetInt64(Datum X)
Definition: postgres.h:385
FmgrInfo hash_extended_proc_finfo
Definition: typcache.h:78
#define TYPECACHE_HASH_EXTENDED_PROC_FINFO
Definition: typcache.h:152

References 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 848 of file multirangetypes.c.

849 {
850  return make_multirange(mltrngtypoid, rangetyp, 0, NULL);
851 }
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 646 of file multirangetypes.c.

648 {
649  MultirangeType *multirange;
650  Size size;
651 
652  /* Sort and merge input ranges. */
653  range_count = multirange_canonicalize(rangetyp, range_count, ranges);
654 
655  /* Note: zero-fill is required here, just as in heap tuples */
656  size = multirange_size_estimate(rangetyp, range_count, ranges);
657  multirange = palloc0(size);
658  SET_VARSIZE(multirange, size);
659 
660  /* Now fill in the datum */
661  multirange->multirangetypid = mltrngtypoid;
662  multirange->rangeCount = range_count;
663 
664  write_multirange_data(multirange, rangetyp, range_count, ranges);
665 
666  return multirange;
667 }
size_t Size
Definition: c.h:605
void * palloc0(Size size)
Definition: mcxt.c:1346
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)
static pg_noinline void Size size
Definition: slab.c:607
#define SET_VARSIZE(PTR, len)
Definition: varatt.h:305

References multirange_canonicalize(), multirange_size_estimate(), MultirangeType::multirangetypid, palloc0(), MultirangeType::rangeCount, SET_VARSIZE, size, 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 2534 of file multirangetypes.c.

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

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 2519 of file multirangetypes.c.

2520 {
2522  RangeType *r = PG_GETARG_RANGE_P(1);
2523  TypeCacheEntry *typcache;
2524 
2525  if (RangeIsEmpty(r) || MultirangeIsEmpty(mr))
2526  return false;
2527 
2528  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr));
2529 
2531 }
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:90

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 2389 of file multirangetypes.c.

2390 {
2393  TypeCacheEntry *typcache;
2394 
2395  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr1));
2396 
2398 }
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 2377 of file multirangetypes.c.

2378 {
2380  RangeType *r = PG_GETARG_RANGE_P(1);
2381  TypeCacheEntry *typcache;
2382 
2383  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr));
2384 
2386 }
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 1412 of file multirangetypes.c.

1413 {
1414  MemoryContext aggContext;
1415  Oid mltrngtypoid;
1416  TypeCacheEntry *typcache;
1417  TypeCacheEntry *rngtypcache;
1419 
1420  if (!AggCheckCallContext(fcinfo, &aggContext))
1421  elog(ERROR, "multirange_agg_transfn called in non-aggregate context");
1422 
1423  mltrngtypoid = get_fn_expr_argtype(fcinfo->flinfo, 1);
1424  if (!type_is_multirange(mltrngtypoid))
1425  elog(ERROR, "range_agg must be called with a multirange");
1426 
1427  typcache = multirange_get_typcache(fcinfo, mltrngtypoid);
1428  rngtypcache = typcache->rngtype;
1429 
1430  if (PG_ARGISNULL(0))
1431  state = initArrayResult(rngtypcache->type_id, aggContext, false);
1432  else
1434 
1435  /* skip NULLs */
1436  if (!PG_ARGISNULL(1))
1437  {
1438  MultirangeType *current;
1439  int32 range_count;
1440  RangeType **ranges;
1441 
1442  current = PG_GETARG_MULTIRANGE_P(1);
1443  multirange_deserialize(rngtypcache, current, &range_count, &ranges);
1444  if (range_count == 0)
1445  {
1446  /*
1447  * Add an empty range so we get an empty result (not a null
1448  * result).
1449  */
1451  RangeTypePGetDatum(make_empty_range(rngtypcache)),
1452  false, rngtypcache->type_id, aggContext);
1453  }
1454  else
1455  {
1456  for (int32 i = 0; i < range_count; i++)
1457  accumArrayResult(state, RangeTypePGetDatum(ranges[i]), false, rngtypcache->type_id, aggContext);
1458  }
1459  }
1460 
1462 }
ArrayBuildState * accumArrayResult(ArrayBuildState *astate, Datum dvalue, bool disnull, Oid element_type, MemoryContext rcontext)
Definition: arrayfuncs.c:5331
ArrayBuildState * initArrayResult(Oid element_type, MemoryContext rcontext, bool subcontext)
Definition: arrayfuncs.c:5274
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1910
#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:2698
void multirange_deserialize(TypeCacheEntry *rangetyp, const MultirangeType *multirange, int32 *range_count, RangeType ***ranges)
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4511
RangeType * make_empty_range(TypeCacheEntry *typcache)
Definition: rangetypes.c:2165
static Datum RangeTypePGetDatum(const RangeType *X)
Definition: rangetypes.h:85
Definition: regguts.h:323

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 2424 of file multirangetypes.c.

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

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 2340 of file multirangetypes.c.

2341 {
2343  RangeType *r = PG_GETARG_RANGE_P(1);
2344  TypeCacheEntry *typcache;
2345 
2346  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr));
2347 
2349 }
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 898 of file multirangetypes.c.

900 {
901  uint32 l,
902  u,
903  idx;
904  int comparison;
905  bool match = false;
906 
907  l = 0;
908  u = mr->rangeCount;
909  while (l < u)
910  {
912  upper;
913 
914  idx = (l + u) / 2;
915  multirange_get_bounds(typcache, mr, idx, &lower, &upper);
916  comparison = (*cmp_func) (typcache, &lower, &upper, key, &match);
917 
918  if (comparison < 0)
919  u = idx;
920  else if (comparison > 0)
921  l = idx + 1;
922  else
923  return match;
924  }
925 
926  return false;
927 }
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 477 of file multirangetypes.c.

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

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 2575 of file multirangetypes.c.

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

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 1059 of file multirangetypes.c.

1060 {
1061  Oid mltrngtypid;
1062  TypeCacheEntry *typcache;
1063  TypeCacheEntry *rangetyp;
1064 
1065  /* This should always be called without arguments */
1066  if (PG_NARGS() != 0)
1067  elog(ERROR,
1068  "niladic multirange constructor must not receive arguments");
1069 
1070  mltrngtypid = get_fn_expr_rettype(fcinfo->flinfo);
1071  typcache = multirange_get_typcache(fcinfo, mltrngtypid);
1072  rangetyp = typcache->rngtype;
1073 
1074  PG_RETURN_MULTIRANGE_P(make_multirange(mltrngtypid, rangetyp, 0, NULL));
1075 }
Oid get_fn_expr_rettype(FmgrInfo *flinfo)
Definition: fmgr.c:1888
#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 1023 of file multirangetypes.c.

1024 {
1025  Oid mltrngtypid = get_fn_expr_rettype(fcinfo->flinfo);
1026  Oid rngtypid;
1027  TypeCacheEntry *typcache;
1028  TypeCacheEntry *rangetyp;
1029  RangeType *range;
1030 
1031  typcache = multirange_get_typcache(fcinfo, mltrngtypid);
1032  rangetyp = typcache->rngtype;
1033 
1034  /*
1035  * This check should be guaranteed by our signature, but let's do it just
1036  * in case.
1037  */
1038 
1039  if (PG_ARGISNULL(0))
1040  elog(ERROR,
1041  "multirange values cannot contain null members");
1042 
1043  range = PG_GETARG_RANGE_P(0);
1044 
1045  /* Make sure the range type matches. */
1046  rngtypid = RangeTypeGetOid(range);
1047  if (rngtypid != rangetyp->type_id)
1048  elog(ERROR, "type %u does not match constructor type", rngtypid);
1049 
1050  PG_RETURN_MULTIRANGE_P(make_multirange(mltrngtypid, rangetyp, 1, &range));
1051 }
#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 941 of file multirangetypes.c.

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

2252 {
2255  TypeCacheEntry *typcache;
2256 
2257  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr1));
2258 
2260 }
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 1758 of file multirangetypes.c.

1759 {
1761  RangeType *r = PG_GETARG_RANGE_P(1);
1762  TypeCacheEntry *typcache;
1763 
1764  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr));
1765 
1767 }
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 1707 of file multirangetypes.c.

1709 {
1710  if (MultirangeIsEmpty(mr))
1711  return false;
1712 
1713  return multirange_bsearch_match(rangetyp, mr, &val,
1715 }
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 2266 of file multirangetypes.c.

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

1722 {
1724  RangeType *r = PG_GETARG_RANGE_P(1);
1725  TypeCacheEntry *typcache;
1726 
1727  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr));
1728 
1730 }
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 1801 of file multirangetypes.c.

1804 {
1805  RangeBound bounds[2];
1806  bool empty;
1807 
1808  /*
1809  * Every multirange contains an infinite number of empty ranges, even an
1810  * empty one.
1811  */
1812  if (RangeIsEmpty(r))
1813  return true;
1814 
1815  if (MultirangeIsEmpty(mr))
1816  return false;
1817 
1818  range_deserialize(rangetyp, r, &bounds[0], &bounds[1], &empty);
1819  Assert(!empty);
1820 
1821  return multirange_bsearch_match(rangetyp, mr, bounds,
1823 }
#define Assert(condition)
Definition: c.h:858
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:1856

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 826 of file multirangetypes.c.

829 {
830  *range_count = multirange->rangeCount;
831 
832  /* Convert each ShortRangeType into a RangeType */
833  if (*range_count > 0)
834  {
835  int i;
836 
837  *ranges = palloc(*range_count * sizeof(RangeType *));
838  for (i = 0; i < *range_count; i++)
839  (*ranges)[i] = multirange_get_range(rangetyp, multirange, i);
840  }
841  else
842  {
843  *ranges = NULL;
844  }
845 }
void * palloc(Size size)
Definition: mcxt.c:1316
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 1674 of file multirangetypes.c.

1677 {
1678  Datum val = *((Datum *) key);
1679  int cmp;
1680 
1681  if (!lower->infinite)
1682  {
1684  typcache->rng_collation,
1685  lower->val, val));
1686  if (cmp > 0 || (cmp == 0 && !lower->inclusive))
1687  return -1;
1688  }
1689 
1690  if (!upper->infinite)
1691  {
1693  typcache->rng_collation,
1694  upper->val, val));
1695  if (cmp < 0 || (cmp == 0 && !upper->inclusive))
1696  return 1;
1697  }
1698 
1699  *match = true;
1700  return 0;
1701 }
static int32 DatumGetInt32(Datum X)
Definition: postgres.h:202
FmgrInfo rng_cmp_proc_finfo
Definition: typcache.h:101

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 1556 of file multirangetypes.c.

1557 {
1559 
1561 }

References MultirangeIsEmpty, PG_GETARG_MULTIRANGE_P, and PG_RETURN_BOOL.

◆ multirange_eq()

Datum multirange_eq ( PG_FUNCTION_ARGS  )

Definition at line 1901 of file multirangetypes.c.

1902 {
1905  TypeCacheEntry *typcache;
1906 
1907  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr1));
1908 
1909  PG_RETURN_BOOL(multirange_eq_internal(typcache->rngtype, mr1, mr2));
1910 }
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 1864 of file multirangetypes.c.

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

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 2656 of file multirangetypes.c.

2657 {
2658  int cmp = multirange_cmp(fcinfo);
2659 
2660  PG_RETURN_BOOL(cmp >= 0);
2661 }
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 744 of file multirangetypes.c.

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

References Assert, att_addlength_pointer, att_align_pointer, fetch_att(), 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 673 of file multirangetypes.c.

674 {
675  uint32 *items = MultirangeGetItemsPtr(multirange);
676  uint32 offset = 0;
677 
678  /*
679  * Summarize lengths till we meet an offset.
680  */
681  while (i > 0)
682  {
683  offset += MULTIRANGE_ITEM_GET_OFFLEN(items[i - 1]);
684  if (MULTIRANGE_ITEM_HAS_OFF(items[i - 1]))
685  break;
686  i--;
687  }
688  return offset;
689 }
#define MULTIRANGE_ITEM_GET_OFFLEN(item)
#define MULTIRANGE_ITEM_HAS_OFF(item)
#define MultirangeGetItemsPtr(mr)
static ItemArray items
Definition: test_tidstore.c:49

References i, items, 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 695 of file multirangetypes.c.

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

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

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 802 of file multirangetypes.c.

804 {
806  upper,
807  tmp;
808 
809  if (MultirangeIsEmpty(mr))
810  return make_empty_range(rangetyp);
811 
812  multirange_get_bounds(rangetyp, mr, 0, &lower, &tmp);
813  multirange_get_bounds(rangetyp, mr, mr->rangeCount - 1, &tmp, &upper);
814 
815  return make_range(rangetyp, &lower, &upper, false, NULL);
816 }
RangeType * make_range(TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper, bool empty, struct Node *escontext)
Definition: rangetypes.c:1952

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 2664 of file multirangetypes.c.

2665 {
2666  int cmp = multirange_cmp(fcinfo);
2667 
2668  PG_RETURN_BOOL(cmp > 0);
2669 }

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

◆ multirange_in()

Datum multirange_in ( PG_FUNCTION_ARGS  )

Definition at line 117 of file multirangetypes.c.

118 {
119  char *input_str = PG_GETARG_CSTRING(0);
120  Oid mltrngtypoid = PG_GETARG_OID(1);
121  Oid typmod = PG_GETARG_INT32(2);
122  Node *escontext = fcinfo->context;
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  Datum range_datum;
137 
138  cache = get_multirange_io_data(fcinfo, mltrngtypoid, IOFunc_input);
139  rangetyp = cache->typcache->rngtype;
140 
141  /* consume whitespace */
142  while (*ptr != '\0' && isspace((unsigned char) *ptr))
143  ptr++;
144 
145  if (*ptr == '{')
146  ptr++;
147  else
148  ereturn(escontext, (Datum) 0,
149  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
150  errmsg("malformed multirange literal: \"%s\"",
151  input_str),
152  errdetail("Missing left brace.")));
153 
154  /* consume ranges */
155  parse_state = MULTIRANGE_BEFORE_RANGE;
156  for (; parse_state != MULTIRANGE_FINISHED; ptr++)
157  {
158  char ch = *ptr;
159 
160  if (ch == '\0')
161  ereturn(escontext, (Datum) 0,
162  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
163  errmsg("malformed multirange literal: \"%s\"",
164  input_str),
165  errdetail("Unexpected end of input.")));
166 
167  /* skip whitespace */
168  if (isspace((unsigned char) ch))
169  continue;
170 
171  switch (parse_state)
172  {
174  if (ch == '[' || ch == '(')
175  {
176  range_str_begin = ptr;
177  parse_state = MULTIRANGE_IN_RANGE;
178  }
179  else if (ch == '}' && ranges_seen == 0)
180  parse_state = MULTIRANGE_FINISHED;
181  else if (pg_strncasecmp(ptr, RANGE_EMPTY_LITERAL,
182  strlen(RANGE_EMPTY_LITERAL)) == 0)
183  {
184  ranges_seen++;
185  /* nothing to do with an empty range */
186  ptr += strlen(RANGE_EMPTY_LITERAL) - 1;
187  parse_state = MULTIRANGE_AFTER_RANGE;
188  }
189  else
190  ereturn(escontext, (Datum) 0,
191  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
192  errmsg("malformed multirange literal: \"%s\"",
193  input_str),
194  errdetail("Expected range start.")));
195  break;
196  case MULTIRANGE_IN_RANGE:
197  if (ch == ']' || ch == ')')
198  {
199  range_str_len = ptr - range_str_begin + 1;
200  range_str = pnstrdup(range_str_begin, range_str_len);
201  if (range_capacity == range_count)
202  {
203  range_capacity *= 2;
204  ranges = (RangeType **)
205  repalloc(ranges, range_capacity * sizeof(RangeType *));
206  }
207  ranges_seen++;
208  if (!InputFunctionCallSafe(&cache->typioproc,
209  range_str,
210  cache->typioparam,
211  typmod,
212  escontext,
213  &range_datum))
214  PG_RETURN_NULL();
215  range = DatumGetRangeTypeP(range_datum);
216  if (!RangeIsEmpty(range))
217  ranges[range_count++] = range;
218  parse_state = MULTIRANGE_AFTER_RANGE;
219  }
220  else
221  {
222  if (ch == '"')
223  parse_state = MULTIRANGE_IN_RANGE_QUOTED;
224  else if (ch == '\\')
225  parse_state = MULTIRANGE_IN_RANGE_ESCAPED;
226 
227  /*
228  * We will include this character into range_str once we
229  * find the end of the range value.
230  */
231  }
232  break;
234 
235  /*
236  * We will include this character into range_str once we find
237  * the end of the range value.
238  */
239  parse_state = MULTIRANGE_IN_RANGE;
240  break;
242  if (ch == '"')
243  if (*(ptr + 1) == '"')
244  {
245  /* two quote marks means an escaped quote mark */
246  ptr++;
247  }
248  else
249  parse_state = MULTIRANGE_IN_RANGE;
250  else if (ch == '\\')
252 
253  /*
254  * We will include this character into range_str once we find
255  * the end of the range value.
256  */
257  break;
259  if (ch == ',')
260  parse_state = MULTIRANGE_BEFORE_RANGE;
261  else if (ch == '}')
262  parse_state = MULTIRANGE_FINISHED;
263  else
264  ereturn(escontext, (Datum) 0,
265  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
266  errmsg("malformed multirange literal: \"%s\"",
267  input_str),
268  errdetail("Expected comma or end of multirange.")));
269  break;
271 
272  /*
273  * We will include this character into range_str once we find
274  * the end of the range value.
275  */
276  parse_state = MULTIRANGE_IN_RANGE_QUOTED;
277  break;
278  default:
279  elog(ERROR, "unknown parse state: %d", parse_state);
280  }
281  }
282 
283  /* consume whitespace */
284  while (*ptr != '\0' && isspace((unsigned char) *ptr))
285  ptr++;
286 
287  if (*ptr != '\0')
288  ereturn(escontext, (Datum) 0,
289  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
290  errmsg("malformed multirange literal: \"%s\"",
291  input_str),
292  errdetail("Junk after closing right brace.")));
293 
294  ret = make_multirange(mltrngtypoid, rangetyp, range_count, ranges);
296 }
int errdetail(const char *fmt,...)
Definition: elog.c:1203
#define ereturn(context, dummy_value,...)
Definition: elog.h:276
bool InputFunctionCallSafe(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod, fmNodePtr escontext, Datum *result)
Definition: fmgr.c:1585
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:277
#define PG_RETURN_NULL()
Definition: fmgr.h:345
#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:1706
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1540
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
Definition: nodes.h:129

References DatumGetRangeTypeP(), elog, ereturn, errcode(), errdetail(), errmsg(), ERROR, get_multirange_io_data(), InputFunctionCallSafe(), 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_RETURN_NULL, 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 1230 of file multirangetypes.c.

1231 {
1234  Oid mltrngtypoid = MultirangeTypeGetOid(mr1);
1235  TypeCacheEntry *typcache;
1236  TypeCacheEntry *rangetyp;
1237  int32 range_count1;
1238  int32 range_count2;
1239  RangeType **ranges1;
1240  RangeType **ranges2;
1241 
1242  typcache = multirange_get_typcache(fcinfo, mltrngtypoid);
1243  rangetyp = typcache->rngtype;
1244 
1245  if (MultirangeIsEmpty(mr1) || MultirangeIsEmpty(mr2))
1246  PG_RETURN_MULTIRANGE_P(make_empty_multirange(mltrngtypoid, rangetyp));
1247 
1248  multirange_deserialize(rangetyp, mr1, &range_count1, &ranges1);
1249  multirange_deserialize(rangetyp, mr2, &range_count2, &ranges2);
1250 
1252  rangetyp,
1253  range_count1,
1254  ranges1,
1255  range_count2,
1256  ranges2));
1257 }
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 1465 of file multirangetypes.c.

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

References AggCheckCallContext(), elog, ERROR, get_fn_expr_argtype(), multirange_deserialize(), multirange_get_typcache(), multirange_intersect_internal(), PG_GETARG_MULTIRANGE_P, PG_RETURN_MULTIRANGE_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 1260 of file multirangetypes.c.

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

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

2649 {
2650  int cmp = multirange_cmp(fcinfo);
2651 
2652  PG_RETURN_BOOL(cmp <= 0);
2653 }

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

◆ multirange_lower()

Datum multirange_lower ( PG_FUNCTION_ARGS  )

Definition at line 1507 of file multirangetypes.c.

1508 {
1510  TypeCacheEntry *typcache;
1511  RangeBound lower;
1512  RangeBound upper;
1513 
1514  if (MultirangeIsEmpty(mr))
1515  PG_RETURN_NULL();
1516 
1517  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr));
1518 
1519  multirange_get_bounds(typcache->rngtype, mr, 0,
1520  &lower, &upper);
1521 
1522  if (!lower.infinite)
1523  PG_RETURN_DATUM(lower.val);
1524  else
1525  PG_RETURN_NULL();
1526 }
#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 1565 of file multirangetypes.c.

1566 {
1568  TypeCacheEntry *typcache;
1569  RangeBound lower;
1570  RangeBound upper;
1571 
1572  if (MultirangeIsEmpty(mr))
1573  PG_RETURN_BOOL(false);
1574 
1575  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr));
1576  multirange_get_bounds(typcache->rngtype, mr, 0,
1577  &lower, &upper);
1578 
1579  PG_RETURN_BOOL(lower.inclusive);
1580 }

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 1603 of file multirangetypes.c.

1604 {
1606  TypeCacheEntry *typcache;
1607  RangeBound lower;
1608  RangeBound upper;
1609 
1610  if (MultirangeIsEmpty(mr))
1611  PG_RETURN_BOOL(false);
1612 
1613  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr));
1614  multirange_get_bounds(typcache->rngtype, mr, 0,
1615  &lower, &upper);
1616 
1617  PG_RETURN_BOOL(lower.infinite);
1618 }

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 2640 of file multirangetypes.c.

2641 {
2642  int cmp = multirange_cmp(fcinfo);
2643 
2644  PG_RETURN_BOOL(cmp < 0);
2645 }

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

◆ multirange_minus()

Datum multirange_minus ( PG_FUNCTION_ARGS  )

Definition at line 1114 of file multirangetypes.c.

1115 {
1118  Oid mltrngtypoid = MultirangeTypeGetOid(mr1);
1119  TypeCacheEntry *typcache;
1120  TypeCacheEntry *rangetyp;
1121  int32 range_count1;
1122  int32 range_count2;
1123  RangeType **ranges1;
1124  RangeType **ranges2;
1125 
1126  typcache = multirange_get_typcache(fcinfo, mltrngtypoid);
1127  rangetyp = typcache->rngtype;
1128 
1129  if (MultirangeIsEmpty(mr1) || MultirangeIsEmpty(mr2))
1131 
1132  multirange_deserialize(typcache->rngtype, mr1, &range_count1, &ranges1);
1133  multirange_deserialize(typcache->rngtype, mr2, &range_count2, &ranges2);
1134 
1136  rangetyp,
1137  range_count1,
1138  ranges1,
1139  range_count2,
1140  ranges2));
1141 }
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 1144 of file multirangetypes.c.

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

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 1923 of file multirangetypes.c.

1924 {
1927  TypeCacheEntry *typcache;
1928 
1929  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr1));
1930 
1931  PG_RETURN_BOOL(multirange_ne_internal(typcache->rngtype, mr1, mr2));
1932 }
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 1914 of file multirangetypes.c.

1917 {
1918  return (!multirange_eq_internal(rangetyp, mr1, mr2));
1919 }

References multirange_eq_internal().

Referenced by multirange_ne().

◆ multirange_out()

Datum multirange_out ( PG_FUNCTION_ARGS  )

Definition at line 299 of file multirangetypes.c.

300 {
301  MultirangeType *multirange = PG_GETARG_MULTIRANGE_P(0);
302  Oid mltrngtypoid = MultirangeTypeGetOid(multirange);
303  MultirangeIOData *cache;
305  RangeType *range;
306  char *rangeStr;
307  int32 range_count;
308  int32 i;
309  RangeType **ranges;
310 
311  cache = get_multirange_io_data(fcinfo, mltrngtypoid, IOFunc_output);
312 
314 
315  appendStringInfoChar(&buf, '{');
316 
317  multirange_deserialize(cache->typcache->rngtype, multirange, &range_count, &ranges);
318  for (i = 0; i < range_count; i++)
319  {
320  if (i > 0)
321  appendStringInfoChar(&buf, ',');
322  range = ranges[i];
324  appendStringInfoString(&buf, rangeStr);
325  }
326 
327  appendStringInfoChar(&buf, '}');
328 
329  PG_RETURN_CSTRING(buf.data);
330 }
char * OutputFunctionCall(FmgrInfo *flinfo, Datum val)
Definition: fmgr.c:1683
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:362
@ IOFunc_output
Definition: lsyscache.h:36
static char * buf
Definition: pg_test_fsync.c:73
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:182
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:194
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 1960 of file multirangetypes.c.

1961 {
1964  TypeCacheEntry *typcache;
1965 
1966  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr1));
1967 
1969 }
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 2015 of file multirangetypes.c.

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

1949 {
1951  RangeType *r = PG_GETARG_RANGE_P(1);
1952  TypeCacheEntry *typcache;
1953 
1954  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr));
1955 
1957 }
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 2133 of file multirangetypes.c.

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

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 2108 of file multirangetypes.c.

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

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 2215 of file multirangetypes.c.

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

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

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

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 1774 of file multirangetypes.c.

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

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 1976 of file multirangetypes.c.

1979 {
1980  RangeBound *keyLower = (RangeBound *) key;
1981  RangeBound *keyUpper = (RangeBound *) key + 1;
1982 
1983  if (range_cmp_bounds(typcache, keyUpper, lower) < 0)
1984  return -1;
1985  if (range_cmp_bounds(typcache, keyLower, upper) > 0)
1986  return 1;
1987 
1988  *match = true;
1989  return 0;
1990 }

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 337 of file multirangetypes.c.

338 {
340  Oid mltrngtypoid = PG_GETARG_OID(1);
341  int32 typmod = PG_GETARG_INT32(2);
342  MultirangeIOData *cache;
343  uint32 range_count;
344  RangeType **ranges;
345  MultirangeType *ret;
347 
348  cache = get_multirange_io_data(fcinfo, mltrngtypoid, IOFunc_receive);
349 
350  range_count = pq_getmsgint(buf, 4);
351  ranges = palloc(range_count * sizeof(RangeType *));
352 
354  for (int i = 0; i < range_count; i++)
355  {
356  uint32 range_len = pq_getmsgint(buf, 4);
357  const char *range_data = pq_getmsgbytes(buf, range_len);
358 
360  appendBinaryStringInfo(&tmpbuf, range_data, range_len);
361 
363  &tmpbuf,
364  cache->typioparam,
365  typmod));
366  }
367  pfree(tmpbuf.data);
368 
369  pq_getmsgend(buf);
370 
371  ret = make_multirange(mltrngtypoid, cache->typcache->rngtype,
372  range_count, ranges);
374 }
Datum ReceiveFunctionCall(FmgrInfo *flinfo, StringInfo buf, Oid typioparam, int32 typmod)
Definition: fmgr.c:1697
void pfree(void *pointer)
Definition: mcxt.c:1520
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition: pqformat.c:415
void pq_getmsgend(StringInfo msg)
Definition: pqformat.c:635
const char * pq_getmsgbytes(StringInfo msg, int datalen)
Definition: pqformat.c:508
void resetStringInfo(StringInfo str)
Definition: stringinfo.c:78
void appendBinaryStringInfo(StringInfo str, const void *data, int datalen)
Definition: stringinfo.c:233
StringInfoData * StringInfo
Definition: stringinfo.h:54
static StringInfoData tmpbuf
Definition: walsender.c:170

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 377 of file multirangetypes.c.

378 {
379  MultirangeType *multirange = PG_GETARG_MULTIRANGE_P(0);
380  Oid mltrngtypoid = MultirangeTypeGetOid(multirange);
382  RangeType **ranges;
383  int32 range_count;
384  MultirangeIOData *cache;
385 
386  cache = get_multirange_io_data(fcinfo, mltrngtypoid, IOFunc_send);
387 
388  /* construct output */
390 
391  pq_sendint32(buf, multirange->rangeCount);
392 
393  multirange_deserialize(cache->typcache->rngtype, multirange, &range_count, &ranges);
394  for (int i = 0; i < range_count; i++)
395  {
396  Datum range;
397 
398  range = RangeTypePGetDatum(ranges[i]);
400 
403  }
404 
406 }
#define VARHDRSZ
Definition: c.h:692
bytea * SendFunctionCall(FmgrInfo *flinfo, Datum val)
Definition: fmgr.c:1744
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:371
@ IOFunc_send
Definition: lsyscache.h:38
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
void pq_sendbytes(StringInfo buf, const void *data, int datalen)
Definition: pqformat.c:126
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:326
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:346
static void pq_sendint32(StringInfo buf, uint32 i)
Definition: pqformat.h:144
StringInfo makeStringInfo(void)
Definition: stringinfo.c:41
#define VARDATA(PTR)
Definition: varatt.h:278
#define VARSIZE(PTR)
Definition: varatt.h:279

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 569 of file multirangetypes.c.

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

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

Referenced by make_multirange().

◆ multirange_union()

Datum multirange_union ( PG_FUNCTION_ARGS  )

Definition at line 1082 of file multirangetypes.c.

1083 {
1086  TypeCacheEntry *typcache;
1087  int32 range_count1;
1088  int32 range_count2;
1089  int32 range_count3;
1090  RangeType **ranges1;
1091  RangeType **ranges2;
1092  RangeType **ranges3;
1093 
1094  if (MultirangeIsEmpty(mr1))
1096  if (MultirangeIsEmpty(mr2))
1098 
1099  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr1));
1100 
1101  multirange_deserialize(typcache->rngtype, mr1, &range_count1, &ranges1);
1102  multirange_deserialize(typcache->rngtype, mr2, &range_count2, &ranges2);
1103 
1104  range_count3 = range_count1 + range_count2;
1105  ranges3 = palloc0(range_count3 * sizeof(RangeType *));
1106  memcpy(ranges3, ranges1, range_count1 * sizeof(RangeType *));
1107  memcpy(ranges3 + range_count1, ranges2, range_count2 * sizeof(RangeType *));
1109  range_count3, ranges3));
1110 }

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 2713 of file multirangetypes.c.

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

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 1530 of file multirangetypes.c.

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

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 1584 of file multirangetypes.c.

1585 {
1587  TypeCacheEntry *typcache;
1588  RangeBound lower;
1589  RangeBound upper;
1590 
1591  if (MultirangeIsEmpty(mr))
1592  PG_RETURN_BOOL(false);
1593 
1594  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr));
1595  multirange_get_bounds(typcache->rngtype, mr, mr->rangeCount - 1,
1596  &lower, &upper);
1597 
1598  PG_RETURN_BOOL(upper.inclusive);
1599 }

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 1622 of file multirangetypes.c.

1623 {
1625  TypeCacheEntry *typcache;
1626  RangeBound lower;
1627  RangeBound upper;
1628 
1629  if (MultirangeIsEmpty(mr))
1630  PG_RETURN_BOOL(false);
1631 
1632  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr));
1633  multirange_get_bounds(typcache->rngtype, mr, mr->rangeCount - 1,
1634  &lower, &upper);
1635 
1636  PG_RETURN_BOOL(upper.infinite);
1637 }

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 2471 of file multirangetypes.c.

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

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 2446 of file multirangetypes.c.

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

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 1372 of file multirangetypes.c.

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

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 1340 of file multirangetypes.c.

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

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 2402 of file multirangetypes.c.

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

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 878 of file multirangetypes.c.

881 {
882  if (range_cmp_bounds(typcache, lower1, lower2) <= 0 &&
883  range_cmp_bounds(typcache, upper1, upper2) >= 0)
884  return true;
885 
886  return false;
887 }

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 858 of file multirangetypes.c.

861 {
862  if (range_cmp_bounds(typcache, lower1, lower2) >= 0 &&
863  range_cmp_bounds(typcache, lower1, upper2) <= 0)
864  return true;
865 
866  if (range_cmp_bounds(typcache, lower2, lower1) >= 0 &&
867  range_cmp_bounds(typcache, lower2, upper1) <= 0)
868  return true;
869 
870  return false;
871 }

References 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 1829 of file multirangetypes.c.

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

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 2675 of file multirangetypes.c.

2676 {
2678  Oid mltrngtypoid = MultirangeTypeGetOid(mr);
2679  TypeCacheEntry *typcache;
2680  RangeType *result;
2681 
2682  typcache = multirange_get_typcache(fcinfo, mltrngtypoid);
2683 
2684  if (MultirangeIsEmpty(mr))
2685  {
2686  result = make_empty_range(typcache->rngtype);
2687  }
2688  else if (mr->rangeCount == 1)
2689  {
2690  result = multirange_get_range(typcache->rngtype, mr, 0);
2691  }
2692  else
2693  {
2694  RangeBound firstLower,
2695  firstUpper,
2696  lastLower,
2697  lastUpper;
2698 
2699  multirange_get_bounds(typcache->rngtype, mr, 0,
2700  &firstLower, &firstUpper);
2701  multirange_get_bounds(typcache->rngtype, mr, mr->rangeCount - 1,
2702  &lastLower, &lastUpper);
2703 
2704  result = make_range(typcache->rngtype, &firstLower, &lastUpper,
2705  false, NULL);
2706  }
2707 
2708  PG_RETURN_RANGE_P(result);
2709 }
#define PG_RETURN_RANGE_P(x)
Definition: rangetypes.h:92

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 1993 of file multirangetypes.c.

1996 {
1997  RangeBound bounds[2];
1998  bool empty;
1999 
2000  /*
2001  * Empties never overlap, even with empties. (This seems strange since
2002  * they *do* contain each other, but we want to follow how ranges work.)
2003  */
2004  if (RangeIsEmpty(r) || MultirangeIsEmpty(mr))
2005  return false;
2006 
2007  range_deserialize(rangetyp, r, &bounds[0], &bounds[1], &empty);
2008  Assert(!empty);
2009 
2010  return multirange_bsearch_match(rangetyp, mr, bounds,
2012 }
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 2096 of file multirangetypes.c.

2097 {
2098  RangeType *r = PG_GETARG_RANGE_P(0);
2100  TypeCacheEntry *typcache;
2101 
2102  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr));
2103 
2105 }
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 2073 of file multirangetypes.c.

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

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 2179 of file multirangetypes.c.

2180 {
2181  RangeType *r = PG_GETARG_RANGE_P(0);
2183  TypeCacheEntry *typcache;
2184 
2185  typcache = multirange_get_typcache(fcinfo, MultirangeTypeGetOid(mr));
2186 
2188 }
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 2158 of file multirangetypes.c.

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

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 596 of file multirangetypes.c.

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

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

Referenced by make_multirange().