PostgreSQL Source Code git master
Loading...
Searching...
No Matches
rangetypes.c File Reference
#include "postgres.h"
#include "access/tupmacs.h"
#include "common/hashfn.h"
#include "funcapi.h"
#include "libpq/pqformat.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "nodes/miscnodes.h"
#include "nodes/supportnodes.h"
#include "optimizer/clauses.h"
#include "optimizer/cost.h"
#include "optimizer/optimizer.h"
#include "port/pg_bitutils.h"
#include "utils/builtins.h"
#include "utils/date.h"
#include "utils/lsyscache.h"
#include "utils/rangetypes.h"
#include "utils/sortsupport.h"
#include "utils/timestamp.h"
#include "varatt.h"
Include dependency graph for rangetypes.c:

Go to the source code of this file.

Data Structures

struct  RangeIOData
 

Macros

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

Typedefs

typedef struct RangeIOData RangeIOData
 

Functions

static RangeIODataget_range_io_data (FunctionCallInfo fcinfo, Oid rngtypid, IOFuncSelector func)
 
static int range_fast_cmp (Datum a, Datum b, SortSupport ssup)
 
static char range_parse_flags (const char *flags_str)
 
static bool range_parse (const char *string, char *flags, char **lbound_str, char **ubound_str, Node *escontext)
 
static const charrange_parse_bound (const char *string, const char *ptr, char **bound_str, bool *infinite, Node *escontext)
 
static charrange_deparse (char flags, const char *lbound_str, const char *ubound_str)
 
static charrange_bound_escape (const char *value)
 
static Size datum_compute_size (Size data_length, Datum val, bool typbyval, char typalign, int16 typlen, char typstorage)
 
static chardatum_write (char *ptr, Datum datum, bool typbyval, char typalign, int16 typlen, char typstorage)
 
static Nodefind_simplified_clause (PlannerInfo *root, Expr *rangeExpr, Expr *elemExpr)
 
static Exprbuild_bound_expr (Expr *elemExpr, Datum val, bool isLowerBound, bool isInclusive, TypeCacheEntry *typeCache, Oid opfamily, Oid rng_collation)
 
Datum range_in (PG_FUNCTION_ARGS)
 
Datum range_out (PG_FUNCTION_ARGS)
 
Datum range_recv (PG_FUNCTION_ARGS)
 
Datum range_send (PG_FUNCTION_ARGS)
 
Datum range_constructor2 (PG_FUNCTION_ARGS)
 
Datum range_constructor3 (PG_FUNCTION_ARGS)
 
Datum range_lower (PG_FUNCTION_ARGS)
 
Datum range_upper (PG_FUNCTION_ARGS)
 
Datum range_empty (PG_FUNCTION_ARGS)
 
Datum range_lower_inc (PG_FUNCTION_ARGS)
 
Datum range_upper_inc (PG_FUNCTION_ARGS)
 
Datum range_lower_inf (PG_FUNCTION_ARGS)
 
Datum range_upper_inf (PG_FUNCTION_ARGS)
 
Datum range_contains_elem (PG_FUNCTION_ARGS)
 
Datum elem_contained_by_range (PG_FUNCTION_ARGS)
 
bool range_eq_internal (TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
 
Datum range_eq (PG_FUNCTION_ARGS)
 
bool range_ne_internal (TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
 
Datum range_ne (PG_FUNCTION_ARGS)
 
Datum range_contains (PG_FUNCTION_ARGS)
 
Datum range_contained_by (PG_FUNCTION_ARGS)
 
bool range_before_internal (TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
 
Datum range_before (PG_FUNCTION_ARGS)
 
bool range_after_internal (TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
 
Datum range_after (PG_FUNCTION_ARGS)
 
bool bounds_adjacent (TypeCacheEntry *typcache, RangeBound boundA, RangeBound boundB)
 
bool range_adjacent_internal (TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
 
Datum range_adjacent (PG_FUNCTION_ARGS)
 
bool range_overlaps_internal (TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
 
Datum range_overlaps (PG_FUNCTION_ARGS)
 
bool range_overleft_internal (TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
 
Datum range_overleft (PG_FUNCTION_ARGS)
 
bool range_overright_internal (TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
 
Datum range_overright (PG_FUNCTION_ARGS)
 
Datum range_minus (PG_FUNCTION_ARGS)
 
RangeTyperange_minus_internal (TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
 
RangeTyperange_union_internal (TypeCacheEntry *typcache, RangeType *r1, RangeType *r2, bool strict)
 
Datum range_union (PG_FUNCTION_ARGS)
 
Datum range_merge (PG_FUNCTION_ARGS)
 
Datum range_intersect (PG_FUNCTION_ARGS)
 
RangeTyperange_intersect_internal (TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
 
bool range_split_internal (TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2, RangeType **output1, RangeType **output2)
 
Datum range_minus_multi (PG_FUNCTION_ARGS)
 
void range_minus_multi_internal (TypeCacheEntry *typcache, RangeType *r1, RangeType *r2, RangeType **outputs, int *outputn)
 
Datum range_intersect_agg_transfn (PG_FUNCTION_ARGS)
 
Datum range_cmp (PG_FUNCTION_ARGS)
 
Datum range_sortsupport (PG_FUNCTION_ARGS)
 
Datum range_lt (PG_FUNCTION_ARGS)
 
Datum range_le (PG_FUNCTION_ARGS)
 
Datum range_ge (PG_FUNCTION_ARGS)
 
Datum range_gt (PG_FUNCTION_ARGS)
 
Datum hash_range (PG_FUNCTION_ARGS)
 
Datum hash_range_extended (PG_FUNCTION_ARGS)
 
Datum int4range_canonical (PG_FUNCTION_ARGS)
 
Datum int8range_canonical (PG_FUNCTION_ARGS)
 
Datum daterange_canonical (PG_FUNCTION_ARGS)
 
Datum int4range_subdiff (PG_FUNCTION_ARGS)
 
Datum int8range_subdiff (PG_FUNCTION_ARGS)
 
Datum numrange_subdiff (PG_FUNCTION_ARGS)
 
Datum daterange_subdiff (PG_FUNCTION_ARGS)
 
Datum tsrange_subdiff (PG_FUNCTION_ARGS)
 
Datum tstzrange_subdiff (PG_FUNCTION_ARGS)
 
TypeCacheEntryrange_get_typcache (FunctionCallInfo fcinfo, Oid rngtypid)
 
RangeTyperange_serialize (TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper, bool empty, struct Node *escontext)
 
void range_deserialize (TypeCacheEntry *typcache, const RangeType *range, RangeBound *lower, RangeBound *upper, bool *empty)
 
char range_get_flags (const RangeType *range)
 
void range_set_contain_empty (RangeType *range)
 
RangeTypemake_range (TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper, bool empty, struct Node *escontext)
 
int range_cmp_bounds (TypeCacheEntry *typcache, const RangeBound *b1, const RangeBound *b2)
 
int range_cmp_bound_values (TypeCacheEntry *typcache, const RangeBound *b1, const RangeBound *b2)
 
int range_compare (const void *key1, const void *key2, void *arg)
 
RangeTypemake_empty_range (TypeCacheEntry *typcache)
 
Datum elem_contained_by_range_support (PG_FUNCTION_ARGS)
 
Datum range_contains_elem_support (PG_FUNCTION_ARGS)
 
bool range_contains_internal (TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
 
bool range_contained_by_internal (TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
 
bool range_contains_elem_internal (TypeCacheEntry *typcache, const RangeType *r, Datum val)
 

Macro Definition Documentation

◆ TYPE_IS_PACKABLE

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

Definition at line 2909 of file rangetypes.c.

2918{
2919 if (TYPE_IS_PACKABLE(typlen, typstorage) &&
2921 {
2922 /*
2923 * we're anticipating converting to a short varlena header, so adjust
2924 * length and don't count any alignment
2925 */
2927 }
2928 else
2929 {
2930 data_length = att_align_datum(data_length, typalign, typlen, val);
2931 data_length = att_addlength_datum(data_length, typlen, val);
2932 }
2933
2934 return data_length;
2935}
2936
2937/*
2938 * Write the given datum beginning at ptr (after advancing to correct
2939 * alignment, if needed). Return the pointer incremented by space used.
2940 */
2941static char *
2942datum_write(char *ptr, Datum datum, bool typbyval, char typalign,
2943 int16 typlen, char typstorage)
2944{
2945 Size data_length;
2946
2947 if (typbyval)
2948 {
2949 /* pass-by-value */
2950 ptr = (char *) att_align_nominal(ptr, typalign);
2951 store_att_byval(ptr, datum, typlen);
2952 data_length = typlen;
2953 }
2954 else if (typlen == -1)
2955 {
2956 /* varlena */
2957 Pointer val = DatumGetPointer(datum);
2958
2960 {
2961 /*
2962 * Throw error, because we must never put a toast pointer inside a
2963 * range object. Caller should have detoasted it.
2964 */
2965 elog(ERROR, "cannot store a toast pointer inside a range");
2966 data_length = 0; /* keep compiler quiet */
2967 }
2968 else if (VARATT_IS_SHORT(val))
2969 {
2970 /* no alignment for short varlenas */
2971 data_length = VARSIZE_SHORT(val);
2972 memcpy(ptr, val, data_length);
2973 }
2974 else if (TYPE_IS_PACKABLE(typlen, typstorage) &&
2976 {
2977 /* convert to short varlena -- no alignment */
2978 data_length = VARATT_CONVERTED_SHORT_SIZE(val);
2979 SET_VARSIZE_SHORT(ptr, data_length);
2980 memcpy(ptr + 1, VARDATA(val), data_length - 1);
2981 }
2982 else
2983 {
2984 /* full 4-byte header varlena */
2985 ptr = (char *) att_align_nominal(ptr, typalign);
2986 data_length = VARSIZE(val);
2987 memcpy(ptr, val, data_length);
2988 }
2989 }
2990 else if (typlen == -2)
2991 {
2992 /* cstring ... never needs alignment */
2994 data_length = strlen(DatumGetCString(datum)) + 1;
2995 memcpy(ptr, DatumGetPointer(datum), data_length);
2996 }
2997 else
2998 {
2999 /* fixed-length pass-by-reference */
3000 ptr = (char *) att_align_nominal(ptr, typalign);
3001 Assert(typlen > 0);
3002 data_length = typlen;
3003 memcpy(ptr, DatumGetPointer(datum), data_length);
3004 }
3005
3006 ptr += data_length;
3007
3008 return ptr;
3009}
3010
3011/*
3012 * Common code for the elem_contained_by_range and range_contains_elem
3013 * support functions. The caller has extracted the function argument
3014 * expressions, and swapped them if necessary to pass the range first.
3015 *
3016 * Returns a simplified replacement expression, or NULL if we can't simplify.
3017 */
3018static Node *
3020{
3025 bool empty;
3026
3027 /* can't do anything unless the range is a non-null constant */
3028 if (!IsA(rangeExpr, Const) || ((Const *) rangeExpr)->constisnull)
3029 return NULL;
3031
3034 if (rangetypcache->rngelemtype == NULL)
3035 elog(ERROR, "type %u is not a range type", RangeTypeGetOid(range));
3036
3038
3039 if (empty)
3040 {
3041 /* if the range is empty, then there can be no matches */
3042 return makeBoolConst(false, false);
3043 }
3044 else if (lower.infinite && upper.infinite)
3045 {
3046 /* the range has infinite bounds, so it matches everything */
3047 return makeBoolConst(true, false);
3048 }
3049 else
3050 {
3051 /* at least one bound is available, we have something to work with */
3053 Oid opfamily = rangetypcache->rng_opfamily;
3054 Oid rng_collation = rangetypcache->rng_collation;
3055 Expr *lowerExpr = NULL;
3056 Expr *upperExpr = NULL;
3057
3058 if (!lower.infinite && !upper.infinite)
3059 {
3060 /*
3061 * When both bounds are present, we have a problem: the
3062 * "simplified" clause would need to evaluate the elemExpr twice.
3063 * That's definitely not okay if the elemExpr is volatile, and
3064 * it's also unattractive if the elemExpr is expensive.
3065 */
3067
3069 return NULL;
3070
3071 /*
3072 * We define "expensive" as "contains any subplan or more than 10
3073 * operators". Note that the subplan search has to be done
3074 * explicitly, since cost_qual_eval() will barf on unplanned
3075 * subselects.
3076 */
3078 return NULL;
3080 if (eval_cost.startup + eval_cost.per_tuple >
3081 10 * cpu_operator_cost)
3082 return NULL;
3083 }
3084
3085 /* Okay, try to build boundary comparison expressions */
3086 if (!lower.infinite)
3087 {
3089 lower.val,
3090 true,
3091 lower.inclusive,
3093 opfamily,
3094 rng_collation);
3095 if (lowerExpr == NULL)
3096 return NULL;
3097 }
3098
3099 if (!upper.infinite)
3100 {
3101 /* Copy the elemExpr if we need two copies */
3102 if (!lower.infinite)
3105 upper.val,
3106 false,
3107 upper.inclusive,
3109 opfamily,
3110 rng_collation);
3111 if (upperExpr == NULL)
3112 return NULL;
3113 }
3114
3115 if (lowerExpr != NULL && upperExpr != NULL)
3117 else if (lowerExpr != NULL)
3118 return (Node *) lowerExpr;
3119 else if (upperExpr != NULL)
3120 return (Node *) upperExpr;
3121 else
3122 {
3123 Assert(false);
3124 return NULL;
3125 }
3126 }
3127}
3128
3129/*
3130 * Helper function for find_simplified_clause().
3131 *
3132 * Build the expression (elemExpr Operator val), where the operator is
3133 * the appropriate member of the given opfamily depending on
3134 * isLowerBound and isInclusive. typeCache is the typcache entry for
3135 * the "val" value (presently, this will be the same type as elemExpr).
3136 * rng_collation is the collation to use in the comparison.
3137 *
3138 * Return NULL on failure (if, for some reason, we can't find the operator).
3139 */
3140static Expr *
3142 bool isLowerBound, bool isInclusive,
3144 Oid opfamily, Oid rng_collation)
3145{
3146 Oid elemType = typeCache->type_id;
3147 int16 elemTypeLen = typeCache->typlen;
3148 bool elemByValue = typeCache->typbyval;
3149 Oid elemCollation = typeCache->typcollation;
3150 int16 strategy;
3151 Oid oproid;
3152 Expr *constExpr;
3153
3154 /* Identify the comparison operator to use */
3155 if (isLowerBound)
3157 else
3159
3160 /*
3161 * We could use exprType(elemExpr) here, if it ever becomes possible that
3162 * elemExpr is not the exact same type as the range elements.
3163 */
3164 oproid = get_opfamily_member(opfamily, elemType, elemType, strategy);
3165
3166 /* We don't really expect failure here, but just in case ... */
3167 if (!OidIsValid(oproid))
3168 return NULL;
3169
3170 /* OK, convert "val" to a full-fledged Const node, and make the OpExpr */
3172 -1,
3175 val,
3176 false,
3177 elemByValue);
3178
3179 return make_opclause(oproid,
3180 BOOLOID,
3181 false,
3182 elemExpr,
3183 constExpr,
3184 InvalidOid,
3185 rng_collation);
3186}
#define Assert(condition)
Definition c.h:945
int16_t int16
Definition c.h:613
void * Pointer
Definition c.h:609
#define OidIsValid(objectId)
Definition c.h:860
size_t Size
Definition c.h:691
bool contain_subplans(Node *clause)
Definition clauses.c:341
bool contain_volatile_functions(Node *clause)
Definition clauses.c:549
double cpu_operator_cost
Definition costsize.c:135
void cost_qual_eval_node(QualCost *cost, Node *qual, PlannerInfo *root)
Definition costsize.c:4926
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:226
long val
Definition informix.c:689
Oid get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype, int16 strategy)
Definition lsyscache.c:170
Node * makeBoolConst(bool value, bool isnull)
Definition makefuncs.c:408
Expr * make_andclause(List *andclauses)
Definition makefuncs.c:727
Expr * make_opclause(Oid opno, Oid opresulttype, bool opretset, Expr *leftop, Expr *rightop, Oid opcollid, Oid inputcollid)
Definition makefuncs.c:701
Const * makeConst(Oid consttype, int32 consttypmod, Oid constcollid, int constlen, Datum constvalue, bool constisnull, bool constbyval)
Definition makefuncs.c:350
#define IsA(nodeptr, _type_)
Definition nodes.h:164
#define copyObject(obj)
Definition nodes.h:232
Datum lower(PG_FUNCTION_ARGS)
Datum upper(PG_FUNCTION_ARGS)
#define list_make2(x1, x2)
Definition pg_list.h:246
char typalign
Definition pg_type.h:178
static char * DatumGetCString(Datum X)
Definition postgres.h:355
uint64_t Datum
Definition postgres.h:70
static Pointer DatumGetPointer(Datum X)
Definition postgres.h:332
#define InvalidOid
unsigned int Oid
static int fb(int x)
tree ctl root
Definition radixtree.h:1857
static char * datum_write(char *ptr, Datum datum, bool typbyval, char typalign, int16 typlen, char typstorage)
#define TYPE_IS_PACKABLE(typlen, typstorage)
void range_deserialize(TypeCacheEntry *typcache, const RangeType *range, RangeBound *lower, RangeBound *upper, bool *empty)
static Expr * build_bound_expr(Expr *elemExpr, Datum val, bool isLowerBound, bool isInclusive, TypeCacheEntry *typeCache, Oid opfamily, Oid rng_collation)
static Node * find_simplified_clause(PlannerInfo *root, Expr *rangeExpr, Expr *elemExpr)
static RangeType * DatumGetRangeTypeP(Datum X)
Definition rangetypes.h:73
#define RangeTypeGetOid(r)
Definition rangetypes.h:35
static struct cvec * range(struct vars *v, chr a, chr b, int cases)
#define BTGreaterStrategyNumber
Definition stratnum.h:33
#define BTLessStrategyNumber
Definition stratnum.h:29
#define BTLessEqualStrategyNumber
Definition stratnum.h:30
#define BTGreaterEqualStrategyNumber
Definition stratnum.h:32
Definition nodes.h:135
struct TypeCacheEntry * rngelemtype
Definition typcache.h:99
#define att_align_nominal(cur_offset, attalign)
Definition tupmacs.h:404
#define att_align_datum(cur_offset, attalign, attlen, attdatum)
Definition tupmacs.h:341
#define att_addlength_datum(cur_offset, attlen, attdatum)
Definition tupmacs.h:419
static void store_att_byval(void *T, Datum newdatum, int attlen)
Definition tupmacs.h:457
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition typcache.c:389
#define TYPECACHE_RANGE_INFO
Definition typcache.h:149
static bool VARATT_IS_SHORT(const void *PTR)
Definition varatt.h:403
static bool VARATT_CAN_MAKE_SHORT(const void *PTR)
Definition varatt.h:417
static bool VARATT_IS_EXTERNAL(const void *PTR)
Definition varatt.h:354
static Size VARSIZE(const void *PTR)
Definition varatt.h:298
static char * VARDATA(const void *PTR)
Definition varatt.h:305
static Size VARATT_CONVERTED_SHORT_SIZE(const void *PTR)
Definition varatt.h:425
static void SET_VARSIZE_SHORT(void *PTR, Size len)
Definition varatt.h:439
static Size VARSIZE_SHORT(const void *PTR)
Definition varatt.h:312

Typedef Documentation

◆ RangeIOData

Function Documentation

◆ bounds_adjacent()

bool bounds_adjacent ( TypeCacheEntry typcache,
RangeBound  boundA,
RangeBound  boundB 
)

Definition at line 763 of file rangetypes.c.

764{
765 int cmp;
766
767 Assert(!boundA.lower && boundB.lower);
768
769 cmp = range_cmp_bound_values(typcache, &boundA, &boundB);
770 if (cmp < 0)
771 {
772 RangeType *r;
773
774 /*
775 * Bounds do not overlap; see if there are points in between.
776 */
777
778 /* in a continuous subtype, there are assumed to be points between */
779 if (!OidIsValid(typcache->rng_canonical_finfo.fn_oid))
780 return false;
781
782 /*
783 * The bounds are of a discrete range type; so make a range A..B and
784 * see if it's empty.
785 */
786
787 /* flip the inclusion flags */
788 boundA.inclusive = !boundA.inclusive;
789 boundB.inclusive = !boundB.inclusive;
790 /* change upper/lower labels to avoid Assert failures */
791 boundA.lower = true;
792 boundB.lower = false;
793 r = make_range(typcache, &boundA, &boundB, false, NULL);
794 return RangeIsEmpty(r);
795 }
796 else if (cmp == 0)
797 return boundA.inclusive != boundB.inclusive;
798 else
799 return false; /* bounds overlap */
800}
RangeType * make_range(TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper, bool empty, struct Node *escontext)
int range_cmp_bound_values(TypeCacheEntry *typcache, const RangeBound *b1, const RangeBound *b2)
#define RangeIsEmpty(r)
Definition rangetypes.h:55
static int cmp(const chr *x, const chr *y, size_t len)
Oid fn_oid
Definition fmgr.h:59
FmgrInfo rng_canonical_finfo
Definition typcache.h:103

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

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

◆ build_bound_expr()

static Expr * build_bound_expr ( Expr elemExpr,
Datum  val,
bool  isLowerBound,
bool  isInclusive,
TypeCacheEntry typeCache,
Oid  opfamily,
Oid  rng_collation 
)
static

Definition at line 3142 of file rangetypes.c.

3146{
3147 Oid elemType = typeCache->type_id;
3148 int16 elemTypeLen = typeCache->typlen;
3149 bool elemByValue = typeCache->typbyval;
3150 Oid elemCollation = typeCache->typcollation;
3151 int16 strategy;
3152 Oid oproid;
3153 Expr *constExpr;
3154
3155 /* Identify the comparison operator to use */
3156 if (isLowerBound)
3158 else
3160
3161 /*
3162 * We could use exprType(elemExpr) here, if it ever becomes possible that
3163 * elemExpr is not the exact same type as the range elements.
3164 */
3165 oproid = get_opfamily_member(opfamily, elemType, elemType, strategy);
3166
3167 /* We don't really expect failure here, but just in case ... */
3168 if (!OidIsValid(oproid))
3169 return NULL;
3170
3171 /* OK, convert "val" to a full-fledged Const node, and make the OpExpr */
3173 -1,
3176 val,
3177 false,
3178 elemByValue);
3179
3180 return make_opclause(oproid,
3181 BOOLOID,
3182 false,
3183 elemExpr,
3184 constExpr,
3185 InvalidOid,
3186 rng_collation);
3187}

References BTGreaterEqualStrategyNumber, BTGreaterStrategyNumber, BTLessEqualStrategyNumber, BTLessStrategyNumber, fb(), get_opfamily_member(), InvalidOid, make_opclause(), makeConst(), OidIsValid, and val.

Referenced by find_simplified_clause().

◆ daterange_canonical()

Datum daterange_canonical ( PG_FUNCTION_ARGS  )

Definition at line 1792 of file rangetypes.c.

1793{
1795 Node *escontext = fcinfo->context;
1796 TypeCacheEntry *typcache;
1799 bool empty;
1800
1801 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1802
1803 range_deserialize(typcache, r, &lower, &upper, &empty);
1804
1805 if (empty)
1807
1808 if (!lower.infinite && !DATE_NOT_FINITE(DatumGetDateADT(lower.val)) &&
1809 !lower.inclusive)
1810 {
1812
1813 /* Check for overflow -- note we already eliminated PG_INT32_MAX */
1814 bnd++;
1815 if (unlikely(!IS_VALID_DATE(bnd)))
1816 ereturn(escontext, (Datum) 0,
1818 errmsg("date out of range")));
1819 lower.val = DateADTGetDatum(bnd);
1820 lower.inclusive = true;
1821 }
1822
1823 if (!upper.infinite && !DATE_NOT_FINITE(DatumGetDateADT(upper.val)) &&
1824 upper.inclusive)
1825 {
1827
1828 /* Check for overflow -- note we already eliminated PG_INT32_MAX */
1829 bnd++;
1830 if (unlikely(!IS_VALID_DATE(bnd)))
1831 ereturn(escontext, (Datum) 0,
1833 errmsg("date out of range")));
1834 upper.val = DateADTGetDatum(bnd);
1835 upper.inclusive = false;
1836 }
1837
1839 false, escontext));
1840}
#define unlikely(x)
Definition c.h:432
#define IS_VALID_DATE(d)
Definition timestamp.h:262
static Datum DateADTGetDatum(DateADT X)
Definition date.h:78
#define DATE_NOT_FINITE(j)
Definition date.h:49
int32 DateADT
Definition date.h:21
static DateADT DatumGetDateADT(Datum X)
Definition date.h:60
int errcode(int sqlerrcode)
Definition elog.c:874
#define ereturn(context, dummy_value,...)
Definition elog.h:278
static char * errmsg
RangeType * range_serialize(TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper, bool empty, struct Node *escontext)
TypeCacheEntry * range_get_typcache(FunctionCallInfo fcinfo, Oid rngtypid)
#define PG_RETURN_RANGE_P(x)
Definition rangetypes.h:92
#define PG_GETARG_RANGE_P(n)
Definition rangetypes.h:90

References DATE_NOT_FINITE, DateADTGetDatum(), DatumGetDateADT(), ereturn, errcode(), errmsg, fb(), IS_VALID_DATE, lower(), PG_GETARG_RANGE_P, PG_RETURN_RANGE_P, range_deserialize(), range_get_typcache(), range_serialize(), RangeTypeGetOid, unlikely, and upper().

◆ daterange_subdiff()

Datum daterange_subdiff ( PG_FUNCTION_ARGS  )

Definition at line 1889 of file rangetypes.c.

1890{
1891 int32 v1 = PG_GETARG_INT32(0);
1893
1894 PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
1895}
double float8
Definition c.h:716
int32_t int32
Definition c.h:614
#define PG_RETURN_FLOAT8(x)
Definition fmgr.h:369
#define PG_GETARG_INT32(n)
Definition fmgr.h:269

References fb(), PG_GETARG_INT32, and PG_RETURN_FLOAT8.

◆ datum_compute_size()

static Size datum_compute_size ( Size  data_length,
Datum  val,
bool  typbyval,
char  typalign,
int16  typlen,
char  typstorage 
)
static

Definition at line 2917 of file rangetypes.c.

2919{
2920 if (TYPE_IS_PACKABLE(typlen, typstorage) &&
2922 {
2923 /*
2924 * we're anticipating converting to a short varlena header, so adjust
2925 * length and don't count any alignment
2926 */
2928 }
2929 else
2930 {
2931 data_length = att_align_datum(data_length, typalign, typlen, val);
2932 data_length = att_addlength_datum(data_length, typlen, val);
2933 }
2934
2935 return data_length;
2936}

References att_addlength_datum, att_align_datum, DatumGetPointer(), typalign, TYPE_IS_PACKABLE, val, VARATT_CAN_MAKE_SHORT(), and VARATT_CONVERTED_SHORT_SIZE().

Referenced by range_serialize().

◆ datum_write()

static char * datum_write ( char ptr,
Datum  datum,
bool  typbyval,
char  typalign,
int16  typlen,
char  typstorage 
)
static

Definition at line 2943 of file rangetypes.c.

2945{
2946 Size data_length;
2947
2948 if (typbyval)
2949 {
2950 /* pass-by-value */
2951 ptr = (char *) att_align_nominal(ptr, typalign);
2952 store_att_byval(ptr, datum, typlen);
2953 data_length = typlen;
2954 }
2955 else if (typlen == -1)
2956 {
2957 /* varlena */
2958 Pointer val = DatumGetPointer(datum);
2959
2961 {
2962 /*
2963 * Throw error, because we must never put a toast pointer inside a
2964 * range object. Caller should have detoasted it.
2965 */
2966 elog(ERROR, "cannot store a toast pointer inside a range");
2967 data_length = 0; /* keep compiler quiet */
2968 }
2969 else if (VARATT_IS_SHORT(val))
2970 {
2971 /* no alignment for short varlenas */
2972 data_length = VARSIZE_SHORT(val);
2973 memcpy(ptr, val, data_length);
2974 }
2975 else if (TYPE_IS_PACKABLE(typlen, typstorage) &&
2977 {
2978 /* convert to short varlena -- no alignment */
2979 data_length = VARATT_CONVERTED_SHORT_SIZE(val);
2980 SET_VARSIZE_SHORT(ptr, data_length);
2981 memcpy(ptr + 1, VARDATA(val), data_length - 1);
2982 }
2983 else
2984 {
2985 /* full 4-byte header varlena */
2986 ptr = (char *) att_align_nominal(ptr, typalign);
2987 data_length = VARSIZE(val);
2988 memcpy(ptr, val, data_length);
2989 }
2990 }
2991 else if (typlen == -2)
2992 {
2993 /* cstring ... never needs alignment */
2995 data_length = strlen(DatumGetCString(datum)) + 1;
2996 memcpy(ptr, DatumGetPointer(datum), data_length);
2997 }
2998 else
2999 {
3000 /* fixed-length pass-by-reference */
3001 ptr = (char *) att_align_nominal(ptr, typalign);
3002 Assert(typlen > 0);
3003 data_length = typlen;
3004 memcpy(ptr, DatumGetPointer(datum), data_length);
3005 }
3006
3007 ptr += data_length;
3008
3009 return ptr;
3010}

References Assert, att_align_nominal, DatumGetCString(), DatumGetPointer(), elog, ERROR, fb(), SET_VARSIZE_SHORT(), store_att_byval(), typalign, TYPE_IS_PACKABLE, val, VARATT_CAN_MAKE_SHORT(), VARATT_CONVERTED_SHORT_SIZE(), VARATT_IS_EXTERNAL(), VARATT_IS_SHORT(), VARDATA(), VARSIZE(), and VARSIZE_SHORT().

Referenced by range_serialize().

◆ elem_contained_by_range()

Datum elem_contained_by_range ( PG_FUNCTION_ARGS  )

Definition at line 563 of file rangetypes.c.

564{
567 TypeCacheEntry *typcache;
568
569 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
570
572}
#define PG_GETARG_DATUM(n)
Definition fmgr.h:268
#define PG_RETURN_BOOL(x)
Definition fmgr.h:360
bool range_contains_elem_internal(TypeCacheEntry *typcache, const RangeType *r, Datum val)

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

◆ elem_contained_by_range_support()

Datum elem_contained_by_range_support ( PG_FUNCTION_ARGS  )

Definition at line 2421 of file rangetypes.c.

2422{
2424 Node *ret = NULL;
2425
2427 {
2429 FuncExpr *fexpr = req->fcall;
2430 Expr *leftop,
2431 *rightop;
2432
2433 Assert(list_length(fexpr->args) == 2);
2434 leftop = linitial(fexpr->args);
2435 rightop = lsecond(fexpr->args);
2436
2438 }
2439
2440 PG_RETURN_POINTER(ret);
2441}
#define PG_GETARG_POINTER(n)
Definition fmgr.h:277
#define PG_RETURN_POINTER(x)
Definition fmgr.h:363
static int list_length(const List *l)
Definition pg_list.h:152
#define linitial(l)
Definition pg_list.h:178
#define lsecond(l)
Definition pg_list.h:183

References Assert, fb(), find_simplified_clause(), IsA, linitial, list_length(), lsecond, PG_GETARG_POINTER, and PG_RETURN_POINTER.

◆ find_simplified_clause()

static Node * find_simplified_clause ( PlannerInfo root,
Expr rangeExpr,
Expr elemExpr 
)
static

Definition at line 3020 of file rangetypes.c.

3021{
3026 bool empty;
3027
3028 /* can't do anything unless the range is a non-null constant */
3029 if (!IsA(rangeExpr, Const) || ((Const *) rangeExpr)->constisnull)
3030 return NULL;
3032
3035 if (rangetypcache->rngelemtype == NULL)
3036 elog(ERROR, "type %u is not a range type", RangeTypeGetOid(range));
3037
3039
3040 if (empty)
3041 {
3042 /* if the range is empty, then there can be no matches */
3043 return makeBoolConst(false, false);
3044 }
3045 else if (lower.infinite && upper.infinite)
3046 {
3047 /* the range has infinite bounds, so it matches everything */
3048 return makeBoolConst(true, false);
3049 }
3050 else
3051 {
3052 /* at least one bound is available, we have something to work with */
3054 Oid opfamily = rangetypcache->rng_opfamily;
3055 Oid rng_collation = rangetypcache->rng_collation;
3056 Expr *lowerExpr = NULL;
3057 Expr *upperExpr = NULL;
3058
3059 if (!lower.infinite && !upper.infinite)
3060 {
3061 /*
3062 * When both bounds are present, we have a problem: the
3063 * "simplified" clause would need to evaluate the elemExpr twice.
3064 * That's definitely not okay if the elemExpr is volatile, and
3065 * it's also unattractive if the elemExpr is expensive.
3066 */
3068
3070 return NULL;
3071
3072 /*
3073 * We define "expensive" as "contains any subplan or more than 10
3074 * operators". Note that the subplan search has to be done
3075 * explicitly, since cost_qual_eval() will barf on unplanned
3076 * subselects.
3077 */
3079 return NULL;
3081 if (eval_cost.startup + eval_cost.per_tuple >
3082 10 * cpu_operator_cost)
3083 return NULL;
3084 }
3085
3086 /* Okay, try to build boundary comparison expressions */
3087 if (!lower.infinite)
3088 {
3090 lower.val,
3091 true,
3092 lower.inclusive,
3094 opfamily,
3095 rng_collation);
3096 if (lowerExpr == NULL)
3097 return NULL;
3098 }
3099
3100 if (!upper.infinite)
3101 {
3102 /* Copy the elemExpr if we need two copies */
3103 if (!lower.infinite)
3106 upper.val,
3107 false,
3108 upper.inclusive,
3110 opfamily,
3111 rng_collation);
3112 if (upperExpr == NULL)
3113 return NULL;
3114 }
3115
3116 if (lowerExpr != NULL && upperExpr != NULL)
3118 else if (lowerExpr != NULL)
3119 return (Node *) lowerExpr;
3120 else if (upperExpr != NULL)
3121 return (Node *) upperExpr;
3122 else
3123 {
3124 Assert(false);
3125 return NULL;
3126 }
3127 }
3128}

References Assert, build_bound_expr(), contain_subplans(), contain_volatile_functions(), copyObject, cost_qual_eval_node(), cpu_operator_cost, DatumGetRangeTypeP(), elog, ERROR, fb(), IsA, list_make2, lookup_type_cache(), lower(), make_andclause(), makeBoolConst(), range(), range_deserialize(), RangeTypeGetOid, TypeCacheEntry::rng_opfamily, TypeCacheEntry::rngelemtype, root, TYPECACHE_RANGE_INFO, and upper().

Referenced by elem_contained_by_range_support(), and range_contains_elem_support().

◆ get_range_io_data()

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

Definition at line 323 of file rangetypes.c.

324{
325 RangeIOData *cache = (RangeIOData *) fcinfo->flinfo->fn_extra;
326
327 if (cache == NULL || cache->typcache->type_id != rngtypid)
328 {
329 int16 typlen;
330 bool typbyval;
331 char typalign;
332 char typdelim;
333 Oid typiofunc;
334
335 cache = (RangeIOData *) MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
336 sizeof(RangeIOData));
338 if (cache->typcache->rngelemtype == NULL)
339 elog(ERROR, "type %u is not a range type", rngtypid);
340
341 /* get_type_io_data does more than we need, but is convenient */
342 get_type_io_data(cache->typcache->rngelemtype->type_id,
343 func,
344 &typlen,
345 &typbyval,
346 &typalign,
347 &typdelim,
348 &cache->typioparam,
349 &typiofunc);
350
351 if (!OidIsValid(typiofunc))
352 {
353 /* this could only happen for receive or send */
354 if (func == IOFunc_receive)
357 errmsg("no binary input function available for type %s",
358 format_type_be(cache->typcache->rngelemtype->type_id))));
359 else
362 errmsg("no binary output function available for type %s",
363 format_type_be(cache->typcache->rngelemtype->type_id))));
364 }
365 fmgr_info_cxt(typiofunc, &cache->typioproc,
366 fcinfo->flinfo->fn_mcxt);
367
368 fcinfo->flinfo->fn_extra = cache;
369 }
370
371 return cache;
372}
#define ereport(elevel,...)
Definition elog.h:150
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition fmgr.c:139
char * format_type_be(Oid type_oid)
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:2545
@ IOFunc_receive
Definition lsyscache.h:38
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition mcxt.c:1232
void * fn_extra
Definition fmgr.h:64
MemoryContext fn_mcxt
Definition fmgr.h:65
FmgrInfo * flinfo
Definition fmgr.h:87

References elog, ereport, errcode(), errmsg, ERROR, fb(), FunctionCallInfoBaseData::flinfo, fmgr_info_cxt(), FmgrInfo::fn_extra, FmgrInfo::fn_mcxt, format_type_be(), get_type_io_data(), IOFunc_receive, lookup_type_cache(), MemoryContextAlloc(), OidIsValid, TypeCacheEntry::rngelemtype, typalign, RangeIOData::typcache, TypeCacheEntry::type_id, TYPECACHE_RANGE_INFO, RangeIOData::typioparam, and RangeIOData::typioproc.

Referenced by range_in(), range_out(), range_recv(), and range_send().

◆ hash_range()

Datum hash_range ( PG_FUNCTION_ARGS  )

Definition at line 1564 of file rangetypes.c.

1565{
1567 uint32 result;
1568 TypeCacheEntry *typcache;
1572 bool empty;
1573 char flags;
1576
1577 check_stack_depth(); /* recurses when subtype is a range type */
1578
1579 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1580
1581 /* deserialize */
1582 range_deserialize(typcache, r, &lower, &upper, &empty);
1583 flags = range_get_flags(r);
1584
1585 /*
1586 * Look up the element type's hash function, if not done already.
1587 */
1588 scache = typcache->rngelemtype;
1589 if (!OidIsValid(scache->hash_proc_finfo.fn_oid))
1590 {
1592 if (!OidIsValid(scache->hash_proc_finfo.fn_oid))
1593 ereport(ERROR,
1595 errmsg("could not identify a hash function for type %s",
1596 format_type_be(scache->type_id))));
1597 }
1598
1599 /*
1600 * Apply the hash function to each bound.
1601 */
1602 if (RANGE_HAS_LBOUND(flags))
1604 typcache->rng_collation,
1605 lower.val));
1606 else
1607 lower_hash = 0;
1608
1609 if (RANGE_HAS_UBOUND(flags))
1611 typcache->rng_collation,
1612 upper.val));
1613 else
1614 upper_hash = 0;
1615
1616 /* Merge hashes of flags and bounds */
1617 result = hash_bytes_uint32((uint32) flags);
1618 result ^= lower_hash;
1619 result = pg_rotate_left32(result, 1);
1620 result ^= upper_hash;
1621
1622 PG_RETURN_INT32(result);
1623}
uint32_t uint32
Definition c.h:618
Datum FunctionCall1Coll(FmgrInfo *flinfo, Oid collation, Datum arg1)
Definition fmgr.c:1131
#define PG_RETURN_INT32(x)
Definition fmgr.h:355
uint32 hash_bytes_uint32(uint32 k)
Definition hashfn.c:610
static uint32 pg_rotate_left32(uint32 word, int n)
static uint32 DatumGetUInt32(Datum X)
Definition postgres.h:222
char range_get_flags(const RangeType *range)
#define RANGE_HAS_UBOUND(flags)
Definition rangetypes.h:51
#define RANGE_HAS_LBOUND(flags)
Definition rangetypes.h:47
void check_stack_depth(void)
Definition stack_depth.c:95
#define TYPECACHE_HASH_PROC_FINFO
Definition typcache.h:145

References check_stack_depth(), DatumGetUInt32(), ereport, errcode(), errmsg, ERROR, fb(), format_type_be(), FunctionCall1Coll(), hash_bytes_uint32(), lookup_type_cache(), lower(), OidIsValid, PG_GETARG_RANGE_P, PG_RETURN_INT32, pg_rotate_left32(), range_deserialize(), range_get_flags(), range_get_typcache(), RANGE_HAS_LBOUND, RANGE_HAS_UBOUND, RangeTypeGetOid, TypeCacheEntry::rng_collation, TypeCacheEntry::rngelemtype, TYPECACHE_HASH_PROC_FINFO, and upper().

◆ hash_range_extended()

Datum hash_range_extended ( PG_FUNCTION_ARGS  )

Definition at line 1630 of file rangetypes.c.

1631{
1633 Datum seed = PG_GETARG_DATUM(1);
1634 uint64 result;
1635 TypeCacheEntry *typcache;
1639 bool empty;
1640 char flags;
1643
1645
1646 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1647
1648 range_deserialize(typcache, r, &lower, &upper, &empty);
1649 flags = range_get_flags(r);
1650
1651 scache = typcache->rngelemtype;
1652 if (!OidIsValid(scache->hash_extended_proc_finfo.fn_oid))
1653 {
1654 scache = lookup_type_cache(scache->type_id,
1656 if (!OidIsValid(scache->hash_extended_proc_finfo.fn_oid))
1657 ereport(ERROR,
1659 errmsg("could not identify a hash function for type %s",
1660 format_type_be(scache->type_id))));
1661 }
1662
1663 if (RANGE_HAS_LBOUND(flags))
1664 lower_hash = DatumGetUInt64(FunctionCall2Coll(&scache->hash_extended_proc_finfo,
1665 typcache->rng_collation,
1666 lower.val,
1667 seed));
1668 else
1669 lower_hash = 0;
1670
1671 if (RANGE_HAS_UBOUND(flags))
1672 upper_hash = DatumGetUInt64(FunctionCall2Coll(&scache->hash_extended_proc_finfo,
1673 typcache->rng_collation,
1674 upper.val,
1675 seed));
1676 else
1677 upper_hash = 0;
1678
1679 /* Merge hashes of flags and bounds */
1681 DatumGetInt64(seed)));
1682 result ^= lower_hash;
1683 result = ROTATE_HIGH_AND_LOW_32BITS(result);
1684 result ^= upper_hash;
1685
1686 PG_RETURN_UINT64(result);
1687}
uint64_t uint64
Definition c.h:619
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Definition fmgr.c:1151
#define PG_RETURN_UINT64(x)
Definition fmgr.h:371
#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:423
static int64 DatumGetInt64(Datum X)
Definition postgres.h:403
#define TYPECACHE_HASH_EXTENDED_PROC_FINFO
Definition typcache.h:153

References check_stack_depth(), DatumGetInt64(), DatumGetUInt64(), ereport, errcode(), errmsg, ERROR, fb(), format_type_be(), FunctionCall2Coll(), hash_uint32_extended(), lookup_type_cache(), lower(), OidIsValid, PG_GETARG_DATUM, PG_GETARG_RANGE_P, PG_RETURN_UINT64, range_deserialize(), range_get_flags(), range_get_typcache(), RANGE_HAS_LBOUND, RANGE_HAS_UBOUND, RangeTypeGetOid, TypeCacheEntry::rng_collation, TypeCacheEntry::rngelemtype, ROTATE_HIGH_AND_LOW_32BITS, TYPECACHE_HASH_EXTENDED_PROC_FINFO, and upper().

◆ int4range_canonical()

Datum int4range_canonical ( PG_FUNCTION_ARGS  )

Definition at line 1698 of file rangetypes.c.

1699{
1701 Node *escontext = fcinfo->context;
1702 TypeCacheEntry *typcache;
1705 bool empty;
1706
1707 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1708
1709 range_deserialize(typcache, r, &lower, &upper, &empty);
1710
1711 if (empty)
1713
1714 if (!lower.infinite && !lower.inclusive)
1715 {
1717
1718 /* Handle possible overflow manually */
1719 if (unlikely(bnd == PG_INT32_MAX))
1720 ereturn(escontext, (Datum) 0,
1722 errmsg("integer out of range")));
1723 lower.val = Int32GetDatum(bnd + 1);
1724 lower.inclusive = true;
1725 }
1726
1727 if (!upper.infinite && upper.inclusive)
1728 {
1730
1731 /* Handle possible overflow manually */
1732 if (unlikely(bnd == PG_INT32_MAX))
1733 ereturn(escontext, (Datum) 0,
1735 errmsg("integer out of range")));
1736 upper.val = Int32GetDatum(bnd + 1);
1737 upper.inclusive = false;
1738 }
1739
1741 false, escontext));
1742}
#define PG_INT32_MAX
Definition c.h:675
static Datum Int32GetDatum(int32 X)
Definition postgres.h:212
static int32 DatumGetInt32(Datum X)
Definition postgres.h:202

References DatumGetInt32(), ereturn, errcode(), errmsg, fb(), Int32GetDatum(), lower(), PG_GETARG_RANGE_P, PG_INT32_MAX, PG_RETURN_RANGE_P, range_deserialize(), range_get_typcache(), range_serialize(), RangeTypeGetOid, unlikely, and upper().

◆ int4range_subdiff()

Datum int4range_subdiff ( PG_FUNCTION_ARGS  )

Definition at line 1855 of file rangetypes.c.

1856{
1857 int32 v1 = PG_GETARG_INT32(0);
1859
1860 PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
1861}

References fb(), PG_GETARG_INT32, and PG_RETURN_FLOAT8.

◆ int8range_canonical()

Datum int8range_canonical ( PG_FUNCTION_ARGS  )

Definition at line 1745 of file rangetypes.c.

1746{
1748 Node *escontext = fcinfo->context;
1749 TypeCacheEntry *typcache;
1752 bool empty;
1753
1754 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1755
1756 range_deserialize(typcache, r, &lower, &upper, &empty);
1757
1758 if (empty)
1760
1761 if (!lower.infinite && !lower.inclusive)
1762 {
1764
1765 /* Handle possible overflow manually */
1766 if (unlikely(bnd == PG_INT64_MAX))
1767 ereturn(escontext, (Datum) 0,
1769 errmsg("bigint out of range")));
1770 lower.val = Int64GetDatum(bnd + 1);
1771 lower.inclusive = true;
1772 }
1773
1774 if (!upper.infinite && upper.inclusive)
1775 {
1777
1778 /* Handle possible overflow manually */
1779 if (unlikely(bnd == PG_INT64_MAX))
1780 ereturn(escontext, (Datum) 0,
1782 errmsg("bigint out of range")));
1783 upper.val = Int64GetDatum(bnd + 1);
1784 upper.inclusive = false;
1785 }
1786
1788 false, escontext));
1789}
int64_t int64
Definition c.h:615
#define PG_INT64_MAX
Definition c.h:678
static Datum Int64GetDatum(int64 X)
Definition postgres.h:413

References DatumGetInt64(), ereturn, errcode(), errmsg, fb(), Int64GetDatum(), lower(), PG_GETARG_RANGE_P, PG_INT64_MAX, PG_RETURN_RANGE_P, range_deserialize(), range_get_typcache(), range_serialize(), RangeTypeGetOid, unlikely, and upper().

◆ int8range_subdiff()

Datum int8range_subdiff ( PG_FUNCTION_ARGS  )

Definition at line 1864 of file rangetypes.c.

1865{
1866 int64 v1 = PG_GETARG_INT64(0);
1868
1869 PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
1870}
#define PG_GETARG_INT64(n)
Definition fmgr.h:284

References fb(), PG_GETARG_INT64, and PG_RETURN_FLOAT8.

◆ make_empty_range()

RangeType * make_empty_range ( TypeCacheEntry typcache)

Definition at line 2399 of file rangetypes.c.

2400{
2403
2404 lower.val = (Datum) 0;
2405 lower.infinite = false;
2406 lower.inclusive = false;
2407 lower.lower = true;
2408
2409 upper.val = (Datum) 0;
2410 upper.infinite = false;
2411 upper.inclusive = false;
2412 upper.lower = false;
2413
2414 return make_range(typcache, &lower, &upper, true, NULL);
2415}
Datum val
Definition rangetypes.h:63

References fb(), lower(), make_range(), upper(), and RangeBound::val.

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

◆ make_range()

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

Definition at line 2186 of file rangetypes.c.

2188{
2190
2191 range = range_serialize(typcache, lower, upper, empty, escontext);
2192
2193 if (SOFT_ERROR_OCCURRED(escontext))
2194 return NULL;
2195
2196 /* no need to call canonical on empty ranges ... */
2197 if (OidIsValid(typcache->rng_canonical_finfo.fn_oid) &&
2199 {
2200 /* Do this the hard way so that we can pass escontext */
2201 LOCAL_FCINFO(fcinfo, 1);
2202 Datum result;
2203
2204 InitFunctionCallInfoData(*fcinfo, &typcache->rng_canonical_finfo, 1,
2205 InvalidOid, escontext, NULL);
2206
2207 fcinfo->args[0].value = RangeTypePGetDatum(range);
2208 fcinfo->args[0].isnull = false;
2209
2210 result = FunctionCallInvoke(fcinfo);
2211
2212 if (SOFT_ERROR_OCCURRED(escontext))
2213 return NULL;
2214
2215 /* Should not get a null result if there was no error */
2216 if (fcinfo->isnull)
2217 elog(ERROR, "function %u returned NULL",
2218 typcache->rng_canonical_finfo.fn_oid);
2219
2220 range = DatumGetRangeTypeP(result);
2221 }
2222
2223 return range;
2224}
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition fmgr.h:150
#define LOCAL_FCINFO(name, nargs)
Definition fmgr.h:110
#define FunctionCallInvoke(fcinfo)
Definition fmgr.h:172
#define SOFT_ERROR_OCCURRED(escontext)
Definition miscnodes.h:53
static Datum RangeTypePGetDatum(const RangeType *X)
Definition rangetypes.h:85

References DatumGetRangeTypeP(), elog, ERROR, fb(), FmgrInfo::fn_oid, FunctionCallInvoke, InitFunctionCallInfoData, InvalidOid, LOCAL_FCINFO, lower(), OidIsValid, range(), range_serialize(), RangeIsEmpty, RangeTypePGetDatum(), TypeCacheEntry::rng_canonical_finfo, SOFT_ERROR_OCCURRED, and upper().

Referenced by bounds_adjacent(), make_empty_range(), multirange_get_union_range(), range_constructor2(), range_constructor3(), range_in(), range_intersect_internal(), range_merge_from_multirange(), range_minus_internal(), range_minus_multi_internal(), range_recv(), range_split_internal(), range_super_union(), and range_union_internal().

◆ numrange_subdiff()

Datum numrange_subdiff ( PG_FUNCTION_ARGS  )

Definition at line 1873 of file rangetypes.c.

1874{
1875 Datum v1 = PG_GETARG_DATUM(0);
1879
1881
1883 numresult));
1884
1886}
Datum numeric_sub(PG_FUNCTION_ARGS)
Definition numeric.c:2941
Datum numeric_float8(PG_FUNCTION_ARGS)
Definition numeric.c:4574
#define DirectFunctionCall2(func, arg1, arg2)
Definition fmgr.h:686
#define DirectFunctionCall1(func, arg1)
Definition fmgr.h:684
static float8 DatumGetFloat8(Datum X)
Definition postgres.h:485

References DatumGetFloat8(), DirectFunctionCall1, DirectFunctionCall2, fb(), numeric_float8(), numeric_sub(), PG_GETARG_DATUM, and PG_RETURN_FLOAT8.

◆ range_adjacent()

Datum range_adjacent ( PG_FUNCTION_ARGS  )

Definition at line 834 of file rangetypes.c.

835{
838 TypeCacheEntry *typcache;
839
840 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
841
843}
bool range_adjacent_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition rangetypes.c:804

References fb(), PG_GETARG_RANGE_P, PG_RETURN_BOOL, range_adjacent_internal(), range_get_typcache(), and RangeTypeGetOid.

◆ range_adjacent_internal()

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

Definition at line 804 of file rangetypes.c.

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

References bounds_adjacent(), elog, ERROR, fb(), range_deserialize(), and RangeTypeGetOid.

Referenced by multirange_canonicalize(), range_adjacent(), range_gist_consistent_int_range(), range_gist_consistent_leaf_range(), range_union_internal(), and spg_range_quad_leaf_consistent().

◆ range_after()

Datum range_after ( PG_FUNCTION_ARGS  )

Definition at line 733 of file rangetypes.c.

734{
737 TypeCacheEntry *typcache;
738
739 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
740
742}
bool range_after_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition rangetypes.c:708

References fb(), PG_GETARG_RANGE_P, PG_RETURN_BOOL, range_after_internal(), range_get_typcache(), and RangeTypeGetOid.

◆ range_after_internal()

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

Definition at line 708 of file rangetypes.c.

709{
711 lower2;
713 upper2;
714 bool empty1,
715 empty2;
716
717 /* Different types should be prevented by ANYRANGE matching rules */
719 elog(ERROR, "range types do not match");
720
721 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
722 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
723
724 /* An empty range is neither before nor after any other range */
725 if (empty1 || empty2)
726 return false;
727
728 return (range_cmp_bounds(typcache, &lower1, &upper2) > 0);
729}
int range_cmp_bounds(TypeCacheEntry *typcache, const RangeBound *b1, const RangeBound *b2)

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

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

◆ range_before()

Datum range_before ( PG_FUNCTION_ARGS  )

Definition at line 695 of file rangetypes.c.

696{
699 TypeCacheEntry *typcache;
700
701 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
702
704}
bool range_before_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition rangetypes.c:670

References fb(), PG_GETARG_RANGE_P, PG_RETURN_BOOL, range_before_internal(), range_get_typcache(), and RangeTypeGetOid.

◆ range_before_internal()

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

Definition at line 670 of file rangetypes.c.

671{
673 lower2;
675 upper2;
676 bool empty1,
677 empty2;
678
679 /* Different types should be prevented by ANYRANGE matching rules */
681 elog(ERROR, "range types do not match");
682
683 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
684 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
685
686 /* An empty range is neither before nor after any other range */
687 if (empty1 || empty2)
688 return false;
689
690 return (range_cmp_bounds(typcache, &upper1, &lower2) < 0);
691}

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

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

◆ range_bound_escape()

static char * range_bound_escape ( const char value)
static

Definition at line 2771 of file rangetypes.c.

2772{
2773 bool nq;
2774 const char *ptr;
2776
2778
2779 /* Detect whether we need double quotes for this value */
2780 nq = (value[0] == '\0'); /* force quotes for empty string */
2781 for (ptr = value; *ptr; ptr++)
2782 {
2783 char ch = *ptr;
2784
2785 if (ch == '"' || ch == '\\' ||
2786 ch == '(' || ch == ')' ||
2787 ch == '[' || ch == ']' ||
2788 ch == ',' ||
2789 isspace((unsigned char) ch))
2790 {
2791 nq = true;
2792 break;
2793 }
2794 }
2795
2796 /* And emit the string */
2797 if (nq)
2799 for (ptr = value; *ptr; ptr++)
2800 {
2801 char ch = *ptr;
2802
2803 if (ch == '"' || ch == '\\')
2806 }
2807 if (nq)
2809
2810 return buf.data;
2811}
static struct @173 value
static char buf[DEFAULT_XLOG_SEG_SIZE]
void appendStringInfoChar(StringInfo str, char ch)
Definition stringinfo.c:242
void initStringInfo(StringInfo str)
Definition stringinfo.c:97

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

Referenced by range_deparse().

◆ range_cmp()

Datum range_cmp ( PG_FUNCTION_ARGS  )

Definition at line 1421 of file rangetypes.c.

1422{
1425 TypeCacheEntry *typcache;
1427 lower2;
1429 upper2;
1430 bool empty1,
1431 empty2;
1432 int cmp;
1433
1434 check_stack_depth(); /* recurses when subtype is a range type */
1435
1436 /* Different types should be prevented by ANYRANGE matching rules */
1438 elog(ERROR, "range types do not match");
1439
1440 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
1441
1442 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
1443 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
1444
1445 /* For b-tree use, empty ranges sort before all else */
1446 if (empty1 && empty2)
1447 cmp = 0;
1448 else if (empty1)
1449 cmp = -1;
1450 else if (empty2)
1451 cmp = 1;
1452 else
1453 {
1454 cmp = range_cmp_bounds(typcache, &lower1, &lower2);
1455 if (cmp == 0)
1456 cmp = range_cmp_bounds(typcache, &upper1, &upper2);
1457 }
1458
1459 PG_FREE_IF_COPY(r1, 0);
1460 PG_FREE_IF_COPY(r2, 1);
1461
1463}
#define PG_FREE_IF_COPY(ptr, n)
Definition fmgr.h:260

References check_stack_depth(), cmp(), elog, ERROR, fb(), PG_FREE_IF_COPY, PG_GETARG_RANGE_P, PG_RETURN_INT32, range_cmp_bounds(), range_deserialize(), range_get_typcache(), and RangeTypeGetOid.

Referenced by range_ge(), range_gt(), range_le(), and range_lt().

◆ range_cmp_bound_values()

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

Definition at line 2324 of file rangetypes.c.

2326{
2327 /*
2328 * First, handle cases involving infinity, which don't require invoking
2329 * the comparison proc.
2330 */
2331 if (b1->infinite && b2->infinite)
2332 {
2333 /*
2334 * Both are infinity, so they are equal unless one is lower and the
2335 * other not.
2336 */
2337 if (b1->lower == b2->lower)
2338 return 0;
2339 else
2340 return b1->lower ? -1 : 1;
2341 }
2342 else if (b1->infinite)
2343 return b1->lower ? -1 : 1;
2344 else if (b2->infinite)
2345 return b2->lower ? 1 : -1;
2346
2347 /*
2348 * Both boundaries are finite, so compare the held values.
2349 */
2351 typcache->rng_collation,
2352 b1->val, b2->val));
2353}
FmgrInfo rng_cmp_proc_finfo
Definition typcache.h:102

References DatumGetInt32(), fb(), FunctionCall2Coll(), TypeCacheEntry::rng_cmp_proc_finfo, and TypeCacheEntry::rng_collation.

Referenced by bounds_adjacent(), and range_serialize().

◆ range_cmp_bounds()

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

Definition at line 2250 of file rangetypes.c.

2251{
2252 int32 result;
2253
2254 /*
2255 * First, handle cases involving infinity, which don't require invoking
2256 * the comparison proc.
2257 */
2258 if (b1->infinite && b2->infinite)
2259 {
2260 /*
2261 * Both are infinity, so they are equal unless one is lower and the
2262 * other not.
2263 */
2264 if (b1->lower == b2->lower)
2265 return 0;
2266 else
2267 return b1->lower ? -1 : 1;
2268 }
2269 else if (b1->infinite)
2270 return b1->lower ? -1 : 1;
2271 else if (b2->infinite)
2272 return b2->lower ? 1 : -1;
2273
2274 /*
2275 * Both boundaries are finite, so compare the held values.
2276 */
2278 typcache->rng_collation,
2279 b1->val, b2->val));
2280
2281 /*
2282 * If the comparison is anything other than equal, we're done. If they
2283 * compare equal though, we still have to consider whether the boundaries
2284 * are inclusive or exclusive.
2285 */
2286 if (result == 0)
2287 {
2288 if (!b1->inclusive && !b2->inclusive)
2289 {
2290 /* both are exclusive */
2291 if (b1->lower == b2->lower)
2292 return 0;
2293 else
2294 return b1->lower ? 1 : -1;
2295 }
2296 else if (!b1->inclusive)
2297 return b1->lower ? 1 : -1;
2298 else if (!b2->inclusive)
2299 return b2->lower ? -1 : 1;
2300 else
2301 {
2302 /*
2303 * Both are inclusive and the values held are equal, so they are
2304 * equal regardless of whether they are upper or lower boundaries,
2305 * or a mix.
2306 */
2307 return 0;
2308 }
2309 }
2310
2311 return result;
2312}

References DatumGetInt32(), fb(), FunctionCall2Coll(), TypeCacheEntry::rng_cmp_proc_finfo, and TypeCacheEntry::rng_collation.

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

◆ range_compare()

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

Definition at line 2363 of file rangetypes.c.

2364{
2365 RangeType *r1 = *(RangeType *const *) key1;
2366 RangeType *r2 = *(RangeType *const *) key2;
2367 TypeCacheEntry *typcache = (TypeCacheEntry *) arg;
2372 bool empty1;
2373 bool empty2;
2374 int cmp;
2375
2376 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
2377 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
2378
2379 if (empty1 && empty2)
2380 cmp = 0;
2381 else if (empty1)
2382 cmp = -1;
2383 else if (empty2)
2384 cmp = 1;
2385 else
2386 {
2387 cmp = range_cmp_bounds(typcache, &lower1, &lower2);
2388 if (cmp == 0)
2389 cmp = range_cmp_bounds(typcache, &upper1, &upper2);
2390 }
2391
2392 return cmp;
2393}
Datum arg
Definition elog.c:1322

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

Referenced by multirange_canonicalize().

◆ range_constructor2()

Datum range_constructor2 ( PG_FUNCTION_ARGS  )

Definition at line 383 of file rangetypes.c.

384{
387 Oid rngtypid = get_fn_expr_rettype(fcinfo->flinfo);
389 TypeCacheEntry *typcache;
392
393 typcache = range_get_typcache(fcinfo, rngtypid);
394
395 lower.val = PG_ARGISNULL(0) ? (Datum) 0 : arg1;
396 lower.infinite = PG_ARGISNULL(0);
397 lower.inclusive = true;
398 lower.lower = true;
399
400 upper.val = PG_ARGISNULL(1) ? (Datum) 0 : arg2;
401 upper.infinite = PG_ARGISNULL(1);
402 upper.inclusive = false;
403 upper.lower = false;
404
405 range = make_range(typcache, &lower, &upper, false, NULL);
406
408}
Oid get_fn_expr_rettype(FmgrInfo *flinfo)
Definition fmgr.c:1854
#define PG_ARGISNULL(n)
Definition fmgr.h:209

References fb(), get_fn_expr_rettype(), lower(), make_range(), PG_ARGISNULL, PG_GETARG_DATUM, PG_RETURN_RANGE_P, range(), range_get_typcache(), and upper().

◆ range_constructor3()

Datum range_constructor3 ( PG_FUNCTION_ARGS  )

Definition at line 412 of file rangetypes.c.

413{
416 Oid rngtypid = get_fn_expr_rettype(fcinfo->flinfo);
418 TypeCacheEntry *typcache;
421 char flags;
422
423 typcache = range_get_typcache(fcinfo, rngtypid);
424
425 if (PG_ARGISNULL(2))
428 errmsg("range constructor flags argument must not be null")));
429
431
432 lower.val = PG_ARGISNULL(0) ? (Datum) 0 : arg1;
433 lower.infinite = PG_ARGISNULL(0);
434 lower.inclusive = (flags & RANGE_LB_INC) != 0;
435 lower.lower = true;
436
437 upper.val = PG_ARGISNULL(1) ? (Datum) 0 : arg2;
438 upper.infinite = PG_ARGISNULL(1);
439 upper.inclusive = (flags & RANGE_UB_INC) != 0;
440 upper.lower = false;
441
442 range = make_range(typcache, &lower, &upper, false, NULL);
443
445}
#define PG_GETARG_TEXT_PP(n)
Definition fmgr.h:310
static char range_parse_flags(const char *flags_str)
#define RANGE_UB_INC
Definition rangetypes.h:40
#define RANGE_LB_INC
Definition rangetypes.h:39
char * text_to_cstring(const text *t)
Definition varlena.c:217

References ereport, errcode(), errmsg, ERROR, fb(), get_fn_expr_rettype(), lower(), make_range(), PG_ARGISNULL, PG_GETARG_DATUM, PG_GETARG_TEXT_PP, PG_RETURN_RANGE_P, range(), range_get_typcache(), RANGE_LB_INC, range_parse_flags(), RANGE_UB_INC, text_to_cstring(), and upper().

◆ range_contained_by()

Datum range_contained_by ( PG_FUNCTION_ARGS  )

Definition at line 657 of file rangetypes.c.

658{
661 TypeCacheEntry *typcache;
662
663 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
664
666}
bool range_contained_by_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)

References fb(), PG_GETARG_RANGE_P, PG_RETURN_BOOL, range_contained_by_internal(), range_get_typcache(), and RangeTypeGetOid.

◆ range_contained_by_internal()

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

Definition at line 2852 of file rangetypes.c.

2853{
2854 return range_contains_internal(typcache, r2, r1);
2855}
bool range_contains_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)

References fb(), and range_contains_internal().

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

◆ range_contains()

Datum range_contains ( PG_FUNCTION_ARGS  )

Definition at line 644 of file rangetypes.c.

645{
648 TypeCacheEntry *typcache;
649
650 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
651
653}

References fb(), PG_GETARG_RANGE_P, PG_RETURN_BOOL, range_contains_internal(), range_get_typcache(), and RangeTypeGetOid.

◆ range_contains_elem()

Datum range_contains_elem ( PG_FUNCTION_ARGS  )

◆ range_contains_elem_internal()

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

Definition at line 2861 of file rangetypes.c.

2862{
2865 bool empty;
2866 int32 cmp;
2867
2868 range_deserialize(typcache, r, &lower, &upper, &empty);
2869
2870 if (empty)
2871 return false;
2872
2873 if (!lower.infinite)
2874 {
2876 typcache->rng_collation,
2877 lower.val, val));
2878 if (cmp > 0)
2879 return false;
2880 if (cmp == 0 && !lower.inclusive)
2881 return false;
2882 }
2883
2884 if (!upper.infinite)
2885 {
2887 typcache->rng_collation,
2888 upper.val, val));
2889 if (cmp < 0)
2890 return false;
2891 if (cmp == 0 && !upper.inclusive)
2892 return false;
2893 }
2894
2895 return true;
2896}

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

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

◆ range_contains_elem_support()

Datum range_contains_elem_support ( PG_FUNCTION_ARGS  )

Definition at line 2447 of file rangetypes.c.

2448{
2450 Node *ret = NULL;
2451
2453 {
2455 FuncExpr *fexpr = req->fcall;
2456 Expr *leftop,
2457 *rightop;
2458
2459 Assert(list_length(fexpr->args) == 2);
2460 leftop = linitial(fexpr->args);
2461 rightop = lsecond(fexpr->args);
2462
2464 }
2465
2466 PG_RETURN_POINTER(ret);
2467}

References Assert, fb(), find_simplified_clause(), IsA, linitial, list_length(), lsecond, PG_GETARG_POINTER, and PG_RETURN_POINTER.

◆ range_contains_internal()

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

Definition at line 2820 of file rangetypes.c.

2821{
2824 bool empty1;
2827 bool empty2;
2828
2829 /* Different types should be prevented by ANYRANGE matching rules */
2831 elog(ERROR, "range types do not match");
2832
2833 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
2834 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
2835
2836 /* If either range is empty, the answer is easy */
2837 if (empty2)
2838 return true;
2839 else if (empty1)
2840 return false;
2841
2842 /* Else we must have lower1 <= lower2 and upper1 >= upper2 */
2843 if (range_cmp_bounds(typcache, &lower1, &lower2) > 0)
2844 return false;
2845 if (range_cmp_bounds(typcache, &upper1, &upper2) < 0)
2846 return false;
2847
2848 return true;
2849}

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

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

◆ range_deparse()

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

Definition at line 2741 of file rangetypes.c.

2742{
2744
2745 if (flags & RANGE_EMPTY)
2747
2749
2750 appendStringInfoChar(&buf, (flags & RANGE_LB_INC) ? '[' : '(');
2751
2752 if (RANGE_HAS_LBOUND(flags))
2754
2756
2757 if (RANGE_HAS_UBOUND(flags))
2759
2760 appendStringInfoChar(&buf, (flags & RANGE_UB_INC) ? ']' : ')');
2761
2762 return buf.data;
2763}
char * pstrdup(const char *in)
Definition mcxt.c:1781
static char * range_bound_escape(const char *value)
#define RANGE_EMPTY
Definition rangetypes.h:38
#define RANGE_EMPTY_LITERAL
Definition rangetypes.h:32
void appendStringInfoString(StringInfo str, const char *s)
Definition stringinfo.c:230

References appendStringInfoChar(), appendStringInfoString(), buf, fb(), initStringInfo(), pstrdup(), range_bound_escape(), RANGE_EMPTY, RANGE_EMPTY_LITERAL, RANGE_HAS_LBOUND, RANGE_HAS_UBOUND, RANGE_LB_INC, and RANGE_UB_INC.

Referenced by range_out().

◆ range_deserialize()

void range_deserialize ( TypeCacheEntry typcache,
const RangeType range,
RangeBound lower,
RangeBound upper,
bool empty 
)

Definition at line 2090 of file rangetypes.c.

2092{
2093 char flags;
2094 int16 typlen;
2095 bool typbyval;
2096 char typalign;
2097 const char *ptr;
2098 Datum lbound;
2099 Datum ubound;
2100
2101 /* assert caller passed the right typcache entry */
2102 Assert(RangeTypeGetOid(range) == typcache->type_id);
2103
2104 /* fetch the flag byte from datum's last byte */
2105 flags = *((const char *) range + VARSIZE(range) - 1);
2106
2107 /* fetch information about range's element type */
2108 typlen = typcache->rngelemtype->typlen;
2109 typbyval = typcache->rngelemtype->typbyval;
2110 typalign = typcache->rngelemtype->typalign;
2111
2112 /* initialize data pointer just after the range OID */
2113 ptr = (const char *) (range + 1);
2114
2115 /* fetch lower bound, if any */
2116 if (RANGE_HAS_LBOUND(flags))
2117 {
2118 /* att_align_pointer cannot be necessary here */
2119 lbound = fetch_att(ptr, typbyval, typlen);
2120 ptr = (char *) att_addlength_pointer(ptr, typlen, ptr);
2121 }
2122 else
2123 lbound = (Datum) 0;
2124
2125 /* fetch upper bound, if any */
2126 if (RANGE_HAS_UBOUND(flags))
2127 {
2128 ptr = (char *) att_align_pointer(ptr, typalign, typlen, ptr);
2129 ubound = fetch_att(ptr, typbyval, typlen);
2130 /* no need for att_addlength_pointer */
2131 }
2132 else
2133 ubound = (Datum) 0;
2134
2135 /* emit results */
2136
2137 *empty = (flags & RANGE_EMPTY) != 0;
2138
2139 lower->val = lbound;
2140 lower->infinite = (flags & RANGE_LB_INF) != 0;
2141 lower->inclusive = (flags & RANGE_LB_INC) != 0;
2142 lower->lower = true;
2143
2144 upper->val = ubound;
2145 upper->infinite = (flags & RANGE_UB_INF) != 0;
2146 upper->inclusive = (flags & RANGE_UB_INC) != 0;
2147 upper->lower = false;
2148}
#define RANGE_UB_INF
Definition rangetypes.h:42
#define RANGE_LB_INF
Definition rangetypes.h:41
#define att_align_pointer(cur_offset, attalign, attlen, attptr)
Definition tupmacs.h:372
#define att_addlength_pointer(cur_offset, attlen, attptr)
Definition tupmacs.h:431
static Datum fetch_att(const void *T, bool attbyval, int attlen)
Definition tupmacs.h:108

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

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

◆ range_empty()

Datum range_empty ( PG_FUNCTION_ARGS  )

Definition at line 497 of file rangetypes.c.

498{
500 char flags = range_get_flags(r1);
501
503}

References fb(), PG_GETARG_RANGE_P, PG_RETURN_BOOL, RANGE_EMPTY, and range_get_flags().

◆ range_eq()

Datum range_eq ( PG_FUNCTION_ARGS  )

Definition at line 611 of file rangetypes.c.

612{
615 TypeCacheEntry *typcache;
616
617 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
618
620}
bool range_eq_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition rangetypes.c:579

References fb(), PG_GETARG_RANGE_P, PG_RETURN_BOOL, range_eq_internal(), range_get_typcache(), and RangeTypeGetOid.

◆ range_eq_internal()

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

Definition at line 579 of file rangetypes.c.

580{
582 lower2;
584 upper2;
585 bool empty1,
586 empty2;
587
588 /* Different types should be prevented by ANYRANGE matching rules */
590 elog(ERROR, "range types do not match");
591
592 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
593 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
594
595 if (empty1 && empty2)
596 return true;
597 if (empty1 != empty2)
598 return false;
599
600 if (range_cmp_bounds(typcache, &lower1, &lower2) != 0)
601 return false;
602
603 if (range_cmp_bounds(typcache, &upper1, &upper2) != 0)
604 return false;
605
606 return true;
607}

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

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

◆ range_fast_cmp()

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

Definition at line 1479 of file rangetypes.c.

1480{
1483 TypeCacheEntry *typcache;
1485 lower2;
1487 upper2;
1488 bool empty1,
1489 empty2;
1490 int cmp;
1491
1492 /* cache the range info between calls */
1493 if (ssup->ssup_extra == NULL)
1494 {
1496 ssup->ssup_extra =
1498 }
1499 typcache = ssup->ssup_extra;
1500
1501 range_deserialize(typcache, range_a, &lower1, &upper1, &empty1);
1502 range_deserialize(typcache, range_b, &lower2, &upper2, &empty2);
1503
1504 /* For b-tree use, empty ranges sort before all else */
1505 if (empty1 && empty2)
1506 cmp = 0;
1507 else if (empty1)
1508 cmp = -1;
1509 else if (empty2)
1510 cmp = 1;
1511 else
1512 {
1513 cmp = range_cmp_bounds(typcache, &lower1, &lower2);
1514 if (cmp == 0)
1515 cmp = range_cmp_bounds(typcache, &upper1, &upper2);
1516 }
1517
1518 if (range_a != DatumGetPointer(a))
1519 pfree(range_a);
1520 if (range_b != DatumGetPointer(b))
1521 pfree(range_b);
1522
1523 return cmp;
1524}
int b
Definition isn.c:74
int a
Definition isn.c:73
void pfree(void *pointer)
Definition mcxt.c:1616

References a, Assert, b, cmp(), DatumGetPointer(), DatumGetRangeTypeP(), fb(), lookup_type_cache(), pfree(), range_cmp_bounds(), range_deserialize(), RangeTypeGetOid, SortSupportData::ssup_extra, and TYPECACHE_RANGE_INFO.

Referenced by range_sortsupport().

◆ range_ge()

Datum range_ge ( PG_FUNCTION_ARGS  )

Definition at line 1545 of file rangetypes.c.

1546{
1547 int cmp = DatumGetInt32(range_cmp(fcinfo));
1548
1549 PG_RETURN_BOOL(cmp >= 0);
1550}
Datum range_cmp(PG_FUNCTION_ARGS)

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

◆ range_get_flags()

char range_get_flags ( const RangeType range)

Definition at line 2157 of file rangetypes.c.

2158{
2159 /* fetch the flag byte from datum's last byte */
2160 return *((const char *) range + VARSIZE(range) - 1);
2161}

References range(), and VARSIZE().

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

◆ range_get_typcache()

TypeCacheEntry * range_get_typcache ( FunctionCallInfo  fcinfo,
Oid  rngtypid 
)

◆ range_gt()

Datum range_gt ( PG_FUNCTION_ARGS  )

Definition at line 1553 of file rangetypes.c.

1554{
1555 int cmp = DatumGetInt32(range_cmp(fcinfo));
1556
1557 PG_RETURN_BOOL(cmp > 0);
1558}

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

◆ range_in()

Datum range_in ( PG_FUNCTION_ARGS  )

Definition at line 94 of file rangetypes.c.

95{
98 Oid typmod = PG_GETARG_INT32(2);
99 Node *escontext = fcinfo->context;
101 RangeIOData *cache;
102 char flags;
103 char *lbound_str;
104 char *ubound_str;
107
108 check_stack_depth(); /* recurses when subtype is a range type */
109
110 cache = get_range_io_data(fcinfo, rngtypoid, IOFunc_input);
111
112 /* parse */
113 if (!range_parse(input_str, &flags, &lbound_str, &ubound_str, escontext))
115
116 /* call element type's input function */
117 if (RANGE_HAS_LBOUND(flags))
119 cache->typioparam, typmod,
120 escontext, &lower.val))
122 if (RANGE_HAS_UBOUND(flags))
124 cache->typioparam, typmod,
125 escontext, &upper.val))
127
128 lower.infinite = (flags & RANGE_LB_INF) != 0;
129 lower.inclusive = (flags & RANGE_LB_INC) != 0;
130 lower.lower = true;
131 upper.infinite = (flags & RANGE_UB_INF) != 0;
132 upper.inclusive = (flags & RANGE_UB_INC) != 0;
133 upper.lower = false;
134
135 /* serialize and canonicalize */
136 range = make_range(cache->typcache, &lower, &upper,
137 flags & RANGE_EMPTY, escontext);
138
140}
bool InputFunctionCallSafe(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod, Node *escontext, Datum *result)
Definition fmgr.c:1586
#define PG_GETARG_OID(n)
Definition fmgr.h:275
#define PG_GETARG_CSTRING(n)
Definition fmgr.h:278
#define PG_RETURN_NULL()
Definition fmgr.h:346
@ IOFunc_input
Definition lsyscache.h:36
static bool range_parse(const char *string, char *flags, char **lbound_str, char **ubound_str, Node *escontext)
static RangeIOData * get_range_io_data(FunctionCallInfo fcinfo, Oid rngtypid, IOFuncSelector func)
Definition rangetypes.c:323
TypeCacheEntry * typcache
Definition rangetypes.c:57
FmgrInfo typioproc
Definition rangetypes.c:58

References check_stack_depth(), fb(), get_range_io_data(), InputFunctionCallSafe(), IOFunc_input, lower(), make_range(), PG_GETARG_CSTRING, PG_GETARG_INT32, PG_GETARG_OID, PG_RETURN_NULL, PG_RETURN_RANGE_P, range(), RANGE_EMPTY, RANGE_HAS_LBOUND, RANGE_HAS_UBOUND, RANGE_LB_INC, RANGE_LB_INF, range_parse(), RANGE_UB_INC, RANGE_UB_INF, RangeIOData::typcache, RangeIOData::typioparam, RangeIOData::typioproc, and upper().

◆ range_intersect()

Datum range_intersect ( PG_FUNCTION_ARGS  )

Definition at line 1133 of file rangetypes.c.

1134{
1137 TypeCacheEntry *typcache;
1138
1139 /* Different types should be prevented by ANYRANGE matching rules */
1141 elog(ERROR, "range types do not match");
1142
1143 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
1144
1146}
RangeType * range_intersect_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)

References elog, ERROR, fb(), PG_GETARG_RANGE_P, PG_RETURN_RANGE_P, range_get_typcache(), range_intersect_internal(), and RangeTypeGetOid.

◆ range_intersect_agg_transfn()

Datum range_intersect_agg_transfn ( PG_FUNCTION_ARGS  )

Definition at line 1391 of file rangetypes.c.

1392{
1394 Oid rngtypoid;
1395 TypeCacheEntry *typcache;
1396 RangeType *result;
1397 RangeType *current;
1398
1399 if (!AggCheckCallContext(fcinfo, &aggContext))
1400 elog(ERROR, "range_intersect_agg_transfn called in non-aggregate context");
1401
1402 rngtypoid = get_fn_expr_argtype(fcinfo->flinfo, 1);
1404 elog(ERROR, "range_intersect_agg must be called with a range");
1405
1406 typcache = range_get_typcache(fcinfo, rngtypoid);
1407
1408 /* strictness ensures these are non-null */
1409 result = PG_GETARG_RANGE_P(0);
1410 current = PG_GETARG_RANGE_P(1);
1411
1412 result = range_intersect_internal(typcache, result, current);
1413 PG_RETURN_RANGE_P(result);
1414}
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition fmgr.c:1876
bool type_is_range(Oid typid)
Definition lsyscache.c:2910
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition nodeAgg.c:4609

References AggCheckCallContext(), elog, ERROR, fb(), get_fn_expr_argtype(), PG_GETARG_RANGE_P, PG_RETURN_RANGE_P, range_get_typcache(), range_intersect_internal(), and type_is_range().

◆ range_intersect_internal()

RangeType * range_intersect_internal ( TypeCacheEntry typcache,
const RangeType r1,
const RangeType r2 
)

Definition at line 1149 of file rangetypes.c.

1150{
1152 lower2;
1154 upper2;
1155 bool empty1,
1156 empty2;
1159
1160 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
1161 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
1162
1163 if (empty1 || empty2 || !range_overlaps_internal(typcache, r1, r2))
1164 return make_empty_range(typcache);
1165
1166 if (range_cmp_bounds(typcache, &lower1, &lower2) >= 0)
1168 else
1170
1171 if (range_cmp_bounds(typcache, &upper1, &upper2) <= 0)
1173 else
1175
1176 return make_range(typcache, result_lower, result_upper, false, NULL);
1177}
bool range_overlaps_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition rangetypes.c:847
RangeType * make_empty_range(TypeCacheEntry *typcache)

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

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

◆ range_le()

Datum range_le ( PG_FUNCTION_ARGS  )

Definition at line 1537 of file rangetypes.c.

1538{
1539 int cmp = DatumGetInt32(range_cmp(fcinfo));
1540
1541 PG_RETURN_BOOL(cmp <= 0);
1542}

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

◆ range_lower()

Datum range_lower ( PG_FUNCTION_ARGS  )

Definition at line 452 of file rangetypes.c.

453{
455 TypeCacheEntry *typcache;
458 bool empty;
459
460 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
461
462 range_deserialize(typcache, r1, &lower, &upper, &empty);
463
464 /* Return NULL if there's no finite lower bound */
465 if (empty || lower.infinite)
467
469}
#define PG_RETURN_DATUM(x)
Definition fmgr.h:354

References fb(), lower(), PG_GETARG_RANGE_P, PG_RETURN_DATUM, PG_RETURN_NULL, range_deserialize(), range_get_typcache(), RangeTypeGetOid, and upper().

◆ range_lower_inc()

Datum range_lower_inc ( PG_FUNCTION_ARGS  )

Definition at line 507 of file rangetypes.c.

508{
510 char flags = range_get_flags(r1);
511
513}

References fb(), PG_GETARG_RANGE_P, PG_RETURN_BOOL, range_get_flags(), and RANGE_LB_INC.

◆ range_lower_inf()

Datum range_lower_inf ( PG_FUNCTION_ARGS  )

Definition at line 527 of file rangetypes.c.

528{
530 char flags = range_get_flags(r1);
531
533}

References fb(), PG_GETARG_RANGE_P, PG_RETURN_BOOL, range_get_flags(), and RANGE_LB_INF.

◆ range_lt()

Datum range_lt ( PG_FUNCTION_ARGS  )

Definition at line 1529 of file rangetypes.c.

1530{
1531 int cmp = DatumGetInt32(range_cmp(fcinfo));
1532
1533 PG_RETURN_BOOL(cmp < 0);
1534}

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

◆ range_merge()

Datum range_merge ( PG_FUNCTION_ARGS  )

Definition at line 1120 of file rangetypes.c.

1121{
1124 TypeCacheEntry *typcache;
1125
1126 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
1127
1128 PG_RETURN_RANGE_P(range_union_internal(typcache, r1, r2, false));
1129}
RangeType * range_union_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2, bool strict)

References fb(), PG_GETARG_RANGE_P, PG_RETURN_RANGE_P, range_get_typcache(), range_union_internal(), and RangeTypeGetOid.

◆ range_minus()

Datum range_minus ( PG_FUNCTION_ARGS  )

Definition at line 978 of file rangetypes.c.

979{
982 RangeType *ret;
983 TypeCacheEntry *typcache;
984
985 /* Different types should be prevented by ANYRANGE matching rules */
987 elog(ERROR, "range types do not match");
988
989 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
990
991 ret = range_minus_internal(typcache, r1, r2);
992 if (ret)
994 else
996}
RangeType * range_minus_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
Definition rangetypes.c:999

References elog, ERROR, fb(), PG_GETARG_RANGE_P, PG_RETURN_NULL, PG_RETURN_RANGE_P, range_get_typcache(), range_minus_internal(), and RangeTypeGetOid.

◆ range_minus_internal()

RangeType * range_minus_internal ( TypeCacheEntry typcache,
RangeType r1,
RangeType r2 
)

Definition at line 999 of file rangetypes.c.

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

References elog, ereport, errcode(), errmsg, ERROR, fb(), make_empty_range(), make_range(), range_cmp_bounds(), and range_deserialize().

Referenced by multirange_minus_internal(), and range_minus().

◆ range_minus_multi()

Datum range_minus_multi ( PG_FUNCTION_ARGS  )

Definition at line 1227 of file rangetypes.c.

1228{
1230 {
1231 RangeType *rs[2];
1232 int n;
1233 };
1234
1237 MemoryContext oldcontext;
1238
1239 /* stuff done only on the first call of the function */
1240 if (SRF_IS_FIRSTCALL())
1241 {
1242 RangeType *r1;
1243 RangeType *r2;
1244 Oid rngtypid;
1245 TypeCacheEntry *typcache;
1246
1247 /* create a function context for cross-call persistence */
1249
1250 /*
1251 * switch to memory context appropriate for multiple function calls
1252 */
1253 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1254
1255 r1 = PG_GETARG_RANGE_P(0);
1256 r2 = PG_GETARG_RANGE_P(1);
1257
1258 /* Different types should be prevented by ANYRANGE matching rules */
1260 elog(ERROR, "range types do not match");
1261
1262 /* allocate memory for user context */
1264
1265 /*
1266 * Initialize state. We can't store the range typcache in fn_extra
1267 * because the caller uses that for the SRF state.
1268 */
1271 if (typcache->rngelemtype == NULL)
1272 elog(ERROR, "type %u is not a range type", rngtypid);
1273 range_minus_multi_internal(typcache, r1, r2, fctx->rs, &fctx->n);
1274
1275 funcctx->user_fctx = fctx;
1276 MemoryContextSwitchTo(oldcontext);
1277 }
1278
1279 /* stuff done on every call of the function */
1281 fctx = funcctx->user_fctx;
1282
1283 if (funcctx->call_cntr < fctx->n)
1284 {
1285 /*
1286 * We must keep these on separate lines because SRF_RETURN_NEXT does
1287 * call_cntr++:
1288 */
1289 RangeType *ret = fctx->rs[funcctx->call_cntr];
1290
1292 }
1293 else
1294 /* do when there is no more left */
1296}
#define palloc_object(type)
Definition fe_memutils.h:74
#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
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124
void range_minus_multi_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2, RangeType **outputs, int *outputn)

References elog, ERROR, fb(), lookup_type_cache(), MemoryContextSwitchTo(), palloc_object, PG_GETARG_RANGE_P, range_minus_multi_internal(), RangeTypeGetOid, RangeTypePGetDatum(), TypeCacheEntry::rngelemtype, SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, SRF_RETURN_NEXT, and TYPECACHE_RANGE_INFO.

◆ range_minus_multi_internal()

void range_minus_multi_internal ( TypeCacheEntry typcache,
RangeType r1,
RangeType r2,
RangeType **  outputs,
int outputn 
)

Definition at line 1308 of file rangetypes.c.

1310{
1311 int cmp_l1l2,
1312 cmp_l1u2,
1313 cmp_u1l2,
1314 cmp_u1u2;
1316 lower2;
1318 upper2;
1319 bool empty1,
1320 empty2;
1321
1322 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
1323 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
1324
1325 if (empty1)
1326 {
1327 /* if r1 is empty then r1 - r2 is empty, so return zero results */
1328 *outputn = 0;
1329 return;
1330 }
1331 else if (empty2)
1332 {
1333 /* r2 is empty so the result is just r1 (which we know is not empty) */
1334 outputs[0] = r1;
1335 *outputn = 1;
1336 return;
1337 }
1338
1339 /*
1340 * Use the same logic as range_minus_internal, but support the split case
1341 */
1342 cmp_l1l2 = range_cmp_bounds(typcache, &lower1, &lower2);
1343 cmp_l1u2 = range_cmp_bounds(typcache, &lower1, &upper2);
1344 cmp_u1l2 = range_cmp_bounds(typcache, &upper1, &lower2);
1345 cmp_u1u2 = range_cmp_bounds(typcache, &upper1, &upper2);
1346
1348 {
1349 lower2.inclusive = !lower2.inclusive;
1350 lower2.lower = false; /* it will become the upper bound */
1351 outputs[0] = make_range(typcache, &lower1, &lower2, false, NULL);
1352
1353 upper2.inclusive = !upper2.inclusive;
1354 upper2.lower = true; /* it will become the lower bound */
1355 outputs[1] = make_range(typcache, &upper2, &upper1, false, NULL);
1356
1357 *outputn = 2;
1358 }
1359 else if (cmp_l1u2 > 0 || cmp_u1l2 < 0)
1360 {
1361 outputs[0] = r1;
1362 *outputn = 1;
1363 }
1364 else if (cmp_l1l2 >= 0 && cmp_u1u2 <= 0)
1365 {
1366 *outputn = 0;
1367 }
1368 else if (cmp_l1l2 <= 0 && cmp_u1l2 >= 0 && cmp_u1u2 <= 0)
1369 {
1370 lower2.inclusive = !lower2.inclusive;
1371 lower2.lower = false; /* it will become the upper bound */
1372 outputs[0] = make_range(typcache, &lower1, &lower2, false, NULL);
1373 *outputn = 1;
1374 }
1375 else if (cmp_l1l2 >= 0 && cmp_u1u2 >= 0 && cmp_l1u2 <= 0)
1376 {
1377 upper2.inclusive = !upper2.inclusive;
1378 upper2.lower = true; /* it will become the lower bound */
1379 outputs[0] = make_range(typcache, &upper2, &upper1, false, NULL);
1380 *outputn = 1;
1381 }
1382 else
1383 {
1384 elog(ERROR, "unexpected case in range_minus_multi");
1385 }
1386}

References elog, ERROR, fb(), make_range(), range_cmp_bounds(), and range_deserialize().

Referenced by range_minus_multi().

◆ range_ne()

Datum range_ne ( PG_FUNCTION_ARGS  )

Definition at line 631 of file rangetypes.c.

632{
635 TypeCacheEntry *typcache;
636
637 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
638
640}
bool range_ne_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition rangetypes.c:624

References fb(), PG_GETARG_RANGE_P, PG_RETURN_BOOL, range_get_typcache(), range_ne_internal(), and RangeTypeGetOid.

◆ range_ne_internal()

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

Definition at line 624 of file rangetypes.c.

625{
626 return (!range_eq_internal(typcache, r1, r2));
627}

References fb(), and range_eq_internal().

Referenced by range_ne().

◆ range_out()

Datum range_out ( PG_FUNCTION_ARGS  )

Definition at line 143 of file rangetypes.c.

144{
146 char *output_str;
147 RangeIOData *cache;
148 char flags;
149 char *lbound_str = NULL;
150 char *ubound_str = NULL;
153 bool empty;
154
155 check_stack_depth(); /* recurses when subtype is a range type */
156
158
159 /* deserialize */
160 range_deserialize(cache->typcache, range, &lower, &upper, &empty);
161 flags = range_get_flags(range);
162
163 /* call element type's output function */
164 if (RANGE_HAS_LBOUND(flags))
166 if (RANGE_HAS_UBOUND(flags))
168
169 /* construct result string */
171
173}
char * OutputFunctionCall(FmgrInfo *flinfo, Datum val)
Definition fmgr.c:1684
#define PG_RETURN_CSTRING(x)
Definition fmgr.h:364
@ IOFunc_output
Definition lsyscache.h:37
static char * range_deparse(char flags, const char *lbound_str, const char *ubound_str)

References check_stack_depth(), fb(), get_range_io_data(), IOFunc_output, lower(), OutputFunctionCall(), PG_GETARG_RANGE_P, PG_RETURN_CSTRING, range(), range_deparse(), range_deserialize(), range_get_flags(), RANGE_HAS_LBOUND, RANGE_HAS_UBOUND, RangeTypeGetOid, RangeIOData::typcache, RangeIOData::typioproc, and upper().

Referenced by anycompatiblerange_out(), and anyrange_out().

◆ range_overlaps()

Datum range_overlaps ( PG_FUNCTION_ARGS  )

Definition at line 880 of file rangetypes.c.

881{
884 TypeCacheEntry *typcache;
885
886 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
887
889}

References fb(), PG_GETARG_RANGE_P, PG_RETURN_BOOL, range_get_typcache(), range_overlaps_internal(), and RangeTypeGetOid.

◆ range_overlaps_internal()

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

Definition at line 847 of file rangetypes.c.

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

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

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

◆ range_overleft()

Datum range_overleft ( PG_FUNCTION_ARGS  )

Definition at line 921 of file rangetypes.c.

922{
925 TypeCacheEntry *typcache;
926
927 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
928
930}
bool range_overleft_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition rangetypes.c:893

References fb(), PG_GETARG_RANGE_P, PG_RETURN_BOOL, range_get_typcache(), range_overleft_internal(), and RangeTypeGetOid.

◆ range_overleft_internal()

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

Definition at line 893 of file rangetypes.c.

894{
896 lower2;
898 upper2;
899 bool empty1,
900 empty2;
901
902 /* Different types should be prevented by ANYRANGE matching rules */
904 elog(ERROR, "range types do not match");
905
906 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
907 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
908
909 /* An empty range is neither before nor after any other range */
910 if (empty1 || empty2)
911 return false;
912
913 if (range_cmp_bounds(typcache, &upper1, &upper2) <= 0)
914 return true;
915
916 return false;
917}

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

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

◆ range_overright()

Datum range_overright ( PG_FUNCTION_ARGS  )

Definition at line 962 of file rangetypes.c.

963{
966 TypeCacheEntry *typcache;
967
968 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
969
971}
bool range_overright_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition rangetypes.c:934

References fb(), PG_GETARG_RANGE_P, PG_RETURN_BOOL, range_get_typcache(), range_overright_internal(), and RangeTypeGetOid.

◆ range_overright_internal()

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

Definition at line 934 of file rangetypes.c.

935{
937 lower2;
939 upper2;
940 bool empty1,
941 empty2;
942
943 /* Different types should be prevented by ANYRANGE matching rules */
945 elog(ERROR, "range types do not match");
946
947 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
948 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
949
950 /* An empty range is neither before nor after any other range */
951 if (empty1 || empty2)
952 return false;
953
954 if (range_cmp_bounds(typcache, &lower1, &lower2) >= 0)
955 return true;
956
957 return false;
958}

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

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

◆ range_parse()

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

Definition at line 2556 of file rangetypes.c.

2558{
2559 const char *ptr = string;
2560 bool infinite;
2561
2562 *flags = 0;
2563
2564 /* consume whitespace */
2565 while (*ptr != '\0' && isspace((unsigned char) *ptr))
2566 ptr++;
2567
2568 /* check for empty range */
2571 {
2572 *flags = RANGE_EMPTY;
2573 *lbound_str = NULL;
2574 *ubound_str = NULL;
2575
2577
2578 /* the rest should be whitespace */
2579 while (*ptr != '\0' && isspace((unsigned char) *ptr))
2580 ptr++;
2581
2582 /* should have consumed everything */
2583 if (*ptr != '\0')
2584 ereturn(escontext, false,
2586 errmsg("malformed range literal: \"%s\"",
2587 string),
2588 errdetail("Junk after \"empty\" key word.")));
2589
2590 return true;
2591 }
2592
2593 if (*ptr == '[')
2594 {
2595 *flags |= RANGE_LB_INC;
2596 ptr++;
2597 }
2598 else if (*ptr == '(')
2599 ptr++;
2600 else
2601 ereturn(escontext, false,
2603 errmsg("malformed range literal: \"%s\"",
2604 string),
2605 errdetail("Missing left parenthesis or bracket.")));
2606
2607 ptr = range_parse_bound(string, ptr, lbound_str, &infinite, escontext);
2608 if (ptr == NULL)
2609 return false;
2610 if (infinite)
2611 *flags |= RANGE_LB_INF;
2612
2613 if (*ptr == ',')
2614 ptr++;
2615 else
2616 ereturn(escontext, false,
2618 errmsg("malformed range literal: \"%s\"",
2619 string),
2620 errdetail("Missing comma after lower bound.")));
2621
2622 ptr = range_parse_bound(string, ptr, ubound_str, &infinite, escontext);
2623 if (ptr == NULL)
2624 return false;
2625 if (infinite)
2626 *flags |= RANGE_UB_INF;
2627
2628 if (*ptr == ']')
2629 {
2630 *flags |= RANGE_UB_INC;
2631 ptr++;
2632 }
2633 else if (*ptr == ')')
2634 ptr++;
2635 else /* must be a comma */
2636 ereturn(escontext, false,
2638 errmsg("malformed range literal: \"%s\"",
2639 string),
2640 errdetail("Too many commas.")));
2641
2642 /* consume whitespace */
2643 while (*ptr != '\0' && isspace((unsigned char) *ptr))
2644 ptr++;
2645
2646 if (*ptr != '\0')
2647 ereturn(escontext, false,
2649 errmsg("malformed range literal: \"%s\"",
2650 string),
2651 errdetail("Junk after right parenthesis or bracket.")));
2652
2653 return true;
2654}
int errdetail(const char *fmt,...) pg_attribute_printf(1
int pg_strncasecmp(const char *s1, const char *s2, size_t n)
char string[11]
static const char * range_parse_bound(const char *string, const char *ptr, char **bound_str, bool *infinite, Node *escontext)

References ereturn, errcode(), errdetail(), errmsg, fb(), pg_strncasecmp(), RANGE_EMPTY, RANGE_EMPTY_LITERAL, RANGE_LB_INC, RANGE_LB_INF, range_parse_bound(), RANGE_UB_INC, and RANGE_UB_INF.

Referenced by range_in().

◆ range_parse_bound()

static const char * range_parse_bound ( const char string,
const char ptr,
char **  bound_str,
bool infinite,
Node escontext 
)
static

Definition at line 2672 of file rangetypes.c.

2674{
2676
2677 /* Check for null: completely empty input means null */
2678 if (*ptr == ',' || *ptr == ')' || *ptr == ']')
2679 {
2680 *bound_str = NULL;
2681 *infinite = true;
2682 }
2683 else
2684 {
2685 /* Extract string for this bound */
2686 bool inquote = false;
2687
2689 while (inquote || !(*ptr == ',' || *ptr == ')' || *ptr == ']'))
2690 {
2691 char ch = *ptr++;
2692
2693 if (ch == '\0')
2694 ereturn(escontext, NULL,
2696 errmsg("malformed range literal: \"%s\"",
2697 string),
2698 errdetail("Unexpected end of input.")));
2699 if (ch == '\\')
2700 {
2701 if (*ptr == '\0')
2702 ereturn(escontext, NULL,
2704 errmsg("malformed range literal: \"%s\"",
2705 string),
2706 errdetail("Unexpected end of input.")));
2707 appendStringInfoChar(&buf, *ptr++);
2708 }
2709 else if (ch == '"')
2710 {
2711 if (!inquote)
2712 inquote = true;
2713 else if (*ptr == '"')
2714 {
2715 /* doubled quote within quote sequence */
2716 appendStringInfoChar(&buf, *ptr++);
2717 }
2718 else
2719 inquote = false;
2720 }
2721 else
2723 }
2724
2725 *bound_str = buf.data;
2726 *infinite = false;
2727 }
2728
2729 return ptr;
2730}

References appendStringInfoChar(), buf, ereturn, errcode(), errdetail(), errmsg, fb(), and initStringInfo().

Referenced by range_parse().

◆ range_parse_flags()

static char range_parse_flags ( const char flags_str)
static

Definition at line 2481 of file rangetypes.c.

2482{
2483 char flags = 0;
2484
2485 if (flags_str[0] == '\0' ||
2486 flags_str[1] == '\0' ||
2487 flags_str[2] != '\0')
2488 ereport(ERROR,
2490 errmsg("invalid range bound flags"),
2491 errhint("Valid values are \"[]\", \"[)\", \"(]\", and \"()\".")));
2492
2493 switch (flags_str[0])
2494 {
2495 case '[':
2496 flags |= RANGE_LB_INC;
2497 break;
2498 case '(':
2499 break;
2500 default:
2501 ereport(ERROR,
2503 errmsg("invalid range bound flags"),
2504 errhint("Valid values are \"[]\", \"[)\", \"(]\", and \"()\".")));
2505 }
2506
2507 switch (flags_str[1])
2508 {
2509 case ']':
2510 flags |= RANGE_UB_INC;
2511 break;
2512 case ')':
2513 break;
2514 default:
2515 ereport(ERROR,
2517 errmsg("invalid range bound flags"),
2518 errhint("Valid values are \"[]\", \"[)\", \"(]\", and \"()\".")));
2519 }
2520
2521 return flags;
2522}
int errhint(const char *fmt,...) pg_attribute_printf(1

References ereport, errcode(), errhint(), errmsg, ERROR, fb(), RANGE_LB_INC, and RANGE_UB_INC.

Referenced by range_constructor3().

◆ range_recv()

Datum range_recv ( PG_FUNCTION_ARGS  )

Definition at line 183 of file rangetypes.c.

184{
187 int32 typmod = PG_GETARG_INT32(2);
189 RangeIOData *cache;
190 char flags;
193
194 check_stack_depth(); /* recurses when subtype is a range type */
195
197
198 /* receive the flags... */
199 flags = (unsigned char) pq_getmsgbyte(buf);
200
201 /*
202 * Mask out any unsupported flags, particularly RANGE_xB_NULL which would
203 * confuse following tests. Note that range_serialize will take care of
204 * cleaning up any inconsistencies in the remaining flags.
205 */
206 flags &= (RANGE_EMPTY |
211
212 /* receive the bounds ... */
213 if (RANGE_HAS_LBOUND(flags))
214 {
216 const char *bound_data = pq_getmsgbytes(buf, bound_len);
218
221
222 lower.val = ReceiveFunctionCall(&cache->typioproc,
223 &bound_buf,
224 cache->typioparam,
225 typmod);
226 pfree(bound_buf.data);
227 }
228 else
229 lower.val = (Datum) 0;
230
231 if (RANGE_HAS_UBOUND(flags))
232 {
234 const char *bound_data = pq_getmsgbytes(buf, bound_len);
236
239
240 upper.val = ReceiveFunctionCall(&cache->typioproc,
241 &bound_buf,
242 cache->typioparam,
243 typmod);
244 pfree(bound_buf.data);
245 }
246 else
247 upper.val = (Datum) 0;
248
250
251 /* finish constructing RangeBound representation */
252 lower.infinite = (flags & RANGE_LB_INF) != 0;
253 lower.inclusive = (flags & RANGE_LB_INC) != 0;
254 lower.lower = true;
255 upper.infinite = (flags & RANGE_UB_INF) != 0;
256 upper.inclusive = (flags & RANGE_UB_INC) != 0;
257 upper.lower = false;
258
259 /* serialize and canonicalize */
260 range = make_range(cache->typcache, &lower, &upper,
261 flags & RANGE_EMPTY, NULL);
262
264}
Datum ReceiveFunctionCall(FmgrInfo *flinfo, StringInfo buf, Oid typioparam, int32 typmod)
Definition fmgr.c:1698
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition pqformat.c:414
void pq_getmsgend(StringInfo msg)
Definition pqformat.c:634
int pq_getmsgbyte(StringInfo msg)
Definition pqformat.c:398
const char * pq_getmsgbytes(StringInfo msg, int datalen)
Definition pqformat.c:507
struct StringInfoData * StringInfo
Definition string.h:15
void appendBinaryStringInfo(StringInfo str, const void *data, int datalen)
Definition stringinfo.c:281

References appendBinaryStringInfo(), buf, check_stack_depth(), fb(), get_range_io_data(), initStringInfo(), IOFunc_receive, lower(), make_range(), pfree(), PG_GETARG_INT32, PG_GETARG_OID, PG_GETARG_POINTER, PG_RETURN_RANGE_P, pq_getmsgbyte(), pq_getmsgbytes(), pq_getmsgend(), pq_getmsgint(), range(), RANGE_EMPTY, RANGE_HAS_LBOUND, RANGE_HAS_UBOUND, RANGE_LB_INC, RANGE_LB_INF, RANGE_UB_INC, RANGE_UB_INF, ReceiveFunctionCall(), RangeIOData::typcache, RangeIOData::typioparam, RangeIOData::typioproc, and upper().

◆ range_send()

Datum range_send ( PG_FUNCTION_ARGS  )

Definition at line 267 of file rangetypes.c.

268{
271 RangeIOData *cache;
272 char flags;
275 bool empty;
276
277 check_stack_depth(); /* recurses when subtype is a range type */
278
280
282
283 /* deserialize */
284 range_deserialize(cache->typcache, range, &lower, &upper, &empty);
285 flags = range_get_flags(range);
286
287 /* construct output */
289
290 pq_sendbyte(&buf, flags);
291
292 if (RANGE_HAS_LBOUND(flags))
293 {
294 bytea *bound = SendFunctionCall(&cache->typioproc, lower.val);
295 uint32 bound_len = VARSIZE(bound) - VARHDRSZ;
296 char *bound_data = VARDATA(bound);
297
300 }
301
302 if (RANGE_HAS_UBOUND(flags))
303 {
304 bytea *bound = SendFunctionCall(&cache->typioproc, upper.val);
305 uint32 bound_len = VARSIZE(bound) - VARHDRSZ;
306 char *bound_data = VARDATA(bound);
307
310 }
311
313}
#define VARHDRSZ
Definition c.h:783
bytea * SendFunctionCall(FmgrInfo *flinfo, Datum val)
Definition fmgr.c:1745
#define PG_RETURN_BYTEA_P(x)
Definition fmgr.h:373
@ IOFunc_send
Definition lsyscache.h:39
void pq_sendbytes(StringInfo buf, const void *data, int datalen)
Definition pqformat.c:126
void pq_begintypsend(StringInfo buf)
Definition pqformat.c:325
bytea * pq_endtypsend(StringInfo buf)
Definition pqformat.c:345
static void pq_sendint32(StringInfo buf, uint32 i)
Definition pqformat.h:144
static void pq_sendbyte(StringInfo buf, uint8 byt)
Definition pqformat.h:160
Definition c.h:778

References buf, check_stack_depth(), fb(), get_range_io_data(), initStringInfo(), IOFunc_send, lower(), PG_GETARG_RANGE_P, PG_RETURN_BYTEA_P, pq_begintypsend(), pq_endtypsend(), pq_sendbyte(), pq_sendbytes(), pq_sendint32(), range(), range_deserialize(), range_get_flags(), RANGE_HAS_LBOUND, RANGE_HAS_UBOUND, RangeTypeGetOid, SendFunctionCall(), RangeIOData::typcache, RangeIOData::typioproc, upper(), VARDATA(), VARHDRSZ, and VARSIZE().

◆ range_serialize()

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

Definition at line 1961 of file rangetypes.c.

1963{
1965 int cmp;
1966 Size msize;
1967 Pointer ptr;
1968 int16 typlen;
1969 bool typbyval;
1970 char typalign;
1971 char typstorage;
1972 char flags = 0;
1973
1974 /*
1975 * Verify range is not invalid on its face, and construct flags value,
1976 * preventing any non-canonical combinations such as infinite+inclusive.
1977 */
1978 Assert(lower->lower);
1979 Assert(!upper->lower);
1980
1981 if (empty)
1982 flags |= RANGE_EMPTY;
1983 else
1984 {
1985 cmp = range_cmp_bound_values(typcache, lower, upper);
1986
1987 /* error check: if lower bound value is above upper, it's wrong */
1988 if (cmp > 0)
1989 ereturn(escontext, NULL,
1991 errmsg("range lower bound must be less than or equal to range upper bound")));
1992
1993 /* if bounds are equal, and not both inclusive, range is empty */
1994 if (cmp == 0 && !(lower->inclusive && upper->inclusive))
1995 flags |= RANGE_EMPTY;
1996 else
1997 {
1998 /* infinite boundaries are never inclusive */
1999 if (lower->infinite)
2000 flags |= RANGE_LB_INF;
2001 else if (lower->inclusive)
2002 flags |= RANGE_LB_INC;
2003 if (upper->infinite)
2004 flags |= RANGE_UB_INF;
2005 else if (upper->inclusive)
2006 flags |= RANGE_UB_INC;
2007 }
2008 }
2009
2010 /* Fetch information about range's element type */
2011 typlen = typcache->rngelemtype->typlen;
2012 typbyval = typcache->rngelemtype->typbyval;
2013 typalign = typcache->rngelemtype->typalign;
2014 typstorage = typcache->rngelemtype->typstorage;
2015
2016 /* Count space for varlena header and range type's OID */
2017 msize = sizeof(RangeType);
2019
2020 /* Count space for bounds */
2021 if (RANGE_HAS_LBOUND(flags))
2022 {
2023 /*
2024 * Make sure item to be inserted is not toasted. It is essential that
2025 * we not insert an out-of-line toast value pointer into a range
2026 * object, for the same reasons that arrays and records can't contain
2027 * them. It would work to store a compressed-in-line value, but we
2028 * prefer to decompress and then let compression be applied to the
2029 * whole range object if necessary. But, unlike arrays, we do allow
2030 * short-header varlena objects to stay as-is.
2031 */
2032 if (typlen == -1)
2034
2035 msize = datum_compute_size(msize, lower->val, typbyval, typalign,
2036 typlen, typstorage);
2037 }
2038
2039 if (RANGE_HAS_UBOUND(flags))
2040 {
2041 /* Make sure item to be inserted is not toasted */
2042 if (typlen == -1)
2044
2045 msize = datum_compute_size(msize, upper->val, typbyval, typalign,
2046 typlen, typstorage);
2047 }
2048
2049 /* Add space for flag byte */
2050 msize += sizeof(char);
2051
2052 /* Note: zero-fill is required here, just as in heap tuples */
2055
2056 /* Now fill in the datum */
2057 range->rangetypid = typcache->type_id;
2058
2059 ptr = (char *) (range + 1);
2060
2061 if (RANGE_HAS_LBOUND(flags))
2062 {
2063 Assert(lower->lower);
2064 ptr = datum_write(ptr, lower->val, typbyval, typalign, typlen,
2065 typstorage);
2066 }
2067
2068 if (RANGE_HAS_UBOUND(flags))
2069 {
2070 Assert(!upper->lower);
2071 ptr = datum_write(ptr, upper->val, typbyval, typalign, typlen,
2072 typstorage);
2073 }
2074
2075 *((char *) ptr) = flags;
2076
2077 return range;
2078}
#define MAXALIGN(LEN)
Definition c.h:898
#define PG_DETOAST_DATUM_PACKED(datum)
Definition fmgr.h:248
void * palloc0(Size size)
Definition mcxt.c:1417
static Datum PointerGetDatum(const void *X)
Definition postgres.h:342
static Size datum_compute_size(Size data_length, Datum val, bool typbyval, char typalign, int16 typlen, char typstorage)
char typstorage
Definition typcache.h:42
static void SET_VARSIZE(void *PTR, Size len)
Definition varatt.h:432

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

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

◆ range_set_contain_empty()

void range_set_contain_empty ( RangeType range)

Definition at line 2171 of file rangetypes.c.

2172{
2173 char *flagsp;
2174
2175 /* flag byte is datum's last byte */
2176 flagsp = (char *) range + VARSIZE(range) - 1;
2177
2179}
#define RANGE_CONTAIN_EMPTY
Definition rangetypes.h:45

References fb(), range(), RANGE_CONTAIN_EMPTY, and VARSIZE().

Referenced by range_super_union().

◆ range_sortsupport()

Datum range_sortsupport ( PG_FUNCTION_ARGS  )

Definition at line 1467 of file rangetypes.c.

1468{
1470
1471 ssup->comparator = range_fast_cmp;
1472 ssup->ssup_extra = NULL;
1473
1475}
struct SortSupportData * SortSupport
Definition execnodes.h:60
#define PG_RETURN_VOID()
Definition fmgr.h:350
static int range_fast_cmp(Datum a, Datum b, SortSupport ssup)
int(* comparator)(Datum x, Datum y, SortSupport ssup)

References SortSupportData::comparator, fb(), PG_GETARG_POINTER, PG_RETURN_VOID, range_fast_cmp(), and SortSupportData::ssup_extra.

◆ range_split_internal()

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

Definition at line 1188 of file rangetypes.c.

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

References fb(), make_range(), range_cmp_bounds(), and range_deserialize().

Referenced by multirange_minus_internal().

◆ range_union()

Datum range_union ( PG_FUNCTION_ARGS  )

Definition at line 1104 of file rangetypes.c.

1105{
1108 TypeCacheEntry *typcache;
1109
1110 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
1111
1112 PG_RETURN_RANGE_P(range_union_internal(typcache, r1, r2, true));
1113}

References fb(), PG_GETARG_RANGE_P, PG_RETURN_RANGE_P, range_get_typcache(), range_union_internal(), and RangeTypeGetOid.

◆ range_union_internal()

RangeType * range_union_internal ( TypeCacheEntry typcache,
RangeType r1,
RangeType r2,
bool  strict 
)

Definition at line 1058 of file rangetypes.c.

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

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

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

◆ range_upper()

Datum range_upper ( PG_FUNCTION_ARGS  )

Definition at line 473 of file rangetypes.c.

474{
476 TypeCacheEntry *typcache;
479 bool empty;
480
481 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
482
483 range_deserialize(typcache, r1, &lower, &upper, &empty);
484
485 /* Return NULL if there's no finite upper bound */
486 if (empty || upper.infinite)
488
490}

References fb(), lower(), PG_GETARG_RANGE_P, PG_RETURN_DATUM, PG_RETURN_NULL, range_deserialize(), range_get_typcache(), RangeTypeGetOid, and upper().

◆ range_upper_inc()

Datum range_upper_inc ( PG_FUNCTION_ARGS  )

Definition at line 517 of file rangetypes.c.

518{
520 char flags = range_get_flags(r1);
521
523}

References fb(), PG_GETARG_RANGE_P, PG_RETURN_BOOL, range_get_flags(), and RANGE_UB_INC.

◆ range_upper_inf()

Datum range_upper_inf ( PG_FUNCTION_ARGS  )

Definition at line 537 of file rangetypes.c.

538{
540 char flags = range_get_flags(r1);
541
543}

References fb(), PG_GETARG_RANGE_P, PG_RETURN_BOOL, range_get_flags(), and RANGE_UB_INF.

◆ tsrange_subdiff()

Datum tsrange_subdiff ( PG_FUNCTION_ARGS  )

Definition at line 1898 of file rangetypes.c.

1899{
1902 float8 result;
1903
1904 result = ((float8) v1 - (float8) v2) / USECS_PER_SEC;
1905 PG_RETURN_FLOAT8(result);
1906}
int64 Timestamp
Definition timestamp.h:38
#define USECS_PER_SEC
Definition timestamp.h:134
#define PG_GETARG_TIMESTAMP(n)
Definition timestamp.h:63

References fb(), PG_GETARG_TIMESTAMP, PG_RETURN_FLOAT8, and USECS_PER_SEC.

◆ tstzrange_subdiff()

Datum tstzrange_subdiff ( PG_FUNCTION_ARGS  )

Definition at line 1909 of file rangetypes.c.

1910{
1913 float8 result;
1914
1915 result = ((float8) v1 - (float8) v2) / USECS_PER_SEC;
1916 PG_RETURN_FLOAT8(result);
1917}

References fb(), PG_GETARG_TIMESTAMP, PG_RETURN_FLOAT8, and USECS_PER_SEC.