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, &centroidLower, &centroidUpper,
-					  &centroidEmpty);
-	range_deserialize(typcache, tst, &lower, &upper, &empty);
+					  &centroidFlags);
+	range_deserialize(typcache, tst, &lower, &upper, &flags);
 
-	if (empty)
+	if (RangeFlagsIsEmpty(flags))
 		return 5;
 
 	if (range_cmp_bounds(typcache, &lower, &centroidLower) >= 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, &centroidLower, &centroidUpper,
-						  &centroidEmpty);
+						  &centroidFlags);
 
 		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,

Reply via email to