1 /*-------------------------------------------------------------------------
4 * I/O functions, operators, and support functions for range types.
6 * The stored (serialized) format of a range value is:
8 * 4 bytes: varlena header
9 * 4 bytes: range type's OID
10 * Lower boundary value, if any, aligned according to subtype's typalign
11 * Upper boundary value, if any, aligned according to subtype's typalign
14 * This representation is chosen to avoid needing any padding before the
15 * lower boundary value, even when it requires double alignment. We can
16 * expect that the varlena header is presented to us on a suitably aligned
17 * boundary (possibly after detoasting), and then the lower boundary is too.
18 * Note that this means we can't work with a packed (short varlena header)
19 * value; we must detoast it first.
22 * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
23 * Portions Copyright (c) 1994, Regents of the University of California
27 * src/backend/utils/adt/rangetypes.c
29 *-------------------------------------------------------------------------
33 #include "access/hash.h"
34 #include "lib/stringinfo.h"
35 #include "libpq/pqformat.h"
36 #include "miscadmin.h"
37 #include "utils/builtins.h"
38 #include "utils/date.h"
39 #include "utils/int8.h"
40 #include "utils/lsyscache.h"
41 #include "utils/rangetypes.h"
42 #include "utils/timestamp.h"
45 #define RANGE_EMPTY_LITERAL "empty"
47 /* fn_extra cache entry for one of the range I/O functions */
48 typedef struct RangeIOData
50 TypeCacheEntry *typcache; /* range type's typcache entry */
51 Oid typiofunc; /* element type's I/O function */
52 Oid typioparam; /* element type's I/O parameter */
53 FmgrInfo proc; /* lookup result for typiofunc */
57 static RangeIOData *get_range_io_data(FunctionCallInfo fcinfo, Oid rngtypid,
59 static char range_parse_flags(const char *flags_str);
60 static void range_parse(const char *input_str, char *flags, char **lbound_str,
62 static const char *range_parse_bound(const char *string, const char *ptr,
63 char **bound_str, bool *infinite);
64 static char *range_deparse(char flags, const char *lbound_str,
65 const char *ubound_str);
66 static char *range_bound_escape(const char *value);
67 static Size datum_compute_size(Size sz, Datum datum, bool typbyval,
68 char typalign, int16 typlen, char typstorage);
69 static Pointer datum_write(Pointer ptr, Datum datum, bool typbyval,
70 char typalign, int16 typlen, char typstorage);
74 *----------------------------------------------------------
76 *----------------------------------------------------------
80 range_in(PG_FUNCTION_ARGS)
82 char *input_str = PG_GETARG_CSTRING(0);
83 Oid rngtypoid = PG_GETARG_OID(1);
84 Oid typmod = PG_GETARG_INT32(2);
93 check_stack_depth(); /* recurses when subtype is a range type */
95 cache = get_range_io_data(fcinfo, rngtypoid, IOFunc_input);
98 range_parse(input_str, &flags, &lbound_str, &ubound_str);
100 /* call element type's input function */
101 if (RANGE_HAS_LBOUND(flags))
102 lower.val = InputFunctionCall(&cache->proc, lbound_str,
103 cache->typioparam, typmod);
104 if (RANGE_HAS_UBOUND(flags))
105 upper.val = InputFunctionCall(&cache->proc, ubound_str,
106 cache->typioparam, typmod);
108 lower.infinite = (flags & RANGE_LB_INF) != 0;
109 lower.inclusive = (flags & RANGE_LB_INC) != 0;
111 upper.infinite = (flags & RANGE_UB_INF) != 0;
112 upper.inclusive = (flags & RANGE_UB_INC) != 0;
115 /* serialize and canonicalize */
116 range = make_range(cache->typcache, &lower, &upper, flags & RANGE_EMPTY);
118 PG_RETURN_RANGE(range);
122 range_out(PG_FUNCTION_ARGS)
124 RangeType *range = PG_GETARG_RANGE(0);
128 char *lbound_str = NULL;
129 char *ubound_str = NULL;
134 check_stack_depth(); /* recurses when subtype is a range type */
136 cache = get_range_io_data(fcinfo, RangeTypeGetOid(range), IOFunc_output);
139 range_deserialize(cache->typcache, range, &lower, &upper, &empty);
140 flags = range_get_flags(range);
142 /* call element type's output function */
143 if (RANGE_HAS_LBOUND(flags))
144 lbound_str = OutputFunctionCall(&cache->proc, lower.val);
145 if (RANGE_HAS_UBOUND(flags))
146 ubound_str = OutputFunctionCall(&cache->proc, upper.val);
148 /* construct result string */
149 output_str = range_deparse(flags, lbound_str, ubound_str);
151 PG_RETURN_CSTRING(output_str);
155 * Binary representation: The first byte is the flags, then the lower bound
156 * (if present), then the upper bound (if present). Each bound is represented
157 * by a 4-byte length header and the binary representation of that bound (as
158 * returned by a call to the send function for the subtype).
162 range_recv(PG_FUNCTION_ARGS)
164 StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
165 Oid rngtypoid = PG_GETARG_OID(1);
166 int32 typmod = PG_GETARG_INT32(2);
173 check_stack_depth(); /* recurses when subtype is a range type */
175 cache = get_range_io_data(fcinfo, rngtypoid, IOFunc_receive);
177 /* receive the flags... */
178 flags = (unsigned char) pq_getmsgbyte(buf);
181 * Mask out any unsupported flags, particularly RANGE_xB_NULL which would
182 * confuse following tests. Note that range_serialize will take care of
183 * cleaning up any inconsistencies in the remaining flags.
185 flags &= (RANGE_EMPTY |
191 /* receive the bounds ... */
192 if (RANGE_HAS_LBOUND(flags))
194 uint32 bound_len = pq_getmsgint(buf, 4);
195 const char *bound_data = pq_getmsgbytes(buf, bound_len);
196 StringInfoData bound_buf;
198 initStringInfo(&bound_buf);
199 appendBinaryStringInfo(&bound_buf, bound_data, bound_len);
201 lower.val = ReceiveFunctionCall(&cache->proc,
205 pfree(bound_buf.data);
208 lower.val = (Datum) 0;
210 if (RANGE_HAS_UBOUND(flags))
212 uint32 bound_len = pq_getmsgint(buf, 4);
213 const char *bound_data = pq_getmsgbytes(buf, bound_len);
214 StringInfoData bound_buf;
216 initStringInfo(&bound_buf);
217 appendBinaryStringInfo(&bound_buf, bound_data, bound_len);
219 upper.val = ReceiveFunctionCall(&cache->proc,
223 pfree(bound_buf.data);
226 upper.val = (Datum) 0;
230 /* finish constructing RangeBound representation */
231 lower.infinite = (flags & RANGE_LB_INF) != 0;
232 lower.inclusive = (flags & RANGE_LB_INC) != 0;
234 upper.infinite = (flags & RANGE_UB_INF) != 0;
235 upper.inclusive = (flags & RANGE_UB_INC) != 0;
238 /* serialize and canonicalize */
239 range = make_range(cache->typcache, &lower, &upper, flags & RANGE_EMPTY);
241 PG_RETURN_RANGE(range);
245 range_send(PG_FUNCTION_ARGS)
247 RangeType *range = PG_GETARG_RANGE(0);
248 StringInfo buf = makeStringInfo();
255 check_stack_depth(); /* recurses when subtype is a range type */
257 cache = get_range_io_data(fcinfo, RangeTypeGetOid(range), IOFunc_send);
260 range_deserialize(cache->typcache, range, &lower, &upper, &empty);
261 flags = range_get_flags(range);
263 /* construct output */
264 pq_begintypsend(buf);
266 pq_sendbyte(buf, flags);
268 if (RANGE_HAS_LBOUND(flags))
270 Datum bound = PointerGetDatum(SendFunctionCall(&cache->proc,
272 uint32 bound_len = VARSIZE(bound) - VARHDRSZ;
273 char *bound_data = VARDATA(bound);
275 pq_sendint(buf, bound_len, 4);
276 pq_sendbytes(buf, bound_data, bound_len);
279 if (RANGE_HAS_UBOUND(flags))
281 Datum bound = PointerGetDatum(SendFunctionCall(&cache->proc,
283 uint32 bound_len = VARSIZE(bound) - VARHDRSZ;
284 char *bound_data = VARDATA(bound);
286 pq_sendint(buf, bound_len, 4);
287 pq_sendbytes(buf, bound_data, bound_len);
290 PG_RETURN_BYTEA_P(pq_endtypsend(buf));
294 * get_range_io_data: get cached information needed for range type I/O
296 * The range I/O functions need a bit more cached info than other range
297 * functions, so they store a RangeIOData struct in fn_extra, not just a
298 * pointer to a type cache entry.
301 get_range_io_data(FunctionCallInfo fcinfo, Oid rngtypid, IOFuncSelector func)
303 RangeIOData *cache = (RangeIOData *) fcinfo->flinfo->fn_extra;
305 if (cache == NULL || cache->typcache->type_id != rngtypid)
312 cache = (RangeIOData *) MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
313 sizeof(RangeIOData));
314 cache->typcache = lookup_type_cache(rngtypid, TYPECACHE_RANGE_INFO);
315 if (cache->typcache->rngelemtype == NULL)
316 elog(ERROR, "type %u is not a range type", rngtypid);
318 /* get_type_io_data does more than we need, but is convenient */
319 get_type_io_data(cache->typcache->rngelemtype->type_id,
328 if (!OidIsValid(cache->typiofunc))
330 /* this could only happen for receive or send */
331 if (func == IOFunc_receive)
333 (errcode(ERRCODE_UNDEFINED_FUNCTION),
334 errmsg("no binary input function available for type %s",
335 format_type_be(cache->typcache->rngelemtype->type_id))));
338 (errcode(ERRCODE_UNDEFINED_FUNCTION),
339 errmsg("no binary output function available for type %s",
340 format_type_be(cache->typcache->rngelemtype->type_id))));
342 fmgr_info_cxt(cache->typiofunc, &cache->proc,
343 fcinfo->flinfo->fn_mcxt);
345 fcinfo->flinfo->fn_extra = (void *) cache;
353 *----------------------------------------------------------
355 *----------------------------------------------------------
358 /* Construct standard-form range value from two arguments */
360 range_constructor2(PG_FUNCTION_ARGS)
362 Datum arg1 = PG_GETARG_DATUM(0);
363 Datum arg2 = PG_GETARG_DATUM(1);
364 Oid rngtypid = get_fn_expr_rettype(fcinfo->flinfo);
366 TypeCacheEntry *typcache;
370 typcache = range_get_typcache(fcinfo, rngtypid);
372 lower.val = PG_ARGISNULL(0) ? (Datum) 0 : arg1;
373 lower.infinite = PG_ARGISNULL(0);
374 lower.inclusive = true;
377 upper.val = PG_ARGISNULL(1) ? (Datum) 0 : arg2;
378 upper.infinite = PG_ARGISNULL(1);
379 upper.inclusive = false;
382 range = make_range(typcache, &lower, &upper, false);
384 PG_RETURN_RANGE(range);
387 /* Construct general range value from three arguments */
389 range_constructor3(PG_FUNCTION_ARGS)
391 Datum arg1 = PG_GETARG_DATUM(0);
392 Datum arg2 = PG_GETARG_DATUM(1);
393 Oid rngtypid = get_fn_expr_rettype(fcinfo->flinfo);
395 TypeCacheEntry *typcache;
400 typcache = range_get_typcache(fcinfo, rngtypid);
404 (errcode(ERRCODE_DATA_EXCEPTION),
405 errmsg("range constructor flags argument must not be null")));
407 flags = range_parse_flags(text_to_cstring(PG_GETARG_TEXT_PP(2)));
409 lower.val = PG_ARGISNULL(0) ? (Datum) 0 : arg1;
410 lower.infinite = PG_ARGISNULL(0);
411 lower.inclusive = (flags & RANGE_LB_INC) != 0;
414 upper.val = PG_ARGISNULL(1) ? (Datum) 0 : arg2;
415 upper.infinite = PG_ARGISNULL(1);
416 upper.inclusive = (flags & RANGE_UB_INC) != 0;
419 range = make_range(typcache, &lower, &upper, false);
421 PG_RETURN_RANGE(range);
425 /* range -> subtype functions */
427 /* extract lower bound value */
429 range_lower(PG_FUNCTION_ARGS)
431 RangeType *r1 = PG_GETARG_RANGE(0);
432 TypeCacheEntry *typcache;
437 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
439 range_deserialize(typcache, r1, &lower, &upper, &empty);
441 /* Return NULL if there's no finite lower bound */
442 if (empty || lower.infinite)
445 PG_RETURN_DATUM(lower.val);
448 /* extract upper bound value */
450 range_upper(PG_FUNCTION_ARGS)
452 RangeType *r1 = PG_GETARG_RANGE(0);
453 TypeCacheEntry *typcache;
458 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
460 range_deserialize(typcache, r1, &lower, &upper, &empty);
462 /* Return NULL if there's no finite upper bound */
463 if (empty || upper.infinite)
466 PG_RETURN_DATUM(upper.val);
470 /* range -> bool functions */
472 /* is range empty? */
474 range_empty(PG_FUNCTION_ARGS)
476 RangeType *r1 = PG_GETARG_RANGE(0);
477 char flags = range_get_flags(r1);
479 PG_RETURN_BOOL(flags & RANGE_EMPTY);
482 /* is lower bound inclusive? */
484 range_lower_inc(PG_FUNCTION_ARGS)
486 RangeType *r1 = PG_GETARG_RANGE(0);
487 char flags = range_get_flags(r1);
489 PG_RETURN_BOOL(flags & RANGE_LB_INC);
492 /* is upper bound inclusive? */
494 range_upper_inc(PG_FUNCTION_ARGS)
496 RangeType *r1 = PG_GETARG_RANGE(0);
497 char flags = range_get_flags(r1);
499 PG_RETURN_BOOL(flags & RANGE_UB_INC);
502 /* is lower bound infinite? */
504 range_lower_inf(PG_FUNCTION_ARGS)
506 RangeType *r1 = PG_GETARG_RANGE(0);
507 char flags = range_get_flags(r1);
509 PG_RETURN_BOOL(flags & RANGE_LB_INF);
512 /* is upper bound infinite? */
514 range_upper_inf(PG_FUNCTION_ARGS)
516 RangeType *r1 = PG_GETARG_RANGE(0);
517 char flags = range_get_flags(r1);
519 PG_RETURN_BOOL(flags & RANGE_UB_INF);
523 /* range, element -> bool functions */
527 range_contains_elem(PG_FUNCTION_ARGS)
529 RangeType *r = PG_GETARG_RANGE(0);
530 Datum val = PG_GETARG_DATUM(1);
531 TypeCacheEntry *typcache;
533 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
535 PG_RETURN_BOOL(range_contains_elem_internal(typcache, r, val));
540 elem_contained_by_range(PG_FUNCTION_ARGS)
542 Datum val = PG_GETARG_DATUM(0);
543 RangeType *r = PG_GETARG_RANGE(1);
544 TypeCacheEntry *typcache;
546 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
548 PG_RETURN_BOOL(range_contains_elem_internal(typcache, r, val));
552 /* range, range -> bool functions */
554 /* equality (internal version) */
556 range_eq_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
565 /* Different types should be prevented by ANYRANGE matching rules */
566 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
567 elog(ERROR, "range types do not match");
569 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
570 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
572 if (empty1 && empty2)
574 if (empty1 != empty2)
577 if (range_cmp_bounds(typcache, &lower1, &lower2) != 0)
580 if (range_cmp_bounds(typcache, &upper1, &upper2) != 0)
588 range_eq(PG_FUNCTION_ARGS)
590 RangeType *r1 = PG_GETARG_RANGE(0);
591 RangeType *r2 = PG_GETARG_RANGE(1);
592 TypeCacheEntry *typcache;
594 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
596 PG_RETURN_BOOL(range_eq_internal(typcache, r1, r2));
599 /* inequality (internal version) */
601 range_ne_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
603 return (!range_eq_internal(typcache, r1, r2));
608 range_ne(PG_FUNCTION_ARGS)
610 RangeType *r1 = PG_GETARG_RANGE(0);
611 RangeType *r2 = PG_GETARG_RANGE(1);
612 TypeCacheEntry *typcache;
614 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
616 PG_RETURN_BOOL(range_ne_internal(typcache, r1, r2));
621 range_contains(PG_FUNCTION_ARGS)
623 RangeType *r1 = PG_GETARG_RANGE(0);
624 RangeType *r2 = PG_GETARG_RANGE(1);
625 TypeCacheEntry *typcache;
627 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
629 PG_RETURN_BOOL(range_contains_internal(typcache, r1, r2));
634 range_contained_by(PG_FUNCTION_ARGS)
636 RangeType *r1 = PG_GETARG_RANGE(0);
637 RangeType *r2 = PG_GETARG_RANGE(1);
638 TypeCacheEntry *typcache;
640 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
642 PG_RETURN_BOOL(range_contained_by_internal(typcache, r1, r2));
645 /* strictly left of? (internal version) */
647 range_before_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
656 /* Different types should be prevented by ANYRANGE matching rules */
657 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
658 elog(ERROR, "range types do not match");
660 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
661 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
663 /* An empty range is neither before nor after any other range */
664 if (empty1 || empty2)
667 return (range_cmp_bounds(typcache, &upper1, &lower2) < 0);
670 /* strictly left of? */
672 range_before(PG_FUNCTION_ARGS)
674 RangeType *r1 = PG_GETARG_RANGE(0);
675 RangeType *r2 = PG_GETARG_RANGE(1);
676 TypeCacheEntry *typcache;
678 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
680 PG_RETURN_BOOL(range_before_internal(typcache, r1, r2));
683 /* strictly right of? (internal version) */
685 range_after_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
694 /* Different types should be prevented by ANYRANGE matching rules */
695 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
696 elog(ERROR, "range types do not match");
698 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
699 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
701 /* An empty range is neither before nor after any other range */
702 if (empty1 || empty2)
705 return (range_cmp_bounds(typcache, &lower1, &upper2) > 0);
708 /* strictly right of? */
710 range_after(PG_FUNCTION_ARGS)
712 RangeType *r1 = PG_GETARG_RANGE(0);
713 RangeType *r2 = PG_GETARG_RANGE(1);
714 TypeCacheEntry *typcache;
716 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
718 PG_RETURN_BOOL(range_after_internal(typcache, r1, r2));
722 * Check if two bounds A and B are "adjacent", where A is an upper bound and B
723 * is a lower bound. For the bounds to be adjacent, each subtype value must
724 * satisfy strictly one of the bounds: there are no values which satisfy both
725 * bounds (i.e. less than A and greater than B); and there are no values which
726 * satisfy neither bound (i.e. greater than A and less than B).
728 * For discrete ranges, we rely on the canonicalization function to see if A..B
729 * normalizes to empty. (If there is no canonicalization function, it's
730 * impossible for such a range to normalize to empty, so we needn't bother to
733 * If A == B, the ranges are adjacent only if the bounds have different
734 * inclusive flags (i.e., exactly one of the ranges includes the common
737 * And if A > B then the ranges are not adjacent in this order.
740 bounds_adjacent(TypeCacheEntry *typcache, RangeBound boundA, RangeBound boundB)
744 Assert(!boundA.lower && boundB.lower);
746 cmp = range_cmp_bound_values(typcache, &boundA, &boundB);
752 * Bounds do not overlap; see if there are points in between.
755 /* in a continuous subtype, there are assumed to be points between */
756 if (!OidIsValid(typcache->rng_canonical_finfo.fn_oid))
760 * The bounds are of a discrete range type; so make a range A..B and
764 /* flip the inclusion flags */
765 boundA.inclusive = !boundA.inclusive;
766 boundB.inclusive = !boundB.inclusive;
767 /* change upper/lower labels to avoid Assert failures */
769 boundB.lower = false;
770 r = make_range(typcache, &boundA, &boundB, false);
771 return RangeIsEmpty(r);
774 return boundA.inclusive != boundB.inclusive;
776 return false; /* bounds overlap */
779 /* adjacent to (but not overlapping)? (internal version) */
781 range_adjacent_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
790 /* Different types should be prevented by ANYRANGE matching rules */
791 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
792 elog(ERROR, "range types do not match");
794 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
795 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
797 /* An empty range is not adjacent to any other range */
798 if (empty1 || empty2)
802 * Given two ranges A..B and C..D, the ranges are adjacent if and only if
803 * B is adjacent to C, or D is adjacent to A.
805 return (bounds_adjacent(typcache, upper1, lower2) ||
806 bounds_adjacent(typcache, upper2, lower1));
809 /* adjacent to (but not overlapping)? */
811 range_adjacent(PG_FUNCTION_ARGS)
813 RangeType *r1 = PG_GETARG_RANGE(0);
814 RangeType *r2 = PG_GETARG_RANGE(1);
815 TypeCacheEntry *typcache;
817 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
819 PG_RETURN_BOOL(range_adjacent_internal(typcache, r1, r2));
822 /* overlaps? (internal version) */
824 range_overlaps_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
833 /* Different types should be prevented by ANYRANGE matching rules */
834 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
835 elog(ERROR, "range types do not match");
837 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
838 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
840 /* An empty range does not overlap any other range */
841 if (empty1 || empty2)
844 if (range_cmp_bounds(typcache, &lower1, &lower2) >= 0 &&
845 range_cmp_bounds(typcache, &lower1, &upper2) <= 0)
848 if (range_cmp_bounds(typcache, &lower2, &lower1) >= 0 &&
849 range_cmp_bounds(typcache, &lower2, &upper1) <= 0)
857 range_overlaps(PG_FUNCTION_ARGS)
859 RangeType *r1 = PG_GETARG_RANGE(0);
860 RangeType *r2 = PG_GETARG_RANGE(1);
861 TypeCacheEntry *typcache;
863 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
865 PG_RETURN_BOOL(range_overlaps_internal(typcache, r1, r2));
868 /* does not extend to right of? (internal version) */
870 range_overleft_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
879 /* Different types should be prevented by ANYRANGE matching rules */
880 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
881 elog(ERROR, "range types do not match");
883 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
884 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
886 /* An empty range is neither before nor after any other range */
887 if (empty1 || empty2)
890 if (range_cmp_bounds(typcache, &upper1, &upper2) <= 0)
896 /* does not extend to right of? */
898 range_overleft(PG_FUNCTION_ARGS)
900 RangeType *r1 = PG_GETARG_RANGE(0);
901 RangeType *r2 = PG_GETARG_RANGE(1);
902 TypeCacheEntry *typcache;
904 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
906 PG_RETURN_BOOL(range_overleft_internal(typcache, r1, r2));
909 /* does not extend to left of? (internal version) */
911 range_overright_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
920 /* Different types should be prevented by ANYRANGE matching rules */
921 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
922 elog(ERROR, "range types do not match");
924 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
925 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
927 /* An empty range is neither before nor after any other range */
928 if (empty1 || empty2)
931 if (range_cmp_bounds(typcache, &lower1, &lower2) >= 0)
937 /* does not extend to left of? */
939 range_overright(PG_FUNCTION_ARGS)
941 RangeType *r1 = PG_GETARG_RANGE(0);
942 RangeType *r2 = PG_GETARG_RANGE(1);
943 TypeCacheEntry *typcache;
945 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
947 PG_RETURN_BOOL(range_overright_internal(typcache, r1, r2));
951 /* range, range -> range functions */
955 range_minus(PG_FUNCTION_ARGS)
957 RangeType *r1 = PG_GETARG_RANGE(0);
958 RangeType *r2 = PG_GETARG_RANGE(1);
959 TypeCacheEntry *typcache;
971 /* Different types should be prevented by ANYRANGE matching rules */
972 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
973 elog(ERROR, "range types do not match");
975 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
977 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
978 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
980 /* if either is empty, r1 is the correct answer */
981 if (empty1 || empty2)
984 cmp_l1l2 = range_cmp_bounds(typcache, &lower1, &lower2);
985 cmp_l1u2 = range_cmp_bounds(typcache, &lower1, &upper2);
986 cmp_u1l2 = range_cmp_bounds(typcache, &upper1, &lower2);
987 cmp_u1u2 = range_cmp_bounds(typcache, &upper1, &upper2);
989 if (cmp_l1l2 < 0 && cmp_u1u2 > 0)
991 (errcode(ERRCODE_DATA_EXCEPTION),
992 errmsg("result of range difference would not be contiguous")));
994 if (cmp_l1u2 > 0 || cmp_u1l2 < 0)
997 if (cmp_l1l2 >= 0 && cmp_u1u2 <= 0)
998 PG_RETURN_RANGE(make_empty_range(typcache));
1000 if (cmp_l1l2 <= 0 && cmp_u1l2 >= 0 && cmp_u1u2 <= 0)
1002 lower2.inclusive = !lower2.inclusive;
1003 lower2.lower = false; /* it will become the upper bound */
1004 PG_RETURN_RANGE(make_range(typcache, &lower1, &lower2, false));
1007 if (cmp_l1l2 >= 0 && cmp_u1u2 >= 0 && cmp_l1u2 <= 0)
1009 upper2.inclusive = !upper2.inclusive;
1010 upper2.lower = true; /* it will become the lower bound */
1011 PG_RETURN_RANGE(make_range(typcache, &upper2, &upper1, false));
1014 elog(ERROR, "unexpected case in range_minus");
1019 * Set union. If strict is true, it is an error that the two input ranges
1020 * are not adjacent or overlapping.
1023 range_union_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2,
1032 RangeBound *result_lower;
1033 RangeBound *result_upper;
1035 /* Different types should be prevented by ANYRANGE matching rules */
1036 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
1037 elog(ERROR, "range types do not match");
1039 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
1040 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
1042 /* if either is empty, the other is the correct answer */
1049 !DatumGetBool(range_overlaps_internal(typcache, r1, r2)) &&
1050 !DatumGetBool(range_adjacent_internal(typcache, r1, r2)))
1052 (errcode(ERRCODE_DATA_EXCEPTION),
1053 errmsg("result of range union would not be contiguous")));
1055 if (range_cmp_bounds(typcache, &lower1, &lower2) < 0)
1056 result_lower = &lower1;
1058 result_lower = &lower2;
1060 if (range_cmp_bounds(typcache, &upper1, &upper2) > 0)
1061 result_upper = &upper1;
1063 result_upper = &upper2;
1065 return make_range(typcache, result_lower, result_upper, false);
1069 range_union(PG_FUNCTION_ARGS)
1071 RangeType *r1 = PG_GETARG_RANGE(0);
1072 RangeType *r2 = PG_GETARG_RANGE(1);
1073 TypeCacheEntry *typcache;
1075 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
1077 PG_RETURN_RANGE(range_union_internal(typcache, r1, r2, true));
1081 * range merge: like set union, except also allow and account for non-adjacent
1085 range_merge(PG_FUNCTION_ARGS)
1087 RangeType *r1 = PG_GETARG_RANGE(0);
1088 RangeType *r2 = PG_GETARG_RANGE(1);
1089 TypeCacheEntry *typcache;
1091 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
1093 PG_RETURN_RANGE(range_union_internal(typcache, r1, r2, false));
1096 /* set intersection */
1098 range_intersect(PG_FUNCTION_ARGS)
1100 RangeType *r1 = PG_GETARG_RANGE(0);
1101 RangeType *r2 = PG_GETARG_RANGE(1);
1102 TypeCacheEntry *typcache;
1109 RangeBound *result_lower;
1110 RangeBound *result_upper;
1112 /* Different types should be prevented by ANYRANGE matching rules */
1113 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
1114 elog(ERROR, "range types do not match");
1116 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
1118 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
1119 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
1121 if (empty1 || empty2 || !DatumGetBool(range_overlaps(fcinfo)))
1122 PG_RETURN_RANGE(make_empty_range(typcache));
1124 if (range_cmp_bounds(typcache, &lower1, &lower2) >= 0)
1125 result_lower = &lower1;
1127 result_lower = &lower2;
1129 if (range_cmp_bounds(typcache, &upper1, &upper2) <= 0)
1130 result_upper = &upper1;
1132 result_upper = &upper2;
1134 PG_RETURN_RANGE(make_range(typcache, result_lower, result_upper, false));
1139 /* btree comparator */
1141 range_cmp(PG_FUNCTION_ARGS)
1143 RangeType *r1 = PG_GETARG_RANGE(0);
1144 RangeType *r2 = PG_GETARG_RANGE(1);
1145 TypeCacheEntry *typcache;
1154 check_stack_depth(); /* recurses when subtype is a range type */
1156 /* Different types should be prevented by ANYRANGE matching rules */
1157 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
1158 elog(ERROR, "range types do not match");
1160 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
1162 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
1163 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
1165 /* For b-tree use, empty ranges sort before all else */
1166 if (empty1 && empty2)
1174 cmp = range_cmp_bounds(typcache, &lower1, &lower2);
1176 cmp = range_cmp_bounds(typcache, &upper1, &upper2);
1179 PG_FREE_IF_COPY(r1, 0);
1180 PG_FREE_IF_COPY(r2, 1);
1182 PG_RETURN_INT32(cmp);
1185 /* inequality operators using the range_cmp function */
1187 range_lt(PG_FUNCTION_ARGS)
1189 int cmp = range_cmp(fcinfo);
1191 PG_RETURN_BOOL(cmp < 0);
1195 range_le(PG_FUNCTION_ARGS)
1197 int cmp = range_cmp(fcinfo);
1199 PG_RETURN_BOOL(cmp <= 0);
1203 range_ge(PG_FUNCTION_ARGS)
1205 int cmp = range_cmp(fcinfo);
1207 PG_RETURN_BOOL(cmp >= 0);
1211 range_gt(PG_FUNCTION_ARGS)
1213 int cmp = range_cmp(fcinfo);
1215 PG_RETURN_BOOL(cmp > 0);
1220 /* hash a range value */
1222 hash_range(PG_FUNCTION_ARGS)
1224 RangeType *r = PG_GETARG_RANGE(0);
1226 TypeCacheEntry *typcache;
1227 TypeCacheEntry *scache;
1235 check_stack_depth(); /* recurses when subtype is a range type */
1237 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1240 range_deserialize(typcache, r, &lower, &upper, &empty);
1241 flags = range_get_flags(r);
1244 * Look up the element type's hash function, if not done already.
1246 scache = typcache->rngelemtype;
1247 if (!OidIsValid(scache->hash_proc_finfo.fn_oid))
1249 scache = lookup_type_cache(scache->type_id, TYPECACHE_HASH_PROC_FINFO);
1250 if (!OidIsValid(scache->hash_proc_finfo.fn_oid))
1252 (errcode(ERRCODE_UNDEFINED_FUNCTION),
1253 errmsg("could not identify a hash function for type %s",
1254 format_type_be(scache->type_id))));
1258 * Apply the hash function to each bound.
1260 if (RANGE_HAS_LBOUND(flags))
1261 lower_hash = DatumGetUInt32(FunctionCall1Coll(&scache->hash_proc_finfo,
1262 typcache->rng_collation,
1267 if (RANGE_HAS_UBOUND(flags))
1268 upper_hash = DatumGetUInt32(FunctionCall1Coll(&scache->hash_proc_finfo,
1269 typcache->rng_collation,
1274 /* Merge hashes of flags and bounds */
1275 result = hash_uint32((uint32) flags);
1276 result ^= lower_hash;
1277 result = (result << 1) | (result >> 31);
1278 result ^= upper_hash;
1280 PG_RETURN_INT32(result);
1284 *----------------------------------------------------------
1285 * CANONICAL FUNCTIONS
1287 * Functions for specific built-in range types.
1288 *----------------------------------------------------------
1292 int4range_canonical(PG_FUNCTION_ARGS)
1294 RangeType *r = PG_GETARG_RANGE(0);
1295 TypeCacheEntry *typcache;
1300 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1302 range_deserialize(typcache, r, &lower, &upper, &empty);
1307 if (!lower.infinite && !lower.inclusive)
1309 lower.val = DirectFunctionCall2(int4pl, lower.val, Int32GetDatum(1));
1310 lower.inclusive = true;
1313 if (!upper.infinite && upper.inclusive)
1315 upper.val = DirectFunctionCall2(int4pl, upper.val, Int32GetDatum(1));
1316 upper.inclusive = false;
1319 PG_RETURN_RANGE(range_serialize(typcache, &lower, &upper, false));
1323 int8range_canonical(PG_FUNCTION_ARGS)
1325 RangeType *r = PG_GETARG_RANGE(0);
1326 TypeCacheEntry *typcache;
1331 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1333 range_deserialize(typcache, r, &lower, &upper, &empty);
1338 if (!lower.infinite && !lower.inclusive)
1340 lower.val = DirectFunctionCall2(int8pl, lower.val, Int64GetDatum(1));
1341 lower.inclusive = true;
1344 if (!upper.infinite && upper.inclusive)
1346 upper.val = DirectFunctionCall2(int8pl, upper.val, Int64GetDatum(1));
1347 upper.inclusive = false;
1350 PG_RETURN_RANGE(range_serialize(typcache, &lower, &upper, false));
1354 daterange_canonical(PG_FUNCTION_ARGS)
1356 RangeType *r = PG_GETARG_RANGE(0);
1357 TypeCacheEntry *typcache;
1362 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1364 range_deserialize(typcache, r, &lower, &upper, &empty);
1369 if (!lower.infinite && !lower.inclusive)
1371 lower.val = DirectFunctionCall2(date_pli, lower.val, Int32GetDatum(1));
1372 lower.inclusive = true;
1375 if (!upper.infinite && upper.inclusive)
1377 upper.val = DirectFunctionCall2(date_pli, upper.val, Int32GetDatum(1));
1378 upper.inclusive = false;
1381 PG_RETURN_RANGE(range_serialize(typcache, &lower, &upper, false));
1385 *----------------------------------------------------------
1386 * SUBTYPE_DIFF FUNCTIONS
1388 * Functions for specific built-in range types.
1390 * Note that subtype_diff does return the difference, not the absolute value
1391 * of the difference, and it must take care to avoid overflow.
1392 * (numrange_subdiff is at some risk there ...)
1393 *----------------------------------------------------------
1397 int4range_subdiff(PG_FUNCTION_ARGS)
1399 int32 v1 = PG_GETARG_INT32(0);
1400 int32 v2 = PG_GETARG_INT32(1);
1402 PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
1406 int8range_subdiff(PG_FUNCTION_ARGS)
1408 int64 v1 = PG_GETARG_INT64(0);
1409 int64 v2 = PG_GETARG_INT64(1);
1411 PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
1415 numrange_subdiff(PG_FUNCTION_ARGS)
1417 Datum v1 = PG_GETARG_DATUM(0);
1418 Datum v2 = PG_GETARG_DATUM(1);
1422 numresult = DirectFunctionCall2(numeric_sub, v1, v2);
1424 floatresult = DatumGetFloat8(DirectFunctionCall1(numeric_float8,
1427 PG_RETURN_FLOAT8(floatresult);
1431 daterange_subdiff(PG_FUNCTION_ARGS)
1433 int32 v1 = PG_GETARG_INT32(0);
1434 int32 v2 = PG_GETARG_INT32(1);
1436 PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
1440 tsrange_subdiff(PG_FUNCTION_ARGS)
1442 Timestamp v1 = PG_GETARG_TIMESTAMP(0);
1443 Timestamp v2 = PG_GETARG_TIMESTAMP(1);
1446 result = ((float8) v1 - (float8) v2) / USECS_PER_SEC;
1447 PG_RETURN_FLOAT8(result);
1451 tstzrange_subdiff(PG_FUNCTION_ARGS)
1453 Timestamp v1 = PG_GETARG_TIMESTAMP(0);
1454 Timestamp v2 = PG_GETARG_TIMESTAMP(1);
1457 result = ((float8) v1 - (float8) v2) / USECS_PER_SEC;
1458 PG_RETURN_FLOAT8(result);
1462 *----------------------------------------------------------
1465 * These functions aren't in pg_proc, but are useful for
1466 * defining new generic range functions in C.
1467 *----------------------------------------------------------
1471 * range_get_typcache: get cached information about a range type
1473 * This is for use by range-related functions that follow the convention
1474 * of using the fn_extra field as a pointer to the type cache entry for
1475 * the range type. Functions that need to cache more information than
1476 * that must fend for themselves.
1479 range_get_typcache(FunctionCallInfo fcinfo, Oid rngtypid)
1481 TypeCacheEntry *typcache = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
1483 if (typcache == NULL ||
1484 typcache->type_id != rngtypid)
1486 typcache = lookup_type_cache(rngtypid, TYPECACHE_RANGE_INFO);
1487 if (typcache->rngelemtype == NULL)
1488 elog(ERROR, "type %u is not a range type", rngtypid);
1489 fcinfo->flinfo->fn_extra = (void *) typcache;
1496 * range_serialize: construct a range value from bounds and empty-flag
1498 * This does not force canonicalization of the range value. In most cases,
1499 * external callers should only be canonicalization functions. Note that
1500 * we perform some datatype-independent canonicalization checks anyway.
1503 range_serialize(TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper,
1517 * Verify range is not invalid on its face, and construct flags value,
1518 * preventing any non-canonical combinations such as infinite+inclusive.
1520 Assert(lower->lower);
1521 Assert(!upper->lower);
1524 flags |= RANGE_EMPTY;
1527 cmp = range_cmp_bound_values(typcache, lower, upper);
1529 /* error check: if lower bound value is above upper, it's wrong */
1532 (errcode(ERRCODE_DATA_EXCEPTION),
1533 errmsg("range lower bound must be less than or equal to range upper bound")));
1535 /* if bounds are equal, and not both inclusive, range is empty */
1536 if (cmp == 0 && !(lower->inclusive && upper->inclusive))
1537 flags |= RANGE_EMPTY;
1540 /* infinite boundaries are never inclusive */
1541 if (lower->infinite)
1542 flags |= RANGE_LB_INF;
1543 else if (lower->inclusive)
1544 flags |= RANGE_LB_INC;
1545 if (upper->infinite)
1546 flags |= RANGE_UB_INF;
1547 else if (upper->inclusive)
1548 flags |= RANGE_UB_INC;
1552 /* Fetch information about range's element type */
1553 typlen = typcache->rngelemtype->typlen;
1554 typbyval = typcache->rngelemtype->typbyval;
1555 typalign = typcache->rngelemtype->typalign;
1556 typstorage = typcache->rngelemtype->typstorage;
1558 /* Count space for varlena header and range type's OID */
1559 msize = sizeof(RangeType);
1560 Assert(msize == MAXALIGN(msize));
1562 /* Count space for bounds */
1563 if (RANGE_HAS_LBOUND(flags))
1566 * Make sure item to be inserted is not toasted. It is essential that
1567 * we not insert an out-of-line toast value pointer into a range
1568 * object, for the same reasons that arrays and records can't contain
1569 * them. It would work to store a compressed-in-line value, but we
1570 * prefer to decompress and then let compression be applied to the
1571 * whole range object if necessary. But, unlike arrays, we do allow
1572 * short-header varlena objects to stay as-is.
1575 lower->val = PointerGetDatum(PG_DETOAST_DATUM_PACKED(lower->val));
1577 msize = datum_compute_size(msize, lower->val, typbyval, typalign,
1578 typlen, typstorage);
1581 if (RANGE_HAS_UBOUND(flags))
1583 /* Make sure item to be inserted is not toasted */
1585 upper->val = PointerGetDatum(PG_DETOAST_DATUM_PACKED(upper->val));
1587 msize = datum_compute_size(msize, upper->val, typbyval, typalign,
1588 typlen, typstorage);
1591 /* Add space for flag byte */
1592 msize += sizeof(char);
1594 /* Note: zero-fill is required here, just as in heap tuples */
1595 range = (RangeType *) palloc0(msize);
1596 SET_VARSIZE(range, msize);
1598 /* Now fill in the datum */
1599 range->rangetypid = typcache->type_id;
1601 ptr = (char *) (range + 1);
1603 if (RANGE_HAS_LBOUND(flags))
1605 Assert(lower->lower);
1606 ptr = datum_write(ptr, lower->val, typbyval, typalign, typlen,
1610 if (RANGE_HAS_UBOUND(flags))
1612 Assert(!upper->lower);
1613 ptr = datum_write(ptr, upper->val, typbyval, typalign, typlen,
1617 *((char *) ptr) = flags;
1623 * range_deserialize: deconstruct a range value
1625 * NB: the given range object must be fully detoasted; it cannot have a
1626 * short varlena header.
1628 * Note that if the element type is pass-by-reference, the datums in the
1629 * RangeBound structs will be pointers into the given range object.
1632 range_deserialize(TypeCacheEntry *typcache, RangeType *range,
1633 RangeBound *lower, RangeBound *upper, bool *empty)
1643 /* assert caller passed the right typcache entry */
1644 Assert(RangeTypeGetOid(range) == typcache->type_id);
1646 /* fetch the flag byte from datum's last byte */
1647 flags = *((char *) range + VARSIZE(range) - 1);
1649 /* fetch information about range's element type */
1650 typlen = typcache->rngelemtype->typlen;
1651 typbyval = typcache->rngelemtype->typbyval;
1652 typalign = typcache->rngelemtype->typalign;
1654 /* initialize data pointer just after the range OID */
1655 ptr = (Pointer) (range + 1);
1657 /* fetch lower bound, if any */
1658 if (RANGE_HAS_LBOUND(flags))
1660 /* att_align_pointer cannot be necessary here */
1661 lbound = fetch_att(ptr, typbyval, typlen);
1662 ptr = (Pointer) att_addlength_pointer(ptr, typlen, ptr);
1667 /* fetch upper bound, if any */
1668 if (RANGE_HAS_UBOUND(flags))
1670 ptr = (Pointer) att_align_pointer(ptr, typalign, typlen, ptr);
1671 ubound = fetch_att(ptr, typbyval, typlen);
1672 /* no need for att_addlength_pointer */
1679 *empty = (flags & RANGE_EMPTY) != 0;
1681 lower->val = lbound;
1682 lower->infinite = (flags & RANGE_LB_INF) != 0;
1683 lower->inclusive = (flags & RANGE_LB_INC) != 0;
1684 lower->lower = true;
1686 upper->val = ubound;
1687 upper->infinite = (flags & RANGE_UB_INF) != 0;
1688 upper->inclusive = (flags & RANGE_UB_INC) != 0;
1689 upper->lower = false;
1693 * range_get_flags: just get the flags from a RangeType value.
1695 * This is frequently useful in places that only need the flags and not
1696 * the full results of range_deserialize.
1699 range_get_flags(RangeType *range)
1701 /* fetch the flag byte from datum's last byte */
1702 return *((char *) range + VARSIZE(range) - 1);
1706 * range_set_contain_empty: set the RANGE_CONTAIN_EMPTY bit in the value.
1708 * This is only needed in GiST operations, so we don't include a provision
1709 * for setting it in range_serialize; rather, this function must be applied
1713 range_set_contain_empty(RangeType *range)
1717 /* flag byte is datum's last byte */
1718 flagsp = (char *) range + VARSIZE(range) - 1;
1720 *flagsp |= RANGE_CONTAIN_EMPTY;
1724 * This both serializes and canonicalizes (if applicable) the range.
1725 * This should be used by most callers.
1728 make_range(TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper,
1733 range = range_serialize(typcache, lower, upper, empty);
1735 /* no need to call canonical on empty ranges ... */
1736 if (OidIsValid(typcache->rng_canonical_finfo.fn_oid) &&
1737 !RangeIsEmpty(range))
1738 range = DatumGetRangeType(FunctionCall1(&typcache->rng_canonical_finfo,
1739 RangeTypeGetDatum(range)));
1745 * Compare two range boundary points, returning <0, 0, or >0 according to
1746 * whether b1 is less than, equal to, or greater than b2.
1748 * The boundaries can be any combination of upper and lower; so it's useful
1749 * for a variety of operators.
1751 * The simple case is when b1 and b2 are both finite and inclusive, in which
1752 * case the result is just a comparison of the values held in b1 and b2.
1754 * If a bound is exclusive, then we need to know whether it's a lower bound,
1755 * in which case we treat the boundary point as "just greater than" the held
1756 * value; or an upper bound, in which case we treat the boundary point as
1757 * "just less than" the held value.
1759 * If a bound is infinite, it represents minus infinity (less than every other
1760 * point) if it's a lower bound; or plus infinity (greater than every other
1761 * point) if it's an upper bound.
1763 * There is only one case where two boundaries compare equal but are not
1764 * identical: when both bounds are inclusive and hold the same finite value,
1765 * but one is an upper bound and the other a lower bound.
1768 range_cmp_bounds(TypeCacheEntry *typcache, RangeBound *b1, RangeBound *b2)
1773 * First, handle cases involving infinity, which don't require invoking
1774 * the comparison proc.
1776 if (b1->infinite && b2->infinite)
1779 * Both are infinity, so they are equal unless one is lower and the
1782 if (b1->lower == b2->lower)
1785 return b1->lower ? -1 : 1;
1787 else if (b1->infinite)
1788 return b1->lower ? -1 : 1;
1789 else if (b2->infinite)
1790 return b2->lower ? 1 : -1;
1793 * Both boundaries are finite, so compare the held values.
1795 result = DatumGetInt32(FunctionCall2Coll(&typcache->rng_cmp_proc_finfo,
1796 typcache->rng_collation,
1800 * If the comparison is anything other than equal, we're done. If they
1801 * compare equal though, we still have to consider whether the boundaries
1802 * are inclusive or exclusive.
1806 if (!b1->inclusive && !b2->inclusive)
1808 /* both are exclusive */
1809 if (b1->lower == b2->lower)
1812 return b1->lower ? 1 : -1;
1814 else if (!b1->inclusive)
1815 return b1->lower ? 1 : -1;
1816 else if (!b2->inclusive)
1817 return b2->lower ? -1 : 1;
1821 * Both are inclusive and the values held are equal, so they are
1822 * equal regardless of whether they are upper or lower boundaries,
1833 * Compare two range boundary point values, returning <0, 0, or >0 according
1834 * to whether b1 is less than, equal to, or greater than b2.
1836 * This is similar to but simpler than range_cmp_bounds(). We just compare
1837 * the values held in b1 and b2, ignoring inclusive/exclusive flags. The
1838 * lower/upper flags only matter for infinities, where they tell us if the
1839 * infinity is plus or minus.
1842 range_cmp_bound_values(TypeCacheEntry *typcache, RangeBound *b1,
1846 * First, handle cases involving infinity, which don't require invoking
1847 * the comparison proc.
1849 if (b1->infinite && b2->infinite)
1852 * Both are infinity, so they are equal unless one is lower and the
1855 if (b1->lower == b2->lower)
1858 return b1->lower ? -1 : 1;
1860 else if (b1->infinite)
1861 return b1->lower ? -1 : 1;
1862 else if (b2->infinite)
1863 return b2->lower ? 1 : -1;
1866 * Both boundaries are finite, so compare the held values.
1868 return DatumGetInt32(FunctionCall2Coll(&typcache->rng_cmp_proc_finfo,
1869 typcache->rng_collation,
1874 * Build an empty range value of the type indicated by the typcache entry.
1877 make_empty_range(TypeCacheEntry *typcache)
1882 lower.val = (Datum) 0;
1883 lower.infinite = false;
1884 lower.inclusive = false;
1887 upper.val = (Datum) 0;
1888 upper.infinite = false;
1889 upper.inclusive = false;
1890 upper.lower = false;
1892 return make_range(typcache, &lower, &upper, true);
1897 *----------------------------------------------------------
1899 *----------------------------------------------------------
1903 * Given a string representing the flags for the range type, return the flags
1904 * represented as a char.
1907 range_parse_flags(const char *flags_str)
1911 if (flags_str[0] == '\0' ||
1912 flags_str[1] == '\0' ||
1913 flags_str[2] != '\0')
1915 (errcode(ERRCODE_SYNTAX_ERROR),
1916 errmsg("invalid range bound flags"),
1917 errhint("Valid values are \"[]\", \"[)\", \"(]\", and \"()\".")));
1919 switch (flags_str[0])
1922 flags |= RANGE_LB_INC;
1928 (errcode(ERRCODE_SYNTAX_ERROR),
1929 errmsg("invalid range bound flags"),
1930 errhint("Valid values are \"[]\", \"[)\", \"(]\", and \"()\".")));
1933 switch (flags_str[1])
1936 flags |= RANGE_UB_INC;
1942 (errcode(ERRCODE_SYNTAX_ERROR),
1943 errmsg("invalid range bound flags"),
1944 errhint("Valid values are \"[]\", \"[)\", \"(]\", and \"()\".")));
1951 * Parse range input.
1954 * string: input string to be parsed
1955 * Output parameters:
1956 * *flags: receives flags bitmask
1957 * *lbound_str: receives palloc'd lower bound string, or NULL if none
1958 * *ubound_str: receives palloc'd upper bound string, or NULL if none
1960 * This is modeled somewhat after record_in in rowtypes.c.
1961 * The input syntax is:
1963 * | <lb-inc> <string>, <string> <ub-inc>
1964 * <lb-inc> := '[' | '('
1965 * <ub-inc> := ']' | ')'
1967 * Whitespace before or after <range> is ignored. Whitespace within a <string>
1968 * is taken literally and becomes part of the input string for that bound.
1970 * A <string> of length zero is taken as "infinite" (i.e. no bound), unless it
1971 * is surrounded by double-quotes, in which case it is the literal empty
1974 * Within a <string>, special characters (such as comma, parenthesis, or
1975 * brackets) can be enclosed in double-quotes or escaped with backslash. Within
1976 * double-quotes, a double-quote can be escaped with double-quote or backslash.
1979 range_parse(const char *string, char *flags, char **lbound_str,
1982 const char *ptr = string;
1987 /* consume whitespace */
1988 while (*ptr != '\0' && isspace((unsigned char) *ptr))
1991 /* check for empty range */
1992 if (pg_strncasecmp(ptr, RANGE_EMPTY_LITERAL,
1993 strlen(RANGE_EMPTY_LITERAL)) == 0)
1995 *flags = RANGE_EMPTY;
1999 ptr += strlen(RANGE_EMPTY_LITERAL);
2001 /* the rest should be whitespace */
2002 while (*ptr != '\0' && isspace((unsigned char) *ptr))
2005 /* should have consumed everything */
2008 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2009 errmsg("malformed range literal: \"%s\"",
2011 errdetail("Junk after \"empty\" key word.")));
2018 *flags |= RANGE_LB_INC;
2021 else if (*ptr == '(')
2025 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2026 errmsg("malformed range literal: \"%s\"",
2028 errdetail("Missing left parenthesis or bracket.")));
2030 ptr = range_parse_bound(string, ptr, lbound_str, &infinite);
2032 *flags |= RANGE_LB_INF;
2038 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2039 errmsg("malformed range literal: \"%s\"",
2041 errdetail("Missing comma after lower bound.")));
2043 ptr = range_parse_bound(string, ptr, ubound_str, &infinite);
2045 *flags |= RANGE_UB_INF;
2049 *flags |= RANGE_UB_INC;
2052 else if (*ptr == ')')
2054 else /* must be a comma */
2056 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2057 errmsg("malformed range literal: \"%s\"",
2059 errdetail("Too many commas.")));
2061 /* consume whitespace */
2062 while (*ptr != '\0' && isspace((unsigned char) *ptr))
2067 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2068 errmsg("malformed range literal: \"%s\"",
2070 errdetail("Junk after right parenthesis or bracket.")));
2074 * Helper for range_parse: parse and de-quote one bound string.
2076 * We scan until finding comma, right parenthesis, or right bracket.
2079 * string: entire input string (used only for error reports)
2080 * ptr: where to start parsing bound
2081 * Output parameters:
2082 * *bound_str: receives palloc'd bound string, or NULL if none
2083 * *infinite: set true if no bound, else false
2085 * The return value is the scan ptr, advanced past the bound string.
2088 range_parse_bound(const char *string, const char *ptr,
2089 char **bound_str, bool *infinite)
2093 /* Check for null: completely empty input means null */
2094 if (*ptr == ',' || *ptr == ')' || *ptr == ']')
2101 /* Extract string for this bound */
2102 bool inquote = false;
2104 initStringInfo(&buf);
2105 while (inquote || !(*ptr == ',' || *ptr == ')' || *ptr == ']'))
2111 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2112 errmsg("malformed range literal: \"%s\"",
2114 errdetail("Unexpected end of input.")));
2119 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2120 errmsg("malformed range literal: \"%s\"",
2122 errdetail("Unexpected end of input.")));
2123 appendStringInfoChar(&buf, *ptr++);
2129 else if (*ptr == '"')
2131 /* doubled quote within quote sequence */
2132 appendStringInfoChar(&buf, *ptr++);
2138 appendStringInfoChar(&buf, ch);
2141 *bound_str = buf.data;
2149 * Convert a deserialized range value to text form
2151 * Inputs are the flags byte, and the two bound values already converted to
2152 * text (but not yet quoted). If no bound value, pass NULL.
2154 * Result is a palloc'd string
2157 range_deparse(char flags, const char *lbound_str, const char *ubound_str)
2161 if (flags & RANGE_EMPTY)
2162 return pstrdup(RANGE_EMPTY_LITERAL);
2164 initStringInfo(&buf);
2166 appendStringInfoChar(&buf, (flags & RANGE_LB_INC) ? '[' : '(');
2168 if (RANGE_HAS_LBOUND(flags))
2169 appendStringInfoString(&buf, range_bound_escape(lbound_str));
2171 appendStringInfoChar(&buf, ',');
2173 if (RANGE_HAS_UBOUND(flags))
2174 appendStringInfoString(&buf, range_bound_escape(ubound_str));
2176 appendStringInfoChar(&buf, (flags & RANGE_UB_INC) ? ']' : ')');
2182 * Helper for range_deparse: quote a bound value as needed
2184 * Result is a palloc'd string
2187 range_bound_escape(const char *value)
2193 initStringInfo(&buf);
2195 /* Detect whether we need double quotes for this value */
2196 nq = (value[0] == '\0'); /* force quotes for empty string */
2197 for (ptr = value; *ptr; ptr++)
2201 if (ch == '"' || ch == '\\' ||
2202 ch == '(' || ch == ')' ||
2203 ch == '[' || ch == ']' ||
2205 isspace((unsigned char) ch))
2212 /* And emit the string */
2214 appendStringInfoChar(&buf, '"');
2215 for (ptr = value; *ptr; ptr++)
2219 if (ch == '"' || ch == '\\')
2220 appendStringInfoChar(&buf, ch);
2221 appendStringInfoChar(&buf, ch);
2224 appendStringInfoChar(&buf, '"');
2230 * Test whether range r1 contains range r2.
2232 * Caller has already checked that they are the same range type, and looked up
2233 * the necessary typcache entry.
2236 range_contains_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
2245 /* Different types should be prevented by ANYRANGE matching rules */
2246 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
2247 elog(ERROR, "range types do not match");
2249 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
2250 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
2252 /* If either range is empty, the answer is easy */
2258 /* Else we must have lower1 <= lower2 and upper1 >= upper2 */
2259 if (range_cmp_bounds(typcache, &lower1, &lower2) > 0)
2261 if (range_cmp_bounds(typcache, &upper1, &upper2) < 0)
2268 range_contained_by_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
2270 return range_contains_internal(typcache, r2, r1);
2274 * Test whether range r contains a specific element value.
2277 range_contains_elem_internal(TypeCacheEntry *typcache, RangeType *r, Datum val)
2284 range_deserialize(typcache, r, &lower, &upper, &empty);
2289 if (!lower.infinite)
2291 cmp = DatumGetInt32(FunctionCall2Coll(&typcache->rng_cmp_proc_finfo,
2292 typcache->rng_collation,
2296 if (cmp == 0 && !lower.inclusive)
2300 if (!upper.infinite)
2302 cmp = DatumGetInt32(FunctionCall2Coll(&typcache->rng_cmp_proc_finfo,
2303 typcache->rng_collation,
2307 if (cmp == 0 && !upper.inclusive)
2316 * datum_compute_size() and datum_write() are used to insert the bound
2317 * values into a range object. They are modeled after heaptuple.c's
2318 * heap_compute_data_size() and heap_fill_tuple(), but we need not handle
2319 * null values here. TYPE_IS_PACKABLE must test the same conditions as
2320 * heaptuple.c's ATT_IS_PACKABLE macro.
2323 /* Does datatype allow packing into the 1-byte-header varlena format? */
2324 #define TYPE_IS_PACKABLE(typlen, typstorage) \
2325 ((typlen) == -1 && (typstorage) != 'p')
2328 * Increment data_length by the space needed by the datum, including any
2329 * preceding alignment padding.
2332 datum_compute_size(Size data_length, Datum val, bool typbyval, char typalign,
2333 int16 typlen, char typstorage)
2335 if (TYPE_IS_PACKABLE(typlen, typstorage) &&
2336 VARATT_CAN_MAKE_SHORT(DatumGetPointer(val)))
2339 * we're anticipating converting to a short varlena header, so adjust
2340 * length and don't count any alignment
2342 data_length += VARATT_CONVERTED_SHORT_SIZE(DatumGetPointer(val));
2346 data_length = att_align_datum(data_length, typalign, typlen, val);
2347 data_length = att_addlength_datum(data_length, typlen, val);
2354 * Write the given datum beginning at ptr (after advancing to correct
2355 * alignment, if needed). Return the pointer incremented by space used.
2358 datum_write(Pointer ptr, Datum datum, bool typbyval, char typalign,
2359 int16 typlen, char typstorage)
2366 ptr = (char *) att_align_nominal(ptr, typalign);
2367 store_att_byval(ptr, datum, typlen);
2368 data_length = typlen;
2370 else if (typlen == -1)
2373 Pointer val = DatumGetPointer(datum);
2375 if (VARATT_IS_EXTERNAL(val))
2378 * Throw error, because we must never put a toast pointer inside a
2379 * range object. Caller should have detoasted it.
2381 elog(ERROR, "cannot store a toast pointer inside a range");
2382 data_length = 0; /* keep compiler quiet */
2384 else if (VARATT_IS_SHORT(val))
2386 /* no alignment for short varlenas */
2387 data_length = VARSIZE_SHORT(val);
2388 memcpy(ptr, val, data_length);
2390 else if (TYPE_IS_PACKABLE(typlen, typstorage) &&
2391 VARATT_CAN_MAKE_SHORT(val))
2393 /* convert to short varlena -- no alignment */
2394 data_length = VARATT_CONVERTED_SHORT_SIZE(val);
2395 SET_VARSIZE_SHORT(ptr, data_length);
2396 memcpy(ptr + 1, VARDATA(val), data_length - 1);
2400 /* full 4-byte header varlena */
2401 ptr = (char *) att_align_nominal(ptr, typalign);
2402 data_length = VARSIZE(val);
2403 memcpy(ptr, val, data_length);
2406 else if (typlen == -2)
2408 /* cstring ... never needs alignment */
2409 Assert(typalign == 'c');
2410 data_length = strlen(DatumGetCString(datum)) + 1;
2411 memcpy(ptr, DatumGetPointer(datum), data_length);
2415 /* fixed-length pass-by-reference */
2416 ptr = (char *) att_align_nominal(ptr, typalign);
2418 data_length = typlen;
2419 memcpy(ptr, DatumGetPointer(datum), data_length);