#include "utils/typcache.h"

Go to the source code of this file.
| #define DatumGetRangeType | ( | X | ) | ((RangeType *) PG_DETOAST_DATUM(X)) |
Definition at line 71 of file rangetypes.h.
Referenced by calc_hist_selectivity(), compute_range_stats(), make_range(), range_gist_class_split(), range_gist_consistent(), range_gist_consistent_int(), range_gist_consistent_leaf(), range_gist_double_sorting_split(), range_gist_fallback_split(), range_gist_penalty(), range_gist_picksplit(), range_gist_single_sorting_split(), range_gist_union(), rangesel(), spg_range_quad_choose(), spg_range_quad_inner_consistent(), spg_range_quad_leaf_consistent(), and spg_range_quad_picksplit().
| #define DatumGetRangeTypeCopy | ( | X | ) | ((RangeType *) PG_DETOAST_DATUM_COPY(X)) |
Definition at line 72 of file rangetypes.h.
| #define PG_GETARG_RANGE | ( | n | ) | DatumGetRangeType(PG_GETARG_DATUM(n)) |
Definition at line 74 of file rangetypes.h.
Referenced by daterange_canonical(), elem_contained_by_range(), hash_range(), int4range_canonical(), int8range_canonical(), range_adjacent(), range_after(), range_before(), range_cmp(), range_contained_by(), range_contains(), range_contains_elem(), range_empty(), range_eq(), range_gist_same(), range_intersect(), range_lower(), range_lower_inc(), range_lower_inf(), range_minus(), range_ne(), range_out(), range_overlaps(), range_overleft(), range_overright(), range_send(), range_union(), range_upper(), range_upper_inc(), and range_upper_inf().
| #define PG_GETARG_RANGE_COPY | ( | n | ) | DatumGetRangeTypeCopy(PG_GETARG_DATUM(n)) |
Definition at line 75 of file rangetypes.h.
| #define PG_RETURN_RANGE | ( | x | ) | return RangeTypeGetDatum(x) |
Definition at line 76 of file rangetypes.h.
Referenced by daterange_canonical(), int4range_canonical(), int8range_canonical(), range_constructor2(), range_constructor3(), range_gist_union(), range_in(), range_intersect(), range_minus(), range_recv(), and range_union().
| #define RANGE_CONTAIN_EMPTY 0x80 |
Definition at line 43 of file rangetypes.h.
Referenced by get_gist_range_class(), and range_super_union().
| #define RANGE_EMPTY 0x01 |
Definition at line 36 of file rangetypes.h.
Referenced by get_gist_range_class(), range_deparse(), range_empty(), range_in(), range_recv(), and range_super_union().
| #define RANGE_HAS_LBOUND | ( | flags | ) |
(!((flags) & (RANGE_EMPTY | \ RANGE_LB_NULL | \ RANGE_LB_INF)))
Definition at line 46 of file rangetypes.h.
Referenced by hash_range(), range_deparse(), range_deserialize(), range_in(), range_out(), range_recv(), range_send(), and range_serialize().
| #define RANGE_HAS_UBOUND | ( | flags | ) |
(!((flags) & (RANGE_EMPTY | \ RANGE_UB_NULL | \ RANGE_UB_INF)))
Definition at line 50 of file rangetypes.h.
Referenced by hash_range(), range_deparse(), range_deserialize(), range_in(), range_out(), range_recv(), range_send(), and range_serialize().
| #define RANGE_LB_INC 0x02 |
Definition at line 37 of file rangetypes.h.
Referenced by range_deparse(), range_lower_inc(), and range_recv().
| #define RANGE_LB_INF 0x08 |
Definition at line 39 of file rangetypes.h.
Referenced by get_gist_range_class(), range_lower_inf(), and range_recv().
| #define RANGE_LB_NULL 0x20 |
Definition at line 41 of file rangetypes.h.
| #define RANGE_UB_INC 0x04 |
Definition at line 38 of file rangetypes.h.
Referenced by range_deparse(), range_recv(), and range_upper_inc().
| #define RANGE_UB_INF 0x10 |
Definition at line 40 of file rangetypes.h.
Referenced by get_gist_range_class(), and range_upper_inf().
| #define RANGE_UB_NULL 0x40 |
Definition at line 42 of file rangetypes.h.
| #define RangeIsEmpty | ( | r | ) | ((range_get_flags(r) & RANGE_EMPTY) != 0) |
Definition at line 54 of file rangetypes.h.
Referenced by bounds_adjacent(), calc_rangesel(), make_range(), range_gist_consistent_int(), spg_range_quad_choose(), and spg_range_quad_inner_consistent().
| #define RangeIsOrContainsEmpty | ( | r | ) | ((range_get_flags(r) & (RANGE_EMPTY | RANGE_CONTAIN_EMPTY)) != 0) |
Definition at line 55 of file rangetypes.h.
Referenced by range_gist_consistent_int(), and range_gist_penalty().
| #define RANGESTRAT_ADJACENT 6 |
Definition at line 85 of file rangetypes.h.
Referenced by range_gist_consistent_int(), range_gist_consistent_leaf(), spg_range_quad_inner_consistent(), and spg_range_quad_leaf_consistent().
| #define RANGESTRAT_AFTER 5 |
Definition at line 84 of file rangetypes.h.
Referenced by range_gist_consistent_int(), range_gist_consistent_leaf(), spg_range_quad_inner_consistent(), and spg_range_quad_leaf_consistent().
| #define RANGESTRAT_BEFORE 1 |
Definition at line 80 of file rangetypes.h.
Referenced by range_gist_consistent_int(), range_gist_consistent_leaf(), spg_range_quad_inner_consistent(), and spg_range_quad_leaf_consistent().
| #define RANGESTRAT_CONTAINED_BY 8 |
Definition at line 87 of file rangetypes.h.
Referenced by range_gist_consistent_int(), range_gist_consistent_leaf(), spg_range_quad_inner_consistent(), and spg_range_quad_leaf_consistent().
| #define RANGESTRAT_CONTAINS 7 |
Definition at line 86 of file rangetypes.h.
Referenced by range_gist_consistent_int(), range_gist_consistent_leaf(), spg_range_quad_inner_consistent(), and spg_range_quad_leaf_consistent().
| #define RANGESTRAT_CONTAINS_ELEM 16 |
Definition at line 88 of file rangetypes.h.
Referenced by range_gist_consistent_int(), range_gist_consistent_leaf(), spg_range_quad_inner_consistent(), and spg_range_quad_leaf_consistent().
| #define RANGESTRAT_EQ 18 |
Definition at line 89 of file rangetypes.h.
Referenced by range_gist_consistent_int(), range_gist_consistent_leaf(), spg_range_quad_inner_consistent(), and spg_range_quad_leaf_consistent().
| #define RANGESTRAT_OVERLAPS 3 |
Definition at line 82 of file rangetypes.h.
Referenced by range_gist_consistent_int(), range_gist_consistent_leaf(), spg_range_quad_inner_consistent(), and spg_range_quad_leaf_consistent().
| #define RANGESTRAT_OVERLEFT 2 |
Definition at line 81 of file rangetypes.h.
Referenced by range_gist_consistent_int(), range_gist_consistent_leaf(), spg_range_quad_inner_consistent(), and spg_range_quad_leaf_consistent().
| #define RANGESTRAT_OVERRIGHT 4 |
Definition at line 83 of file rangetypes.h.
Referenced by range_gist_consistent_int(), range_gist_consistent_leaf(), spg_range_quad_inner_consistent(), and spg_range_quad_leaf_consistent().
| #define RangeTypeGetDatum | ( | X | ) | PointerGetDatum(X) |
Definition at line 73 of file rangetypes.h.
Referenced by make_range(), range_gist_class_split(), range_gist_fallback_split(), range_gist_single_sorting_split(), spg_range_quad_choose(), and spg_range_quad_picksplit().
| #define RangeTypeGetOid | ( | r | ) | ((r)->rangetypid) |
Definition at line 33 of file rangetypes.h.
Referenced by daterange_canonical(), elem_contained_by_range(), hash_range(), int4range_canonical(), int8range_canonical(), range_adjacent(), range_adjacent_internal(), range_after(), range_after_internal(), range_before(), range_before_internal(), range_cmp(), range_contained_by(), range_contains(), range_contains_elem(), range_contains_internal(), range_deserialize(), range_eq(), range_eq_internal(), range_gist_consistent(), range_gist_penalty(), range_gist_picksplit(), range_gist_same(), range_gist_union(), range_intersect(), range_lower(), range_minus(), range_ne(), range_out(), range_overlaps(), range_overlaps_internal(), range_overleft(), range_overleft_internal(), range_overright(), range_overright_internal(), range_send(), range_union(), range_upper(), spg_range_quad_choose(), spg_range_quad_inner_consistent(), spg_range_quad_leaf_consistent(), and spg_range_quad_picksplit().
| bool bounds_adjacent | ( | TypeCacheEntry * | typcache, | |
| RangeBound | bound1, | |||
| RangeBound | bound2 | |||
| ) |
Definition at line 731 of file rangetypes.c.
References Assert, FmgrInfo::fn_oid, RangeBound::inclusive, RangeBound::lower, make_range(), OidIsValid, range_cmp_bound_values(), RangeIsEmpty, and TypeCacheEntry::rng_canonical_finfo.
Referenced by range_adjacent_internal(), and spg_range_quad_inner_consistent().
{
int cmp;
Assert(!boundA.lower && boundB.lower);
cmp = range_cmp_bound_values(typcache, &boundA, &boundB);
if (cmp < 0)
{
RangeType *r;
/*
* Bounds do not overlap; see if there are points in between.
*/
/* in a continuous subtype, there are assumed to be points between */
if (!OidIsValid(typcache->rng_canonical_finfo.fn_oid))
return false;
/*
* The bounds are of a discrete range type; so make a range A..B and
* see if it's empty.
*/
/* flip the inclusion flags */
boundA.inclusive = !boundA.inclusive;
boundB.inclusive = !boundB.inclusive;
/* change upper/lower labels to avoid Assert failures */
boundA.lower = true;
boundB.lower = false;
r = make_range(typcache, &boundA, &boundB, false);
return RangeIsEmpty(r);
}
else if (cmp == 0)
return boundA.inclusive != boundB.inclusive;
else
return false; /* bounds overlap */
}
| Datum daterange_canonical | ( | PG_FUNCTION_ARGS | ) |
Definition at line 1307 of file rangetypes.c.
References date_pli(), DirectFunctionCall2, RangeBound::inclusive, RangeBound::infinite, Int32GetDatum, PG_GETARG_RANGE, PG_RETURN_RANGE, range_deserialize(), range_get_typcache(), range_serialize(), RangeTypeGetOid, and RangeBound::val.
{
RangeType *r = PG_GETARG_RANGE(0);
TypeCacheEntry *typcache;
RangeBound lower;
RangeBound upper;
bool empty;
typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
range_deserialize(typcache, r, &lower, &upper, &empty);
if (empty)
PG_RETURN_RANGE(r);
if (!lower.infinite && !lower.inclusive)
{
lower.val = DirectFunctionCall2(date_pli, lower.val, Int32GetDatum(1));
lower.inclusive = true;
}
if (!upper.infinite && upper.inclusive)
{
upper.val = DirectFunctionCall2(date_pli, upper.val, Int32GetDatum(1));
upper.inclusive = false;
}
PG_RETURN_RANGE(range_serialize(typcache, &lower, &upper, false));
}
| Datum daterange_subdiff | ( | PG_FUNCTION_ARGS | ) |
Definition at line 1384 of file rangetypes.c.
References PG_GETARG_INT32, and PG_RETURN_FLOAT8.
{
int32 v1 = PG_GETARG_INT32(0);
int32 v2 = PG_GETARG_INT32(1);
PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
}
| Datum elem_contained_by_range | ( | PG_FUNCTION_ARGS | ) |
Definition at line 531 of file rangetypes.c.
References PG_GETARG_DATUM, PG_GETARG_RANGE, PG_RETURN_BOOL, range_contains_elem_internal(), range_get_typcache(), RangeTypeGetOid, and val.
{
Datum val = PG_GETARG_DATUM(0);
RangeType *r = PG_GETARG_RANGE(1);
TypeCacheEntry *typcache;
typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
PG_RETURN_BOOL(range_contains_elem_internal(typcache, r, val));
}
| Datum hash_range | ( | PG_FUNCTION_ARGS | ) |
Definition at line 1177 of file rangetypes.c.
References DatumGetUInt32, ereport, errcode(), errmsg(), ERROR, FmgrInfo::fn_oid, format_type_be(), FunctionCall1Coll(), TypeCacheEntry::hash_proc_finfo, hash_uint32(), lookup_type_cache(), OidIsValid, PG_GETARG_RANGE, PG_RETURN_INT32, range_deserialize(), range_get_flags(), range_get_typcache(), RANGE_HAS_LBOUND, RANGE_HAS_UBOUND, RangeTypeGetOid, TypeCacheEntry::rng_collation, TypeCacheEntry::rngelemtype, TypeCacheEntry::type_id, TYPECACHE_HASH_PROC_FINFO, and RangeBound::val.
{
RangeType *r = PG_GETARG_RANGE(0);
uint32 result;
TypeCacheEntry *typcache;
TypeCacheEntry *scache;
RangeBound lower;
RangeBound upper;
bool empty;
char flags;
uint32 lower_hash;
uint32 upper_hash;
typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
/* deserialize */
range_deserialize(typcache, r, &lower, &upper, &empty);
flags = range_get_flags(r);
/*
* Look up the element type's hash function, if not done already.
*/
scache = typcache->rngelemtype;
if (!OidIsValid(scache->hash_proc_finfo.fn_oid))
{
scache = lookup_type_cache(scache->type_id, TYPECACHE_HASH_PROC_FINFO);
if (!OidIsValid(scache->hash_proc_finfo.fn_oid))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_FUNCTION),
errmsg("could not identify a hash function for type %s",
format_type_be(scache->type_id))));
}
/*
* Apply the hash function to each bound.
*/
if (RANGE_HAS_LBOUND(flags))
lower_hash = DatumGetUInt32(FunctionCall1Coll(&scache->hash_proc_finfo,
typcache->rng_collation,
lower.val));
else
lower_hash = 0;
if (RANGE_HAS_UBOUND(flags))
upper_hash = DatumGetUInt32(FunctionCall1Coll(&scache->hash_proc_finfo,
typcache->rng_collation,
upper.val));
else
upper_hash = 0;
/* Merge hashes of flags and bounds */
result = hash_uint32((uint32) flags);
result ^= lower_hash;
result = (result << 1) | (result >> 31);
result ^= upper_hash;
PG_RETURN_INT32(result);
}
| Datum int4range_canonical | ( | PG_FUNCTION_ARGS | ) |
Definition at line 1245 of file rangetypes.c.
References DirectFunctionCall2, RangeBound::inclusive, RangeBound::infinite, Int32GetDatum, int4pl(), PG_GETARG_RANGE, PG_RETURN_RANGE, range_deserialize(), range_get_typcache(), range_serialize(), RangeTypeGetOid, and RangeBound::val.
{
RangeType *r = PG_GETARG_RANGE(0);
TypeCacheEntry *typcache;
RangeBound lower;
RangeBound upper;
bool empty;
typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
range_deserialize(typcache, r, &lower, &upper, &empty);
if (empty)
PG_RETURN_RANGE(r);
if (!lower.infinite && !lower.inclusive)
{
lower.val = DirectFunctionCall2(int4pl, lower.val, Int32GetDatum(1));
lower.inclusive = true;
}
if (!upper.infinite && upper.inclusive)
{
upper.val = DirectFunctionCall2(int4pl, upper.val, Int32GetDatum(1));
upper.inclusive = false;
}
PG_RETURN_RANGE(range_serialize(typcache, &lower, &upper, false));
}
| Datum int4range_subdiff | ( | PG_FUNCTION_ARGS | ) |
Definition at line 1350 of file rangetypes.c.
References PG_GETARG_INT32, and PG_RETURN_FLOAT8.
{
int32 v1 = PG_GETARG_INT32(0);
int32 v2 = PG_GETARG_INT32(1);
PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
}
| Datum int8range_canonical | ( | PG_FUNCTION_ARGS | ) |
Definition at line 1276 of file rangetypes.c.
References DirectFunctionCall2, RangeBound::inclusive, RangeBound::infinite, Int64GetDatum(), int8pl(), PG_GETARG_RANGE, PG_RETURN_RANGE, range_deserialize(), range_get_typcache(), range_serialize(), RangeTypeGetOid, and RangeBound::val.
{
RangeType *r = PG_GETARG_RANGE(0);
TypeCacheEntry *typcache;
RangeBound lower;
RangeBound upper;
bool empty;
typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
range_deserialize(typcache, r, &lower, &upper, &empty);
if (empty)
PG_RETURN_RANGE(r);
if (!lower.infinite && !lower.inclusive)
{
lower.val = DirectFunctionCall2(int8pl, lower.val, Int64GetDatum(1));
lower.inclusive = true;
}
if (!upper.infinite && upper.inclusive)
{
upper.val = DirectFunctionCall2(int8pl, upper.val, Int64GetDatum(1));
upper.inclusive = false;
}
PG_RETURN_RANGE(range_serialize(typcache, &lower, &upper, false));
}
| Datum int8range_subdiff | ( | PG_FUNCTION_ARGS | ) |
Definition at line 1359 of file rangetypes.c.
References PG_GETARG_INT64, and PG_RETURN_FLOAT8.
{
int64 v1 = PG_GETARG_INT64(0);
int64 v2 = PG_GETARG_INT64(1);
PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
}
| RangeType* make_empty_range | ( | TypeCacheEntry * | typcache | ) |
Definition at line 1840 of file rangetypes.c.
References RangeBound::inclusive, RangeBound::infinite, RangeBound::lower, make_range(), and RangeBound::val.
Referenced by range_intersect(), and range_minus().
{
RangeBound lower;
RangeBound upper;
lower.val = (Datum) 0;
lower.infinite = false;
lower.inclusive = false;
lower.lower = true;
upper.val = (Datum) 0;
upper.infinite = false;
upper.inclusive = false;
upper.lower = false;
return make_range(typcache, &lower, &upper, true);
}
| RangeType* make_range | ( | TypeCacheEntry * | typcache, | |
| RangeBound * | lower, | |||
| RangeBound * | upper, | |||
| bool | empty | |||
| ) |
Definition at line 1691 of file rangetypes.c.
References DatumGetRangeType, FmgrInfo::fn_oid, FunctionCall1, OidIsValid, range_serialize(), RangeIsEmpty, RangeTypeGetDatum, and TypeCacheEntry::rng_canonical_finfo.
Referenced by bounds_adjacent(), make_empty_range(), range_constructor2(), range_constructor3(), range_in(), range_intersect(), range_minus(), range_recv(), range_super_union(), and range_union().
{
RangeType *range;
range = range_serialize(typcache, lower, upper, empty);
/* no need to call canonical on empty ranges ... */
if (OidIsValid(typcache->rng_canonical_finfo.fn_oid) &&
!RangeIsEmpty(range))
range = DatumGetRangeType(FunctionCall1(&typcache->rng_canonical_finfo,
RangeTypeGetDatum(range)));
return range;
}
| Datum numrange_subdiff | ( | PG_FUNCTION_ARGS | ) |
Definition at line 1368 of file rangetypes.c.
References DatumGetFloat8, DirectFunctionCall1, DirectFunctionCall2, numeric_float8(), numeric_sub(), PG_GETARG_DATUM, and PG_RETURN_FLOAT8.
{
Datum v1 = PG_GETARG_DATUM(0);
Datum v2 = PG_GETARG_DATUM(1);
Datum numresult;
float8 floatresult;
numresult = DirectFunctionCall2(numeric_sub, v1, v2);
floatresult = DatumGetFloat8(DirectFunctionCall1(numeric_float8,
numresult));
PG_RETURN_FLOAT8(floatresult);
}
| Datum range_adjacent | ( | PG_FUNCTION_ARGS | ) |
Definition at line 802 of file rangetypes.c.
References PG_GETARG_RANGE, PG_RETURN_BOOL, range_adjacent_internal(), range_get_typcache(), and RangeTypeGetOid.
Referenced by range_union().
{
RangeType *r1 = PG_GETARG_RANGE(0);
RangeType *r2 = PG_GETARG_RANGE(1);
TypeCacheEntry *typcache;
typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
PG_RETURN_BOOL(range_adjacent_internal(typcache, r1, r2));
}
| bool range_adjacent_internal | ( | TypeCacheEntry * | typcache, | |
| RangeType * | r1, | |||
| RangeType * | r2 | |||
| ) |
Definition at line 772 of file rangetypes.c.
References bounds_adjacent(), elog, ERROR, range_deserialize(), and RangeTypeGetOid.
Referenced by range_adjacent(), range_gist_consistent_int(), range_gist_consistent_leaf(), and spg_range_quad_leaf_consistent().
{
RangeBound lower1,
lower2;
RangeBound upper1,
upper2;
bool empty1,
empty2;
/* Different types should be prevented by ANYRANGE matching rules */
if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
elog(ERROR, "range types do not match");
range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
/* An empty range is not adjacent to any other range */
if (empty1 || empty2)
return false;
/*
* Given two ranges A..B and C..D, the ranges are adjacent if and only if
* B is adjacent to C, or D is adjacent to A.
*/
return (bounds_adjacent(typcache, upper1, lower2) ||
bounds_adjacent(typcache, upper2, lower1));
}
| Datum range_after | ( | PG_FUNCTION_ARGS | ) |
Definition at line 701 of file rangetypes.c.
References PG_GETARG_RANGE, PG_RETURN_BOOL, range_after_internal(), range_get_typcache(), and RangeTypeGetOid.
{
RangeType *r1 = PG_GETARG_RANGE(0);
RangeType *r2 = PG_GETARG_RANGE(1);
TypeCacheEntry *typcache;
typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
PG_RETURN_BOOL(range_after_internal(typcache, r1, r2));
}
| bool range_after_internal | ( | TypeCacheEntry * | typcache, | |
| RangeType * | r1, | |||
| RangeType * | r2 | |||
| ) |
Definition at line 676 of file rangetypes.c.
References elog, ERROR, range_cmp_bounds(), range_deserialize(), and RangeTypeGetOid.
Referenced by range_after(), range_gist_consistent_int(), range_gist_consistent_leaf(), and spg_range_quad_leaf_consistent().
{
RangeBound lower1,
lower2;
RangeBound upper1,
upper2;
bool empty1,
empty2;
/* Different types should be prevented by ANYRANGE matching rules */
if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
elog(ERROR, "range types do not match");
range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
/* An empty range is neither before nor after any other range */
if (empty1 || empty2)
return false;
return (range_cmp_bounds(typcache, &lower1, &upper2) > 0);
}
| Datum range_before | ( | PG_FUNCTION_ARGS | ) |
Definition at line 663 of file rangetypes.c.
References PG_GETARG_RANGE, PG_RETURN_BOOL, range_before_internal(), range_get_typcache(), and RangeTypeGetOid.
{
RangeType *r1 = PG_GETARG_RANGE(0);
RangeType *r2 = PG_GETARG_RANGE(1);
TypeCacheEntry *typcache;
typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
PG_RETURN_BOOL(range_before_internal(typcache, r1, r2));
}
| bool range_before_internal | ( | TypeCacheEntry * | typcache, | |
| RangeType * | r1, | |||
| RangeType * | r2 | |||
| ) |
Definition at line 638 of file rangetypes.c.
References elog, ERROR, range_cmp_bounds(), range_deserialize(), and RangeTypeGetOid.
Referenced by range_before(), range_gist_consistent_int(), range_gist_consistent_leaf(), and spg_range_quad_leaf_consistent().
{
RangeBound lower1,
lower2;
RangeBound upper1,
upper2;
bool empty1,
empty2;
/* Different types should be prevented by ANYRANGE matching rules */
if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
elog(ERROR, "range types do not match");
range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
/* An empty range is neither before nor after any other range */
if (empty1 || empty2)
return false;
return (range_cmp_bounds(typcache, &upper1, &lower2) < 0);
}
| Datum range_cmp | ( | PG_FUNCTION_ARGS | ) |
Definition at line 1104 of file rangetypes.c.
References elog, ERROR, PG_GETARG_RANGE, PG_RETURN_INT32, range_cmp_bounds(), range_deserialize(), range_get_typcache(), and RangeTypeGetOid.
Referenced by range_ge(), range_gt(), range_le(), and range_lt().
{
RangeType *r1 = PG_GETARG_RANGE(0);
RangeType *r2 = PG_GETARG_RANGE(1);
TypeCacheEntry *typcache;
RangeBound lower1,
lower2;
RangeBound upper1,
upper2;
bool empty1,
empty2;
int cmp;
/* Different types should be prevented by ANYRANGE matching rules */
if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
elog(ERROR, "range types do not match");
typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
/* For b-tree use, empty ranges sort before all else */
if (empty1 && empty2)
PG_RETURN_INT32(0);
else if (empty1)
PG_RETURN_INT32(-1);
else if (empty2)
PG_RETURN_INT32(1);
if ((cmp = range_cmp_bounds(typcache, &lower1, &lower2)) != 0)
PG_RETURN_INT32(cmp);
PG_RETURN_INT32(range_cmp_bounds(typcache, &upper1, &upper2));
}
| int range_cmp_bound_values | ( | TypeCacheEntry * | typcache, | |
| RangeBound * | b1, | |||
| RangeBound * | b2 | |||
| ) |
Definition at line 1805 of file rangetypes.c.
References DatumGetInt32, FunctionCall2Coll(), RangeBound::infinite, RangeBound::lower, TypeCacheEntry::rng_cmp_proc_finfo, TypeCacheEntry::rng_collation, and RangeBound::val.
Referenced by bounds_adjacent(), and range_serialize().
{
/*
* First, handle cases involving infinity, which don't require invoking
* the comparison proc.
*/
if (b1->infinite && b2->infinite)
{
/*
* Both are infinity, so they are equal unless one is lower and the
* other not.
*/
if (b1->lower == b2->lower)
return 0;
else
return b1->lower ? -1 : 1;
}
else if (b1->infinite)
return b1->lower ? -1 : 1;
else if (b2->infinite)
return b2->lower ? 1 : -1;
/*
* Both boundaries are finite, so compare the held values.
*/
return DatumGetInt32(FunctionCall2Coll(&typcache->rng_cmp_proc_finfo,
typcache->rng_collation,
b1->val, b2->val));
}
| int range_cmp_bounds | ( | TypeCacheEntry * | typcache, | |
| RangeBound * | b1, | |||
| RangeBound * | b2 | |||
| ) |
Definition at line 1731 of file rangetypes.c.
References DatumGetInt32, FunctionCall2Coll(), RangeBound::inclusive, RangeBound::infinite, RangeBound::lower, TypeCacheEntry::rng_cmp_proc_finfo, TypeCacheEntry::rng_collation, and RangeBound::val.
Referenced by bound_cmp(), calc_hist_selectivity_contained(), getQuadrant(), interval_cmp_lower(), interval_cmp_upper(), range_after_internal(), range_before_internal(), range_bound_qsort_cmp(), range_cmp(), range_contains_internal(), range_eq_internal(), range_gist_double_sorting_split(), range_gist_penalty(), range_intersect(), range_minus(), range_overlaps_internal(), range_overleft_internal(), range_overright_internal(), range_super_union(), range_union(), rbound_bsearch(), single_bound_cmp(), and spg_range_quad_inner_consistent().
{
int32 result;
/*
* First, handle cases involving infinity, which don't require invoking
* the comparison proc.
*/
if (b1->infinite && b2->infinite)
{
/*
* Both are infinity, so they are equal unless one is lower and the
* other not.
*/
if (b1->lower == b2->lower)
return 0;
else
return b1->lower ? -1 : 1;
}
else if (b1->infinite)
return b1->lower ? -1 : 1;
else if (b2->infinite)
return b2->lower ? 1 : -1;
/*
* Both boundaries are finite, so compare the held values.
*/
result = DatumGetInt32(FunctionCall2Coll(&typcache->rng_cmp_proc_finfo,
typcache->rng_collation,
b1->val, b2->val));
/*
* If the comparison is anything other than equal, we're done. If they
* compare equal though, we still have to consider whether the boundaries
* are inclusive or exclusive.
*/
if (result == 0)
{
if (!b1->inclusive && !b2->inclusive)
{
/* both are exclusive */
if (b1->lower == b2->lower)
return 0;
else
return b1->lower ? 1 : -1;
}
else if (!b1->inclusive)
return b1->lower ? 1 : -1;
else if (!b2->inclusive)
return b2->lower ? -1 : 1;
else
{
/*
* Both are inclusive and the values held are equal, so they are
* equal regardless of whether they are upper or lower boundaries,
* or a mix.
*/
return 0;
}
}
return result;
}
| Datum range_constructor2 | ( | PG_FUNCTION_ARGS | ) |
Definition at line 351 of file rangetypes.c.
References get_fn_expr_rettype(), RangeBound::inclusive, RangeBound::infinite, RangeBound::lower, make_range(), PG_ARGISNULL, PG_GETARG_DATUM, PG_RETURN_RANGE, range_get_typcache(), and RangeBound::val.
{
Datum arg1 = PG_GETARG_DATUM(0);
Datum arg2 = PG_GETARG_DATUM(1);
Oid rngtypid = get_fn_expr_rettype(fcinfo->flinfo);
RangeType *range;
TypeCacheEntry *typcache;
RangeBound lower;
RangeBound upper;
typcache = range_get_typcache(fcinfo, rngtypid);
lower.val = PG_ARGISNULL(0) ? (Datum) 0 : arg1;
lower.infinite = PG_ARGISNULL(0);
lower.inclusive = true;
lower.lower = true;
upper.val = PG_ARGISNULL(1) ? (Datum) 0 : arg2;
upper.infinite = PG_ARGISNULL(1);
upper.inclusive = false;
upper.lower = false;
range = make_range(typcache, &lower, &upper, false);
PG_RETURN_RANGE(range);
}
| Datum range_constructor3 | ( | PG_FUNCTION_ARGS | ) |
Definition at line 380 of file rangetypes.c.
References ereport, errcode(), errmsg(), ERROR, get_fn_expr_rettype(), RangeBound::inclusive, RangeBound::infinite, RangeBound::lower, make_range(), PG_ARGISNULL, PG_GETARG_DATUM, PG_GETARG_TEXT_P, PG_RETURN_RANGE, range_get_typcache(), range_parse_flags(), text_to_cstring(), and RangeBound::val.
{
Datum arg1 = PG_GETARG_DATUM(0);
Datum arg2 = PG_GETARG_DATUM(1);
Oid rngtypid = get_fn_expr_rettype(fcinfo->flinfo);
RangeType *range;
TypeCacheEntry *typcache;
RangeBound lower;
RangeBound upper;
char flags;
typcache = range_get_typcache(fcinfo, rngtypid);
if (PG_ARGISNULL(2))
ereport(ERROR,
(errcode(ERRCODE_DATA_EXCEPTION),
errmsg("range constructor flags argument must not be null")));
flags = range_parse_flags(text_to_cstring(PG_GETARG_TEXT_P(2)));
lower.val = PG_ARGISNULL(0) ? (Datum) 0 : arg1;
lower.infinite = PG_ARGISNULL(0);
lower.inclusive = (flags & RANGE_LB_INC) != 0;
lower.lower = true;
upper.val = PG_ARGISNULL(1) ? (Datum) 0 : arg2;
upper.infinite = PG_ARGISNULL(1);
upper.inclusive = (flags & RANGE_UB_INC) != 0;
upper.lower = false;
range = make_range(typcache, &lower, &upper, false);
PG_RETURN_RANGE(range);
}
| Datum range_contained_by | ( | PG_FUNCTION_ARGS | ) |
Definition at line 625 of file rangetypes.c.
References PG_GETARG_RANGE, PG_RETURN_BOOL, range_contained_by_internal(), range_get_typcache(), and RangeTypeGetOid.
{
RangeType *r1 = PG_GETARG_RANGE(0);
RangeType *r2 = PG_GETARG_RANGE(1);
TypeCacheEntry *typcache;
typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
PG_RETURN_BOOL(range_contained_by_internal(typcache, r1, r2));
}
| bool range_contained_by_internal | ( | TypeCacheEntry * | typcache, | |
| RangeType * | r1, | |||
| RangeType * | r2 | |||
| ) |
Definition at line 2231 of file rangetypes.c.
References range_contains_internal().
Referenced by range_contained_by(), range_gist_consistent_leaf(), and spg_range_quad_leaf_consistent().
{
return range_contains_internal(typcache, r2, r1);
}
| Datum range_contains | ( | PG_FUNCTION_ARGS | ) |
Definition at line 612 of file rangetypes.c.
References PG_GETARG_RANGE, PG_RETURN_BOOL, range_contains_internal(), range_get_typcache(), and RangeTypeGetOid.
{
RangeType *r1 = PG_GETARG_RANGE(0);
RangeType *r2 = PG_GETARG_RANGE(1);
TypeCacheEntry *typcache;
typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
PG_RETURN_BOOL(range_contains_internal(typcache, r1, r2));
}
| Datum range_contains_elem | ( | PG_FUNCTION_ARGS | ) |
Definition at line 518 of file rangetypes.c.
References PG_GETARG_DATUM, PG_GETARG_RANGE, PG_RETURN_BOOL, range_contains_elem_internal(), range_get_typcache(), RangeTypeGetOid, and val.
{
RangeType *r = PG_GETARG_RANGE(0);
Datum val = PG_GETARG_DATUM(1);
TypeCacheEntry *typcache;
typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
PG_RETURN_BOOL(range_contains_elem_internal(typcache, r, val));
}
| bool range_contains_elem_internal | ( | TypeCacheEntry * | typcache, | |
| RangeType * | r, | |||
| Datum | val | |||
| ) |
Definition at line 2240 of file rangetypes.c.
References DatumGetInt32, FunctionCall2Coll(), RangeBound::inclusive, RangeBound::infinite, range_deserialize(), TypeCacheEntry::rng_cmp_proc_finfo, TypeCacheEntry::rng_collation, and RangeBound::val.
Referenced by elem_contained_by_range(), range_contains_elem(), range_gist_consistent_int(), range_gist_consistent_leaf(), and spg_range_quad_leaf_consistent().
{
RangeBound lower;
RangeBound upper;
bool empty;
int32 cmp;
range_deserialize(typcache, r, &lower, &upper, &empty);
if (empty)
return false;
if (!lower.infinite)
{
cmp = DatumGetInt32(FunctionCall2Coll(&typcache->rng_cmp_proc_finfo,
typcache->rng_collation,
lower.val, val));
if (cmp > 0)
return false;
if (cmp == 0 && !lower.inclusive)
return false;
}
if (!upper.infinite)
{
cmp = DatumGetInt32(FunctionCall2Coll(&typcache->rng_cmp_proc_finfo,
typcache->rng_collation,
upper.val, val));
if (cmp < 0)
return false;
if (cmp == 0 && !upper.inclusive)
return false;
}
return true;
}
| bool range_contains_internal | ( | TypeCacheEntry * | typcache, | |
| RangeType * | r1, | |||
| RangeType * | r2 | |||
| ) |
Definition at line 2199 of file rangetypes.c.
References elog, ERROR, range_cmp_bounds(), range_deserialize(), and RangeTypeGetOid.
Referenced by range_contained_by_internal(), range_contains(), range_gist_consistent_int(), range_gist_consistent_leaf(), and spg_range_quad_leaf_consistent().
{
RangeBound lower1;
RangeBound upper1;
bool empty1;
RangeBound lower2;
RangeBound upper2;
bool empty2;
/* Different types should be prevented by ANYRANGE matching rules */
if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
elog(ERROR, "range types do not match");
range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
/* If either range is empty, the answer is easy */
if (empty2)
return true;
else if (empty1)
return false;
/* Else we must have lower1 <= lower2 and upper1 >= upper2 */
if (range_cmp_bounds(typcache, &lower1, &lower2) > 0)
return false;
if (range_cmp_bounds(typcache, &upper1, &upper2) < 0)
return false;
return true;
}
| void range_deserialize | ( | TypeCacheEntry * | typcache, | |
| RangeType * | range, | |||
| RangeBound * | lower, | |||
| RangeBound * | upper, | |||
| bool * | empty | |||
| ) |
Definition at line 1595 of file rangetypes.c.
References Assert, att_addlength_pointer, att_align_pointer, fetch_att, RangeBound::inclusive, RangeBound::infinite, RangeBound::lower, RANGE_HAS_LBOUND, RANGE_HAS_UBOUND, RangeTypeGetOid, TypeCacheEntry::rngelemtype, TypeCacheEntry::typalign, TypeCacheEntry::typbyval, TypeCacheEntry::type_id, TypeCacheEntry::typlen, RangeBound::val, and VARSIZE.
Referenced by calc_hist_selectivity(), compute_range_stats(), daterange_canonical(), getQuadrant(), hash_range(), int4range_canonical(), int8range_canonical(), range_adjacent_internal(), range_after_internal(), range_before_internal(), range_cmp(), range_contains_elem_internal(), range_contains_internal(), range_eq_internal(), range_gist_double_sorting_split(), range_gist_penalty(), range_gist_single_sorting_split(), range_intersect(), range_lower(), range_minus(), range_out(), range_overlaps_internal(), range_overleft_internal(), range_overright_internal(), range_send(), range_super_union(), range_union(), range_upper(), spg_range_quad_inner_consistent(), and spg_range_quad_picksplit().
{
char flags;
int16 typlen;
bool typbyval;
char typalign;
Pointer ptr;
Datum lbound;
Datum ubound;
/* assert caller passed the right typcache entry */
Assert(RangeTypeGetOid(range) == typcache->type_id);
/* fetch the flag byte from datum's last byte */
flags = *((char *) range + VARSIZE(range) - 1);
/* fetch information about range's element type */
typlen = typcache->rngelemtype->typlen;
typbyval = typcache->rngelemtype->typbyval;
typalign = typcache->rngelemtype->typalign;
/* initialize data pointer just after the range OID */
ptr = (Pointer) (range + 1);
/* fetch lower bound, if any */
if (RANGE_HAS_LBOUND(flags))
{
/* att_align_pointer cannot be necessary here */
lbound = fetch_att(ptr, typbyval, typlen);
ptr = (Pointer) att_addlength_pointer(ptr, typlen, ptr);
}
else
lbound = (Datum) 0;
/* fetch upper bound, if any */
if (RANGE_HAS_UBOUND(flags))
{
ptr = (Pointer) att_align_pointer(ptr, typalign, typlen, ptr);
ubound = fetch_att(ptr, typbyval, typlen);
/* no need for att_addlength_pointer */
}
else
ubound = (Datum) 0;
/* emit results */
*empty = (flags & RANGE_EMPTY) != 0;
lower->val = lbound;
lower->infinite = (flags & RANGE_LB_INF) != 0;
lower->inclusive = (flags & RANGE_LB_INC) != 0;
lower->lower = true;
upper->val = ubound;
upper->infinite = (flags & RANGE_UB_INF) != 0;
upper->inclusive = (flags & RANGE_UB_INC) != 0;
upper->lower = false;
}
| Datum range_empty | ( | PG_FUNCTION_ARGS | ) |
Definition at line 465 of file rangetypes.c.
References PG_GETARG_RANGE, PG_RETURN_BOOL, RANGE_EMPTY, and range_get_flags().
{
RangeType *r1 = PG_GETARG_RANGE(0);
char flags = range_get_flags(r1);
PG_RETURN_BOOL(flags & RANGE_EMPTY);
}
| Datum range_eq | ( | PG_FUNCTION_ARGS | ) |
Definition at line 579 of file rangetypes.c.
References PG_GETARG_RANGE, PG_RETURN_BOOL, range_eq_internal(), range_get_typcache(), and RangeTypeGetOid.
{
RangeType *r1 = PG_GETARG_RANGE(0);
RangeType *r2 = PG_GETARG_RANGE(1);
TypeCacheEntry *typcache;
typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
PG_RETURN_BOOL(range_eq_internal(typcache, r1, r2));
}
| bool range_eq_internal | ( | TypeCacheEntry * | typcache, | |
| RangeType * | r1, | |||
| RangeType * | r2 | |||
| ) |
Definition at line 547 of file rangetypes.c.
References elog, ERROR, range_cmp_bounds(), range_deserialize(), and RangeTypeGetOid.
Referenced by range_eq(), range_gist_consistent_leaf(), range_gist_same(), range_ne_internal(), and spg_range_quad_leaf_consistent().
{
RangeBound lower1,
lower2;
RangeBound upper1,
upper2;
bool empty1,
empty2;
/* Different types should be prevented by ANYRANGE matching rules */
if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
elog(ERROR, "range types do not match");
range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
if (empty1 && empty2)
return true;
if (empty1 != empty2)
return false;
if (range_cmp_bounds(typcache, &lower1, &lower2) != 0)
return false;
if (range_cmp_bounds(typcache, &upper1, &upper2) != 0)
return false;
return true;
}
| Datum range_ge | ( | PG_FUNCTION_ARGS | ) |
Definition at line 1158 of file rangetypes.c.
References cmp(), PG_RETURN_BOOL, and range_cmp().
{
int cmp = range_cmp(fcinfo);
PG_RETURN_BOOL(cmp >= 0);
}
| char range_get_flags | ( | RangeType * | range | ) |
Definition at line 1662 of file rangetypes.c.
References VARSIZE.
Referenced by get_gist_range_class(), hash_range(), 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().
{
/* fetch the flag byte from datum's last byte */
return *((char *) range + VARSIZE(range) - 1);
}
| TypeCacheEntry* range_get_typcache | ( | FunctionCallInfo | fcinfo, | |
| Oid | rngtypid | |||
| ) |
Definition at line 1442 of file rangetypes.c.
References elog, ERROR, FunctionCallInfoData::flinfo, FmgrInfo::fn_extra, lookup_type_cache(), NULL, TypeCacheEntry::rngelemtype, TypeCacheEntry::type_id, and TYPECACHE_RANGE_INFO.
Referenced by daterange_canonical(), elem_contained_by_range(), hash_range(), int4range_canonical(), int8range_canonical(), range_adjacent(), range_after(), range_before(), range_cmp(), range_constructor2(), range_constructor3(), range_contained_by(), range_contains(), range_contains_elem(), range_eq(), range_gist_consistent(), range_gist_penalty(), range_gist_picksplit(), range_gist_same(), range_gist_union(), range_intersect(), range_lower(), range_minus(), range_ne(), range_overlaps(), range_overleft(), range_overright(), range_typanalyze(), range_union(), range_upper(), rangesel(), spg_range_quad_choose(), spg_range_quad_inner_consistent(), spg_range_quad_leaf_consistent(), and spg_range_quad_picksplit().
{
TypeCacheEntry *typcache = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
if (typcache == NULL ||
typcache->type_id != rngtypid)
{
typcache = lookup_type_cache(rngtypid, TYPECACHE_RANGE_INFO);
if (typcache->rngelemtype == NULL)
elog(ERROR, "type %u is not a range type", rngtypid);
fcinfo->flinfo->fn_extra = (void *) typcache;
}
return typcache;
}
| Datum range_gist_compress | ( | PG_FUNCTION_ARGS | ) |
Definition at line 221 of file rangetypes_gist.c.
References PG_GETARG_POINTER, and PG_RETURN_POINTER.
{
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
PG_RETURN_POINTER(entry);
}
| Datum range_gist_consistent | ( | PG_FUNCTION_ARGS | ) |
Definition at line 172 of file rangetypes_gist.c.
References DatumGetRangeType, GIST_LEAF, GISTENTRY::key, PG_GETARG_DATUM, PG_GETARG_POINTER, PG_GETARG_UINT16, PG_RETURN_BOOL, range_get_typcache(), range_gist_consistent_int(), range_gist_consistent_leaf(), and RangeTypeGetOid.
{
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
Datum query = PG_GETARG_DATUM(1);
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
/* Oid subtype = PG_GETARG_OID(3); */
bool *recheck = (bool *) PG_GETARG_POINTER(4);
RangeType *key = DatumGetRangeType(entry->key);
TypeCacheEntry *typcache;
/* All operators served by this function are exact */
*recheck = false;
typcache = range_get_typcache(fcinfo, RangeTypeGetOid(key));
if (GIST_LEAF(entry))
PG_RETURN_BOOL(range_gist_consistent_leaf(typcache, strategy,
key, query));
else
PG_RETURN_BOOL(range_gist_consistent_int(typcache, strategy,
key, query));
}
| Datum range_gist_decompress | ( | PG_FUNCTION_ARGS | ) |
Definition at line 229 of file rangetypes_gist.c.
References PG_GETARG_POINTER, and PG_RETURN_POINTER.
{
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
PG_RETURN_POINTER(entry);
}
| Datum range_gist_penalty | ( | PG_FUNCTION_ARGS | ) |
Definition at line 247 of file rangetypes_gist.c.
References call_subtype_diff(), DatumGetRangeType, elog, ERROR, FmgrInfo::fn_oid, get_float4_infinity(), RangeBound::infinite, GISTENTRY::key, OidIsValid, PG_GETARG_POINTER, PG_RETURN_POINTER, range_cmp_bounds(), range_deserialize(), range_get_typcache(), RangeIsOrContainsEmpty, RangeTypeGetOid, TypeCacheEntry::rng_subdiff_finfo, and RangeBound::val.
{
GISTENTRY *origentry = (GISTENTRY *) PG_GETARG_POINTER(0);
GISTENTRY *newentry = (GISTENTRY *) PG_GETARG_POINTER(1);
float *penalty = (float *) PG_GETARG_POINTER(2);
RangeType *orig = DatumGetRangeType(origentry->key);
RangeType *new = DatumGetRangeType(newentry->key);
TypeCacheEntry *typcache;
bool has_subtype_diff;
RangeBound orig_lower,
new_lower,
orig_upper,
new_upper;
bool orig_empty,
new_empty;
if (RangeTypeGetOid(orig) != RangeTypeGetOid(new))
elog(ERROR, "range types do not match");
typcache = range_get_typcache(fcinfo, RangeTypeGetOid(orig));
has_subtype_diff = OidIsValid(typcache->rng_subdiff_finfo.fn_oid);
range_deserialize(typcache, orig, &orig_lower, &orig_upper, &orig_empty);
range_deserialize(typcache, new, &new_lower, &new_upper, &new_empty);
/*
* Distinct branches for handling distinct classes of ranges. Note that
* penalty values only need to be commensurate within the same class of
* new range.
*/
if (new_empty)
{
/* Handle insertion of empty range */
if (orig_empty)
{
/*
* The best case is to insert it to empty original range.
* Insertion here means no broadening of original range. Also
* original range is the most narrow.
*/
*penalty = 0.0;
}
else if (RangeIsOrContainsEmpty(orig))
{
/*
* The second case is to insert empty range into range which
* contains at least one underlying empty range. There is still
* no broadening of original range, but original range is not as
* narrow as possible.
*/
*penalty = CONTAIN_EMPTY_PENALTY;
}
else if (orig_lower.infinite && orig_upper.infinite)
{
/*
* Original range requires broadening. (-inf; +inf) is most far
* from normal range in this case.
*/
*penalty = 2 * CONTAIN_EMPTY_PENALTY;
}
else if (orig_lower.infinite || orig_upper.infinite)
{
/*
* (-inf, x) or (x, +inf) original ranges are closer to normal
* ranges, so it's worse to mix it with empty ranges.
*/
*penalty = 3 * CONTAIN_EMPTY_PENALTY;
}
else
{
/*
* The least preferred case is broadening of normal range.
*/
*penalty = 4 * CONTAIN_EMPTY_PENALTY;
}
}
else if (new_lower.infinite && new_upper.infinite)
{
/* Handle insertion of (-inf, +inf) range */
if (orig_lower.infinite && orig_upper.infinite)
{
/*
* Best case is inserting to (-inf, +inf) original range.
*/
*penalty = 0.0;
}
else if (orig_lower.infinite || orig_upper.infinite)
{
/*
* When original range is (-inf, x) or (x, +inf) it requires
* broadening of original range (extension of one bound to
* infinity).
*/
*penalty = INFINITE_BOUND_PENALTY;
}
else
{
/*
* Insertion to normal original range is least preferred.
*/
*penalty = 2 * INFINITE_BOUND_PENALTY;
}
if (RangeIsOrContainsEmpty(orig))
{
/*
* Original range is narrower when it doesn't contain empty
* ranges. Add additional penalty otherwise.
*/
*penalty += CONTAIN_EMPTY_PENALTY;
}
}
else if (new_lower.infinite)
{
/* Handle insertion of (-inf, x) range */
if (!orig_empty && orig_lower.infinite)
{
if (orig_upper.infinite)
{
/*
* (-inf, +inf) range won't be extended by insertion of (-inf,
* x) range. It's a less desirable case than insertion to
* (-inf, y) original range without extension, because in that
* case original range is narrower. But we can't express that
* in single float value.
*/
*penalty = 0.0;
}
else
{
if (range_cmp_bounds(typcache, &new_upper, &orig_upper) > 0)
{
/*
* Get extension of original range using subtype_diff. Use
* constant if subtype_diff unavailable.
*/
if (has_subtype_diff)
*penalty = call_subtype_diff(typcache,
new_upper.val,
orig_upper.val);
else
*penalty = DEFAULT_SUBTYPE_DIFF_PENALTY;
}
else
{
/* No extension of original range */
*penalty = 0.0;
}
}
}
else
{
/*
* If lower bound of original range is not -inf, then extension of
* it is infinity.
*/
*penalty = get_float4_infinity();
}
}
else if (new_upper.infinite)
{
/* Handle insertion of (x, +inf) range */
if (!orig_empty && orig_upper.infinite)
{
if (orig_lower.infinite)
{
/*
* (-inf, +inf) range won't be extended by insertion of (x,
* +inf) range. It's a less desirable case than insertion to
* (y, +inf) original range without extension, because in that
* case original range is narrower. But we can't express that
* in single float value.
*/
*penalty = 0.0;
}
else
{
if (range_cmp_bounds(typcache, &new_lower, &orig_lower) < 0)
{
/*
* Get extension of original range using subtype_diff. Use
* constant if subtype_diff unavailable.
*/
if (has_subtype_diff)
*penalty = call_subtype_diff(typcache,
orig_lower.val,
new_lower.val);
else
*penalty = DEFAULT_SUBTYPE_DIFF_PENALTY;
}
else
{
/* No extension of original range */
*penalty = 0.0;
}
}
}
else
{
/*
* If upper bound of original range is not +inf, then extension of
* it is infinity.
*/
*penalty = get_float4_infinity();
}
}
else
{
/* Handle insertion of normal (non-empty, non-infinite) range */
if (orig_empty || orig_lower.infinite || orig_upper.infinite)
{
/*
* Avoid mixing normal ranges with infinite and empty ranges.
*/
*penalty = get_float4_infinity();
}
else
{
/*
* Calculate extension of original range by calling subtype_diff.
* Use constant if subtype_diff unavailable.
*/
float8 diff = 0.0;
if (range_cmp_bounds(typcache, &new_lower, &orig_lower) < 0)
{
if (has_subtype_diff)
diff += call_subtype_diff(typcache,
orig_lower.val,
new_lower.val);
else
diff += DEFAULT_SUBTYPE_DIFF_PENALTY;
}
if (range_cmp_bounds(typcache, &new_upper, &orig_upper) > 0)
{
if (has_subtype_diff)
diff += call_subtype_diff(typcache,
new_upper.val,
orig_upper.val);
else
diff += DEFAULT_SUBTYPE_DIFF_PENALTY;
}
*penalty = diff;
}
}
PG_RETURN_POINTER(penalty);
}
| Datum range_gist_picksplit | ( | PG_FUNCTION_ARGS | ) |
Definition at line 504 of file rangetypes_gist.c.
References Abs, Assert, CLS_CONTAIN_EMPTY, CLS_LOWER_INF, CLS_NORMAL, CLS_UPPER_INF, DatumGetRangeType, FirstOffsetNumber, get_gist_range_class(), i, GISTENTRY::key, GistEntryVector::n, OffsetNumberNext, palloc(), PG_GETARG_POINTER, PG_RETURN_POINTER, range(), range_get_typcache(), range_gist_class_split(), range_gist_double_sorting_split(), range_gist_fallback_split(), range_gist_single_sorting_split(), RangeTypeGetOid, GIST_SPLITVEC::spl_left, GIST_SPLITVEC::spl_right, and GistEntryVector::vector.
{
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
TypeCacheEntry *typcache;
OffsetNumber i;
RangeType *pred_left;
int nbytes;
OffsetNumber maxoff;
int count_in_classes[CLS_COUNT];
int j;
int non_empty_classes_count = 0;
int biggest_class = -1;
int biggest_class_count = 0;
int total_count;
/* use first item to look up range type's info */
pred_left = DatumGetRangeType(entryvec->vector[FirstOffsetNumber].key);
typcache = range_get_typcache(fcinfo, RangeTypeGetOid(pred_left));
maxoff = entryvec->n - 1;
nbytes = (maxoff + 1) * sizeof(OffsetNumber);
v->spl_left = (OffsetNumber *) palloc(nbytes);
v->spl_right = (OffsetNumber *) palloc(nbytes);
/*
* Get count distribution of range classes.
*/
memset(count_in_classes, 0, sizeof(count_in_classes));
for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
{
RangeType *range = DatumGetRangeType(entryvec->vector[i].key);
count_in_classes[get_gist_range_class(range)]++;
}
/*
* Count non-empty classes and find biggest class.
*/
total_count = maxoff;
for (j = 0; j < CLS_COUNT; j++)
{
if (count_in_classes[j] > 0)
{
if (count_in_classes[j] > biggest_class_count)
{
biggest_class_count = count_in_classes[j];
biggest_class = j;
}
non_empty_classes_count++;
}
}
Assert(non_empty_classes_count > 0);
if (non_empty_classes_count == 1)
{
/* One non-empty class, so split inside class */
if ((biggest_class & ~CLS_CONTAIN_EMPTY) == CLS_NORMAL)
{
/* double sorting split for normal ranges */
range_gist_double_sorting_split(typcache, entryvec, v);
}
else if ((biggest_class & ~CLS_CONTAIN_EMPTY) == CLS_LOWER_INF)
{
/* upper bound sorting split for (-inf, x) ranges */
range_gist_single_sorting_split(typcache, entryvec, v, true);
}
else if ((biggest_class & ~CLS_CONTAIN_EMPTY) == CLS_UPPER_INF)
{
/* lower bound sorting split for (x, +inf) ranges */
range_gist_single_sorting_split(typcache, entryvec, v, false);
}
else
{
/* trivial split for all (-inf, +inf) or all empty ranges */
range_gist_fallback_split(typcache, entryvec, v);
}
}
else
{
/*
* Class based split.
*
* To which side of the split should each class go? Initialize them
* all to go to the left side.
*/
SplitLR classes_groups[CLS_COUNT];
memset(classes_groups, 0, sizeof(classes_groups));
if (count_in_classes[CLS_NORMAL] > 0)
{
/* separate normal ranges if any */
classes_groups[CLS_NORMAL] = SPLIT_RIGHT;
}
else
{
/*----------
* Try to split classes in one of two ways:
* 1) containing infinities - not containing infinities
* 2) containing empty - not containing empty
*
* Select the way which balances the ranges between left and right
* the best. If split in these ways is not possible, there are at
* most 3 classes, so just separate biggest class.
*----------
*/
int infCount,
nonInfCount;
int emptyCount,
nonEmptyCount;
nonInfCount =
count_in_classes[CLS_NORMAL] +
count_in_classes[CLS_CONTAIN_EMPTY] +
count_in_classes[CLS_EMPTY];
infCount = total_count - nonInfCount;
nonEmptyCount =
count_in_classes[CLS_NORMAL] +
count_in_classes[CLS_LOWER_INF] +
count_in_classes[CLS_UPPER_INF] +
count_in_classes[CLS_LOWER_INF | CLS_UPPER_INF];
emptyCount = total_count - nonEmptyCount;
if (infCount > 0 && nonInfCount > 0 &&
(Abs(infCount - nonInfCount) <=
Abs(emptyCount - nonEmptyCount)))
{
classes_groups[CLS_NORMAL] = SPLIT_RIGHT;
classes_groups[CLS_CONTAIN_EMPTY] = SPLIT_RIGHT;
classes_groups[CLS_EMPTY] = SPLIT_RIGHT;
}
else if (emptyCount > 0 && nonEmptyCount > 0)
{
classes_groups[CLS_NORMAL] = SPLIT_RIGHT;
classes_groups[CLS_LOWER_INF] = SPLIT_RIGHT;
classes_groups[CLS_UPPER_INF] = SPLIT_RIGHT;
classes_groups[CLS_LOWER_INF | CLS_UPPER_INF] = SPLIT_RIGHT;
}
else
{
/*
* Either total_count == emptyCount or total_count ==
* infCount.
*/
classes_groups[biggest_class] = SPLIT_RIGHT;
}
}
range_gist_class_split(typcache, entryvec, v, classes_groups);
}
PG_RETURN_POINTER(v);
}
| Datum range_gist_same | ( | PG_FUNCTION_ARGS | ) |
Definition at line 663 of file rangetypes_gist.c.
References PG_GETARG_POINTER, PG_GETARG_RANGE, PG_RETURN_POINTER, range_eq_internal(), range_get_flags(), range_get_typcache(), and RangeTypeGetOid.
{
RangeType *r1 = PG_GETARG_RANGE(0);
RangeType *r2 = PG_GETARG_RANGE(1);
bool *result = (bool *) PG_GETARG_POINTER(2);
/*
* range_eq will ignore the RANGE_CONTAIN_EMPTY flag, so we have to check
* that for ourselves. More generally, if the entries have been properly
* normalized, then unequal flags bytes must mean unequal ranges ... so
* let's just test all the flag bits at once.
*/
if (range_get_flags(r1) != range_get_flags(r2))
*result = false;
else
{
TypeCacheEntry *typcache;
typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
*result = range_eq_internal(typcache, r1, r2);
}
PG_RETURN_POINTER(result);
}
| Datum range_gist_union | ( | PG_FUNCTION_ARGS | ) |
Definition at line 198 of file rangetypes_gist.c.
References DatumGetRangeType, i, GistEntryVector::n, PG_GETARG_POINTER, PG_RETURN_RANGE, range_get_typcache(), range_super_union(), RangeTypeGetOid, and GistEntryVector::vector.
{
GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
GISTENTRY *ent = entryvec->vector;
RangeType *result_range;
TypeCacheEntry *typcache;
int i;
result_range = DatumGetRangeType(ent[0].key);
typcache = range_get_typcache(fcinfo, RangeTypeGetOid(result_range));
for (i = 1; i < entryvec->n; i++)
{
result_range = range_super_union(typcache, result_range,
DatumGetRangeType(ent[i].key));
}
PG_RETURN_RANGE(result_range);
}
| Datum range_gt | ( | PG_FUNCTION_ARGS | ) |
Definition at line 1166 of file rangetypes.c.
References cmp(), PG_RETURN_BOOL, and range_cmp().
{
int cmp = range_cmp(fcinfo);
PG_RETURN_BOOL(cmp > 0);
}
| Datum range_in | ( | PG_FUNCTION_ARGS | ) |
Definition at line 79 of file rangetypes.c.
References get_range_io_data(), RangeBound::inclusive, RangeBound::infinite, InputFunctionCall(), IOFunc_input, RangeBound::lower, make_range(), PG_GETARG_CSTRING, PG_GETARG_INT32, PG_GETARG_OID, PG_RETURN_RANGE, RangeIOData::proc, RANGE_EMPTY, RANGE_HAS_LBOUND, RANGE_HAS_UBOUND, range_parse(), RangeIOData::typcache, RangeIOData::typioparam, and RangeBound::val.
{
char *input_str = PG_GETARG_CSTRING(0);
Oid rngtypoid = PG_GETARG_OID(1);
Oid typmod = PG_GETARG_INT32(2);
RangeType *range;
RangeIOData *cache;
char flags;
char *lbound_str;
char *ubound_str;
RangeBound lower;
RangeBound upper;
cache = get_range_io_data(fcinfo, rngtypoid, IOFunc_input);
/* parse */
range_parse(input_str, &flags, &lbound_str, &ubound_str);
/* call element type's input function */
if (RANGE_HAS_LBOUND(flags))
lower.val = InputFunctionCall(&cache->proc, lbound_str,
cache->typioparam, typmod);
if (RANGE_HAS_UBOUND(flags))
upper.val = InputFunctionCall(&cache->proc, ubound_str,
cache->typioparam, typmod);
lower.infinite = (flags & RANGE_LB_INF) != 0;
lower.inclusive = (flags & RANGE_LB_INC) != 0;
lower.lower = true;
upper.infinite = (flags & RANGE_UB_INF) != 0;
upper.inclusive = (flags & RANGE_UB_INC) != 0;
upper.lower = false;
/* serialize and canonicalize */
range = make_range(cache->typcache, &lower, &upper, flags & RANGE_EMPTY);
PG_RETURN_RANGE(range);
}
| Datum range_intersect | ( | PG_FUNCTION_ARGS | ) |
Definition at line 1061 of file rangetypes.c.
References DatumGetBool, elog, ERROR, make_empty_range(), make_range(), PG_GETARG_RANGE, PG_RETURN_RANGE, range_cmp_bounds(), range_deserialize(), range_get_typcache(), range_overlaps(), and RangeTypeGetOid.
{
RangeType *r1 = PG_GETARG_RANGE(0);
RangeType *r2 = PG_GETARG_RANGE(1);
TypeCacheEntry *typcache;
RangeBound lower1,
lower2;
RangeBound upper1,
upper2;
bool empty1,
empty2;
RangeBound *result_lower;
RangeBound *result_upper;
/* Different types should be prevented by ANYRANGE matching rules */
if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
elog(ERROR, "range types do not match");
typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
if (empty1 || empty2 || !DatumGetBool(range_overlaps(fcinfo)))
PG_RETURN_RANGE(make_empty_range(typcache));
if (range_cmp_bounds(typcache, &lower1, &lower2) >= 0)
result_lower = &lower1;
else
result_lower = &lower2;
if (range_cmp_bounds(typcache, &upper1, &upper2) <= 0)
result_upper = &upper1;
else
result_upper = &upper2;
PG_RETURN_RANGE(make_range(typcache, result_lower, result_upper, false));
}
| Datum range_le | ( | PG_FUNCTION_ARGS | ) |
Definition at line 1150 of file rangetypes.c.
References cmp(), PG_RETURN_BOOL, and range_cmp().
{
int cmp = range_cmp(fcinfo);
PG_RETURN_BOOL(cmp <= 0);
}
| Datum range_lower | ( | PG_FUNCTION_ARGS | ) |
Definition at line 420 of file rangetypes.c.
References RangeBound::infinite, PG_GETARG_RANGE, PG_RETURN_DATUM, PG_RETURN_NULL, range_deserialize(), range_get_typcache(), RangeTypeGetOid, and RangeBound::val.
{
RangeType *r1 = PG_GETARG_RANGE(0);
TypeCacheEntry *typcache;
RangeBound lower;
RangeBound upper;
bool empty;
typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
range_deserialize(typcache, r1, &lower, &upper, &empty);
/* Return NULL if there's no finite lower bound */
if (empty || lower.infinite)
PG_RETURN_NULL();
PG_RETURN_DATUM(lower.val);
}
| Datum range_lower_inc | ( | PG_FUNCTION_ARGS | ) |
Definition at line 475 of file rangetypes.c.
References PG_GETARG_RANGE, PG_RETURN_BOOL, range_get_flags(), and RANGE_LB_INC.
{
RangeType *r1 = PG_GETARG_RANGE(0);
char flags = range_get_flags(r1);
PG_RETURN_BOOL(flags & RANGE_LB_INC);
}
| Datum range_lower_inf | ( | PG_FUNCTION_ARGS | ) |
Definition at line 495 of file rangetypes.c.
References PG_GETARG_RANGE, PG_RETURN_BOOL, range_get_flags(), and RANGE_LB_INF.
{
RangeType *r1 = PG_GETARG_RANGE(0);
char flags = range_get_flags(r1);
PG_RETURN_BOOL(flags & RANGE_LB_INF);
}
| Datum range_lt | ( | PG_FUNCTION_ARGS | ) |
Definition at line 1142 of file rangetypes.c.
References cmp(), PG_RETURN_BOOL, and range_cmp().
{
int cmp = range_cmp(fcinfo);
PG_RETURN_BOOL(cmp < 0);
}
| Datum range_minus | ( | PG_FUNCTION_ARGS | ) |
Definition at line 946 of file rangetypes.c.
References elog, ereport, errcode(), errmsg(), ERROR, RangeBound::inclusive, RangeBound::lower, make_empty_range(), make_range(), PG_GETARG_RANGE, PG_RETURN_NULL, PG_RETURN_RANGE, range_cmp_bounds(), range_deserialize(), range_get_typcache(), and RangeTypeGetOid.
{
RangeType *r1 = PG_GETARG_RANGE(0);
RangeType *r2 = PG_GETARG_RANGE(1);
TypeCacheEntry *typcache;
RangeBound lower1,
lower2;
RangeBound upper1,
upper2;
bool empty1,
empty2;
int cmp_l1l2,
cmp_l1u2,
cmp_u1l2,
cmp_u1u2;
/* Different types should be prevented by ANYRANGE matching rules */
if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
elog(ERROR, "range types do not match");
typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
/* if either is empty, r1 is the correct answer */
if (empty1 || empty2)
PG_RETURN_RANGE(r1);
cmp_l1l2 = range_cmp_bounds(typcache, &lower1, &lower2);
cmp_l1u2 = range_cmp_bounds(typcache, &lower1, &upper2);
cmp_u1l2 = range_cmp_bounds(typcache, &upper1, &lower2);
cmp_u1u2 = range_cmp_bounds(typcache, &upper1, &upper2);
if (cmp_l1l2 < 0 && cmp_u1u2 > 0)
ereport(ERROR,
(errcode(ERRCODE_DATA_EXCEPTION),
errmsg("result of range difference would not be contiguous")));
if (cmp_l1u2 > 0 || cmp_u1l2 < 0)
PG_RETURN_RANGE(r1);
if (cmp_l1l2 >= 0 && cmp_u1u2 <= 0)
PG_RETURN_RANGE(make_empty_range(typcache));
if (cmp_l1l2 <= 0 && cmp_u1l2 >= 0 && cmp_u1u2 <= 0)
{
lower2.inclusive = !lower2.inclusive;
lower2.lower = false; /* it will become the upper bound */
PG_RETURN_RANGE(make_range(typcache, &lower1, &lower2, false));
}
if (cmp_l1l2 >= 0 && cmp_u1u2 >= 0 && cmp_l1u2 <= 0)
{
upper2.inclusive = !upper2.inclusive;
upper2.lower = true; /* it will become the lower bound */
PG_RETURN_RANGE(make_range(typcache, &upper2, &upper1, false));
}
elog(ERROR, "unexpected case in range_minus");
PG_RETURN_NULL();
}
| Datum range_ne | ( | PG_FUNCTION_ARGS | ) |
Definition at line 599 of file rangetypes.c.
References PG_GETARG_RANGE, PG_RETURN_BOOL, range_get_typcache(), range_ne_internal(), and RangeTypeGetOid.
{
RangeType *r1 = PG_GETARG_RANGE(0);
RangeType *r2 = PG_GETARG_RANGE(1);
TypeCacheEntry *typcache;
typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
PG_RETURN_BOOL(range_ne_internal(typcache, r1, r2));
}
| bool range_ne_internal | ( | TypeCacheEntry * | typcache, | |
| RangeType * | r1, | |||
| RangeType * | r2 | |||
| ) |
Definition at line 592 of file rangetypes.c.
References range_eq_internal().
Referenced by range_ne().
{
return (!range_eq_internal(typcache, r1, r2));
}
| Datum range_out | ( | PG_FUNCTION_ARGS | ) |
Definition at line 119 of file rangetypes.c.
References get_range_io_data(), IOFunc_output, OutputFunctionCall(), PG_GETARG_RANGE, PG_RETURN_CSTRING, RangeIOData::proc, range(), range_deparse(), range_deserialize(), range_get_flags(), RANGE_HAS_LBOUND, RANGE_HAS_UBOUND, RangeTypeGetOid, RangeIOData::typcache, and RangeBound::val.
Referenced by anyrange_out().
{
RangeType *range = PG_GETARG_RANGE(0);
char *output_str;
RangeIOData *cache;
char flags;
char *lbound_str = NULL;
char *ubound_str = NULL;
RangeBound lower;
RangeBound upper;
bool empty;
cache = get_range_io_data(fcinfo, RangeTypeGetOid(range), IOFunc_output);
/* deserialize */
range_deserialize(cache->typcache, range, &lower, &upper, &empty);
flags = range_get_flags(range);
/* call element type's output function */
if (RANGE_HAS_LBOUND(flags))
lbound_str = OutputFunctionCall(&cache->proc, lower.val);
if (RANGE_HAS_UBOUND(flags))
ubound_str = OutputFunctionCall(&cache->proc, upper.val);
/* construct result string */
output_str = range_deparse(flags, lbound_str, ubound_str);
PG_RETURN_CSTRING(output_str);
}
| Datum range_overlaps | ( | PG_FUNCTION_ARGS | ) |
Definition at line 848 of file rangetypes.c.
References PG_GETARG_RANGE, PG_RETURN_BOOL, range_get_typcache(), range_overlaps_internal(), and RangeTypeGetOid.
Referenced by range_intersect(), and range_union().
{
RangeType *r1 = PG_GETARG_RANGE(0);
RangeType *r2 = PG_GETARG_RANGE(1);
TypeCacheEntry *typcache;
typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
PG_RETURN_BOOL(range_overlaps_internal(typcache, r1, r2));
}
| bool range_overlaps_internal | ( | TypeCacheEntry * | typcache, | |
| RangeType * | r1, | |||
| RangeType * | r2 | |||
| ) |
Definition at line 815 of file rangetypes.c.
References elog, ERROR, range_cmp_bounds(), range_deserialize(), and RangeTypeGetOid.
Referenced by range_gist_consistent_int(), range_gist_consistent_leaf(), range_overlaps(), and spg_range_quad_leaf_consistent().
{
RangeBound lower1,
lower2;
RangeBound upper1,
upper2;
bool empty1,
empty2;
/* Different types should be prevented by ANYRANGE matching rules */
if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
elog(ERROR, "range types do not match");
range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
/* An empty range does not overlap any other range */
if (empty1 || empty2)
return false;
if (range_cmp_bounds(typcache, &lower1, &lower2) >= 0 &&
range_cmp_bounds(typcache, &lower1, &upper2) <= 0)
return true;
if (range_cmp_bounds(typcache, &lower2, &lower1) >= 0 &&
range_cmp_bounds(typcache, &lower2, &upper1) <= 0)
return true;
return false;
}
| Datum range_overleft | ( | PG_FUNCTION_ARGS | ) |
Definition at line 889 of file rangetypes.c.
References PG_GETARG_RANGE, PG_RETURN_BOOL, range_get_typcache(), range_overleft_internal(), and RangeTypeGetOid.
{
RangeType *r1 = PG_GETARG_RANGE(0);
RangeType *r2 = PG_GETARG_RANGE(1);
TypeCacheEntry *typcache;
typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
PG_RETURN_BOOL(range_overleft_internal(typcache, r1, r2));
}
| bool range_overleft_internal | ( | TypeCacheEntry * | typcache, | |
| RangeType * | r1, | |||
| RangeType * | r2 | |||
| ) |
Definition at line 861 of file rangetypes.c.
References elog, ERROR, range_cmp_bounds(), range_deserialize(), and RangeTypeGetOid.
Referenced by range_gist_consistent_int(), range_gist_consistent_leaf(), range_overleft(), and spg_range_quad_leaf_consistent().
{
RangeBound lower1,
lower2;
RangeBound upper1,
upper2;
bool empty1,
empty2;
/* Different types should be prevented by ANYRANGE matching rules */
if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
elog(ERROR, "range types do not match");
range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
/* An empty range is neither before nor after any other range */
if (empty1 || empty2)
return false;
if (range_cmp_bounds(typcache, &upper1, &upper2) <= 0)
return true;
return false;
}
| Datum range_overright | ( | PG_FUNCTION_ARGS | ) |
Definition at line 930 of file rangetypes.c.
References PG_GETARG_RANGE, PG_RETURN_BOOL, range_get_typcache(), range_overright_internal(), and RangeTypeGetOid.
{
RangeType *r1 = PG_GETARG_RANGE(0);
RangeType *r2 = PG_GETARG_RANGE(1);
TypeCacheEntry *typcache;
typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
PG_RETURN_BOOL(range_overright_internal(typcache, r1, r2));
}
| bool range_overright_internal | ( | TypeCacheEntry * | typcache, | |
| RangeType * | r1, | |||
| RangeType * | r2 | |||
| ) |
Definition at line 902 of file rangetypes.c.
References elog, ERROR, PG_RETURN_BOOL, range_cmp_bounds(), range_deserialize(), and RangeTypeGetOid.
Referenced by range_gist_consistent_int(), range_gist_consistent_leaf(), range_overright(), and spg_range_quad_leaf_consistent().
{
RangeBound lower1,
lower2;
RangeBound upper1,
upper2;
bool empty1,
empty2;
/* Different types should be prevented by ANYRANGE matching rules */
if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
elog(ERROR, "range types do not match");
range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
/* An empty range is neither before nor after any other range */
if (empty1 || empty2)
PG_RETURN_BOOL(false);
if (range_cmp_bounds(typcache, &lower1, &lower2) >= 0)
PG_RETURN_BOOL(true);
PG_RETURN_BOOL(false);
}
| Datum range_recv | ( | PG_FUNCTION_ARGS | ) |
Definition at line 157 of file rangetypes.c.
References appendBinaryStringInfo(), buf, StringInfoData::data, get_range_io_data(), RangeBound::inclusive, RangeBound::infinite, initStringInfo(), IOFunc_receive, RangeBound::lower, make_range(), pfree(), PG_GETARG_INT32, PG_GETARG_OID, PG_GETARG_POINTER, PG_RETURN_RANGE, pq_getmsgbyte(), pq_getmsgbytes(), pq_getmsgend(), pq_getmsgint(), RangeIOData::proc, RANGE_EMPTY, RANGE_HAS_LBOUND, RANGE_HAS_UBOUND, RANGE_LB_INC, RANGE_LB_INF, RANGE_UB_INC, ReceiveFunctionCall(), RangeIOData::typcache, RangeIOData::typioparam, and RangeBound::val.
{
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
Oid rngtypoid = PG_GETARG_OID(1);
int32 typmod = PG_GETARG_INT32(2);
RangeType *range;
RangeIOData *cache;
char flags;
RangeBound lower;
RangeBound upper;
cache = get_range_io_data(fcinfo, rngtypoid, IOFunc_receive);
/* receive the flags... */
flags = (unsigned char) pq_getmsgbyte(buf);
/*
* Mask out any unsupported flags, particularly RANGE_xB_NULL which would
* confuse following tests. Note that range_serialize will take care of
* cleaning up any inconsistencies in the remaining flags.
*/
flags &= (RANGE_EMPTY |
RANGE_LB_INC |
RANGE_LB_INF |
RANGE_UB_INC |
RANGE_UB_INF);
/* receive the bounds ... */
if (RANGE_HAS_LBOUND(flags))
{
uint32 bound_len = pq_getmsgint(buf, 4);
const char *bound_data = pq_getmsgbytes(buf, bound_len);
StringInfoData bound_buf;
initStringInfo(&bound_buf);
appendBinaryStringInfo(&bound_buf, bound_data, bound_len);
lower.val = ReceiveFunctionCall(&cache->proc,
&bound_buf,
cache->typioparam,
typmod);
pfree(bound_buf.data);
}
else
lower.val = (Datum) 0;
if (RANGE_HAS_UBOUND(flags))
{
uint32 bound_len = pq_getmsgint(buf, 4);
const char *bound_data = pq_getmsgbytes(buf, bound_len);
StringInfoData bound_buf;
initStringInfo(&bound_buf);
appendBinaryStringInfo(&bound_buf, bound_data, bound_len);
upper.val = ReceiveFunctionCall(&cache->proc,
&bound_buf,
cache->typioparam,
typmod);
pfree(bound_buf.data);
}
else
upper.val = (Datum) 0;
pq_getmsgend(buf);
/* finish constructing RangeBound representation */
lower.infinite = (flags & RANGE_LB_INF) != 0;
lower.inclusive = (flags & RANGE_LB_INC) != 0;
lower.lower = true;
upper.infinite = (flags & RANGE_UB_INF) != 0;
upper.inclusive = (flags & RANGE_UB_INC) != 0;
upper.lower = false;
/* serialize and canonicalize */
range = make_range(cache->typcache, &lower, &upper, flags & RANGE_EMPTY);
PG_RETURN_RANGE(range);
}
| Datum range_send | ( | PG_FUNCTION_ARGS | ) |
Definition at line 238 of file rangetypes.c.
References buf, get_range_io_data(), IOFunc_send, makeStringInfo(), PG_GETARG_RANGE, PG_RETURN_BYTEA_P, PointerGetDatum, pq_begintypsend(), pq_endtypsend(), pq_sendbyte(), pq_sendbytes(), pq_sendint(), RangeIOData::proc, range(), range_deserialize(), range_get_flags(), RANGE_HAS_LBOUND, RANGE_HAS_UBOUND, RangeTypeGetOid, SendFunctionCall(), RangeIOData::typcache, RangeBound::val, VARDATA, and VARSIZE.
{
RangeType *range = PG_GETARG_RANGE(0);
StringInfo buf = makeStringInfo();
RangeIOData *cache;
char flags;
RangeBound lower;
RangeBound upper;
bool empty;
cache = get_range_io_data(fcinfo, RangeTypeGetOid(range), IOFunc_send);
/* deserialize */
range_deserialize(cache->typcache, range, &lower, &upper, &empty);
flags = range_get_flags(range);
/* construct output */
pq_begintypsend(buf);
pq_sendbyte(buf, flags);
if (RANGE_HAS_LBOUND(flags))
{
Datum bound = PointerGetDatum(SendFunctionCall(&cache->proc,
lower.val));
uint32 bound_len = VARSIZE(bound) - VARHDRSZ;
char *bound_data = VARDATA(bound);
pq_sendint(buf, bound_len, 4);
pq_sendbytes(buf, bound_data, bound_len);
}
if (RANGE_HAS_UBOUND(flags))
{
Datum bound = PointerGetDatum(SendFunctionCall(&cache->proc,
upper.val));
uint32 bound_len = VARSIZE(bound) - VARHDRSZ;
char *bound_data = VARDATA(bound);
pq_sendint(buf, bound_len, 4);
pq_sendbytes(buf, bound_data, bound_len);
}
PG_RETURN_BYTEA_P(pq_endtypsend(buf));
}
| RangeType* range_serialize | ( | TypeCacheEntry * | typcache, | |
| RangeBound * | lower, | |||
| RangeBound * | upper, | |||
| bool | empty | |||
| ) |
Definition at line 1466 of file rangetypes.c.
References Assert, datum_compute_size(), datum_write(), ereport, errcode(), errmsg(), ERROR, RangeBound::inclusive, RangeBound::infinite, RangeBound::lower, MAXALIGN, palloc0(), PG_DETOAST_DATUM_PACKED, PointerGetDatum, range_cmp_bound_values(), RANGE_HAS_LBOUND, RANGE_HAS_UBOUND, RangeType::rangetypid, TypeCacheEntry::rngelemtype, SET_VARSIZE, TypeCacheEntry::typalign, TypeCacheEntry::typbyval, TypeCacheEntry::type_id, TypeCacheEntry::typlen, TypeCacheEntry::typstorage, and RangeBound::val.
Referenced by compute_range_stats(), daterange_canonical(), int4range_canonical(), int8range_canonical(), make_range(), rangesel(), and spg_range_quad_picksplit().
{
RangeType *range;
int cmp;
Size msize;
Pointer ptr;
int16 typlen;
bool typbyval;
char typalign;
char typstorage;
char flags = 0;
/*
* Verify range is not invalid on its face, and construct flags value,
* preventing any non-canonical combinations such as infinite+inclusive.
*/
Assert(lower->lower);
Assert(!upper->lower);
if (empty)
flags |= RANGE_EMPTY;
else
{
cmp = range_cmp_bound_values(typcache, lower, upper);
/* error check: if lower bound value is above upper, it's wrong */
if (cmp > 0)
ereport(ERROR,
(errcode(ERRCODE_DATA_EXCEPTION),
errmsg("range lower bound must be less than or equal to range upper bound")));
/* if bounds are equal, and not both inclusive, range is empty */
if (cmp == 0 && !(lower->inclusive && upper->inclusive))
flags |= RANGE_EMPTY;
else
{
/* infinite boundaries are never inclusive */
if (lower->infinite)
flags |= RANGE_LB_INF;
else if (lower->inclusive)
flags |= RANGE_LB_INC;
if (upper->infinite)
flags |= RANGE_UB_INF;
else if (upper->inclusive)
flags |= RANGE_UB_INC;
}
}
/* Fetch information about range's element type */
typlen = typcache->rngelemtype->typlen;
typbyval = typcache->rngelemtype->typbyval;
typalign = typcache->rngelemtype->typalign;
typstorage = typcache->rngelemtype->typstorage;
/* Count space for varlena header and range type's OID */
msize = sizeof(RangeType);
Assert(msize == MAXALIGN(msize));
/* Count space for bounds */
if (RANGE_HAS_LBOUND(flags))
{
/*
* Make sure item to be inserted is not toasted. It is essential that
* we not insert an out-of-line toast value pointer into a range
* object, for the same reasons that arrays and records can't contain
* them. It would work to store a compressed-in-line value, but we
* prefer to decompress and then let compression be applied to the
* whole range object if necessary. But, unlike arrays, we do allow
* short-header varlena objects to stay as-is.
*/
if (typlen == -1)
lower->val = PointerGetDatum(PG_DETOAST_DATUM_PACKED(lower->val));
msize = datum_compute_size(msize, lower->val, typbyval, typalign,
typlen, typstorage);
}
if (RANGE_HAS_UBOUND(flags))
{
/* Make sure item to be inserted is not toasted */
if (typlen == -1)
upper->val = PointerGetDatum(PG_DETOAST_DATUM_PACKED(upper->val));
msize = datum_compute_size(msize, upper->val, typbyval, typalign,
typlen, typstorage);
}
/* Add space for flag byte */
msize += sizeof(char);
/* Note: zero-fill is required here, just as in heap tuples */
range = (RangeType *) palloc0(msize);
SET_VARSIZE(range, msize);
/* Now fill in the datum */
range->rangetypid = typcache->type_id;
ptr = (char *) (range + 1);
if (RANGE_HAS_LBOUND(flags))
{
Assert(lower->lower);
ptr = datum_write(ptr, lower->val, typbyval, typalign, typlen,
typstorage);
}
if (RANGE_HAS_UBOUND(flags))
{
Assert(!upper->lower);
ptr = datum_write(ptr, upper->val, typbyval, typalign, typlen,
typstorage);
}
*((char *) ptr) = flags;
return range;
}
| void range_set_contain_empty | ( | RangeType * | range | ) |
Definition at line 1676 of file rangetypes.c.
References VARSIZE.
Referenced by range_super_union().
{
char *flagsp;
/* flag byte is datum's last byte */
flagsp = (char *) range + VARSIZE(range) - 1;
*flagsp |= RANGE_CONTAIN_EMPTY;
}
| Datum range_typanalyze | ( | PG_FUNCTION_ARGS | ) |
Definition at line 41 of file rangetypes_typanalyze.c.
References VacAttrStats::attr, VacAttrStats::attrtypid, VacAttrStats::compute_stats, default_statistics_target, VacAttrStats::extra_data, VacAttrStats::minrows, PG_GETARG_POINTER, PG_RETURN_BOOL, and range_get_typcache().
{
VacAttrStats *stats = (VacAttrStats *) PG_GETARG_POINTER(0);
TypeCacheEntry *typcache;
Form_pg_attribute attr = stats->attr;
/* Get information about range type */
typcache = range_get_typcache(fcinfo, stats->attrtypid);
if (attr->attstattarget < 0)
attr->attstattarget = default_statistics_target;
stats->compute_stats = compute_range_stats;
stats->extra_data = typcache;
/* same as in std_typanalyze */
stats->minrows = 300 * attr->attstattarget;
PG_RETURN_BOOL(true);
}
| Datum range_union | ( | PG_FUNCTION_ARGS | ) |
Definition at line 1011 of file rangetypes.c.
References DatumGetBool, elog, ereport, errcode(), errmsg(), ERROR, make_range(), PG_GETARG_RANGE, PG_RETURN_RANGE, range_adjacent(), range_cmp_bounds(), range_deserialize(), range_get_typcache(), range_overlaps(), and RangeTypeGetOid.
{
RangeType *r1 = PG_GETARG_RANGE(0);
RangeType *r2 = PG_GETARG_RANGE(1);
TypeCacheEntry *typcache;
RangeBound lower1,
lower2;
RangeBound upper1,
upper2;
bool empty1,
empty2;
RangeBound *result_lower;
RangeBound *result_upper;
/* Different types should be prevented by ANYRANGE matching rules */
if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
elog(ERROR, "range types do not match");
typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
/* if either is empty, the other is the correct answer */
if (empty1)
PG_RETURN_RANGE(r2);
if (empty2)
PG_RETURN_RANGE(r1);
if (!DatumGetBool(range_overlaps(fcinfo)) &&
!DatumGetBool(range_adjacent(fcinfo)))
ereport(ERROR,
(errcode(ERRCODE_DATA_EXCEPTION),
errmsg("result of range union would not be contiguous")));
if (range_cmp_bounds(typcache, &lower1, &lower2) < 0)
result_lower = &lower1;
else
result_lower = &lower2;
if (range_cmp_bounds(typcache, &upper1, &upper2) > 0)
result_upper = &upper1;
else
result_upper = &upper2;
PG_RETURN_RANGE(make_range(typcache, result_lower, result_upper, false));
}
| Datum range_upper | ( | PG_FUNCTION_ARGS | ) |
Definition at line 441 of file rangetypes.c.
References RangeBound::infinite, PG_GETARG_RANGE, PG_RETURN_DATUM, PG_RETURN_NULL, range_deserialize(), range_get_typcache(), RangeTypeGetOid, and RangeBound::val.
{
RangeType *r1 = PG_GETARG_RANGE(0);
TypeCacheEntry *typcache;
RangeBound lower;
RangeBound upper;
bool empty;
typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
range_deserialize(typcache, r1, &lower, &upper, &empty);
/* Return NULL if there's no finite upper bound */
if (empty || upper.infinite)
PG_RETURN_NULL();
PG_RETURN_DATUM(upper.val);
}
| Datum range_upper_inc | ( | PG_FUNCTION_ARGS | ) |
Definition at line 485 of file rangetypes.c.
References PG_GETARG_RANGE, PG_RETURN_BOOL, range_get_flags(), and RANGE_UB_INC.
{
RangeType *r1 = PG_GETARG_RANGE(0);
char flags = range_get_flags(r1);
PG_RETURN_BOOL(flags & RANGE_UB_INC);
}
| Datum range_upper_inf | ( | PG_FUNCTION_ARGS | ) |
Definition at line 505 of file rangetypes.c.
References PG_GETARG_RANGE, PG_RETURN_BOOL, range_get_flags(), and RANGE_UB_INF.
{
RangeType *r1 = PG_GETARG_RANGE(0);
char flags = range_get_flags(r1);
PG_RETURN_BOOL(flags & RANGE_UB_INF);
}
| Datum rangesel | ( | PG_FUNCTION_ARGS | ) |
Definition at line 101 of file rangetypes_selfuncs.c.
References calc_rangesel(), CLAMP_PROBABILITY, DatumGetRangeType, default_range_selectivity(), get_restriction_variable(), RangeBound::inclusive, RangeBound::infinite, IsA, RangeBound::lower, OID_RANGE_CONTAINS_ELEM_OP, PG_GETARG_INT32, PG_GETARG_POINTER, PG_RETURN_FLOAT8, range_get_typcache(), range_serialize(), ReleaseVariableStats, TypeCacheEntry::rngelemtype, TypeCacheEntry::type_id, RangeBound::val, and VariableStatData::vartype.
{
PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0);
Oid operator = PG_GETARG_OID(1);
List *args = (List *) PG_GETARG_POINTER(2);
int varRelid = PG_GETARG_INT32(3);
VariableStatData vardata;
Node *other;
bool varonleft;
Selectivity selec;
TypeCacheEntry *typcache;
RangeType *constrange = NULL;
/*
* If expression is not (variable op something) or (something op
* variable), then punt and return a default estimate.
*/
if (!get_restriction_variable(root, args, varRelid,
&vardata, &other, &varonleft))
PG_RETURN_FLOAT8(default_range_selectivity(operator));
/*
* Can't do anything useful if the something is not a constant, either.
*/
if (!IsA(other, Const))
{
ReleaseVariableStats(vardata);
PG_RETURN_FLOAT8(default_range_selectivity(operator));
}
/*
* All the range operators are strict, so we can cope with a NULL constant
* right away.
*/
if (((Const *) other)->constisnull)
{
ReleaseVariableStats(vardata);
PG_RETURN_FLOAT8(0.0);
}
/*
* If var is on the right, commute the operator, so that we can assume the
* var is on the left in what follows.
*/
if (!varonleft)
{
/* we have other Op var, commute to make var Op other */
operator = get_commutator(operator);
if (!operator)
{
/* Use default selectivity (should we raise an error instead?) */
ReleaseVariableStats(vardata);
PG_RETURN_FLOAT8(default_range_selectivity(operator));
}
}
/*
* OK, there's a Var and a Const we're dealing with here. We need the
* Const to be of same range type as the column, else we can't do anything
* useful. (Such cases will likely fail at runtime, but here we'd rather
* just return a default estimate.)
*
* If the operator is "range @> element", the constant should be of the
* element type of the range column. Convert it to a range that includes
* only that single point, so that we don't need special handling for
* that in what follows.
*/
if (operator == OID_RANGE_CONTAINS_ELEM_OP)
{
typcache = range_get_typcache(fcinfo, vardata.vartype);
if (((Const *) other)->consttype == typcache->rngelemtype->type_id)
{
RangeBound lower, upper;
lower.inclusive = true;
lower.val = ((Const *) other)->constvalue;
lower.infinite = false;
lower.lower = true;
upper.inclusive = true;
upper.val = ((Const *) other)->constvalue;
upper.infinite = false;
upper.lower = false;
constrange = range_serialize(typcache, &lower, &upper, false);
}
}
else
{
typcache = range_get_typcache(fcinfo, ((Const *) other)->consttype);
if (((Const *) other)->consttype == vardata.vartype)
constrange = DatumGetRangeType(((Const *) other)->constvalue);
}
/*
* If we got a valid constant on one side of the operator, proceed to
* estimate using statistics. Otherwise punt and return a default
* constant estimate.
*/
if (constrange)
selec = calc_rangesel(typcache, &vardata, constrange, operator);
else
selec = default_range_selectivity(operator);
ReleaseVariableStats(vardata);
CLAMP_PROBABILITY(selec);
PG_RETURN_FLOAT8((float8) selec);
}
| Datum tsrange_subdiff | ( | PG_FUNCTION_ARGS | ) |
Definition at line 1393 of file rangetypes.c.
References PG_GETARG_TIMESTAMP, PG_RETURN_FLOAT8, and USECS_PER_SEC.
{
Timestamp v1 = PG_GETARG_TIMESTAMP(0);
Timestamp v2 = PG_GETARG_TIMESTAMP(1);
float8 result;
#ifdef HAVE_INT64_TIMESTAMP
result = ((float8) v1 - (float8) v2) / USECS_PER_SEC;
#else
result = v1 - v2;
#endif
PG_RETURN_FLOAT8(result);
}
| Datum tstzrange_subdiff | ( | PG_FUNCTION_ARGS | ) |
Definition at line 1409 of file rangetypes.c.
References PG_GETARG_TIMESTAMP, PG_RETURN_FLOAT8, and USECS_PER_SEC.
{
Timestamp v1 = PG_GETARG_TIMESTAMP(0);
Timestamp v2 = PG_GETARG_TIMESTAMP(1);
float8 result;
#ifdef HAVE_INT64_TIMESTAMP
result = ((float8) v1 - (float8) v2) / USECS_PER_SEC;
#else
result = v1 - v2;
#endif
PG_RETURN_FLOAT8(result);
}
1.7.1