I noticed a weird thing about rangetypes API while reviewing multiranges
-- the combination of range_deserialize immediately followed by
range_get_flags. It seems quite odd to have range_deserialize return
only one flag (empty) and force callers to use a separate
range_get_flags call in order to fetch anything else they need. I
propose that it's simpler to have range_deserialize have an out param
for flags (replacing "empty"), and callers can examine "IsEmpty" from
that using a macro accessor. So there are two macros now:
RangeFlagsIsEmpty() takes the 'flags' value and return whether the bit
is set. Its companion RangeIsEmpty() does the range_get_flags() dance.
The attached patch does that, with a net savings of 8 lines of code in
rangetypes.c. I know, it's not amazing. But it's slightly cleaner this
way IMO.
The reason things are this way is that initially (commit 4429f6a9e3e1)
were all opaque; the external observer could only see "empty" when
deserializing the value. Then commit 37ee4b75db8f added
range_get_flags() to obtain the flags from a range, but at that point it
was only used in places that did not deserialized the range anyway, so
it was okay. I think it was commit c66e4f138b04 that ended up having
both deserialize and get_flags in succession. So things are weird now,
but they have not always been like that.
I also chose to represent the flags out param as uint8 in
range_deserialize. With this change, the compiler warns for callers
using the old API (it used to take bool *), giving a chance to update.
--
Álvaro Herrera
diff --git a/src/backend/utils/adt/rangetypes.c b/src/backend/utils/adt/rangetypes.c
index 01ad8bc240..475165a912 100644
--- a/src/backend/utils/adt/rangetypes.c
+++ b/src/backend/utils/adt/rangetypes.c
@@ -124,20 +124,18 @@ range_out(PG_FUNCTION_ARGS)
RangeType *range = PG_GETARG_RANGE_P(0);
char *output_str;
RangeIOData *cache;
- char flags;
+ uint8 flags;
char *lbound_str = NULL;
char *ubound_str = NULL;
RangeBound lower;
RangeBound upper;
- bool empty;
check_stack_depth(); /* recurses when subtype is a range type */
cache = get_range_io_data(fcinfo, RangeTypeGetOid(range), IOFunc_output);
/* deserialize */
- range_deserialize(cache->typcache, range, &lower, &upper, &empty);
- flags = range_get_flags(range);
+ range_deserialize(cache->typcache, range, &lower, &upper, &flags);
/* call element type's output function */
if (RANGE_HAS_LBOUND(flags))
@@ -166,7 +164,7 @@ range_recv(PG_FUNCTION_ARGS)
int32 typmod = PG_GETARG_INT32(2);
RangeType *range;
RangeIOData *cache;
- char flags;
+ uint8 flags;
RangeBound lower;
RangeBound upper;
@@ -175,7 +173,7 @@ range_recv(PG_FUNCTION_ARGS)
cache = get_range_io_data(fcinfo, rngtypoid, IOFunc_receive);
/* receive the flags... */
- flags = (unsigned char) pq_getmsgbyte(buf);
+ flags = (uint8) pq_getmsgbyte(buf);
/*
* Mask out any unsupported flags, particularly RANGE_xB_NULL which would
@@ -247,18 +245,16 @@ range_send(PG_FUNCTION_ARGS)
RangeType *range = PG_GETARG_RANGE_P(0);
StringInfo buf = makeStringInfo();
RangeIOData *cache;
- char flags;
+ uint8 flags;
RangeBound lower;
RangeBound upper;
- bool empty;
check_stack_depth(); /* recurses when subtype is a range type */
cache = get_range_io_data(fcinfo, RangeTypeGetOid(range), IOFunc_send);
/* deserialize */
- range_deserialize(cache->typcache, range, &lower, &upper, &empty);
- flags = range_get_flags(range);
+ range_deserialize(cache->typcache, range, &lower, &upper, &flags);
/* construct output */
pq_begintypsend(buf);
@@ -433,14 +429,14 @@ range_lower(PG_FUNCTION_ARGS)
TypeCacheEntry *typcache;
RangeBound lower;
RangeBound upper;
- bool empty;
+ uint8 flags;
typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
- range_deserialize(typcache, r1, &lower, &upper, &empty);
+ range_deserialize(typcache, r1, &lower, &upper, &flags);
/* Return NULL if there's no finite lower bound */
- if (empty || lower.infinite)
+ if (RangeFlagsIsEmpty(flags) || lower.infinite)
PG_RETURN_NULL();
PG_RETURN_DATUM(lower.val);
@@ -454,14 +450,14 @@ range_upper(PG_FUNCTION_ARGS)
TypeCacheEntry *typcache;
RangeBound lower;
RangeBound upper;
- bool empty;
+ uint8 flags;
typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
- range_deserialize(typcache, r1, &lower, &upper, &empty);
+ range_deserialize(typcache, r1, &lower, &upper, &flags);
/* Return NULL if there's no finite upper bound */
- if (empty || upper.infinite)
+ if (RangeFlagsIsEmpty(flags) || upper.infinite)
PG_RETURN_NULL();
PG_RETURN_DATUM(upper.val);
@@ -475,9 +471,8 @@ Datum
range_empty(PG_FUNCTION_ARGS)
{
RangeType *r1 = PG_GETARG_RANGE_P(0);
- char flags = range_get_flags(r1);
- PG_RETURN_BOOL(flags & RANGE_EMPTY);
+ PG_RETURN_BOOL(RangeIsEmpty(r1));
}
/* is lower bound inclusive? */
@@ -560,19 +555,19 @@ range_eq_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType
lower2;
RangeBound upper1,
upper2;
- bool empty1,
- empty2;
+ uint8 flags1,
+ flags2;
/* 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);
+ range_deserialize(typcache, r1, &lower1, &upper1, &flags1);
+ range_deserialize(typcache, r2, &lower2, &upper2, &flags2);
- if (empty1 && empty2)
+ if (RangeFlagsIsEmpty(flags1) && RangeFlagsIsEmpty(flags2))
return true;
- if (empty1 != empty2)
+ if (RangeFlagsIsEmpty(flags1) != RangeFlagsIsEmpty(flags2))
return false;
if (range_cmp_bounds(typcache, &lower1, &lower2) != 0)
@@ -651,18 +646,18 @@ range_before_internal(TypeCacheEntry *typcache, const RangeType *r1, const Range
lower2;
RangeBound upper1,
upper2;
- bool empty1,
- empty2;
+ uint8 flags1,
+ flags2;
/* 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);
+ range_deserialize(typcache, r1, &lower1, &upper1, &flags1);
+ range_deserialize(typcache, r2, &lower2, &upper2, &flags2);
/* An empty range is neither before nor after any other range */
- if (empty1 || empty2)
+ if (RangeFlagsIsEmpty(flags1) || RangeFlagsIsEmpty(flags2))
return false;
return (range_cmp_bounds(typcache, &upper1, &lower2) < 0);
@@ -689,18 +684,18 @@ range_after_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeT
lower2;
RangeBound upper1,
upper2;
- bool empty1,
- empty2;
+ uint8 flags1,
+ flags2;
/* 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);
+ range_deserialize(typcache, r1, &lower1, &upper1, &flags1);
+ range_deserialize(typcache, r2, &lower2, &upper2, &flags2);
/* An empty range is neither before nor after any other range */
- if (empty1 || empty2)
+ if (RangeFlagsIsEmpty(flags1) || RangeFlagsIsEmpty(flags2))
return false;
return (range_cmp_bounds(typcache, &lower1, &upper2) > 0);
@@ -785,18 +780,18 @@ range_adjacent_internal(TypeCacheEntry *typcache, const RangeType *r1, const Ran
lower2;
RangeBound upper1,
upper2;
- bool empty1,
- empty2;
+ uint8 flags1,
+ flags2;
/* 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);
+ range_deserialize(typcache, r1, &lower1, &upper1, &flags1);
+ range_deserialize(typcache, r2, &lower2, &upper2, &flags2);
/* An empty range is not adjacent to any other range */
- if (empty1 || empty2)
+ if (RangeFlagsIsEmpty(flags1) || RangeFlagsIsEmpty(flags2))
return false;
/*
@@ -828,18 +823,18 @@ range_overlaps_internal(TypeCacheEntry *typcache, const RangeType *r1, const Ran
lower2;
RangeBound upper1,
upper2;
- bool empty1,
- empty2;
+ uint8 flags1,
+ flags2;
/* 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);
+ range_deserialize(typcache, r1, &lower1, &upper1, &flags1);
+ range_deserialize(typcache, r2, &lower2, &upper2, &flags2);
/* An empty range does not overlap any other range */
- if (empty1 || empty2)
+ if (RangeFlagsIsEmpty(flags1) || RangeFlagsIsEmpty(flags2))
return false;
if (range_cmp_bounds(typcache, &lower1, &lower2) >= 0 &&
@@ -874,18 +869,18 @@ range_overleft_internal(TypeCacheEntry *typcache, const RangeType *r1, const Ran
lower2;
RangeBound upper1,
upper2;
- bool empty1,
- empty2;
+ uint8 flags1,
+ flags2;
/* 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);
+ range_deserialize(typcache, r1, &lower1, &upper1, &flags1);
+ range_deserialize(typcache, r2, &lower2, &upper2, &flags2);
/* An empty range is neither before nor after any other range */
- if (empty1 || empty2)
+ if (RangeFlagsIsEmpty(flags1) || RangeFlagsIsEmpty(flags2))
return false;
if (range_cmp_bounds(typcache, &upper1, &upper2) <= 0)
@@ -915,18 +910,18 @@ range_overright_internal(TypeCacheEntry *typcache, const RangeType *r1, const Ra
lower2;
RangeBound upper1,
upper2;
- bool empty1,
- empty2;
+ uint8 flags1,
+ flags2;
/* 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);
+ range_deserialize(typcache, r1, &lower1, &upper1, &flags1);
+ range_deserialize(typcache, r2, &lower2, &upper2, &flags2);
/* An empty range is neither before nor after any other range */
- if (empty1 || empty2)
+ if (RangeFlagsIsEmpty(flags1) || RangeFlagsIsEmpty(flags2))
return false;
if (range_cmp_bounds(typcache, &lower1, &lower2) >= 0)
@@ -962,8 +957,8 @@ range_minus(PG_FUNCTION_ARGS)
lower2;
RangeBound upper1,
upper2;
- bool empty1,
- empty2;
+ uint8 flags1,
+ flags2;
int cmp_l1l2,
cmp_l1u2,
cmp_u1l2,
@@ -975,11 +970,11 @@ range_minus(PG_FUNCTION_ARGS)
typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
- range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
- range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
+ range_deserialize(typcache, r1, &lower1, &upper1, &flags1);
+ range_deserialize(typcache, r2, &lower2, &upper2, &flags2);
/* if either is empty, r1 is the correct answer */
- if (empty1 || empty2)
+ if (RangeFlagsIsEmpty(flags1) || RangeFlagsIsEmpty(flags2))
PG_RETURN_RANGE_P(r1);
cmp_l1l2 = range_cmp_bounds(typcache, &lower1, &lower2);
@@ -1028,8 +1023,8 @@ range_union_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2,
lower2;
RangeBound upper1,
upper2;
- bool empty1,
- empty2;
+ uint8 flags1,
+ flags2;
RangeBound *result_lower;
RangeBound *result_upper;
@@ -1037,13 +1032,13 @@ range_union_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2,
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);
+ range_deserialize(typcache, r1, &lower1, &upper1, &flags1);
+ range_deserialize(typcache, r2, &lower2, &upper2, &flags2);
/* if either is empty, the other is the correct answer */
- if (empty1)
+ if (RangeFlagsIsEmpty(flags1))
return r2;
- if (empty2)
+ if (RangeFlagsIsEmpty(flags2))
return r1;
if (strict &&
@@ -1105,8 +1100,8 @@ range_intersect(PG_FUNCTION_ARGS)
lower2;
RangeBound upper1,
upper2;
- bool empty1,
- empty2;
+ uint8 flags1,
+ flags2;
RangeBound *result_lower;
RangeBound *result_upper;
@@ -1116,10 +1111,11 @@ range_intersect(PG_FUNCTION_ARGS)
typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
- range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
- range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
+ range_deserialize(typcache, r1, &lower1, &upper1, &flags1);
+ range_deserialize(typcache, r2, &lower2, &upper2, &flags2);
- if (empty1 || empty2 || !DatumGetBool(range_overlaps(fcinfo)))
+ if (RangeFlagsIsEmpty(flags1) || RangeFlagsIsEmpty(flags2) ||
+ !DatumGetBool(range_overlaps(fcinfo)))
PG_RETURN_RANGE_P(make_empty_range(typcache));
if (range_cmp_bounds(typcache, &lower1, &lower2) >= 0)
@@ -1148,8 +1144,8 @@ range_cmp(PG_FUNCTION_ARGS)
lower2;
RangeBound upper1,
upper2;
- bool empty1,
- empty2;
+ uint8 flags1,
+ flags2;
int cmp;
check_stack_depth(); /* recurses when subtype is a range type */
@@ -1160,15 +1156,15 @@ range_cmp(PG_FUNCTION_ARGS)
typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
- range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
- range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
+ range_deserialize(typcache, r1, &lower1, &upper1, &flags1);
+ range_deserialize(typcache, r2, &lower2, &upper2, &flags2);
/* For b-tree use, empty ranges sort before all else */
- if (empty1 && empty2)
+ if (RangeFlagsIsEmpty(flags1) && RangeFlagsIsEmpty(flags2))
cmp = 0;
- else if (empty1)
+ else if (RangeFlagsIsEmpty(flags1))
cmp = -1;
- else if (empty2)
+ else if (RangeFlagsIsEmpty(flags2))
cmp = 1;
else
{
@@ -1228,8 +1224,7 @@ hash_range(PG_FUNCTION_ARGS)
TypeCacheEntry *scache;
RangeBound lower;
RangeBound upper;
- bool empty;
- char flags;
+ uint8 flags;
uint32 lower_hash;
uint32 upper_hash;
@@ -1238,8 +1233,7 @@ hash_range(PG_FUNCTION_ARGS)
typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
/* deserialize */
- range_deserialize(typcache, r, &lower, &upper, &empty);
- flags = range_get_flags(r);
+ range_deserialize(typcache, r, &lower, &upper, &flags);
/*
* Look up the element type's hash function, if not done already.
@@ -1295,8 +1289,7 @@ hash_range_extended(PG_FUNCTION_ARGS)
TypeCacheEntry *scache;
RangeBound lower;
RangeBound upper;
- bool empty;
- char flags;
+ uint8 flags;
uint64 lower_hash;
uint64 upper_hash;
@@ -1304,8 +1297,7 @@ hash_range_extended(PG_FUNCTION_ARGS)
typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
- range_deserialize(typcache, r, &lower, &upper, &empty);
- flags = range_get_flags(r);
+ range_deserialize(typcache, r, &lower, &upper, &flags);
scache = typcache->rngelemtype;
if (!OidIsValid(scache->hash_extended_proc_finfo.fn_oid))
@@ -1360,13 +1352,13 @@ int4range_canonical(PG_FUNCTION_ARGS)
TypeCacheEntry *typcache;
RangeBound lower;
RangeBound upper;
- bool empty;
+ uint8 flags;
typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
- range_deserialize(typcache, r, &lower, &upper, &empty);
+ range_deserialize(typcache, r, &lower, &upper, &flags);
- if (empty)
+ if (RangeFlagsIsEmpty(flags))
PG_RETURN_RANGE_P(r);
if (!lower.infinite && !lower.inclusive)
@@ -1391,13 +1383,13 @@ int8range_canonical(PG_FUNCTION_ARGS)
TypeCacheEntry *typcache;
RangeBound lower;
RangeBound upper;
- bool empty;
+ uint8 flags;
typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
- range_deserialize(typcache, r, &lower, &upper, &empty);
+ range_deserialize(typcache, r, &lower, &upper, &flags);
- if (empty)
+ if (RangeFlagsIsEmpty(flags))
PG_RETURN_RANGE_P(r);
if (!lower.infinite && !lower.inclusive)
@@ -1422,13 +1414,13 @@ daterange_canonical(PG_FUNCTION_ARGS)
TypeCacheEntry *typcache;
RangeBound lower;
RangeBound upper;
- bool empty;
+ uint8 flags;
typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
- range_deserialize(typcache, r, &lower, &upper, &empty);
+ range_deserialize(typcache, r, &lower, &upper, &flags);
- if (empty)
+ if (RangeFlagsIsEmpty(flags))
PG_RETURN_RANGE_P(r);
if (!lower.infinite && !DATE_NOT_FINITE(DatumGetDateADT(lower.val)) &&
@@ -1697,9 +1689,8 @@ range_serialize(TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper,
*/
void
range_deserialize(TypeCacheEntry *typcache, const RangeType *range,
- RangeBound *lower, RangeBound *upper, bool *empty)
+ RangeBound *lower, RangeBound *upper, uint8 *flags)
{
- char flags;
int16 typlen;
bool typbyval;
char typalign;
@@ -1711,7 +1702,7 @@ range_deserialize(TypeCacheEntry *typcache, const RangeType *range,
Assert(RangeTypeGetOid(range) == typcache->type_id);
/* fetch the flag byte from datum's last byte */
- flags = *((const char *) range + VARSIZE(range) - 1);
+ *flags = *((const char *) range + VARSIZE(range) - 1);
/* fetch information about range's element type */
typlen = typcache->rngelemtype->typlen;
@@ -1722,7 +1713,7 @@ range_deserialize(TypeCacheEntry *typcache, const RangeType *range,
ptr = (Pointer) (range + 1);
/* fetch lower bound, if any */
- if (RANGE_HAS_LBOUND(flags))
+ if (RANGE_HAS_LBOUND(*flags))
{
/* att_align_pointer cannot be necessary here */
lbound = fetch_att(ptr, typbyval, typlen);
@@ -1732,7 +1723,7 @@ range_deserialize(TypeCacheEntry *typcache, const RangeType *range,
lbound = (Datum) 0;
/* fetch upper bound, if any */
- if (RANGE_HAS_UBOUND(flags))
+ if (RANGE_HAS_UBOUND(*flags))
{
ptr = (Pointer) att_align_pointer(ptr, typalign, typlen, ptr);
ubound = fetch_att(ptr, typbyval, typlen);
@@ -1743,16 +1734,14 @@ range_deserialize(TypeCacheEntry *typcache, const RangeType *range,
/* 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->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->infinite = (*flags & RANGE_UB_INF) != 0;
+ upper->inclusive = (*flags & RANGE_UB_INC) != 0;
upper->lower = false;
}
@@ -1799,7 +1788,10 @@ make_range(TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper,
range = range_serialize(typcache, lower, upper, empty);
- /* no need to call canonical on empty ranges ... */
+ /*
+ * no need to call canonical on empty ranges ... but don't rely
+ * solely on caller's idea of emptiness.
+ */
if (OidIsValid(typcache->rng_canonical_finfo.fn_oid) &&
!RangeIsEmpty(range))
range = DatumGetRangeTypeP(FunctionCall1(&typcache->rng_canonical_finfo,
@@ -2304,22 +2296,22 @@ range_contains_internal(TypeCacheEntry *typcache, const RangeType *r1, const Ran
{
RangeBound lower1;
RangeBound upper1;
- bool empty1;
+ uint8 flags1;
RangeBound lower2;
RangeBound upper2;
- bool empty2;
+ uint8 flags2;
/* 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);
+ range_deserialize(typcache, r1, &lower1, &upper1, &flags1);
+ range_deserialize(typcache, r2, &lower2, &upper2, &flags2);
/* If either range is empty, the answer is easy */
- if (empty2)
+ if (RangeFlagsIsEmpty(flags2))
return true;
- else if (empty1)
+ else if (RangeFlagsIsEmpty(flags1))
return false;
/* Else we must have lower1 <= lower2 and upper1 >= upper2 */
@@ -2345,12 +2337,12 @@ range_contains_elem_internal(TypeCacheEntry *typcache, const RangeType *r, Datum
{
RangeBound lower;
RangeBound upper;
- bool empty;
+ uint8 flags;
int32 cmp;
- range_deserialize(typcache, r, &lower, &upper, &empty);
+ range_deserialize(typcache, r, &lower, &upper, &flags);
- if (empty)
+ if (RangeFlagsIsEmpty(flags))
return false;
if (!lower.infinite)
diff --git a/src/backend/utils/adt/rangetypes_gist.c b/src/backend/utils/adt/rangetypes_gist.c
index 75069c3ac2..0cc91efab8 100644
--- a/src/backend/utils/adt/rangetypes_gist.c
+++ b/src/backend/utils/adt/rangetypes_gist.c
@@ -246,8 +246,8 @@ range_gist_penalty(PG_FUNCTION_ARGS)
new_lower,
orig_upper,
new_upper;
- bool orig_empty,
- new_empty;
+ uint8 orig_flags,
+ new_flags;
if (RangeTypeGetOid(orig) != RangeTypeGetOid(new))
elog(ERROR, "range types do not match");
@@ -256,18 +256,18 @@ range_gist_penalty(PG_FUNCTION_ARGS)
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);
+ range_deserialize(typcache, orig, &orig_lower, &orig_upper, &orig_flags);
+ range_deserialize(typcache, new, &new_lower, &new_upper, &new_flags);
/*
* 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)
+ if (RangeFlagsIsEmpty(new_flags))
{
/* Handle insertion of empty range */
- if (orig_empty)
+ if (RangeFlagsIsEmpty(orig_flags))
{
/*
* The best case is to insert it to empty original range.
@@ -276,7 +276,7 @@ range_gist_penalty(PG_FUNCTION_ARGS)
*/
*penalty = 0.0;
}
- else if (RangeIsOrContainsEmpty(orig))
+ else if (RangeFlagsIsOrContainsEmpty(orig_flags))
{
/*
* The second case is to insert empty range into range which
@@ -337,7 +337,7 @@ range_gist_penalty(PG_FUNCTION_ARGS)
*penalty = 2 * INFINITE_BOUND_PENALTY;
}
- if (RangeIsOrContainsEmpty(orig))
+ if (RangeFlagsIsOrContainsEmpty(orig_flags))
{
/*
* Original range is narrower when it doesn't contain empty
@@ -349,7 +349,7 @@ range_gist_penalty(PG_FUNCTION_ARGS)
else if (new_lower.infinite)
{
/* Handle insertion of (-inf, x) range */
- if (!orig_empty && orig_lower.infinite)
+ if (!RangeFlagsIsEmpty(orig_flags) && orig_lower.infinite)
{
if (orig_upper.infinite)
{
@@ -396,7 +396,7 @@ range_gist_penalty(PG_FUNCTION_ARGS)
else if (new_upper.infinite)
{
/* Handle insertion of (x, +inf) range */
- if (!orig_empty && orig_upper.infinite)
+ if (!RangeFlagsIsEmpty(orig_flags) && orig_upper.infinite)
{
if (orig_lower.infinite)
{
@@ -443,7 +443,7 @@ range_gist_penalty(PG_FUNCTION_ARGS)
else
{
/* Handle insertion of normal (non-empty, non-infinite) range */
- if (orig_empty || orig_lower.infinite || orig_upper.infinite)
+ if (RangeFlagsIsEmpty(orig_flags) || orig_lower.infinite || orig_upper.infinite)
{
/*
* Avoid mixing normal ranges with infinite and empty ranges.
@@ -699,19 +699,15 @@ range_super_union(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
lower2;
RangeBound upper1,
upper2;
- bool empty1,
- empty2;
- char flags1,
+ uint8 flags1,
flags2;
RangeBound *result_lower;
RangeBound *result_upper;
- range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
- range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
- flags1 = range_get_flags(r1);
- flags2 = range_get_flags(r2);
+ range_deserialize(typcache, r1, &lower1, &upper1, &flags1);
+ range_deserialize(typcache, r2, &lower2, &upper2, &flags2);
- if (empty1)
+ if (RangeFlagsIsEmpty(flags1))
{
/* We can return r2 as-is if it already is or contains empty */
if (flags2 & (RANGE_EMPTY | RANGE_CONTAIN_EMPTY))
@@ -721,7 +717,7 @@ range_super_union(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
range_set_contain_empty(r2);
return r2;
}
- if (empty2)
+ if (RangeFlagsIsEmpty(flags2))
{
/* We can return r1 as-is if it already is or contains empty */
if (flags1 & (RANGE_EMPTY | RANGE_CONTAIN_EMPTY))
@@ -983,17 +979,17 @@ range_gist_single_sorting_split(TypeCacheEntry *typcache,
{
RangeType *range = DatumGetRangeTypeP(entryvec->vector[i].key);
RangeBound bound2;
- bool empty;
+ uint8 flags;
sortItems[i - 1].index = i;
/* Put appropriate bound into array */
if (use_upper_bound)
range_deserialize(typcache, range, &bound2,
- &sortItems[i - 1].bound, &empty);
+ &sortItems[i - 1].bound, &flags);
else
range_deserialize(typcache, range, &sortItems[i - 1].bound,
- &bound2, &empty);
- Assert(!empty);
+ &bound2, &flags);
+ Assert(!RangeFlagsIsEmpty(flags));
}
qsort_arg(sortItems, maxoff, sizeof(SingleBoundSortItem),
@@ -1084,13 +1080,13 @@ range_gist_double_sorting_split(TypeCacheEntry *typcache,
for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
{
RangeType *range = DatumGetRangeTypeP(entryvec->vector[i].key);
- bool empty;
+ uint8 flags;
range_deserialize(typcache, range,
&by_lower[i - FirstOffsetNumber].lower,
&by_lower[i - FirstOffsetNumber].upper,
- &empty);
- Assert(!empty);
+ &flags);
+ Assert(!RangeFlagsIsEmpty(flags));
}
/*
@@ -1253,14 +1249,14 @@ range_gist_double_sorting_split(TypeCacheEntry *typcache,
{
RangeBound lower,
upper;
- bool empty;
+ uint8 flags;
/*
* Get upper and lower bounds along selected axis.
*/
range = DatumGetRangeTypeP(entryvec->vector[i].key);
- range_deserialize(typcache, range, &lower, &upper, &empty);
+ range_deserialize(typcache, range, &lower, &upper, &flags);
if (range_cmp_bounds(typcache, &upper, context.left_upper) <= 0)
{
diff --git a/src/backend/utils/adt/rangetypes_selfuncs.c b/src/backend/utils/adt/rangetypes_selfuncs.c
index 25dd84f4df..c518b73fa9 100644
--- a/src/backend/utils/adt/rangetypes_selfuncs.c
+++ b/src/backend/utils/adt/rangetypes_selfuncs.c
@@ -381,7 +381,7 @@ calc_hist_selectivity(TypeCacheEntry *typcache, VariableStatData *vardata,
int i;
RangeBound const_lower;
RangeBound const_upper;
- bool empty;
+ uint8 flags;
double hist_selec;
/* Can't use the histogram with insecure range support functions */
@@ -417,9 +417,9 @@ calc_hist_selectivity(TypeCacheEntry *typcache, VariableStatData *vardata,
for (i = 0; i < nhist; i++)
{
range_deserialize(typcache, DatumGetRangeTypeP(hslot.values[i]),
- &hist_lower[i], &hist_upper[i], &empty);
+ &hist_lower[i], &hist_upper[i], &flags);
/* The histogram should not contain any empty ranges */
- if (empty)
+ if (RangeFlagsIsEmpty(flags))
elog(ERROR, "bounds histogram contains an empty range");
}
@@ -449,8 +449,8 @@ calc_hist_selectivity(TypeCacheEntry *typcache, VariableStatData *vardata,
memset(&lslot, 0, sizeof(lslot));
/* Extract the bounds of the constant value. */
- range_deserialize(typcache, constval, &const_lower, &const_upper, &empty);
- Assert(!empty);
+ range_deserialize(typcache, constval, &const_lower, &const_upper, &flags);
+ Assert(!RangeFlagsIsEmpty(flags));
/*
* Calculate selectivity comparing the lower or upper bound of the
diff --git a/src/backend/utils/adt/rangetypes_spgist.c b/src/backend/utils/adt/rangetypes_spgist.c
index dd2bc742aa..edcd0eb1a9 100644
--- a/src/backend/utils/adt/rangetypes_spgist.c
+++ b/src/backend/utils/adt/rangetypes_spgist.c
@@ -96,16 +96,16 @@ getQuadrant(TypeCacheEntry *typcache, const RangeType *centroid, const RangeType
{
RangeBound centroidLower,
centroidUpper;
- bool centroidEmpty;
+ uint8 centroidFlags;
RangeBound lower,
upper;
- bool empty;
+ uint8 flags;
range_deserialize(typcache, centroid, ¢roidLower, ¢roidUpper,
- ¢roidEmpty);
- range_deserialize(typcache, tst, &lower, &upper, &empty);
+ ¢roidFlags);
+ range_deserialize(typcache, tst, &lower, &upper, &flags);
- if (empty)
+ if (RangeFlagsIsEmpty(flags))
return 5;
if (range_cmp_bounds(typcache, &lower, ¢roidLower) >= 0)
@@ -205,7 +205,7 @@ spg_range_quad_picksplit(PG_FUNCTION_ARGS)
int j;
int nonEmptyCount;
RangeType *centroid;
- bool empty;
+ uint8 flags;
TypeCacheEntry *typcache;
/* Use the median values of lower and upper bounds as the centroid range */
@@ -224,8 +224,8 @@ spg_range_quad_picksplit(PG_FUNCTION_ARGS)
for (i = 0; i < in->nTuples; i++)
{
range_deserialize(typcache, DatumGetRangeTypeP(in->datums[i]),
- &lowerBounds[j], &upperBounds[j], &empty);
- if (!empty)
+ &lowerBounds[j], &upperBounds[j], &flags);
+ if (!RangeFlagsIsEmpty(flags))
j++;
}
nonEmptyCount = j;
@@ -409,7 +409,7 @@ spg_range_quad_inner_consistent(PG_FUNCTION_ARGS)
{
RangeBound centroidLower,
centroidUpper;
- bool centroidEmpty;
+ uint8 centroidFlags;
TypeCacheEntry *typcache;
RangeType *centroid;
@@ -418,7 +418,7 @@ spg_range_quad_inner_consistent(PG_FUNCTION_ARGS)
typcache = range_get_typcache(fcinfo,
RangeTypeGetOid(DatumGetRangeTypeP(centroid)));
range_deserialize(typcache, centroid, ¢roidLower, ¢roidUpper,
- ¢roidEmpty);
+ ¢roidFlags);
Assert(in->nNodes == 4 || in->nNodes == 5);
@@ -434,13 +434,13 @@ spg_range_quad_inner_consistent(PG_FUNCTION_ARGS)
StrategyNumber strategy;
RangeBound lower,
upper;
- bool empty;
+ uint8 flags;
RangeType *range = NULL;
RangeType *prevCentroid = NULL;
RangeBound prevLower,
prevUpper;
- bool prevEmpty;
+ uint8 prevFlags;
/* Restrictions on range bounds according to scan strategy */
RangeBound *minLower = NULL,
@@ -475,14 +475,14 @@ spg_range_quad_inner_consistent(PG_FUNCTION_ARGS)
upper.lower = false;
upper.val = in->scankeys[i].sk_argument;
- empty = false;
+ flags = 0;
strategy = RANGESTRAT_CONTAINS;
}
else
{
range = DatumGetRangeTypeP(in->scankeys[i].sk_argument);
- range_deserialize(typcache, range, &lower, &upper, &empty);
+ range_deserialize(typcache, range, &lower, &upper, &flags);
}
/*
@@ -547,7 +547,7 @@ spg_range_quad_inner_consistent(PG_FUNCTION_ARGS)
break;
case RANGESTRAT_ADJACENT:
- if (empty)
+ if (RangeFlagsIsEmpty(flags))
break; /* Skip to strictEmpty check. */
/*
@@ -559,7 +559,7 @@ spg_range_quad_inner_consistent(PG_FUNCTION_ARGS)
{
prevCentroid = DatumGetRangeTypeP(in->traversalValue);
range_deserialize(typcache, prevCentroid,
- &prevLower, &prevUpper, &prevEmpty);
+ &prevLower, &prevUpper, &prevFlags);
}
/*
@@ -614,7 +614,7 @@ spg_range_quad_inner_consistent(PG_FUNCTION_ARGS)
* All non-empty ranges contain an empty range.
*/
strictEmpty = false;
- if (!empty)
+ if (!RangeFlagsIsEmpty(flags))
{
which &= (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4);
maxLower = &lower;
@@ -625,7 +625,7 @@ spg_range_quad_inner_consistent(PG_FUNCTION_ARGS)
case RANGESTRAT_CONTAINED_BY:
/* The opposite of contains. */
strictEmpty = false;
- if (empty)
+ if (RangeFlagsIsEmpty(flags))
{
/* An empty range is only contained by an empty range */
which &= (1 << 5);
@@ -654,7 +654,7 @@ spg_range_quad_inner_consistent(PG_FUNCTION_ARGS)
if (strictEmpty)
{
- if (empty)
+ if (RangeFlagsIsEmpty(flags))
{
/* Scan key is empty, no branches are satisfying */
which = 0;
diff --git a/src/backend/utils/adt/rangetypes_typanalyze.c b/src/backend/utils/adt/rangetypes_typanalyze.c
index 57413b0720..f020537fb0 100644
--- a/src/backend/utils/adt/rangetypes_typanalyze.c
+++ b/src/backend/utils/adt/rangetypes_typanalyze.c
@@ -121,11 +121,11 @@ compute_range_stats(VacAttrStats *stats, AnalyzeAttrFetchFunc fetchfunc,
for (range_no = 0; range_no < samplerows; range_no++)
{
Datum value;
- bool isnull,
- empty;
+ bool isnull;
RangeType *range;
RangeBound lower,
upper;
+ uint8 flags;
float8 length;
vacuum_delay_point();
@@ -146,9 +146,9 @@ compute_range_stats(VacAttrStats *stats, AnalyzeAttrFetchFunc fetchfunc,
/* Get range and deserialize it for further analysis. */
range = DatumGetRangeTypeP(value);
- range_deserialize(typcache, range, &lower, &upper, &empty);
+ range_deserialize(typcache, range, &lower, &upper, &flags);
- if (!empty)
+ if (!RangeFlagsIsEmpty(flags))
{
/* Remember bounds and length for further usage in histograms */
lowers[non_empty_cnt] = lower;
diff --git a/src/include/utils/rangetypes.h b/src/include/utils/rangetypes.h
index 0cbbf09033..158fe78322 100644
--- a/src/include/utils/rangetypes.h
+++ b/src/include/utils/rangetypes.h
@@ -51,9 +51,13 @@ typedef struct
RANGE_UB_NULL | \
RANGE_UB_INF)))
-#define RangeIsEmpty(r) ((range_get_flags(r) & RANGE_EMPTY) != 0)
-#define RangeIsOrContainsEmpty(r) \
- ((range_get_flags(r) & (RANGE_EMPTY | RANGE_CONTAIN_EMPTY)) != 0)
+#define RangeFlagsIsEmpty(flags) \
+ (((flags) & RANGE_EMPTY) != 0)
+#define RangeFlagsIsOrContainsEmpty(flags) \
+ (((flags) & (RANGE_EMPTY | RANGE_CONTAIN_EMPTY)) != 0)
+
+#define RangeIsEmpty(r) (RangeFlagsIsEmpty(range_get_flags(r)))
+#define RangeIsOrContainsEmpty(r) (RangeFlagsIsOrContainsEmpty(range_get_flags(r)))
/* Internal representation of either bound of a range (not what's on disk) */
@@ -123,7 +127,7 @@ extern RangeType *range_serialize(TypeCacheEntry *typcache, RangeBound *lower,
RangeBound *upper, bool empty);
extern void range_deserialize(TypeCacheEntry *typcache, const RangeType *range,
RangeBound *lower, RangeBound *upper,
- bool *empty);
+ uint8 *flags);
extern char range_get_flags(const RangeType *range);
extern void range_set_contain_empty(RangeType *range);
extern RangeType *make_range(TypeCacheEntry *typcache, RangeBound *lower,