1 /*-------------------------------------------------------------------------
4 * I/O functions, operators, and support functions for range types.
6 * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * src/backend/utils/adt/rangetypes.c
13 *-------------------------------------------------------------------------
17 #include "access/hash.h"
18 #include "access/nbtree.h"
19 #include "catalog/pg_opclass.h"
20 #include "catalog/pg_range.h"
21 #include "catalog/pg_type.h"
23 #include "lib/stringinfo.h"
24 #include "libpq/pqformat.h"
25 #include "utils/builtins.h"
26 #include "utils/date.h"
27 #include "utils/fmgroids.h"
28 #include "utils/int8.h"
29 #include "utils/lsyscache.h"
30 #include "utils/rangetypes.h"
31 #include "utils/syscache.h"
32 #include "utils/timestamp.h"
33 #include "utils/typcache.h"
36 #define TYPE_IS_PACKABLE(typlen, typstorage) \
37 (typlen == -1 && typstorage != 'p')
40 #define RANGE_EMPTY 0x01
41 #define RANGE_LB_INC 0x02
42 #define RANGE_LB_NULL 0x04 /* NOT USED */
43 #define RANGE_LB_INF 0x08
44 #define RANGE_UB_INC 0x10
45 #define RANGE_UB_NULL 0x20 /* NOT USED */
46 #define RANGE_UB_INF 0x40
48 #define RANGE_HAS_LBOUND(flags) (!(flags & (RANGE_EMPTY | \
52 #define RANGE_HAS_UBOUND(flags) (!(flags & (RANGE_EMPTY | \
56 #define RANGE_EMPTY_LITERAL "empty"
58 #define RANGE_DEFAULT_FLAGS "[)"
61 static char range_parse_flags(const char *flags_str);
62 static void range_parse(char *input_str, char *flags, char **lbound_str,
64 static char *range_parse_bound(char *string, char *ptr, char **bound_str,
66 static char *range_deparse(char flags, char *lbound_str, char *ubound_str);
67 static char *range_bound_escape(char *in_str);
68 static bool range_contains_internal(FunctionCallInfo fcinfo, RangeType *r1,
70 static Size datum_compute_size(Size sz, Datum datum, bool typbyval,
71 char typalign, int16 typlen, char typstorage);
72 static Pointer datum_write(Pointer ptr, Datum datum, bool typbyval,
73 char typalign, int16 typlen, char typstorage);
77 *----------------------------------------------------------
79 *----------------------------------------------------------
83 range_in(PG_FUNCTION_ARGS)
85 char *input_str = PG_GETARG_CSTRING(0);
86 Oid rngtypoid = PG_GETARG_OID(1);
87 Oid typmod = PG_GETARG_INT32(2);
95 RangeTypeInfo rngtypinfo;
99 if (rngtypoid == ANYRANGEOID)
101 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
102 errmsg("cannot accept a value of type anyrange")));
104 range_gettypinfo(fcinfo, rngtypoid, &rngtypinfo);
107 range_parse(input_str, &flags, &lbound_str, &ubound_str);
110 getTypeInputInfo(rngtypinfo.subtype, &subInput, &ioParam);
111 fmgr_info(subInput, &subInputFn);
113 lower.rngtypid = rngtypoid;
114 lower.infinite = (flags & RANGE_LB_INF) != 0;
115 lower.inclusive = (flags & RANGE_LB_INC) != 0;
117 upper.rngtypid = rngtypoid;
118 upper.infinite = (flags & RANGE_UB_INF) != 0;
119 upper.inclusive = (flags & RANGE_UB_INC) != 0;
122 if (RANGE_HAS_LBOUND(flags))
123 lower.val = InputFunctionCall(&subInputFn, lbound_str,
125 if (RANGE_HAS_UBOUND(flags))
126 upper.val = InputFunctionCall(&subInputFn, ubound_str,
129 /* serialize and canonicalize */
130 range = make_range(fcinfo, &lower, &upper, flags & RANGE_EMPTY);
132 PG_RETURN_RANGE(range);
136 range_out(PG_FUNCTION_ARGS)
138 RangeType *range = PG_GETARG_RANGE(0);
141 FmgrInfo subOutputFn;
144 char *lbound_str = NULL;
145 char *ubound_str = NULL;
147 RangeTypeInfo rngtypinfo;
152 range_deserialize(fcinfo, range, &lower, &upper, &empty);
154 if (lower.rngtypid != upper.rngtypid)
155 elog(ERROR, "range types do not match");
157 range_gettypinfo(fcinfo, lower.rngtypid, &rngtypinfo);
160 flags |= RANGE_EMPTY;
162 flags |= (lower.inclusive) ? RANGE_LB_INC : 0;
163 flags |= (lower.infinite) ? RANGE_LB_INF : 0;
164 flags |= (upper.inclusive) ? RANGE_UB_INC : 0;
165 flags |= (upper.infinite) ? RANGE_UB_INF : 0;
168 getTypeOutputInfo(rngtypinfo.subtype, &subOutput, &isVarlena);
169 fmgr_info(subOutput, &subOutputFn);
171 if (RANGE_HAS_LBOUND(flags))
172 lbound_str = OutputFunctionCall(&subOutputFn, lower.val);
173 if (RANGE_HAS_UBOUND(flags))
174 ubound_str = OutputFunctionCall(&subOutputFn, upper.val);
177 output_str = range_deparse(flags, lbound_str, ubound_str);
179 PG_RETURN_CSTRING(output_str);
183 * Binary representation: The first byte is the flags, then 4 bytes are the
184 * range type Oid, then the lower bound (if present) then the upper bound (if
185 * present). Each bound is represented by a 4-byte length header and the binary
186 * representation of that bound (as returned by a call to the send function for
191 range_recv(PG_FUNCTION_ARGS)
193 StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
194 Oid rngtypid = PG_GETARG_OID(1);
195 int32 typmod = PG_GETARG_INT32(2);
202 RangeTypeInfo rngtypinfo;
204 flags = (unsigned char) pq_getmsgbyte(buf);
206 range_gettypinfo(fcinfo, rngtypid, &rngtypinfo);
208 getTypeBinaryInputInfo(rngtypinfo.subtype, &subrecv, &ioparam);
210 if (RANGE_HAS_LBOUND(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 lower.val = OidReceiveFunctionCall(subrecv,
223 pfree(bound_buf.data);
226 lower.val = (Datum) 0;
228 if (RANGE_HAS_UBOUND(flags))
230 uint32 bound_len = pq_getmsgint(buf, 4);
231 const char *bound_data = pq_getmsgbytes(buf, bound_len);
232 StringInfoData bound_buf;
234 initStringInfo(&bound_buf);
235 appendBinaryStringInfo(&bound_buf, bound_data, bound_len);
237 upper.val = OidReceiveFunctionCall(subrecv,
241 pfree(bound_buf.data);
244 upper.val = (Datum) 0;
248 lower.rngtypid = rngtypid;
249 lower.infinite = (flags & RANGE_LB_INF) != 0;
250 lower.inclusive = (flags & RANGE_LB_INC) != 0;
252 upper.rngtypid = rngtypid;
253 upper.infinite = (flags & RANGE_UB_INF) != 0;
254 upper.inclusive = (flags & RANGE_UB_INC) != 0;
257 /* serialize and canonicalize */
258 range = make_range(fcinfo, &lower, &upper, flags & RANGE_EMPTY);
260 PG_RETURN_RANGE(range);
264 range_send(PG_FUNCTION_ARGS)
266 RangeType *range = PG_GETARG_RANGE(0);
267 StringInfo buf = makeStringInfo();
274 RangeTypeInfo rngtypinfo;
276 pq_begintypsend(buf);
278 range_deserialize(fcinfo, range, &lower, &upper, &empty);
281 flags |= RANGE_EMPTY;
283 flags |= (lower.inclusive) ? RANGE_LB_INC : 0;
284 flags |= (lower.infinite) ? RANGE_LB_INF : 0;
285 flags |= (upper.inclusive) ? RANGE_UB_INC : 0;
286 flags |= (upper.infinite) ? RANGE_UB_INF : 0;
288 range_gettypinfo(fcinfo, lower.rngtypid, &rngtypinfo);
290 getTypeBinaryOutputInfo(rngtypinfo.subtype,
291 &subsend, &typIsVarlena);
293 pq_sendbyte(buf, flags);
295 if (RANGE_HAS_LBOUND(flags))
297 Datum bound = PointerGetDatum(OidSendFunctionCall(subsend,
299 uint32 bound_len = VARSIZE(bound) - VARHDRSZ;
300 char *bound_data = VARDATA(bound);
302 pq_sendint(buf, bound_len, 4);
303 pq_sendbytes(buf, bound_data, bound_len);
306 if (RANGE_HAS_UBOUND(flags))
308 Datum bound = PointerGetDatum(OidSendFunctionCall(subsend,
310 uint32 bound_len = VARSIZE(bound) - VARHDRSZ;
311 char *bound_data = VARDATA(bound);
313 pq_sendint(buf, bound_len, 4);
314 pq_sendbytes(buf, bound_data, bound_len);
317 PG_RETURN_BYTEA_P(pq_endtypsend(buf));
322 *----------------------------------------------------------
324 *----------------------------------------------------------
328 range_constructor0(PG_FUNCTION_ARGS)
330 Oid rngtypid = get_fn_expr_rettype(fcinfo->flinfo);
335 lower.rngtypid = rngtypid;
336 lower.val = (Datum) 0;
337 lower.inclusive = false;
338 lower.infinite = false;
341 upper.rngtypid = rngtypid;
342 upper.val = (Datum) 0;
343 upper.inclusive = false;
344 upper.infinite = false;
347 range = DatumGetRangeType(make_range(fcinfo, &lower, &upper, true));
349 PG_RETURN_RANGE(range);
353 range_constructor1(PG_FUNCTION_ARGS)
355 Datum arg1 = PG_GETARG_DATUM(0);
356 Oid rngtypid = get_fn_expr_rettype(fcinfo->flinfo);
363 (errcode(ERRCODE_DATA_EXCEPTION),
364 errmsg("argument must not be NULL")));
366 lower.rngtypid = rngtypid;
368 lower.inclusive = true;
369 lower.infinite = false;
372 upper.rngtypid = rngtypid;
374 upper.inclusive = true;
375 upper.infinite = false;
378 range = DatumGetRangeType(make_range(fcinfo, &lower, &upper, false));
380 PG_RETURN_RANGE(range);
384 range_constructor2(PG_FUNCTION_ARGS)
386 Datum arg1 = PG_GETARG_DATUM(0);
387 Datum arg2 = PG_GETARG_DATUM(1);
388 Oid rngtypid = get_fn_expr_rettype(fcinfo->flinfo);
394 flags = range_parse_flags(RANGE_DEFAULT_FLAGS);
396 lower.rngtypid = rngtypid;
397 lower.val = PG_ARGISNULL(0) ? (Datum) 0 : arg1;
398 lower.inclusive = flags & RANGE_LB_INC;
399 lower.infinite = PG_ARGISNULL(0);
402 upper.rngtypid = rngtypid;
403 upper.val = PG_ARGISNULL(1) ? (Datum) 0 : arg2;
404 upper.inclusive = flags & RANGE_UB_INC;
405 upper.infinite = PG_ARGISNULL(1);
408 range = DatumGetRangeType(make_range(fcinfo, &lower, &upper, false));
410 PG_RETURN_RANGE(range);
414 range_constructor3(PG_FUNCTION_ARGS)
416 Datum arg1 = PG_GETARG_DATUM(0);
417 Datum arg2 = PG_GETARG_DATUM(1);
418 Oid rngtypid = get_fn_expr_rettype(fcinfo->flinfo);
426 (errcode(ERRCODE_DATA_EXCEPTION),
427 errmsg("flags argument must not be NULL")));
429 flags = range_parse_flags(text_to_cstring(PG_GETARG_TEXT_P(2)));
431 lower.rngtypid = rngtypid;
432 lower.val = PG_ARGISNULL(0) ? (Datum) 0 : arg1;
433 lower.inclusive = flags & RANGE_LB_INC;
434 lower.infinite = PG_ARGISNULL(0);
437 upper.rngtypid = rngtypid;
438 upper.val = PG_ARGISNULL(1) ? (Datum) 0 : arg2;
439 upper.inclusive = flags & RANGE_UB_INC;
440 upper.infinite = PG_ARGISNULL(1);
443 range = DatumGetRangeType(make_range(fcinfo, &lower, &upper, false));
445 PG_RETURN_RANGE(range);
448 /* range -> subtype */
450 range_lower(PG_FUNCTION_ARGS)
452 RangeType *r1 = PG_GETARG_RANGE(0);
457 range_deserialize(fcinfo, r1, &lower, &upper, &empty);
461 (errcode(ERRCODE_DATA_EXCEPTION),
462 errmsg("empty range has no lower bound")));
465 (errcode(ERRCODE_DATA_EXCEPTION),
466 errmsg("range lower bound is infinite")));
468 PG_RETURN_DATUM(lower.val);
472 range_upper(PG_FUNCTION_ARGS)
474 RangeType *r1 = PG_GETARG_RANGE(0);
479 range_deserialize(fcinfo, r1, &lower, &upper, &empty);
483 (errcode(ERRCODE_DATA_EXCEPTION),
484 errmsg("empty range has no upper bound")));
487 (errcode(ERRCODE_DATA_EXCEPTION),
488 errmsg("range upper bound is infinite")));
490 PG_RETURN_DATUM(upper.val);
496 range_empty(PG_FUNCTION_ARGS)
498 RangeType *r1 = PG_GETARG_RANGE(0);
503 range_deserialize(fcinfo, r1, &lower, &upper, &empty);
505 PG_RETURN_BOOL(empty);
509 range_lower_inc(PG_FUNCTION_ARGS)
511 RangeType *r1 = PG_GETARG_RANGE(0);
516 range_deserialize(fcinfo, r1, &lower, &upper, &empty);
518 PG_RETURN_BOOL(lower.inclusive);
522 range_upper_inc(PG_FUNCTION_ARGS)
524 RangeType *r1 = PG_GETARG_RANGE(0);
529 range_deserialize(fcinfo, r1, &lower, &upper, &empty);
531 PG_RETURN_BOOL(upper.inclusive);
535 range_lower_inf(PG_FUNCTION_ARGS)
537 RangeType *r1 = PG_GETARG_RANGE(0);
542 range_deserialize(fcinfo, r1, &lower, &upper, &empty);
544 PG_RETURN_BOOL(lower.infinite);
548 range_upper_inf(PG_FUNCTION_ARGS)
550 RangeType *r1 = PG_GETARG_RANGE(0);
555 range_deserialize(fcinfo, r1, &lower, &upper, &empty);
557 PG_RETURN_BOOL(upper.infinite);
561 /* range, range -> bool */
563 range_eq(PG_FUNCTION_ARGS)
565 RangeType *r1 = PG_GETARG_RANGE(0);
566 RangeType *r2 = PG_GETARG_RANGE(1);
574 range_deserialize(fcinfo, r1, &lower1, &upper1, &empty1);
575 range_deserialize(fcinfo, r2, &lower2, &upper2, &empty2);
577 if (lower1.rngtypid != upper1.rngtypid ||
578 lower1.rngtypid != lower2.rngtypid ||
579 lower1.rngtypid != upper2.rngtypid)
580 elog(ERROR, "range types do not match");
582 if (empty1 && empty2)
583 PG_RETURN_BOOL(true);
584 if (empty1 != empty2)
585 PG_RETURN_BOOL(false);
587 if (range_cmp_bounds(fcinfo, &lower1, &lower2) != 0)
588 PG_RETURN_BOOL(false);
590 if (range_cmp_bounds(fcinfo, &upper1, &upper2) != 0)
591 PG_RETURN_BOOL(false);
593 PG_RETURN_BOOL(true);
597 range_ne(PG_FUNCTION_ARGS)
599 bool eq = DatumGetBool(range_eq(fcinfo));
605 range_contains_elem(PG_FUNCTION_ARGS)
607 RangeType *r1 = PG_GETARG_RANGE(0);
608 Datum val = PG_GETARG_DATUM(1);
616 range_deserialize(fcinfo, r1, &lower1, &upper1, &empty1);
618 lower2.rngtypid = lower1.rngtypid;
619 lower2.inclusive = true;
620 lower2.infinite = false;
624 upper2.rngtypid = lower1.rngtypid;
625 upper2.inclusive = true;
626 upper2.infinite = false;
627 upper2.lower = false;
630 r2 = DatumGetRangeType(make_range(fcinfo, &lower2, &upper2, false));
632 PG_RETURN_BOOL(range_contains_internal(fcinfo, r1, r2));
636 range_contains(PG_FUNCTION_ARGS)
638 RangeType *r1 = PG_GETARG_RANGE(0);
639 RangeType *r2 = PG_GETARG_RANGE(1);
641 PG_RETURN_BOOL(range_contains_internal(fcinfo, r1, r2));
645 elem_contained_by_range(PG_FUNCTION_ARGS)
647 RangeType *r1 = PG_GETARG_RANGE(1);
648 Datum val = PG_GETARG_DATUM(0);
656 range_deserialize(fcinfo, r1, &lower1, &upper1, &empty1);
658 lower2.rngtypid = lower1.rngtypid;
659 lower2.inclusive = true;
660 lower2.infinite = false;
664 upper2.rngtypid = lower1.rngtypid;
665 upper2.inclusive = true;
666 upper2.infinite = false;
667 upper2.lower = false;
670 r2 = DatumGetRangeType(make_range(fcinfo, &lower2, &upper2, false));
672 PG_RETURN_BOOL(range_contains_internal(fcinfo, r1, r2));
676 range_contained_by(PG_FUNCTION_ARGS)
678 RangeType *r1 = PG_GETARG_RANGE(0);
679 RangeType *r2 = PG_GETARG_RANGE(1);
681 PG_RETURN_BOOL(range_contains_internal(fcinfo, r2, r1));
685 range_before(PG_FUNCTION_ARGS)
687 RangeType *r1 = PG_GETARG_RANGE(0);
688 RangeType *r2 = PG_GETARG_RANGE(1);
696 range_deserialize(fcinfo, r1, &lower1, &upper1, &empty1);
697 range_deserialize(fcinfo, r2, &lower2, &upper2, &empty2);
699 if (lower1.rngtypid != upper1.rngtypid ||
700 lower1.rngtypid != lower2.rngtypid ||
701 lower1.rngtypid != upper2.rngtypid)
702 elog(ERROR, "range types do not match");
704 /* An empty range is neither before nor after any other range */
705 if (empty1 || empty2)
706 PG_RETURN_BOOL(false);
708 PG_RETURN_BOOL(range_cmp_bounds(fcinfo, &upper1, &lower2) < 0);
712 range_after(PG_FUNCTION_ARGS)
714 RangeType *r1 = PG_GETARG_RANGE(0);
715 RangeType *r2 = PG_GETARG_RANGE(1);
723 range_deserialize(fcinfo, r1, &lower1, &upper1, &empty1);
724 range_deserialize(fcinfo, r2, &lower2, &upper2, &empty2);
726 if (lower1.rngtypid != upper1.rngtypid ||
727 lower1.rngtypid != lower2.rngtypid ||
728 lower1.rngtypid != upper2.rngtypid)
729 elog(ERROR, "range types do not match");
731 /* An empty range is neither before nor after any other range */
732 if (empty1 || empty2)
733 PG_RETURN_BOOL(false);
735 PG_RETURN_BOOL(range_cmp_bounds(fcinfo, &lower1, &upper2) > 0);
739 range_adjacent(PG_FUNCTION_ARGS)
741 RangeType *r1 = PG_GETARG_RANGE(0);
742 RangeType *r2 = PG_GETARG_RANGE(1);
743 RangeTypeInfo rngtypinfo;
751 range_deserialize(fcinfo, r1, &lower1, &upper1, &empty1);
752 range_deserialize(fcinfo, r2, &lower2, &upper2, &empty2);
754 if (lower1.rngtypid != upper1.rngtypid ||
755 lower1.rngtypid != lower2.rngtypid ||
756 lower1.rngtypid != upper2.rngtypid)
757 elog(ERROR, "range types do not match");
759 /* An empty range is not adjacent to any other range */
760 if (empty1 || empty2)
761 PG_RETURN_BOOL(false);
764 * For two ranges to be adjacent, the lower boundary of one range has to
765 * match the upper boundary of the other. However, the inclusivity of
766 * those two boundaries must also be different.
768 * The semantics for range_cmp_bounds aren't quite what we need here, so
769 * we do the comparison more directly.
772 range_gettypinfo(fcinfo, lower1.rngtypid, &rngtypinfo);
774 if (lower1.inclusive != upper2.inclusive)
776 if (DatumGetInt32(FunctionCall2Coll(&rngtypinfo.cmpFn,
777 rngtypinfo.collation,
778 lower1.val, upper2.val)) == 0)
779 PG_RETURN_BOOL(true);
782 if (upper1.inclusive != lower2.inclusive)
784 if (DatumGetInt32(FunctionCall2Coll(&rngtypinfo.cmpFn,
785 rngtypinfo.collation,
786 upper1.val, lower2.val)) == 0)
787 PG_RETURN_BOOL(true);
790 PG_RETURN_BOOL(false);
794 range_overlaps(PG_FUNCTION_ARGS)
796 RangeType *r1 = PG_GETARG_RANGE(0);
797 RangeType *r2 = PG_GETARG_RANGE(1);
805 range_deserialize(fcinfo, r1, &lower1, &upper1, &empty1);
806 range_deserialize(fcinfo, r2, &lower2, &upper2, &empty2);
808 if (lower1.rngtypid != upper1.rngtypid ||
809 lower1.rngtypid != lower2.rngtypid ||
810 lower1.rngtypid != upper2.rngtypid)
811 elog(ERROR, "range types do not match");
813 /* An empty range does not overlap any other range */
814 if (empty1 || empty2)
815 PG_RETURN_BOOL(false);
817 if (range_cmp_bounds(fcinfo, &lower1, &lower2) >= 0 &&
818 range_cmp_bounds(fcinfo, &lower1, &upper2) <= 0)
819 PG_RETURN_BOOL(true);
821 if (range_cmp_bounds(fcinfo, &lower2, &lower1) >= 0 &&
822 range_cmp_bounds(fcinfo, &lower2, &upper1) <= 0)
823 PG_RETURN_BOOL(true);
825 PG_RETURN_BOOL(false);
829 range_overleft(PG_FUNCTION_ARGS)
831 RangeType *r1 = PG_GETARG_RANGE(0);
832 RangeType *r2 = PG_GETARG_RANGE(1);
840 range_deserialize(fcinfo, r1, &lower1, &upper1, &empty1);
841 range_deserialize(fcinfo, r2, &lower2, &upper2, &empty2);
843 if (lower1.rngtypid != upper1.rngtypid ||
844 lower1.rngtypid != lower2.rngtypid ||
845 lower1.rngtypid != upper2.rngtypid)
846 elog(ERROR, "range types do not match");
848 /* An empty range is neither before nor after any other range */
849 if (empty1 || empty2)
850 PG_RETURN_BOOL(false);
852 if (range_cmp_bounds(fcinfo, &upper1, &upper2) <= 0)
853 PG_RETURN_BOOL(true);
855 PG_RETURN_BOOL(false);
859 range_overright(PG_FUNCTION_ARGS)
861 RangeType *r1 = PG_GETARG_RANGE(0);
862 RangeType *r2 = PG_GETARG_RANGE(1);
870 range_deserialize(fcinfo, r1, &lower1, &upper1, &empty1);
871 range_deserialize(fcinfo, r2, &lower2, &upper2, &empty2);
873 if (lower1.rngtypid != upper1.rngtypid ||
874 lower1.rngtypid != lower2.rngtypid ||
875 lower1.rngtypid != upper2.rngtypid)
876 elog(ERROR, "range types do not match");
878 /* An empty range is neither before nor after any other range */
879 if (empty1 || empty2)
880 PG_RETURN_BOOL(false);
882 if (range_cmp_bounds(fcinfo, &lower1, &lower2) >= 0)
883 PG_RETURN_BOOL(true);
885 PG_RETURN_BOOL(false);
889 /* range, range -> range */
891 range_minus(PG_FUNCTION_ARGS)
893 RangeType *r1 = PG_GETARG_RANGE(0);
894 RangeType *r2 = PG_GETARG_RANGE(1);
906 range_deserialize(fcinfo, r1, &lower1, &upper1, &empty1);
907 range_deserialize(fcinfo, r2, &lower2, &upper2, &empty2);
909 if (lower1.rngtypid != upper1.rngtypid ||
910 lower1.rngtypid != lower2.rngtypid ||
911 lower1.rngtypid != upper2.rngtypid)
912 elog(ERROR, "range types do not match");
914 /* if either is empty, r1 is the correct answer */
915 if (empty1 || empty2)
918 cmp_l1l2 = range_cmp_bounds(fcinfo, &lower1, &lower2);
919 cmp_l1u2 = range_cmp_bounds(fcinfo, &lower1, &upper2);
920 cmp_u1l2 = range_cmp_bounds(fcinfo, &upper1, &lower2);
921 cmp_u1u2 = range_cmp_bounds(fcinfo, &upper1, &upper2);
923 if (cmp_l1l2 < 0 && cmp_u1u2 > 0)
925 (errcode(ERRCODE_DATA_EXCEPTION),
926 errmsg("result of range difference would not be contiguous")));
928 if (cmp_l1u2 > 0 || cmp_u1l2 < 0)
931 if (cmp_l1l2 >= 0 && cmp_u1u2 <= 0)
932 PG_RETURN_RANGE(make_empty_range(fcinfo, lower1.rngtypid));
934 if (cmp_l1l2 <= 0 && cmp_u1l2 >= 0 && cmp_u1u2 <= 0)
936 lower2.inclusive = !lower2.inclusive;
937 lower2.lower = false; /* it will become the upper bound */
938 PG_RETURN_RANGE(make_range(fcinfo, &lower1, &lower2, false));
941 if (cmp_l1l2 >= 0 && cmp_u1u2 >= 0 && cmp_l1u2 <= 0)
943 upper2.inclusive = !upper2.inclusive;
944 upper2.lower = true; /* it will become the lower bound */
945 PG_RETURN_RANGE(make_range(fcinfo, &upper2, &upper1, false));
948 elog(ERROR, "unexpected case in range_minus");
953 range_union(PG_FUNCTION_ARGS)
955 RangeType *r1 = PG_GETARG_RANGE(0);
956 RangeType *r2 = PG_GETARG_RANGE(1);
963 RangeBound *result_lower;
964 RangeBound *result_upper;
966 range_deserialize(fcinfo, r1, &lower1, &upper1, &empty1);
967 range_deserialize(fcinfo, r2, &lower2, &upper2, &empty2);
969 /* if either is empty, the other is the correct answer */
975 if (!DatumGetBool(range_overlaps(fcinfo)) &&
976 !DatumGetBool(range_adjacent(fcinfo)))
978 (errcode(ERRCODE_DATA_EXCEPTION),
979 errmsg("result of range union would not be contiguous")));
981 if (range_cmp_bounds(fcinfo, &lower1, &lower2) < 0)
982 result_lower = &lower1;
984 result_lower = &lower2;
986 if (range_cmp_bounds(fcinfo, &upper1, &upper2) > 0)
987 result_upper = &upper1;
989 result_upper = &upper2;
991 PG_RETURN_RANGE(make_range(fcinfo, result_lower, result_upper, false));
995 range_intersect(PG_FUNCTION_ARGS)
997 RangeType *r1 = PG_GETARG_RANGE(0);
998 RangeType *r2 = PG_GETARG_RANGE(1);
1005 RangeBound *result_lower;
1006 RangeBound *result_upper;
1008 range_deserialize(fcinfo, r1, &lower1, &upper1, &empty1);
1009 range_deserialize(fcinfo, r2, &lower2, &upper2, &empty2);
1011 if (empty1 || empty2 || !DatumGetBool(range_overlaps(fcinfo)))
1012 PG_RETURN_RANGE(make_empty_range(fcinfo, lower1.rngtypid));
1014 if (range_cmp_bounds(fcinfo, &lower1, &lower2) >= 0)
1015 result_lower = &lower1;
1017 result_lower = &lower2;
1019 if (range_cmp_bounds(fcinfo, &upper1, &upper2) <= 0)
1020 result_upper = &upper1;
1022 result_upper = &upper2;
1024 PG_RETURN_RANGE(make_range(fcinfo, result_lower, result_upper, false));
1030 range_cmp(PG_FUNCTION_ARGS)
1032 RangeType *r1 = PG_GETARG_RANGE(0);
1033 RangeType *r2 = PG_GETARG_RANGE(1);
1042 range_deserialize(fcinfo, r1, &lower1, &upper1, &empty1);
1043 range_deserialize(fcinfo, r2, &lower2, &upper2, &empty2);
1045 if (lower1.rngtypid != upper1.rngtypid ||
1046 lower1.rngtypid != lower2.rngtypid ||
1047 lower1.rngtypid != upper2.rngtypid)
1048 elog(ERROR, "range types do not match");
1050 /* For b-tree use, empty ranges sort before all else */
1051 if (empty1 && empty2)
1054 PG_RETURN_INT32(-1);
1058 if ((cmp = range_cmp_bounds(fcinfo, &lower1, &lower2)) != 0)
1059 PG_RETURN_INT32(cmp);
1061 PG_RETURN_INT32(range_cmp_bounds(fcinfo, &upper1, &upper2));
1065 range_lt(PG_FUNCTION_ARGS)
1067 int cmp = range_cmp(fcinfo);
1069 PG_RETURN_BOOL(cmp < 0);
1073 range_le(PG_FUNCTION_ARGS)
1075 int cmp = range_cmp(fcinfo);
1077 PG_RETURN_BOOL(cmp <= 0);
1081 range_ge(PG_FUNCTION_ARGS)
1083 int cmp = range_cmp(fcinfo);
1085 PG_RETURN_BOOL(cmp >= 0);
1089 range_gt(PG_FUNCTION_ARGS)
1091 int cmp = range_cmp(fcinfo);
1093 PG_RETURN_BOOL(cmp > 0);
1099 hash_range(PG_FUNCTION_ARGS)
1101 RangeType *r = PG_GETARG_RANGE(0);
1106 uint32 lower_hash = 0;
1107 uint32 upper_hash = 0;
1109 RangeTypeInfo rngtypinfo;
1110 TypeCacheEntry *typentry;
1112 FunctionCallInfoData locfcinfo;
1114 range_deserialize(fcinfo, r, &lower, &upper, &empty);
1116 if (lower.rngtypid != upper.rngtypid)
1117 elog(ERROR, "range types do not match");
1120 flags |= RANGE_EMPTY;
1122 flags |= (lower.inclusive) ? RANGE_LB_INC : 0;
1123 flags |= (lower.infinite) ? RANGE_LB_INF : 0;
1124 flags |= (upper.inclusive) ? RANGE_UB_INC : 0;
1125 flags |= (upper.infinite) ? RANGE_UB_INF : 0;
1127 range_gettypinfo(fcinfo, lower.rngtypid, &rngtypinfo);
1128 subtype = rngtypinfo.subtype;
1131 * We arrange to look up the hash function only once per series of calls,
1132 * assuming the subtype doesn't change underneath us. The typcache is
1133 * used so that we have no memory leakage when being used as an index
1136 typentry = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
1137 if (typentry == NULL || typentry->type_id != subtype)
1139 typentry = lookup_type_cache(subtype, TYPECACHE_HASH_PROC_FINFO);
1140 if (!OidIsValid(typentry->hash_proc_finfo.fn_oid))
1142 (errcode(ERRCODE_UNDEFINED_FUNCTION),
1143 errmsg("could not identify a hash function for type %s",
1144 format_type_be(subtype))));
1145 fcinfo->flinfo->fn_extra = (void *) typentry;
1149 * Apply the hash function to each bound (the hash function shouldn't care
1150 * about the collation).
1152 InitFunctionCallInfoData(locfcinfo, &typentry->hash_proc_finfo, 1,
1153 InvalidOid, NULL, NULL);
1155 if (RANGE_HAS_LBOUND(flags))
1157 locfcinfo.arg[0] = lower.val;
1158 locfcinfo.argnull[0] = false;
1159 locfcinfo.isnull = false;
1160 lower_hash = DatumGetUInt32(FunctionCallInvoke(&locfcinfo));
1162 if (RANGE_HAS_UBOUND(flags))
1164 locfcinfo.arg[0] = upper.val;
1165 locfcinfo.argnull[0] = false;
1166 locfcinfo.isnull = false;
1167 upper_hash = DatumGetUInt32(FunctionCallInvoke(&locfcinfo));
1170 result = hash_uint32((uint32) flags);
1171 result ^= lower_hash;
1172 result = (result << 1) | (result >> 31);
1173 result ^= upper_hash;
1175 PG_RETURN_INT32(result);
1179 *----------------------------------------------------------
1180 * CANONICAL FUNCTIONS
1182 * Functions for specific built-in range types.
1183 *----------------------------------------------------------
1187 int4range_canonical(PG_FUNCTION_ARGS)
1189 RangeType *r = PG_GETARG_RANGE(0);
1194 range_deserialize(fcinfo, r, &lower, &upper, &empty);
1199 if (!lower.infinite && !lower.inclusive)
1201 lower.val = DirectFunctionCall2(int4pl, lower.val, Int32GetDatum(1));
1202 lower.inclusive = true;
1205 if (!upper.infinite && upper.inclusive)
1207 upper.val = DirectFunctionCall2(int4pl, upper.val, Int32GetDatum(1));
1208 upper.inclusive = false;
1211 PG_RETURN_RANGE(range_serialize(fcinfo, &lower, &upper, false));
1215 int8range_canonical(PG_FUNCTION_ARGS)
1217 RangeType *r = PG_GETARG_RANGE(0);
1222 range_deserialize(fcinfo, r, &lower, &upper, &empty);
1227 if (!lower.infinite && !lower.inclusive)
1229 lower.val = DirectFunctionCall2(int8pl, lower.val, Int64GetDatum(1));
1230 lower.inclusive = true;
1233 if (!upper.infinite && upper.inclusive)
1235 upper.val = DirectFunctionCall2(int8pl, upper.val, Int64GetDatum(1));
1236 upper.inclusive = false;
1239 PG_RETURN_RANGE(range_serialize(fcinfo, &lower, &upper, false));
1243 daterange_canonical(PG_FUNCTION_ARGS)
1245 RangeType *r = PG_GETARG_RANGE(0);
1250 range_deserialize(fcinfo, r, &lower, &upper, &empty);
1255 if (!lower.infinite && !lower.inclusive)
1257 lower.val = DirectFunctionCall2(date_pli, lower.val, Int32GetDatum(1));
1258 lower.inclusive = true;
1261 if (!upper.infinite && upper.inclusive)
1263 upper.val = DirectFunctionCall2(date_pli, upper.val, Int32GetDatum(1));
1264 upper.inclusive = false;
1267 PG_RETURN_RANGE(range_serialize(fcinfo, &lower, &upper, false));
1271 *----------------------------------------------------------
1272 * SUBTYPE_DIFF FUNCTIONS
1274 * Functions for specific built-in range types.
1275 *----------------------------------------------------------
1279 int4range_subdiff(PG_FUNCTION_ARGS)
1281 int32 v1 = PG_GETARG_INT32(0);
1282 int32 v2 = PG_GETARG_INT32(1);
1284 PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
1288 int8range_subdiff(PG_FUNCTION_ARGS)
1290 int64 v1 = PG_GETARG_INT64(0);
1291 int64 v2 = PG_GETARG_INT64(1);
1293 PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
1297 numrange_subdiff(PG_FUNCTION_ARGS)
1299 Datum v1 = PG_GETARG_DATUM(0);
1300 Datum v2 = PG_GETARG_DATUM(1);
1304 numresult = DirectFunctionCall2(numeric_sub, v1, v2);
1306 floatresult = DatumGetFloat8(DirectFunctionCall1(numeric_float8,
1309 PG_RETURN_FLOAT8(floatresult);
1313 daterange_subdiff(PG_FUNCTION_ARGS)
1315 int32 v1 = PG_GETARG_INT32(0);
1316 int32 v2 = PG_GETARG_INT32(1);
1318 PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
1322 tsrange_subdiff(PG_FUNCTION_ARGS)
1324 Timestamp v1 = PG_GETARG_TIMESTAMP(0);
1325 Timestamp v2 = PG_GETARG_TIMESTAMP(1);
1328 #ifdef HAVE_INT64_TIMESTAMP
1329 result = ((float8) v1 - (float8) v2) / USECS_PER_SEC;
1334 PG_RETURN_FLOAT8(result);
1338 tstzrange_subdiff(PG_FUNCTION_ARGS)
1340 Timestamp v1 = PG_GETARG_TIMESTAMP(0);
1341 Timestamp v2 = PG_GETARG_TIMESTAMP(1);
1344 #ifdef HAVE_INT64_TIMESTAMP
1345 result = ((float8) v1 - (float8) v2) / USECS_PER_SEC;
1350 PG_RETURN_FLOAT8(result);
1354 *----------------------------------------------------------
1357 * These functions aren't in pg_proc, but are useful for
1358 * defining new generic range functions in C.
1359 *----------------------------------------------------------
1363 * Serialized format is:
1365 * 4 bytes: Range type Oid
1366 * Lower boundary, if any, aligned according to subtype's typalign
1367 * Upper boundary, if any, aligned according to subtype's typalign
1370 * This representation is chosen to be compact when the boundary
1371 * values need to be MAXALIGNed. A palloc chunk always starts out
1372 * MAXALIGNed, and the first 4 bytes will be the length header (range
1373 * types are always variable-length), then the next 4 bytes will be
1374 * the range type Oid. That leaves the first boundary item MAXALIGNed
1375 * without the need for padding.
1377 * However, it requires a slightly odd deserialization strategy,
1378 * because we have to read the flags byte before we know whether to
1379 * read a boundary value.
1383 * This serializes a range, but does not canonicalize it. This should
1384 * only be called by a canonicalization function.
1387 range_serialize(FunctionCallInfo fcinfo, RangeBound *lower, RangeBound *upper,
1398 RangeTypeInfo rngtypinfo;
1400 if (lower->rngtypid != upper->rngtypid)
1401 elog(ERROR, "range types do not match");
1403 range_gettypinfo(fcinfo, lower->rngtypid, &rngtypinfo);
1405 typlen = rngtypinfo.subtyplen;
1406 typalign = rngtypinfo.subtypalign;
1407 typbyval = rngtypinfo.subtypbyval;
1408 typstorage = rngtypinfo.subtypstorage;
1411 flags |= RANGE_EMPTY;
1412 else if (range_cmp_bounds(fcinfo, lower, upper) > 0)
1414 (errcode(ERRCODE_DATA_EXCEPTION),
1415 errmsg("range lower bound must be less than or equal to range upper bound")));
1417 flags |= (lower->inclusive) ? RANGE_LB_INC : 0;
1418 flags |= (lower->infinite) ? RANGE_LB_INF : 0;
1419 flags |= (upper->inclusive) ? RANGE_UB_INC : 0;
1420 flags |= (upper->infinite) ? RANGE_UB_INF : 0;
1423 msize += sizeof(Oid);
1425 if (RANGE_HAS_LBOUND(flags))
1427 msize = datum_compute_size(msize, lower->val, typbyval, typalign,
1428 typlen, typstorage);
1431 if (RANGE_HAS_UBOUND(flags))
1433 msize = datum_compute_size(msize, upper->val, typbyval, typalign,
1434 typlen, typstorage);
1437 msize += sizeof(char);
1439 ptr = palloc0(msize);
1440 range = (Datum) ptr;
1444 memcpy(ptr, &lower->rngtypid, sizeof(Oid));
1447 if (RANGE_HAS_LBOUND(flags))
1449 Assert(lower->lower);
1450 ptr = datum_write(ptr, lower->val, typbyval, typalign, typlen,
1454 if (RANGE_HAS_UBOUND(flags))
1456 Assert(!upper->lower);
1457 ptr = datum_write(ptr, upper->val, typbyval, typalign, typlen,
1461 memcpy(ptr, &flags, sizeof(char));
1462 ptr += sizeof(char);
1464 SET_VARSIZE(range, msize);
1465 PG_RETURN_RANGE(range);
1469 range_deserialize(FunctionCallInfo fcinfo, RangeType *range, RangeBound *lower,
1470 RangeBound *upper, bool *empty)
1472 Pointer ptr = VARDATA(range);
1481 RangeTypeInfo rngtypinfo;
1483 memset(lower, 0, sizeof(RangeBound));
1484 memset(upper, 0, sizeof(RangeBound));
1486 /* peek at last byte to read the flag byte */
1487 flags_ptr = ptr + VARSIZE(range) - VARHDRSZ - 1;
1488 memcpy(&flags, flags_ptr, sizeof(char));
1490 memcpy(&rngtypid, ptr, sizeof(Oid));
1493 if (rngtypid == ANYRANGEOID)
1495 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1496 errmsg("cannot output a value of type anyrange")));
1498 range_gettypinfo(fcinfo, rngtypid, &rngtypinfo);
1500 typalign = rngtypinfo.subtypalign;
1501 typlen = rngtypinfo.subtyplen;
1502 typbyval = rngtypinfo.subtypbyval;
1504 if (RANGE_HAS_LBOUND(flags))
1506 ptr = (Pointer) att_align_pointer(ptr, typalign, typlen, ptr);
1507 lbound = fetch_att(ptr, typbyval, typlen);
1508 ptr = (Pointer) att_addlength_datum(ptr, typlen, PointerGetDatum(ptr));
1510 lbound = PointerGetDatum(PG_DETOAST_DATUM(lbound));
1515 if (RANGE_HAS_UBOUND(flags))
1517 ptr = (Pointer) att_align_pointer(ptr, typalign, typlen, ptr);
1518 ubound = fetch_att(ptr, typbyval, typlen);
1519 ptr = (Pointer) att_addlength_datum(ptr, typlen, PointerGetDatum(ptr));
1521 ubound = PointerGetDatum(PG_DETOAST_DATUM(ubound));
1526 *empty = flags & RANGE_EMPTY;
1528 lower->rngtypid = rngtypid;
1529 lower->val = lbound;
1530 lower->inclusive = flags & RANGE_LB_INC;
1531 lower->infinite = flags & RANGE_LB_INF;
1532 lower->lower = true;
1534 upper->rngtypid = rngtypid;
1535 upper->val = ubound;
1536 upper->inclusive = flags & RANGE_UB_INC;
1537 upper->infinite = flags & RANGE_UB_INF;
1538 upper->lower = false;
1542 * This both serializes and canonicalizes (if applicable) the range.
1543 * This should be used by most callers.
1546 make_range(FunctionCallInfo fcinfo, RangeBound *lower, RangeBound *upper,
1550 RangeTypeInfo rngtypinfo;
1552 range_gettypinfo(fcinfo, lower->rngtypid, &rngtypinfo);
1554 if (lower->rngtypid != upper->rngtypid)
1555 elog(ERROR, "range types do not match");
1557 range = range_serialize(fcinfo, lower, upper, empty);
1559 if (rngtypinfo.canonicalFn.fn_addr != NULL)
1560 range = FunctionCall1(&rngtypinfo.canonicalFn, range);
1562 PG_RETURN_RANGE(range);
1566 range_cmp_bounds(FunctionCallInfo fcinfo, RangeBound *b1, RangeBound *b2)
1569 RangeTypeInfo rngtypinfo;
1571 if (b1->infinite && b2->infinite)
1573 if (b1->lower == b2->lower)
1576 return (b1->lower) ? -1 : 1;
1578 else if (b1->infinite && !b2->infinite)
1579 return (b1->lower) ? -1 : 1;
1580 else if (!b1->infinite && b2->infinite)
1581 return (b2->lower) ? 1 : -1;
1583 range_gettypinfo(fcinfo, b1->rngtypid, &rngtypinfo);
1585 result = DatumGetInt32(FunctionCall2Coll(&rngtypinfo.cmpFn,
1586 rngtypinfo.collation,
1591 if (b1->inclusive && !b2->inclusive)
1592 return (b2->lower) ? -1 : 1;
1593 else if (!b1->inclusive && b2->inclusive)
1594 return (b1->lower) ? 1 : -1;
1601 make_empty_range(FunctionCallInfo fcinfo, Oid rngtypid)
1606 memset(&lower, 0, sizeof(RangeBound));
1607 memset(&upper, 0, sizeof(RangeBound));
1609 lower.rngtypid = rngtypid;
1611 upper.rngtypid = rngtypid;
1612 upper.lower = false;
1614 return DatumGetRangeType(make_range(fcinfo, &lower, &upper, true));
1618 * Fills in rngtypinfo, from a cached copy if available.
1621 range_gettypinfo(FunctionCallInfo fcinfo, Oid rngtypid,
1622 RangeTypeInfo *rngtypinfo)
1624 RangeTypeInfo *cached = (RangeTypeInfo *) fcinfo->flinfo->fn_extra;
1628 fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
1629 sizeof(RangeTypeInfo));
1630 cached = (RangeTypeInfo *) fcinfo->flinfo->fn_extra;
1631 cached->rngtypid = ~rngtypid;
1634 if (cached->rngtypid != rngtypid)
1636 Form_pg_range pg_range;
1637 Form_pg_opclass pg_opclass;
1638 Form_pg_type pg_type;
1653 /* get information from pg_range */
1654 tup = SearchSysCache1(RANGETYPE, ObjectIdGetDatum(rngtypid));
1655 if (!HeapTupleIsValid(tup))
1656 elog(ERROR, "cache lookup failed for range type %u", rngtypid);
1658 pg_range = (Form_pg_range) GETSTRUCT(tup);
1660 subtypeOid = pg_range->rngsubtype;
1661 collationOid = pg_range->rngcollation;
1662 canonicalOid = pg_range->rngcanonical;
1663 opclassOid = pg_range->rngsubopc;
1664 subdiffOid = pg_range->rngsubdiff;
1666 ReleaseSysCache(tup);
1668 /* get information from pg_opclass */
1669 tup = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclassOid));
1670 if (!HeapTupleIsValid(tup))
1672 (errcode(ERRCODE_UNDEFINED_OBJECT),
1673 errmsg("operator class with OID %u does not exist",
1676 pg_opclass = (Form_pg_opclass) GETSTRUCT(tup);
1678 opfamilyOid = pg_opclass->opcfamily;
1679 opcintype = pg_opclass->opcintype;
1681 ReleaseSysCache(tup);
1683 cmpFnOid = get_opfamily_proc(opfamilyOid, opcintype, opcintype,
1685 if (!RegProcedureIsValid(cmpFnOid))
1686 elog(ERROR, "missing support function %d(%u,%u) in opfamily %u",
1687 BTORDER_PROC, opcintype, opcintype, opfamilyOid);
1689 /* get information from pg_type */
1690 tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(subtypeOid));
1691 if (!HeapTupleIsValid(tup))
1692 elog(ERROR, "cache lookup failed for type %u", subtypeOid);
1694 pg_type = (Form_pg_type) GETSTRUCT(tup);
1696 subtyplen = pg_type->typlen;
1697 subtypalign = pg_type->typalign;
1698 subtypstorage = pg_type->typstorage;
1699 subtypbyval = pg_type->typbyval;
1701 ReleaseSysCache(tup);
1703 /* set up the cache */
1705 if (OidIsValid(canonicalOid))
1706 fmgr_info(canonicalOid, &cached->canonicalFn);
1708 cached->canonicalFn.fn_addr = NULL;
1710 if (OidIsValid(subdiffOid))
1711 fmgr_info(subdiffOid, &cached->subdiffFn);
1713 cached->subdiffFn.fn_addr = NULL;
1715 fmgr_info(cmpFnOid, &cached->cmpFn);
1716 cached->subtype = subtypeOid;
1717 cached->collation = collationOid;
1718 cached->subtyplen = subtyplen;
1719 cached->subtypalign = subtypalign;
1720 cached->subtypstorage = subtypstorage;
1721 cached->subtypbyval = subtypbyval;
1722 cached->rngtypid = rngtypid;
1725 memcpy(rngtypinfo, cached, sizeof(RangeTypeInfo));
1729 *----------------------------------------------------------
1731 *----------------------------------------------------------
1735 * Given a string representing the flags for the range type, return the flags
1736 * represented as a char.
1739 range_parse_flags(const char *flags_str)
1743 if (flags_str[0] == '\0' ||
1744 flags_str[1] == '\0' ||
1745 flags_str[2] != '\0')
1747 (errcode(ERRCODE_SYNTAX_ERROR),
1748 errmsg("invalid range bound flags"),
1749 errhint("Valid values are '[]', '[)', '(]', and '()'.")));
1751 switch (flags_str[0])
1754 flags |= RANGE_LB_INC;
1760 (errcode(ERRCODE_SYNTAX_ERROR),
1761 errmsg("invalid range bound flags"),
1762 errhint("Valid values are '[]', '[)', '(]', and '()'.")));
1765 switch (flags_str[1])
1768 flags |= RANGE_UB_INC;
1774 (errcode(ERRCODE_SYNTAX_ERROR),
1775 errmsg("invalid range bound flags"),
1776 errhint("Valid values are '[]', '[)', '(]', and '()'.")));
1783 * Parse range input, modeled after record_in in rowtypes.c.
1786 * | <lb-inc> <string>, <string> <ub-inc>
1787 * <lb-inc> := '[' | '('
1788 * <ub-inc> := ']' | ')'
1790 * Whitespace before or after <range> is ignored. Whitespace within a <string>
1791 * is taken literally and becomes the input string for that bound.
1793 * A <string> of length zero is taken as "infinite" (i.e. no bound); unless it
1794 * is surrounded by double-quotes, in which case it is the literal empty
1797 * Within a <string>, special characters (such as comma, parenthesis, or
1798 * brackets) can be enclosed in double-quotes or escaped with backslash. Within
1799 * double-quotes, a double-quote can be escaped with double-quote or backslash.
1802 range_parse(char *string, char *flags, char **lbound_str,
1810 /* consume whitespace */
1811 while (*ptr != '\0' && isspace(*ptr))
1814 /* check for empty range */
1815 if (pg_strncasecmp(ptr, RANGE_EMPTY_LITERAL,
1816 strlen(RANGE_EMPTY_LITERAL)) == 0)
1818 *flags = RANGE_EMPTY;
1820 ptr += strlen(RANGE_EMPTY_LITERAL);
1822 /* the rest should be whitespace */
1823 while (*ptr != '\0' && isspace(*ptr))
1826 /* should have consumed everything */
1829 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1830 errmsg("malformed range literal: \"%s\"",
1832 errdetail("Unexpected end of input.")));
1837 if (*ptr == '[' || *ptr == '(')
1840 *flags |= RANGE_LB_INC;
1846 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1847 errmsg("malformed range literal: \"%s\"",
1849 errdetail("Missing left parenthesis or bracket.")));
1852 ptr = range_parse_bound(string, ptr, lbound_str, &infinite);
1855 *flags |= RANGE_LB_INF;
1856 *flags &= ~RANGE_LB_INC;
1861 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1862 errmsg("malformed range literal: \"%s\"",
1864 errdetail("Missing upper bound.")));
1867 ptr = range_parse_bound(string, ptr, ubound_str, &infinite);
1869 if (*ptr == ')' || *ptr == ']')
1872 *flags |= RANGE_UB_INC;
1877 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1878 errmsg("malformed range literal: \"%s\"",
1880 errdetail("Too many boundaries.")));
1887 *flags |= RANGE_UB_INF;
1888 *flags &= ~RANGE_UB_INC;
1891 /* consume whitespace */
1892 while (*ptr != '\0' && isspace(*ptr))
1897 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1898 errmsg("malformed range literal: \"%s\"",
1900 errdetail("Junk after right parenthesis or bracket.")));
1906 range_parse_bound(char *string, char *ptr, char **bound_str, bool *infinite)
1910 /* Check for null: completely empty input means null */
1911 if (*ptr == ',' || *ptr == ')' || *ptr == ']')
1918 /* Extract string for this column */
1919 bool inquote = false;
1921 initStringInfo(&buf);
1922 while (inquote || !(*ptr == ',' || *ptr == ')' || *ptr == ']'))
1928 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1929 errmsg("malformed range literal: \"%s\"",
1931 errdetail("Unexpected end of input.")));
1936 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1937 errmsg("malformed range literal: \"%s\"",
1939 errdetail("Unexpected end of input.")));
1940 appendStringInfoChar(&buf, *ptr++);
1942 else if (ch == '\"')
1946 else if (*ptr == '\"')
1948 /* doubled quote within quote sequence */
1949 appendStringInfoChar(&buf, *ptr++);
1955 appendStringInfoChar(&buf, ch);
1958 *bound_str = buf.data;
1966 range_deparse(char flags, char *lbound_str, char *ubound_str)
1970 initStringInfo(&buf);
1972 if (flags & RANGE_EMPTY)
1973 return pstrdup(RANGE_EMPTY_LITERAL);
1975 appendStringInfoString(&buf, (flags & RANGE_LB_INC) ? "[" : "(");
1977 if (RANGE_HAS_LBOUND(flags))
1978 appendStringInfoString(&buf, range_bound_escape(lbound_str));
1980 appendStringInfoString(&buf, ",");
1982 if (RANGE_HAS_UBOUND(flags))
1983 appendStringInfoString(&buf, range_bound_escape(ubound_str));
1985 appendStringInfoString(&buf, (flags & RANGE_UB_INC) ? "]" : ")");
1991 range_bound_escape(char *value)
1997 initStringInfo(&buf);
1999 /* Detect whether we need double quotes for this value */
2000 nq = (value[0] == '\0'); /* force quotes for empty string */
2001 for (tmp = value; *tmp; tmp++)
2005 if (ch == '"' || ch == '\\' ||
2006 ch == '(' || ch == ')' ||
2007 ch == '[' || ch == ']' ||
2009 isspace((unsigned char) ch))
2016 /* And emit the string */
2018 appendStringInfoChar(&buf, '"');
2019 for (tmp = value; *tmp; tmp++)
2023 if (ch == '"' || ch == '\\')
2024 appendStringInfoChar(&buf, ch);
2025 appendStringInfoChar(&buf, ch);
2028 appendStringInfoChar(&buf, '"');
2034 range_contains_internal(FunctionCallInfo fcinfo, RangeType *r1, RangeType *r2)
2043 range_deserialize(fcinfo, r1, &lower1, &upper1, &empty1);
2044 range_deserialize(fcinfo, r2, &lower2, &upper2, &empty2);
2046 if (lower1.rngtypid != upper1.rngtypid ||
2047 lower1.rngtypid != lower2.rngtypid ||
2048 lower1.rngtypid != upper2.rngtypid)
2049 elog(ERROR, "range types do not match");
2056 if (range_cmp_bounds(fcinfo, &lower1, &lower2) > 0)
2058 if (range_cmp_bounds(fcinfo, &upper1, &upper2) < 0)
2065 * datum_compute_size() and datum_write() are modeled after
2066 * heap_compute_data_size() and heap_fill_tuple().
2070 datum_compute_size(Size data_length, Datum val, bool typbyval, char typalign,
2071 int16 typlen, char typstorage)
2073 if (TYPE_IS_PACKABLE(typlen, typstorage) &&
2074 VARATT_CAN_MAKE_SHORT(DatumGetPointer(val)))
2077 * we're anticipating converting to a short varlena header, so adjust
2078 * length and don't count any alignment
2080 data_length += VARATT_CONVERTED_SHORT_SIZE(DatumGetPointer(val));
2084 data_length = att_align_datum(data_length, typalign, typlen, val);
2085 data_length = att_addlength_datum(data_length, typlen, val);
2092 * Modified version of the code in heap_fill_tuple(). Writes the datum to ptr
2093 * using the correct alignment, and also uses short varlena header if
2097 datum_write(Pointer ptr, Datum datum, bool typbyval, char typalign,
2098 int16 typlen, char typstorage)
2105 ptr = (char *) att_align_nominal(ptr, typalign);
2106 store_att_byval(ptr, datum, typlen);
2107 data_length = typlen;
2109 else if (typlen == -1)
2112 Pointer val = DatumGetPointer(datum);
2114 if (VARATT_IS_EXTERNAL(val))
2116 /* no alignment, since it's short by definition */
2117 data_length = VARSIZE_EXTERNAL(val);
2118 memcpy(ptr, val, data_length);
2120 else if (VARATT_IS_SHORT(val))
2122 /* no alignment for short varlenas */
2123 data_length = VARSIZE_SHORT(val);
2124 memcpy(ptr, val, data_length);
2126 else if (TYPE_IS_PACKABLE(typlen, typstorage) &&
2127 VARATT_CAN_MAKE_SHORT(val))
2129 /* convert to short varlena -- no alignment */
2130 data_length = VARATT_CONVERTED_SHORT_SIZE(val);
2131 SET_VARSIZE_SHORT(ptr, data_length);
2132 memcpy(ptr + 1, VARDATA(val), data_length - 1);
2136 /* full 4-byte header varlena */
2137 ptr = (char *) att_align_nominal(ptr, typalign);
2138 data_length = VARSIZE(val);
2139 memcpy(ptr, val, data_length);
2142 else if (typlen == -2)
2144 /* cstring ... never needs alignment */
2145 Assert(typalign == 'c');
2146 data_length = strlen(DatumGetCString(datum)) + 1;
2147 memcpy(ptr, DatumGetPointer(datum), data_length);
2151 /* fixed-length pass-by-reference */
2152 ptr = (char *) att_align_nominal(ptr, typalign);
2154 data_length = typlen;
2155 memcpy(ptr, DatumGetPointer(datum), data_length);