doc: 1-byte varlena headers can be used for user PLAIN storage
[pgsql.git] / src / backend / utils / adt / rangetypes.c
blob24bad52923975084c1134acfe5b7130417cb329d
1 /*-------------------------------------------------------------------------
3 * rangetypes.c
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
12 * 1 byte for flags
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-2023, PostgreSQL Global Development Group
23 * Portions Copyright (c) 1994, Regents of the University of California
26 * IDENTIFICATION
27 * src/backend/utils/adt/rangetypes.c
29 *-------------------------------------------------------------------------
31 #include "postgres.h"
33 #include "access/tupmacs.h"
34 #include "common/hashfn.h"
35 #include "lib/stringinfo.h"
36 #include "libpq/pqformat.h"
37 #include "miscadmin.h"
38 #include "nodes/miscnodes.h"
39 #include "port/pg_bitutils.h"
40 #include "utils/builtins.h"
41 #include "utils/date.h"
42 #include "utils/lsyscache.h"
43 #include "utils/rangetypes.h"
44 #include "utils/timestamp.h"
45 #include "varatt.h"
48 /* fn_extra cache entry for one of the range I/O functions */
49 typedef struct RangeIOData
51 TypeCacheEntry *typcache; /* range type's typcache entry */
52 FmgrInfo typioproc; /* element type's I/O function */
53 Oid typioparam; /* element type's I/O parameter */
54 } RangeIOData;
57 static RangeIOData *get_range_io_data(FunctionCallInfo fcinfo, Oid rngtypid,
58 IOFuncSelector func);
59 static char range_parse_flags(const char *flags_str);
60 static bool range_parse(const char *string, char *flags, char **lbound_str,
61 char **ubound_str, Node *escontext);
62 static const char *range_parse_bound(const char *string, const char *ptr,
63 char **bound_str, bool *infinite,
64 Node *escontext);
65 static char *range_deparse(char flags, const char *lbound_str,
66 const char *ubound_str);
67 static char *range_bound_escape(const char *value);
68 static Size datum_compute_size(Size data_length, Datum val, bool typbyval,
69 char typalign, int16 typlen, char typstorage);
70 static Pointer datum_write(Pointer ptr, Datum datum, bool typbyval,
71 char typalign, int16 typlen, char typstorage);
75 *----------------------------------------------------------
76 * I/O FUNCTIONS
77 *----------------------------------------------------------
80 Datum
81 range_in(PG_FUNCTION_ARGS)
83 char *input_str = PG_GETARG_CSTRING(0);
84 Oid rngtypoid = PG_GETARG_OID(1);
85 Oid typmod = PG_GETARG_INT32(2);
86 Node *escontext = fcinfo->context;
87 RangeType *range;
88 RangeIOData *cache;
89 char flags;
90 char *lbound_str;
91 char *ubound_str;
92 RangeBound lower;
93 RangeBound upper;
95 check_stack_depth(); /* recurses when subtype is a range type */
97 cache = get_range_io_data(fcinfo, rngtypoid, IOFunc_input);
99 /* parse */
100 if (!range_parse(input_str, &flags, &lbound_str, &ubound_str, escontext))
101 PG_RETURN_NULL();
103 /* call element type's input function */
104 if (RANGE_HAS_LBOUND(flags))
105 if (!InputFunctionCallSafe(&cache->typioproc, lbound_str,
106 cache->typioparam, typmod,
107 escontext, &lower.val))
108 PG_RETURN_NULL();
109 if (RANGE_HAS_UBOUND(flags))
110 if (!InputFunctionCallSafe(&cache->typioproc, ubound_str,
111 cache->typioparam, typmod,
112 escontext, &upper.val))
113 PG_RETURN_NULL();
115 lower.infinite = (flags & RANGE_LB_INF) != 0;
116 lower.inclusive = (flags & RANGE_LB_INC) != 0;
117 lower.lower = true;
118 upper.infinite = (flags & RANGE_UB_INF) != 0;
119 upper.inclusive = (flags & RANGE_UB_INC) != 0;
120 upper.lower = false;
122 /* serialize and canonicalize */
123 range = make_range(cache->typcache, &lower, &upper,
124 flags & RANGE_EMPTY, escontext);
126 PG_RETURN_RANGE_P(range);
129 Datum
130 range_out(PG_FUNCTION_ARGS)
132 RangeType *range = PG_GETARG_RANGE_P(0);
133 char *output_str;
134 RangeIOData *cache;
135 char flags;
136 char *lbound_str = NULL;
137 char *ubound_str = NULL;
138 RangeBound lower;
139 RangeBound upper;
140 bool empty;
142 check_stack_depth(); /* recurses when subtype is a range type */
144 cache = get_range_io_data(fcinfo, RangeTypeGetOid(range), IOFunc_output);
146 /* deserialize */
147 range_deserialize(cache->typcache, range, &lower, &upper, &empty);
148 flags = range_get_flags(range);
150 /* call element type's output function */
151 if (RANGE_HAS_LBOUND(flags))
152 lbound_str = OutputFunctionCall(&cache->typioproc, lower.val);
153 if (RANGE_HAS_UBOUND(flags))
154 ubound_str = OutputFunctionCall(&cache->typioproc, upper.val);
156 /* construct result string */
157 output_str = range_deparse(flags, lbound_str, ubound_str);
159 PG_RETURN_CSTRING(output_str);
163 * Binary representation: The first byte is the flags, then the lower bound
164 * (if present), then the upper bound (if present). Each bound is represented
165 * by a 4-byte length header and the binary representation of that bound (as
166 * returned by a call to the send function for the subtype).
169 Datum
170 range_recv(PG_FUNCTION_ARGS)
172 StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
173 Oid rngtypoid = PG_GETARG_OID(1);
174 int32 typmod = PG_GETARG_INT32(2);
175 RangeType *range;
176 RangeIOData *cache;
177 char flags;
178 RangeBound lower;
179 RangeBound upper;
181 check_stack_depth(); /* recurses when subtype is a range type */
183 cache = get_range_io_data(fcinfo, rngtypoid, IOFunc_receive);
185 /* receive the flags... */
186 flags = (unsigned char) pq_getmsgbyte(buf);
189 * Mask out any unsupported flags, particularly RANGE_xB_NULL which would
190 * confuse following tests. Note that range_serialize will take care of
191 * cleaning up any inconsistencies in the remaining flags.
193 flags &= (RANGE_EMPTY |
194 RANGE_LB_INC |
195 RANGE_LB_INF |
196 RANGE_UB_INC |
197 RANGE_UB_INF);
199 /* receive the bounds ... */
200 if (RANGE_HAS_LBOUND(flags))
202 uint32 bound_len = pq_getmsgint(buf, 4);
203 const char *bound_data = pq_getmsgbytes(buf, bound_len);
204 StringInfoData bound_buf;
206 initStringInfo(&bound_buf);
207 appendBinaryStringInfo(&bound_buf, bound_data, bound_len);
209 lower.val = ReceiveFunctionCall(&cache->typioproc,
210 &bound_buf,
211 cache->typioparam,
212 typmod);
213 pfree(bound_buf.data);
215 else
216 lower.val = (Datum) 0;
218 if (RANGE_HAS_UBOUND(flags))
220 uint32 bound_len = pq_getmsgint(buf, 4);
221 const char *bound_data = pq_getmsgbytes(buf, bound_len);
222 StringInfoData bound_buf;
224 initStringInfo(&bound_buf);
225 appendBinaryStringInfo(&bound_buf, bound_data, bound_len);
227 upper.val = ReceiveFunctionCall(&cache->typioproc,
228 &bound_buf,
229 cache->typioparam,
230 typmod);
231 pfree(bound_buf.data);
233 else
234 upper.val = (Datum) 0;
236 pq_getmsgend(buf);
238 /* finish constructing RangeBound representation */
239 lower.infinite = (flags & RANGE_LB_INF) != 0;
240 lower.inclusive = (flags & RANGE_LB_INC) != 0;
241 lower.lower = true;
242 upper.infinite = (flags & RANGE_UB_INF) != 0;
243 upper.inclusive = (flags & RANGE_UB_INC) != 0;
244 upper.lower = false;
246 /* serialize and canonicalize */
247 range = make_range(cache->typcache, &lower, &upper,
248 flags & RANGE_EMPTY, NULL);
250 PG_RETURN_RANGE_P(range);
253 Datum
254 range_send(PG_FUNCTION_ARGS)
256 RangeType *range = PG_GETARG_RANGE_P(0);
257 StringInfo buf = makeStringInfo();
258 RangeIOData *cache;
259 char flags;
260 RangeBound lower;
261 RangeBound upper;
262 bool empty;
264 check_stack_depth(); /* recurses when subtype is a range type */
266 cache = get_range_io_data(fcinfo, RangeTypeGetOid(range), IOFunc_send);
268 /* deserialize */
269 range_deserialize(cache->typcache, range, &lower, &upper, &empty);
270 flags = range_get_flags(range);
272 /* construct output */
273 pq_begintypsend(buf);
275 pq_sendbyte(buf, flags);
277 if (RANGE_HAS_LBOUND(flags))
279 Datum bound = PointerGetDatum(SendFunctionCall(&cache->typioproc,
280 lower.val));
281 uint32 bound_len = VARSIZE(bound) - VARHDRSZ;
282 char *bound_data = VARDATA(bound);
284 pq_sendint32(buf, bound_len);
285 pq_sendbytes(buf, bound_data, bound_len);
288 if (RANGE_HAS_UBOUND(flags))
290 Datum bound = PointerGetDatum(SendFunctionCall(&cache->typioproc,
291 upper.val));
292 uint32 bound_len = VARSIZE(bound) - VARHDRSZ;
293 char *bound_data = VARDATA(bound);
295 pq_sendint32(buf, bound_len);
296 pq_sendbytes(buf, bound_data, bound_len);
299 PG_RETURN_BYTEA_P(pq_endtypsend(buf));
303 * get_range_io_data: get cached information needed for range type I/O
305 * The range I/O functions need a bit more cached info than other range
306 * functions, so they store a RangeIOData struct in fn_extra, not just a
307 * pointer to a type cache entry.
309 static RangeIOData *
310 get_range_io_data(FunctionCallInfo fcinfo, Oid rngtypid, IOFuncSelector func)
312 RangeIOData *cache = (RangeIOData *) fcinfo->flinfo->fn_extra;
314 if (cache == NULL || cache->typcache->type_id != rngtypid)
316 int16 typlen;
317 bool typbyval;
318 char typalign;
319 char typdelim;
320 Oid typiofunc;
322 cache = (RangeIOData *) MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
323 sizeof(RangeIOData));
324 cache->typcache = lookup_type_cache(rngtypid, TYPECACHE_RANGE_INFO);
325 if (cache->typcache->rngelemtype == NULL)
326 elog(ERROR, "type %u is not a range type", rngtypid);
328 /* get_type_io_data does more than we need, but is convenient */
329 get_type_io_data(cache->typcache->rngelemtype->type_id,
330 func,
331 &typlen,
332 &typbyval,
333 &typalign,
334 &typdelim,
335 &cache->typioparam,
336 &typiofunc);
338 if (!OidIsValid(typiofunc))
340 /* this could only happen for receive or send */
341 if (func == IOFunc_receive)
342 ereport(ERROR,
343 (errcode(ERRCODE_UNDEFINED_FUNCTION),
344 errmsg("no binary input function available for type %s",
345 format_type_be(cache->typcache->rngelemtype->type_id))));
346 else
347 ereport(ERROR,
348 (errcode(ERRCODE_UNDEFINED_FUNCTION),
349 errmsg("no binary output function available for type %s",
350 format_type_be(cache->typcache->rngelemtype->type_id))));
352 fmgr_info_cxt(typiofunc, &cache->typioproc,
353 fcinfo->flinfo->fn_mcxt);
355 fcinfo->flinfo->fn_extra = (void *) cache;
358 return cache;
363 *----------------------------------------------------------
364 * GENERIC FUNCTIONS
365 *----------------------------------------------------------
368 /* Construct standard-form range value from two arguments */
369 Datum
370 range_constructor2(PG_FUNCTION_ARGS)
372 Datum arg1 = PG_GETARG_DATUM(0);
373 Datum arg2 = PG_GETARG_DATUM(1);
374 Oid rngtypid = get_fn_expr_rettype(fcinfo->flinfo);
375 RangeType *range;
376 TypeCacheEntry *typcache;
377 RangeBound lower;
378 RangeBound upper;
380 typcache = range_get_typcache(fcinfo, rngtypid);
382 lower.val = PG_ARGISNULL(0) ? (Datum) 0 : arg1;
383 lower.infinite = PG_ARGISNULL(0);
384 lower.inclusive = true;
385 lower.lower = true;
387 upper.val = PG_ARGISNULL(1) ? (Datum) 0 : arg2;
388 upper.infinite = PG_ARGISNULL(1);
389 upper.inclusive = false;
390 upper.lower = false;
392 range = make_range(typcache, &lower, &upper, false, NULL);
394 PG_RETURN_RANGE_P(range);
397 /* Construct general range value from three arguments */
398 Datum
399 range_constructor3(PG_FUNCTION_ARGS)
401 Datum arg1 = PG_GETARG_DATUM(0);
402 Datum arg2 = PG_GETARG_DATUM(1);
403 Oid rngtypid = get_fn_expr_rettype(fcinfo->flinfo);
404 RangeType *range;
405 TypeCacheEntry *typcache;
406 RangeBound lower;
407 RangeBound upper;
408 char flags;
410 typcache = range_get_typcache(fcinfo, rngtypid);
412 if (PG_ARGISNULL(2))
413 ereport(ERROR,
414 (errcode(ERRCODE_DATA_EXCEPTION),
415 errmsg("range constructor flags argument must not be null")));
417 flags = range_parse_flags(text_to_cstring(PG_GETARG_TEXT_PP(2)));
419 lower.val = PG_ARGISNULL(0) ? (Datum) 0 : arg1;
420 lower.infinite = PG_ARGISNULL(0);
421 lower.inclusive = (flags & RANGE_LB_INC) != 0;
422 lower.lower = true;
424 upper.val = PG_ARGISNULL(1) ? (Datum) 0 : arg2;
425 upper.infinite = PG_ARGISNULL(1);
426 upper.inclusive = (flags & RANGE_UB_INC) != 0;
427 upper.lower = false;
429 range = make_range(typcache, &lower, &upper, false, NULL);
431 PG_RETURN_RANGE_P(range);
435 /* range -> subtype functions */
437 /* extract lower bound value */
438 Datum
439 range_lower(PG_FUNCTION_ARGS)
441 RangeType *r1 = PG_GETARG_RANGE_P(0);
442 TypeCacheEntry *typcache;
443 RangeBound lower;
444 RangeBound upper;
445 bool empty;
447 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
449 range_deserialize(typcache, r1, &lower, &upper, &empty);
451 /* Return NULL if there's no finite lower bound */
452 if (empty || lower.infinite)
453 PG_RETURN_NULL();
455 PG_RETURN_DATUM(lower.val);
458 /* extract upper bound value */
459 Datum
460 range_upper(PG_FUNCTION_ARGS)
462 RangeType *r1 = PG_GETARG_RANGE_P(0);
463 TypeCacheEntry *typcache;
464 RangeBound lower;
465 RangeBound upper;
466 bool empty;
468 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
470 range_deserialize(typcache, r1, &lower, &upper, &empty);
472 /* Return NULL if there's no finite upper bound */
473 if (empty || upper.infinite)
474 PG_RETURN_NULL();
476 PG_RETURN_DATUM(upper.val);
480 /* range -> bool functions */
482 /* is range empty? */
483 Datum
484 range_empty(PG_FUNCTION_ARGS)
486 RangeType *r1 = PG_GETARG_RANGE_P(0);
487 char flags = range_get_flags(r1);
489 PG_RETURN_BOOL(flags & RANGE_EMPTY);
492 /* is lower bound inclusive? */
493 Datum
494 range_lower_inc(PG_FUNCTION_ARGS)
496 RangeType *r1 = PG_GETARG_RANGE_P(0);
497 char flags = range_get_flags(r1);
499 PG_RETURN_BOOL(flags & RANGE_LB_INC);
502 /* is upper bound inclusive? */
503 Datum
504 range_upper_inc(PG_FUNCTION_ARGS)
506 RangeType *r1 = PG_GETARG_RANGE_P(0);
507 char flags = range_get_flags(r1);
509 PG_RETURN_BOOL(flags & RANGE_UB_INC);
512 /* is lower bound infinite? */
513 Datum
514 range_lower_inf(PG_FUNCTION_ARGS)
516 RangeType *r1 = PG_GETARG_RANGE_P(0);
517 char flags = range_get_flags(r1);
519 PG_RETURN_BOOL(flags & RANGE_LB_INF);
522 /* is upper bound infinite? */
523 Datum
524 range_upper_inf(PG_FUNCTION_ARGS)
526 RangeType *r1 = PG_GETARG_RANGE_P(0);
527 char flags = range_get_flags(r1);
529 PG_RETURN_BOOL(flags & RANGE_UB_INF);
533 /* range, element -> bool functions */
535 /* contains? */
536 Datum
537 range_contains_elem(PG_FUNCTION_ARGS)
539 RangeType *r = PG_GETARG_RANGE_P(0);
540 Datum val = PG_GETARG_DATUM(1);
541 TypeCacheEntry *typcache;
543 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
545 PG_RETURN_BOOL(range_contains_elem_internal(typcache, r, val));
548 /* contained by? */
549 Datum
550 elem_contained_by_range(PG_FUNCTION_ARGS)
552 Datum val = PG_GETARG_DATUM(0);
553 RangeType *r = PG_GETARG_RANGE_P(1);
554 TypeCacheEntry *typcache;
556 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
558 PG_RETURN_BOOL(range_contains_elem_internal(typcache, r, val));
562 /* range, range -> bool functions */
564 /* equality (internal version) */
565 bool
566 range_eq_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
568 RangeBound lower1,
569 lower2;
570 RangeBound upper1,
571 upper2;
572 bool empty1,
573 empty2;
575 /* Different types should be prevented by ANYRANGE matching rules */
576 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
577 elog(ERROR, "range types do not match");
579 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
580 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
582 if (empty1 && empty2)
583 return true;
584 if (empty1 != empty2)
585 return false;
587 if (range_cmp_bounds(typcache, &lower1, &lower2) != 0)
588 return false;
590 if (range_cmp_bounds(typcache, &upper1, &upper2) != 0)
591 return false;
593 return true;
596 /* equality */
597 Datum
598 range_eq(PG_FUNCTION_ARGS)
600 RangeType *r1 = PG_GETARG_RANGE_P(0);
601 RangeType *r2 = PG_GETARG_RANGE_P(1);
602 TypeCacheEntry *typcache;
604 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
606 PG_RETURN_BOOL(range_eq_internal(typcache, r1, r2));
609 /* inequality (internal version) */
610 bool
611 range_ne_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
613 return (!range_eq_internal(typcache, r1, r2));
616 /* inequality */
617 Datum
618 range_ne(PG_FUNCTION_ARGS)
620 RangeType *r1 = PG_GETARG_RANGE_P(0);
621 RangeType *r2 = PG_GETARG_RANGE_P(1);
622 TypeCacheEntry *typcache;
624 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
626 PG_RETURN_BOOL(range_ne_internal(typcache, r1, r2));
629 /* contains? */
630 Datum
631 range_contains(PG_FUNCTION_ARGS)
633 RangeType *r1 = PG_GETARG_RANGE_P(0);
634 RangeType *r2 = PG_GETARG_RANGE_P(1);
635 TypeCacheEntry *typcache;
637 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
639 PG_RETURN_BOOL(range_contains_internal(typcache, r1, r2));
642 /* contained by? */
643 Datum
644 range_contained_by(PG_FUNCTION_ARGS)
646 RangeType *r1 = PG_GETARG_RANGE_P(0);
647 RangeType *r2 = PG_GETARG_RANGE_P(1);
648 TypeCacheEntry *typcache;
650 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
652 PG_RETURN_BOOL(range_contained_by_internal(typcache, r1, r2));
655 /* strictly left of? (internal version) */
656 bool
657 range_before_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
659 RangeBound lower1,
660 lower2;
661 RangeBound upper1,
662 upper2;
663 bool empty1,
664 empty2;
666 /* Different types should be prevented by ANYRANGE matching rules */
667 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
668 elog(ERROR, "range types do not match");
670 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
671 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
673 /* An empty range is neither before nor after any other range */
674 if (empty1 || empty2)
675 return false;
677 return (range_cmp_bounds(typcache, &upper1, &lower2) < 0);
680 /* strictly left of? */
681 Datum
682 range_before(PG_FUNCTION_ARGS)
684 RangeType *r1 = PG_GETARG_RANGE_P(0);
685 RangeType *r2 = PG_GETARG_RANGE_P(1);
686 TypeCacheEntry *typcache;
688 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
690 PG_RETURN_BOOL(range_before_internal(typcache, r1, r2));
693 /* strictly right of? (internal version) */
694 bool
695 range_after_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
697 RangeBound lower1,
698 lower2;
699 RangeBound upper1,
700 upper2;
701 bool empty1,
702 empty2;
704 /* Different types should be prevented by ANYRANGE matching rules */
705 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
706 elog(ERROR, "range types do not match");
708 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
709 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
711 /* An empty range is neither before nor after any other range */
712 if (empty1 || empty2)
713 return false;
715 return (range_cmp_bounds(typcache, &lower1, &upper2) > 0);
718 /* strictly right of? */
719 Datum
720 range_after(PG_FUNCTION_ARGS)
722 RangeType *r1 = PG_GETARG_RANGE_P(0);
723 RangeType *r2 = PG_GETARG_RANGE_P(1);
724 TypeCacheEntry *typcache;
726 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
728 PG_RETURN_BOOL(range_after_internal(typcache, r1, r2));
732 * Check if two bounds A and B are "adjacent", where A is an upper bound and B
733 * is a lower bound. For the bounds to be adjacent, each subtype value must
734 * satisfy strictly one of the bounds: there are no values which satisfy both
735 * bounds (i.e. less than A and greater than B); and there are no values which
736 * satisfy neither bound (i.e. greater than A and less than B).
738 * For discrete ranges, we rely on the canonicalization function to see if A..B
739 * normalizes to empty. (If there is no canonicalization function, it's
740 * impossible for such a range to normalize to empty, so we needn't bother to
741 * try.)
743 * If A == B, the ranges are adjacent only if the bounds have different
744 * inclusive flags (i.e., exactly one of the ranges includes the common
745 * boundary point).
747 * And if A > B then the ranges are not adjacent in this order.
749 bool
750 bounds_adjacent(TypeCacheEntry *typcache, RangeBound boundA, RangeBound boundB)
752 int cmp;
754 Assert(!boundA.lower && boundB.lower);
756 cmp = range_cmp_bound_values(typcache, &boundA, &boundB);
757 if (cmp < 0)
759 RangeType *r;
762 * Bounds do not overlap; see if there are points in between.
765 /* in a continuous subtype, there are assumed to be points between */
766 if (!OidIsValid(typcache->rng_canonical_finfo.fn_oid))
767 return false;
770 * The bounds are of a discrete range type; so make a range A..B and
771 * see if it's empty.
774 /* flip the inclusion flags */
775 boundA.inclusive = !boundA.inclusive;
776 boundB.inclusive = !boundB.inclusive;
777 /* change upper/lower labels to avoid Assert failures */
778 boundA.lower = true;
779 boundB.lower = false;
780 r = make_range(typcache, &boundA, &boundB, false, NULL);
781 return RangeIsEmpty(r);
783 else if (cmp == 0)
784 return boundA.inclusive != boundB.inclusive;
785 else
786 return false; /* bounds overlap */
789 /* adjacent to (but not overlapping)? (internal version) */
790 bool
791 range_adjacent_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
793 RangeBound lower1,
794 lower2;
795 RangeBound upper1,
796 upper2;
797 bool empty1,
798 empty2;
800 /* Different types should be prevented by ANYRANGE matching rules */
801 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
802 elog(ERROR, "range types do not match");
804 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
805 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
807 /* An empty range is not adjacent to any other range */
808 if (empty1 || empty2)
809 return false;
812 * Given two ranges A..B and C..D, the ranges are adjacent if and only if
813 * B is adjacent to C, or D is adjacent to A.
815 return (bounds_adjacent(typcache, upper1, lower2) ||
816 bounds_adjacent(typcache, upper2, lower1));
819 /* adjacent to (but not overlapping)? */
820 Datum
821 range_adjacent(PG_FUNCTION_ARGS)
823 RangeType *r1 = PG_GETARG_RANGE_P(0);
824 RangeType *r2 = PG_GETARG_RANGE_P(1);
825 TypeCacheEntry *typcache;
827 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
829 PG_RETURN_BOOL(range_adjacent_internal(typcache, r1, r2));
832 /* overlaps? (internal version) */
833 bool
834 range_overlaps_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
836 RangeBound lower1,
837 lower2;
838 RangeBound upper1,
839 upper2;
840 bool empty1,
841 empty2;
843 /* Different types should be prevented by ANYRANGE matching rules */
844 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
845 elog(ERROR, "range types do not match");
847 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
848 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
850 /* An empty range does not overlap any other range */
851 if (empty1 || empty2)
852 return false;
854 if (range_cmp_bounds(typcache, &lower1, &lower2) >= 0 &&
855 range_cmp_bounds(typcache, &lower1, &upper2) <= 0)
856 return true;
858 if (range_cmp_bounds(typcache, &lower2, &lower1) >= 0 &&
859 range_cmp_bounds(typcache, &lower2, &upper1) <= 0)
860 return true;
862 return false;
865 /* overlaps? */
866 Datum
867 range_overlaps(PG_FUNCTION_ARGS)
869 RangeType *r1 = PG_GETARG_RANGE_P(0);
870 RangeType *r2 = PG_GETARG_RANGE_P(1);
871 TypeCacheEntry *typcache;
873 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
875 PG_RETURN_BOOL(range_overlaps_internal(typcache, r1, r2));
878 /* does not extend to right of? (internal version) */
879 bool
880 range_overleft_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
882 RangeBound lower1,
883 lower2;
884 RangeBound upper1,
885 upper2;
886 bool empty1,
887 empty2;
889 /* Different types should be prevented by ANYRANGE matching rules */
890 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
891 elog(ERROR, "range types do not match");
893 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
894 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
896 /* An empty range is neither before nor after any other range */
897 if (empty1 || empty2)
898 return false;
900 if (range_cmp_bounds(typcache, &upper1, &upper2) <= 0)
901 return true;
903 return false;
906 /* does not extend to right of? */
907 Datum
908 range_overleft(PG_FUNCTION_ARGS)
910 RangeType *r1 = PG_GETARG_RANGE_P(0);
911 RangeType *r2 = PG_GETARG_RANGE_P(1);
912 TypeCacheEntry *typcache;
914 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
916 PG_RETURN_BOOL(range_overleft_internal(typcache, r1, r2));
919 /* does not extend to left of? (internal version) */
920 bool
921 range_overright_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
923 RangeBound lower1,
924 lower2;
925 RangeBound upper1,
926 upper2;
927 bool empty1,
928 empty2;
930 /* Different types should be prevented by ANYRANGE matching rules */
931 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
932 elog(ERROR, "range types do not match");
934 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
935 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
937 /* An empty range is neither before nor after any other range */
938 if (empty1 || empty2)
939 return false;
941 if (range_cmp_bounds(typcache, &lower1, &lower2) >= 0)
942 return true;
944 return false;
947 /* does not extend to left of? */
948 Datum
949 range_overright(PG_FUNCTION_ARGS)
951 RangeType *r1 = PG_GETARG_RANGE_P(0);
952 RangeType *r2 = PG_GETARG_RANGE_P(1);
953 TypeCacheEntry *typcache;
955 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
957 PG_RETURN_BOOL(range_overright_internal(typcache, r1, r2));
961 /* range, range -> range functions */
963 /* set difference */
964 Datum
965 range_minus(PG_FUNCTION_ARGS)
967 RangeType *r1 = PG_GETARG_RANGE_P(0);
968 RangeType *r2 = PG_GETARG_RANGE_P(1);
969 RangeType *ret;
970 TypeCacheEntry *typcache;
972 /* Different types should be prevented by ANYRANGE matching rules */
973 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
974 elog(ERROR, "range types do not match");
976 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
978 ret = range_minus_internal(typcache, r1, r2);
979 if (ret)
980 PG_RETURN_RANGE_P(ret);
981 else
982 PG_RETURN_NULL();
985 RangeType *
986 range_minus_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
988 RangeBound lower1,
989 lower2;
990 RangeBound upper1,
991 upper2;
992 bool empty1,
993 empty2;
994 int cmp_l1l2,
995 cmp_l1u2,
996 cmp_u1l2,
997 cmp_u1u2;
999 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
1000 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
1002 /* if either is empty, r1 is the correct answer */
1003 if (empty1 || empty2)
1004 return r1;
1006 cmp_l1l2 = range_cmp_bounds(typcache, &lower1, &lower2);
1007 cmp_l1u2 = range_cmp_bounds(typcache, &lower1, &upper2);
1008 cmp_u1l2 = range_cmp_bounds(typcache, &upper1, &lower2);
1009 cmp_u1u2 = range_cmp_bounds(typcache, &upper1, &upper2);
1011 if (cmp_l1l2 < 0 && cmp_u1u2 > 0)
1012 ereport(ERROR,
1013 (errcode(ERRCODE_DATA_EXCEPTION),
1014 errmsg("result of range difference would not be contiguous")));
1016 if (cmp_l1u2 > 0 || cmp_u1l2 < 0)
1017 return r1;
1019 if (cmp_l1l2 >= 0 && cmp_u1u2 <= 0)
1020 return make_empty_range(typcache);
1022 if (cmp_l1l2 <= 0 && cmp_u1l2 >= 0 && cmp_u1u2 <= 0)
1024 lower2.inclusive = !lower2.inclusive;
1025 lower2.lower = false; /* it will become the upper bound */
1026 return make_range(typcache, &lower1, &lower2, false, NULL);
1029 if (cmp_l1l2 >= 0 && cmp_u1u2 >= 0 && cmp_l1u2 <= 0)
1031 upper2.inclusive = !upper2.inclusive;
1032 upper2.lower = true; /* it will become the lower bound */
1033 return make_range(typcache, &upper2, &upper1, false, NULL);
1036 elog(ERROR, "unexpected case in range_minus");
1037 return NULL;
1041 * Set union. If strict is true, it is an error that the two input ranges
1042 * are not adjacent or overlapping.
1044 RangeType *
1045 range_union_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2,
1046 bool strict)
1048 RangeBound lower1,
1049 lower2;
1050 RangeBound upper1,
1051 upper2;
1052 bool empty1,
1053 empty2;
1054 RangeBound *result_lower;
1055 RangeBound *result_upper;
1057 /* Different types should be prevented by ANYRANGE matching rules */
1058 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
1059 elog(ERROR, "range types do not match");
1061 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
1062 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
1064 /* if either is empty, the other is the correct answer */
1065 if (empty1)
1066 return r2;
1067 if (empty2)
1068 return r1;
1070 if (strict &&
1071 !DatumGetBool(range_overlaps_internal(typcache, r1, r2)) &&
1072 !DatumGetBool(range_adjacent_internal(typcache, r1, r2)))
1073 ereport(ERROR,
1074 (errcode(ERRCODE_DATA_EXCEPTION),
1075 errmsg("result of range union would not be contiguous")));
1077 if (range_cmp_bounds(typcache, &lower1, &lower2) < 0)
1078 result_lower = &lower1;
1079 else
1080 result_lower = &lower2;
1082 if (range_cmp_bounds(typcache, &upper1, &upper2) > 0)
1083 result_upper = &upper1;
1084 else
1085 result_upper = &upper2;
1087 return make_range(typcache, result_lower, result_upper, false, NULL);
1090 Datum
1091 range_union(PG_FUNCTION_ARGS)
1093 RangeType *r1 = PG_GETARG_RANGE_P(0);
1094 RangeType *r2 = PG_GETARG_RANGE_P(1);
1095 TypeCacheEntry *typcache;
1097 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
1099 PG_RETURN_RANGE_P(range_union_internal(typcache, r1, r2, true));
1103 * range merge: like set union, except also allow and account for non-adjacent
1104 * input ranges.
1106 Datum
1107 range_merge(PG_FUNCTION_ARGS)
1109 RangeType *r1 = PG_GETARG_RANGE_P(0);
1110 RangeType *r2 = PG_GETARG_RANGE_P(1);
1111 TypeCacheEntry *typcache;
1113 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
1115 PG_RETURN_RANGE_P(range_union_internal(typcache, r1, r2, false));
1118 /* set intersection */
1119 Datum
1120 range_intersect(PG_FUNCTION_ARGS)
1122 RangeType *r1 = PG_GETARG_RANGE_P(0);
1123 RangeType *r2 = PG_GETARG_RANGE_P(1);
1124 TypeCacheEntry *typcache;
1126 /* Different types should be prevented by ANYRANGE matching rules */
1127 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
1128 elog(ERROR, "range types do not match");
1130 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
1132 PG_RETURN_RANGE_P(range_intersect_internal(typcache, r1, r2));
1135 RangeType *
1136 range_intersect_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
1138 RangeBound lower1,
1139 lower2;
1140 RangeBound upper1,
1141 upper2;
1142 bool empty1,
1143 empty2;
1144 RangeBound *result_lower;
1145 RangeBound *result_upper;
1147 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
1148 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
1150 if (empty1 || empty2 || !range_overlaps_internal(typcache, r1, r2))
1151 return make_empty_range(typcache);
1153 if (range_cmp_bounds(typcache, &lower1, &lower2) >= 0)
1154 result_lower = &lower1;
1155 else
1156 result_lower = &lower2;
1158 if (range_cmp_bounds(typcache, &upper1, &upper2) <= 0)
1159 result_upper = &upper1;
1160 else
1161 result_upper = &upper2;
1163 return make_range(typcache, result_lower, result_upper, false, NULL);
1166 /* range, range -> range, range functions */
1169 * range_split_internal - if r2 intersects the middle of r1, leaving non-empty
1170 * ranges on both sides, then return true and set output1 and output2 to the
1171 * results of r1 - r2 (in order). Otherwise return false and don't set output1
1172 * or output2. Neither input range should be empty.
1174 bool
1175 range_split_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2,
1176 RangeType **output1, RangeType **output2)
1178 RangeBound lower1,
1179 lower2;
1180 RangeBound upper1,
1181 upper2;
1182 bool empty1,
1183 empty2;
1185 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
1186 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
1188 if (range_cmp_bounds(typcache, &lower1, &lower2) < 0 &&
1189 range_cmp_bounds(typcache, &upper1, &upper2) > 0)
1192 * Need to invert inclusive/exclusive for the lower2 and upper2
1193 * points. They can't be infinite though. We're allowed to overwrite
1194 * these RangeBounds since they only exist locally.
1196 lower2.inclusive = !lower2.inclusive;
1197 lower2.lower = false;
1198 upper2.inclusive = !upper2.inclusive;
1199 upper2.lower = true;
1201 *output1 = make_range(typcache, &lower1, &lower2, false, NULL);
1202 *output2 = make_range(typcache, &upper2, &upper1, false, NULL);
1203 return true;
1206 return false;
1209 /* range -> range aggregate functions */
1211 Datum
1212 range_intersect_agg_transfn(PG_FUNCTION_ARGS)
1214 MemoryContext aggContext;
1215 Oid rngtypoid;
1216 TypeCacheEntry *typcache;
1217 RangeType *result;
1218 RangeType *current;
1220 if (!AggCheckCallContext(fcinfo, &aggContext))
1221 elog(ERROR, "range_intersect_agg_transfn called in non-aggregate context");
1223 rngtypoid = get_fn_expr_argtype(fcinfo->flinfo, 1);
1224 if (!type_is_range(rngtypoid))
1225 elog(ERROR, "range_intersect_agg must be called with a range");
1227 typcache = range_get_typcache(fcinfo, rngtypoid);
1229 /* strictness ensures these are non-null */
1230 result = PG_GETARG_RANGE_P(0);
1231 current = PG_GETARG_RANGE_P(1);
1233 result = range_intersect_internal(typcache, result, current);
1234 PG_RETURN_RANGE_P(result);
1238 /* Btree support */
1240 /* btree comparator */
1241 Datum
1242 range_cmp(PG_FUNCTION_ARGS)
1244 RangeType *r1 = PG_GETARG_RANGE_P(0);
1245 RangeType *r2 = PG_GETARG_RANGE_P(1);
1246 TypeCacheEntry *typcache;
1247 RangeBound lower1,
1248 lower2;
1249 RangeBound upper1,
1250 upper2;
1251 bool empty1,
1252 empty2;
1253 int cmp;
1255 check_stack_depth(); /* recurses when subtype is a range type */
1257 /* Different types should be prevented by ANYRANGE matching rules */
1258 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
1259 elog(ERROR, "range types do not match");
1261 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
1263 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
1264 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
1266 /* For b-tree use, empty ranges sort before all else */
1267 if (empty1 && empty2)
1268 cmp = 0;
1269 else if (empty1)
1270 cmp = -1;
1271 else if (empty2)
1272 cmp = 1;
1273 else
1275 cmp = range_cmp_bounds(typcache, &lower1, &lower2);
1276 if (cmp == 0)
1277 cmp = range_cmp_bounds(typcache, &upper1, &upper2);
1280 PG_FREE_IF_COPY(r1, 0);
1281 PG_FREE_IF_COPY(r2, 1);
1283 PG_RETURN_INT32(cmp);
1286 /* inequality operators using the range_cmp function */
1287 Datum
1288 range_lt(PG_FUNCTION_ARGS)
1290 int cmp = range_cmp(fcinfo);
1292 PG_RETURN_BOOL(cmp < 0);
1295 Datum
1296 range_le(PG_FUNCTION_ARGS)
1298 int cmp = range_cmp(fcinfo);
1300 PG_RETURN_BOOL(cmp <= 0);
1303 Datum
1304 range_ge(PG_FUNCTION_ARGS)
1306 int cmp = range_cmp(fcinfo);
1308 PG_RETURN_BOOL(cmp >= 0);
1311 Datum
1312 range_gt(PG_FUNCTION_ARGS)
1314 int cmp = range_cmp(fcinfo);
1316 PG_RETURN_BOOL(cmp > 0);
1319 /* Hash support */
1321 /* hash a range value */
1322 Datum
1323 hash_range(PG_FUNCTION_ARGS)
1325 RangeType *r = PG_GETARG_RANGE_P(0);
1326 uint32 result;
1327 TypeCacheEntry *typcache;
1328 TypeCacheEntry *scache;
1329 RangeBound lower;
1330 RangeBound upper;
1331 bool empty;
1332 char flags;
1333 uint32 lower_hash;
1334 uint32 upper_hash;
1336 check_stack_depth(); /* recurses when subtype is a range type */
1338 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1340 /* deserialize */
1341 range_deserialize(typcache, r, &lower, &upper, &empty);
1342 flags = range_get_flags(r);
1345 * Look up the element type's hash function, if not done already.
1347 scache = typcache->rngelemtype;
1348 if (!OidIsValid(scache->hash_proc_finfo.fn_oid))
1350 scache = lookup_type_cache(scache->type_id, TYPECACHE_HASH_PROC_FINFO);
1351 if (!OidIsValid(scache->hash_proc_finfo.fn_oid))
1352 ereport(ERROR,
1353 (errcode(ERRCODE_UNDEFINED_FUNCTION),
1354 errmsg("could not identify a hash function for type %s",
1355 format_type_be(scache->type_id))));
1359 * Apply the hash function to each bound.
1361 if (RANGE_HAS_LBOUND(flags))
1362 lower_hash = DatumGetUInt32(FunctionCall1Coll(&scache->hash_proc_finfo,
1363 typcache->rng_collation,
1364 lower.val));
1365 else
1366 lower_hash = 0;
1368 if (RANGE_HAS_UBOUND(flags))
1369 upper_hash = DatumGetUInt32(FunctionCall1Coll(&scache->hash_proc_finfo,
1370 typcache->rng_collation,
1371 upper.val));
1372 else
1373 upper_hash = 0;
1375 /* Merge hashes of flags and bounds */
1376 result = hash_uint32((uint32) flags);
1377 result ^= lower_hash;
1378 result = pg_rotate_left32(result, 1);
1379 result ^= upper_hash;
1381 PG_RETURN_INT32(result);
1385 * Returns 64-bit value by hashing a value to a 64-bit value, with a seed.
1386 * Otherwise, similar to hash_range.
1388 Datum
1389 hash_range_extended(PG_FUNCTION_ARGS)
1391 RangeType *r = PG_GETARG_RANGE_P(0);
1392 Datum seed = PG_GETARG_DATUM(1);
1393 uint64 result;
1394 TypeCacheEntry *typcache;
1395 TypeCacheEntry *scache;
1396 RangeBound lower;
1397 RangeBound upper;
1398 bool empty;
1399 char flags;
1400 uint64 lower_hash;
1401 uint64 upper_hash;
1403 check_stack_depth();
1405 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1407 range_deserialize(typcache, r, &lower, &upper, &empty);
1408 flags = range_get_flags(r);
1410 scache = typcache->rngelemtype;
1411 if (!OidIsValid(scache->hash_extended_proc_finfo.fn_oid))
1413 scache = lookup_type_cache(scache->type_id,
1414 TYPECACHE_HASH_EXTENDED_PROC_FINFO);
1415 if (!OidIsValid(scache->hash_extended_proc_finfo.fn_oid))
1416 ereport(ERROR,
1417 (errcode(ERRCODE_UNDEFINED_FUNCTION),
1418 errmsg("could not identify a hash function for type %s",
1419 format_type_be(scache->type_id))));
1422 if (RANGE_HAS_LBOUND(flags))
1423 lower_hash = DatumGetUInt64(FunctionCall2Coll(&scache->hash_extended_proc_finfo,
1424 typcache->rng_collation,
1425 lower.val,
1426 seed));
1427 else
1428 lower_hash = 0;
1430 if (RANGE_HAS_UBOUND(flags))
1431 upper_hash = DatumGetUInt64(FunctionCall2Coll(&scache->hash_extended_proc_finfo,
1432 typcache->rng_collation,
1433 upper.val,
1434 seed));
1435 else
1436 upper_hash = 0;
1438 /* Merge hashes of flags and bounds */
1439 result = DatumGetUInt64(hash_uint32_extended((uint32) flags,
1440 DatumGetInt64(seed)));
1441 result ^= lower_hash;
1442 result = ROTATE_HIGH_AND_LOW_32BITS(result);
1443 result ^= upper_hash;
1445 PG_RETURN_UINT64(result);
1449 *----------------------------------------------------------
1450 * CANONICAL FUNCTIONS
1452 * Functions for specific built-in range types.
1453 *----------------------------------------------------------
1456 Datum
1457 int4range_canonical(PG_FUNCTION_ARGS)
1459 RangeType *r = PG_GETARG_RANGE_P(0);
1460 Node *escontext = fcinfo->context;
1461 TypeCacheEntry *typcache;
1462 RangeBound lower;
1463 RangeBound upper;
1464 bool empty;
1466 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1468 range_deserialize(typcache, r, &lower, &upper, &empty);
1470 if (empty)
1471 PG_RETURN_RANGE_P(r);
1473 if (!lower.infinite && !lower.inclusive)
1475 int32 bnd = DatumGetInt32(lower.val);
1477 /* Handle possible overflow manually */
1478 if (unlikely(bnd == PG_INT32_MAX))
1479 ereturn(escontext, (Datum) 0,
1480 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1481 errmsg("integer out of range")));
1482 lower.val = Int32GetDatum(bnd + 1);
1483 lower.inclusive = true;
1486 if (!upper.infinite && upper.inclusive)
1488 int32 bnd = DatumGetInt32(upper.val);
1490 /* Handle possible overflow manually */
1491 if (unlikely(bnd == PG_INT32_MAX))
1492 ereturn(escontext, (Datum) 0,
1493 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1494 errmsg("integer out of range")));
1495 upper.val = Int32GetDatum(bnd + 1);
1496 upper.inclusive = false;
1499 PG_RETURN_RANGE_P(range_serialize(typcache, &lower, &upper,
1500 false, escontext));
1503 Datum
1504 int8range_canonical(PG_FUNCTION_ARGS)
1506 RangeType *r = PG_GETARG_RANGE_P(0);
1507 Node *escontext = fcinfo->context;
1508 TypeCacheEntry *typcache;
1509 RangeBound lower;
1510 RangeBound upper;
1511 bool empty;
1513 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1515 range_deserialize(typcache, r, &lower, &upper, &empty);
1517 if (empty)
1518 PG_RETURN_RANGE_P(r);
1520 if (!lower.infinite && !lower.inclusive)
1522 int64 bnd = DatumGetInt64(lower.val);
1524 /* Handle possible overflow manually */
1525 if (unlikely(bnd == PG_INT64_MAX))
1526 ereturn(escontext, (Datum) 0,
1527 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1528 errmsg("bigint out of range")));
1529 lower.val = Int64GetDatum(bnd + 1);
1530 lower.inclusive = true;
1533 if (!upper.infinite && upper.inclusive)
1535 int64 bnd = DatumGetInt64(upper.val);
1537 /* Handle possible overflow manually */
1538 if (unlikely(bnd == PG_INT64_MAX))
1539 ereturn(escontext, (Datum) 0,
1540 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1541 errmsg("bigint out of range")));
1542 upper.val = Int64GetDatum(bnd + 1);
1543 upper.inclusive = false;
1546 PG_RETURN_RANGE_P(range_serialize(typcache, &lower, &upper,
1547 false, escontext));
1550 Datum
1551 daterange_canonical(PG_FUNCTION_ARGS)
1553 RangeType *r = PG_GETARG_RANGE_P(0);
1554 Node *escontext = fcinfo->context;
1555 TypeCacheEntry *typcache;
1556 RangeBound lower;
1557 RangeBound upper;
1558 bool empty;
1560 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1562 range_deserialize(typcache, r, &lower, &upper, &empty);
1564 if (empty)
1565 PG_RETURN_RANGE_P(r);
1567 if (!lower.infinite && !DATE_NOT_FINITE(DatumGetDateADT(lower.val)) &&
1568 !lower.inclusive)
1570 DateADT bnd = DatumGetDateADT(lower.val);
1572 /* Check for overflow -- note we already eliminated PG_INT32_MAX */
1573 bnd++;
1574 if (unlikely(!IS_VALID_DATE(bnd)))
1575 ereturn(escontext, (Datum) 0,
1576 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1577 errmsg("date out of range")));
1578 lower.val = DateADTGetDatum(bnd);
1579 lower.inclusive = true;
1582 if (!upper.infinite && !DATE_NOT_FINITE(DatumGetDateADT(upper.val)) &&
1583 upper.inclusive)
1585 DateADT bnd = DatumGetDateADT(upper.val);
1587 /* Check for overflow -- note we already eliminated PG_INT32_MAX */
1588 bnd++;
1589 if (unlikely(!IS_VALID_DATE(bnd)))
1590 ereturn(escontext, (Datum) 0,
1591 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1592 errmsg("date out of range")));
1593 upper.val = DateADTGetDatum(bnd);
1594 upper.inclusive = false;
1597 PG_RETURN_RANGE_P(range_serialize(typcache, &lower, &upper,
1598 false, escontext));
1602 *----------------------------------------------------------
1603 * SUBTYPE_DIFF FUNCTIONS
1605 * Functions for specific built-in range types.
1607 * Note that subtype_diff does return the difference, not the absolute value
1608 * of the difference, and it must take care to avoid overflow.
1609 * (numrange_subdiff is at some risk there ...)
1610 *----------------------------------------------------------
1613 Datum
1614 int4range_subdiff(PG_FUNCTION_ARGS)
1616 int32 v1 = PG_GETARG_INT32(0);
1617 int32 v2 = PG_GETARG_INT32(1);
1619 PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
1622 Datum
1623 int8range_subdiff(PG_FUNCTION_ARGS)
1625 int64 v1 = PG_GETARG_INT64(0);
1626 int64 v2 = PG_GETARG_INT64(1);
1628 PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
1631 Datum
1632 numrange_subdiff(PG_FUNCTION_ARGS)
1634 Datum v1 = PG_GETARG_DATUM(0);
1635 Datum v2 = PG_GETARG_DATUM(1);
1636 Datum numresult;
1637 float8 floatresult;
1639 numresult = DirectFunctionCall2(numeric_sub, v1, v2);
1641 floatresult = DatumGetFloat8(DirectFunctionCall1(numeric_float8,
1642 numresult));
1644 PG_RETURN_FLOAT8(floatresult);
1647 Datum
1648 daterange_subdiff(PG_FUNCTION_ARGS)
1650 int32 v1 = PG_GETARG_INT32(0);
1651 int32 v2 = PG_GETARG_INT32(1);
1653 PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
1656 Datum
1657 tsrange_subdiff(PG_FUNCTION_ARGS)
1659 Timestamp v1 = PG_GETARG_TIMESTAMP(0);
1660 Timestamp v2 = PG_GETARG_TIMESTAMP(1);
1661 float8 result;
1663 result = ((float8) v1 - (float8) v2) / USECS_PER_SEC;
1664 PG_RETURN_FLOAT8(result);
1667 Datum
1668 tstzrange_subdiff(PG_FUNCTION_ARGS)
1670 Timestamp v1 = PG_GETARG_TIMESTAMP(0);
1671 Timestamp v2 = PG_GETARG_TIMESTAMP(1);
1672 float8 result;
1674 result = ((float8) v1 - (float8) v2) / USECS_PER_SEC;
1675 PG_RETURN_FLOAT8(result);
1679 *----------------------------------------------------------
1680 * SUPPORT FUNCTIONS
1682 * These functions aren't in pg_proc, but are useful for
1683 * defining new generic range functions in C.
1684 *----------------------------------------------------------
1688 * range_get_typcache: get cached information about a range type
1690 * This is for use by range-related functions that follow the convention
1691 * of using the fn_extra field as a pointer to the type cache entry for
1692 * the range type. Functions that need to cache more information than
1693 * that must fend for themselves.
1695 TypeCacheEntry *
1696 range_get_typcache(FunctionCallInfo fcinfo, Oid rngtypid)
1698 TypeCacheEntry *typcache = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
1700 if (typcache == NULL ||
1701 typcache->type_id != rngtypid)
1703 typcache = lookup_type_cache(rngtypid, TYPECACHE_RANGE_INFO);
1704 if (typcache->rngelemtype == NULL)
1705 elog(ERROR, "type %u is not a range type", rngtypid);
1706 fcinfo->flinfo->fn_extra = (void *) typcache;
1709 return typcache;
1713 * range_serialize: construct a range value from bounds and empty-flag
1715 * This does not force canonicalization of the range value. In most cases,
1716 * external callers should only be canonicalization functions. Note that
1717 * we perform some datatype-independent canonicalization checks anyway.
1719 RangeType *
1720 range_serialize(TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper,
1721 bool empty, struct Node *escontext)
1723 RangeType *range;
1724 int cmp;
1725 Size msize;
1726 Pointer ptr;
1727 int16 typlen;
1728 bool typbyval;
1729 char typalign;
1730 char typstorage;
1731 char flags = 0;
1734 * Verify range is not invalid on its face, and construct flags value,
1735 * preventing any non-canonical combinations such as infinite+inclusive.
1737 Assert(lower->lower);
1738 Assert(!upper->lower);
1740 if (empty)
1741 flags |= RANGE_EMPTY;
1742 else
1744 cmp = range_cmp_bound_values(typcache, lower, upper);
1746 /* error check: if lower bound value is above upper, it's wrong */
1747 if (cmp > 0)
1748 ereturn(escontext, NULL,
1749 (errcode(ERRCODE_DATA_EXCEPTION),
1750 errmsg("range lower bound must be less than or equal to range upper bound")));
1752 /* if bounds are equal, and not both inclusive, range is empty */
1753 if (cmp == 0 && !(lower->inclusive && upper->inclusive))
1754 flags |= RANGE_EMPTY;
1755 else
1757 /* infinite boundaries are never inclusive */
1758 if (lower->infinite)
1759 flags |= RANGE_LB_INF;
1760 else if (lower->inclusive)
1761 flags |= RANGE_LB_INC;
1762 if (upper->infinite)
1763 flags |= RANGE_UB_INF;
1764 else if (upper->inclusive)
1765 flags |= RANGE_UB_INC;
1769 /* Fetch information about range's element type */
1770 typlen = typcache->rngelemtype->typlen;
1771 typbyval = typcache->rngelemtype->typbyval;
1772 typalign = typcache->rngelemtype->typalign;
1773 typstorage = typcache->rngelemtype->typstorage;
1775 /* Count space for varlena header and range type's OID */
1776 msize = sizeof(RangeType);
1777 Assert(msize == MAXALIGN(msize));
1779 /* Count space for bounds */
1780 if (RANGE_HAS_LBOUND(flags))
1783 * Make sure item to be inserted is not toasted. It is essential that
1784 * we not insert an out-of-line toast value pointer into a range
1785 * object, for the same reasons that arrays and records can't contain
1786 * them. It would work to store a compressed-in-line value, but we
1787 * prefer to decompress and then let compression be applied to the
1788 * whole range object if necessary. But, unlike arrays, we do allow
1789 * short-header varlena objects to stay as-is.
1791 if (typlen == -1)
1792 lower->val = PointerGetDatum(PG_DETOAST_DATUM_PACKED(lower->val));
1794 msize = datum_compute_size(msize, lower->val, typbyval, typalign,
1795 typlen, typstorage);
1798 if (RANGE_HAS_UBOUND(flags))
1800 /* Make sure item to be inserted is not toasted */
1801 if (typlen == -1)
1802 upper->val = PointerGetDatum(PG_DETOAST_DATUM_PACKED(upper->val));
1804 msize = datum_compute_size(msize, upper->val, typbyval, typalign,
1805 typlen, typstorage);
1808 /* Add space for flag byte */
1809 msize += sizeof(char);
1811 /* Note: zero-fill is required here, just as in heap tuples */
1812 range = (RangeType *) palloc0(msize);
1813 SET_VARSIZE(range, msize);
1815 /* Now fill in the datum */
1816 range->rangetypid = typcache->type_id;
1818 ptr = (char *) (range + 1);
1820 if (RANGE_HAS_LBOUND(flags))
1822 Assert(lower->lower);
1823 ptr = datum_write(ptr, lower->val, typbyval, typalign, typlen,
1824 typstorage);
1827 if (RANGE_HAS_UBOUND(flags))
1829 Assert(!upper->lower);
1830 ptr = datum_write(ptr, upper->val, typbyval, typalign, typlen,
1831 typstorage);
1834 *((char *) ptr) = flags;
1836 return range;
1840 * range_deserialize: deconstruct a range value
1842 * NB: the given range object must be fully detoasted; it cannot have a
1843 * short varlena header.
1845 * Note that if the element type is pass-by-reference, the datums in the
1846 * RangeBound structs will be pointers into the given range object.
1848 void
1849 range_deserialize(TypeCacheEntry *typcache, const RangeType *range,
1850 RangeBound *lower, RangeBound *upper, bool *empty)
1852 char flags;
1853 int16 typlen;
1854 bool typbyval;
1855 char typalign;
1856 Pointer ptr;
1857 Datum lbound;
1858 Datum ubound;
1860 /* assert caller passed the right typcache entry */
1861 Assert(RangeTypeGetOid(range) == typcache->type_id);
1863 /* fetch the flag byte from datum's last byte */
1864 flags = *((const char *) range + VARSIZE(range) - 1);
1866 /* fetch information about range's element type */
1867 typlen = typcache->rngelemtype->typlen;
1868 typbyval = typcache->rngelemtype->typbyval;
1869 typalign = typcache->rngelemtype->typalign;
1871 /* initialize data pointer just after the range OID */
1872 ptr = (Pointer) (range + 1);
1874 /* fetch lower bound, if any */
1875 if (RANGE_HAS_LBOUND(flags))
1877 /* att_align_pointer cannot be necessary here */
1878 lbound = fetch_att(ptr, typbyval, typlen);
1879 ptr = (Pointer) att_addlength_pointer(ptr, typlen, ptr);
1881 else
1882 lbound = (Datum) 0;
1884 /* fetch upper bound, if any */
1885 if (RANGE_HAS_UBOUND(flags))
1887 ptr = (Pointer) att_align_pointer(ptr, typalign, typlen, ptr);
1888 ubound = fetch_att(ptr, typbyval, typlen);
1889 /* no need for att_addlength_pointer */
1891 else
1892 ubound = (Datum) 0;
1894 /* emit results */
1896 *empty = (flags & RANGE_EMPTY) != 0;
1898 lower->val = lbound;
1899 lower->infinite = (flags & RANGE_LB_INF) != 0;
1900 lower->inclusive = (flags & RANGE_LB_INC) != 0;
1901 lower->lower = true;
1903 upper->val = ubound;
1904 upper->infinite = (flags & RANGE_UB_INF) != 0;
1905 upper->inclusive = (flags & RANGE_UB_INC) != 0;
1906 upper->lower = false;
1910 * range_get_flags: just get the flags from a RangeType value.
1912 * This is frequently useful in places that only need the flags and not
1913 * the full results of range_deserialize.
1915 char
1916 range_get_flags(const RangeType *range)
1918 /* fetch the flag byte from datum's last byte */
1919 return *((char *) range + VARSIZE(range) - 1);
1923 * range_set_contain_empty: set the RANGE_CONTAIN_EMPTY bit in the value.
1925 * This is only needed in GiST operations, so we don't include a provision
1926 * for setting it in range_serialize; rather, this function must be applied
1927 * afterwards.
1929 void
1930 range_set_contain_empty(RangeType *range)
1932 char *flagsp;
1934 /* flag byte is datum's last byte */
1935 flagsp = (char *) range + VARSIZE(range) - 1;
1937 *flagsp |= RANGE_CONTAIN_EMPTY;
1941 * This both serializes and canonicalizes (if applicable) the range.
1942 * This should be used by most callers.
1944 RangeType *
1945 make_range(TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper,
1946 bool empty, struct Node *escontext)
1948 RangeType *range;
1950 range = range_serialize(typcache, lower, upper, empty, escontext);
1952 if (SOFT_ERROR_OCCURRED(escontext))
1953 return NULL;
1955 /* no need to call canonical on empty ranges ... */
1956 if (OidIsValid(typcache->rng_canonical_finfo.fn_oid) &&
1957 !RangeIsEmpty(range))
1959 /* Do this the hard way so that we can pass escontext */
1960 LOCAL_FCINFO(fcinfo, 1);
1961 Datum result;
1963 InitFunctionCallInfoData(*fcinfo, &typcache->rng_canonical_finfo, 1,
1964 InvalidOid, escontext, NULL);
1966 fcinfo->args[0].value = RangeTypePGetDatum(range);
1967 fcinfo->args[0].isnull = false;
1969 result = FunctionCallInvoke(fcinfo);
1971 if (SOFT_ERROR_OCCURRED(escontext))
1972 return NULL;
1974 /* Should not get a null result if there was no error */
1975 if (fcinfo->isnull)
1976 elog(ERROR, "function %u returned NULL",
1977 typcache->rng_canonical_finfo.fn_oid);
1979 range = DatumGetRangeTypeP(result);
1982 return range;
1986 * Compare two range boundary points, returning <0, 0, or >0 according to
1987 * whether b1 is less than, equal to, or greater than b2.
1989 * The boundaries can be any combination of upper and lower; so it's useful
1990 * for a variety of operators.
1992 * The simple case is when b1 and b2 are both finite and inclusive, in which
1993 * case the result is just a comparison of the values held in b1 and b2.
1995 * If a bound is exclusive, then we need to know whether it's a lower bound,
1996 * in which case we treat the boundary point as "just greater than" the held
1997 * value; or an upper bound, in which case we treat the boundary point as
1998 * "just less than" the held value.
2000 * If a bound is infinite, it represents minus infinity (less than every other
2001 * point) if it's a lower bound; or plus infinity (greater than every other
2002 * point) if it's an upper bound.
2004 * There is only one case where two boundaries compare equal but are not
2005 * identical: when both bounds are inclusive and hold the same finite value,
2006 * but one is an upper bound and the other a lower bound.
2009 range_cmp_bounds(TypeCacheEntry *typcache, const RangeBound *b1, const RangeBound *b2)
2011 int32 result;
2014 * First, handle cases involving infinity, which don't require invoking
2015 * the comparison proc.
2017 if (b1->infinite && b2->infinite)
2020 * Both are infinity, so they are equal unless one is lower and the
2021 * other not.
2023 if (b1->lower == b2->lower)
2024 return 0;
2025 else
2026 return b1->lower ? -1 : 1;
2028 else if (b1->infinite)
2029 return b1->lower ? -1 : 1;
2030 else if (b2->infinite)
2031 return b2->lower ? 1 : -1;
2034 * Both boundaries are finite, so compare the held values.
2036 result = DatumGetInt32(FunctionCall2Coll(&typcache->rng_cmp_proc_finfo,
2037 typcache->rng_collation,
2038 b1->val, b2->val));
2041 * If the comparison is anything other than equal, we're done. If they
2042 * compare equal though, we still have to consider whether the boundaries
2043 * are inclusive or exclusive.
2045 if (result == 0)
2047 if (!b1->inclusive && !b2->inclusive)
2049 /* both are exclusive */
2050 if (b1->lower == b2->lower)
2051 return 0;
2052 else
2053 return b1->lower ? 1 : -1;
2055 else if (!b1->inclusive)
2056 return b1->lower ? 1 : -1;
2057 else if (!b2->inclusive)
2058 return b2->lower ? -1 : 1;
2059 else
2062 * Both are inclusive and the values held are equal, so they are
2063 * equal regardless of whether they are upper or lower boundaries,
2064 * or a mix.
2066 return 0;
2070 return result;
2074 * Compare two range boundary point values, returning <0, 0, or >0 according
2075 * to whether b1 is less than, equal to, or greater than b2.
2077 * This is similar to but simpler than range_cmp_bounds(). We just compare
2078 * the values held in b1 and b2, ignoring inclusive/exclusive flags. The
2079 * lower/upper flags only matter for infinities, where they tell us if the
2080 * infinity is plus or minus.
2083 range_cmp_bound_values(TypeCacheEntry *typcache, const RangeBound *b1,
2084 const RangeBound *b2)
2087 * First, handle cases involving infinity, which don't require invoking
2088 * the comparison proc.
2090 if (b1->infinite && b2->infinite)
2093 * Both are infinity, so they are equal unless one is lower and the
2094 * other not.
2096 if (b1->lower == b2->lower)
2097 return 0;
2098 else
2099 return b1->lower ? -1 : 1;
2101 else if (b1->infinite)
2102 return b1->lower ? -1 : 1;
2103 else if (b2->infinite)
2104 return b2->lower ? 1 : -1;
2107 * Both boundaries are finite, so compare the held values.
2109 return DatumGetInt32(FunctionCall2Coll(&typcache->rng_cmp_proc_finfo,
2110 typcache->rng_collation,
2111 b1->val, b2->val));
2115 * qsort callback for sorting ranges.
2117 * Two empty ranges compare equal; an empty range sorts to the left of any
2118 * non-empty range. Two non-empty ranges are sorted by lower bound first
2119 * and by upper bound next.
2122 range_compare(const void *key1, const void *key2, void *arg)
2124 RangeType *r1 = *(RangeType **) key1;
2125 RangeType *r2 = *(RangeType **) key2;
2126 TypeCacheEntry *typcache = (TypeCacheEntry *) arg;
2127 RangeBound lower1;
2128 RangeBound upper1;
2129 RangeBound lower2;
2130 RangeBound upper2;
2131 bool empty1;
2132 bool empty2;
2133 int cmp;
2135 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
2136 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
2138 if (empty1 && empty2)
2139 cmp = 0;
2140 else if (empty1)
2141 cmp = -1;
2142 else if (empty2)
2143 cmp = 1;
2144 else
2146 cmp = range_cmp_bounds(typcache, &lower1, &lower2);
2147 if (cmp == 0)
2148 cmp = range_cmp_bounds(typcache, &upper1, &upper2);
2151 return cmp;
2155 * Build an empty range value of the type indicated by the typcache entry.
2157 RangeType *
2158 make_empty_range(TypeCacheEntry *typcache)
2160 RangeBound lower;
2161 RangeBound upper;
2163 lower.val = (Datum) 0;
2164 lower.infinite = false;
2165 lower.inclusive = false;
2166 lower.lower = true;
2168 upper.val = (Datum) 0;
2169 upper.infinite = false;
2170 upper.inclusive = false;
2171 upper.lower = false;
2173 return make_range(typcache, &lower, &upper, true, NULL);
2178 *----------------------------------------------------------
2179 * STATIC FUNCTIONS
2180 *----------------------------------------------------------
2184 * Given a string representing the flags for the range type, return the flags
2185 * represented as a char.
2187 static char
2188 range_parse_flags(const char *flags_str)
2190 char flags = 0;
2192 if (flags_str[0] == '\0' ||
2193 flags_str[1] == '\0' ||
2194 flags_str[2] != '\0')
2195 ereport(ERROR,
2196 (errcode(ERRCODE_SYNTAX_ERROR),
2197 errmsg("invalid range bound flags"),
2198 errhint("Valid values are \"[]\", \"[)\", \"(]\", and \"()\".")));
2200 switch (flags_str[0])
2202 case '[':
2203 flags |= RANGE_LB_INC;
2204 break;
2205 case '(':
2206 break;
2207 default:
2208 ereport(ERROR,
2209 (errcode(ERRCODE_SYNTAX_ERROR),
2210 errmsg("invalid range bound flags"),
2211 errhint("Valid values are \"[]\", \"[)\", \"(]\", and \"()\".")));
2214 switch (flags_str[1])
2216 case ']':
2217 flags |= RANGE_UB_INC;
2218 break;
2219 case ')':
2220 break;
2221 default:
2222 ereport(ERROR,
2223 (errcode(ERRCODE_SYNTAX_ERROR),
2224 errmsg("invalid range bound flags"),
2225 errhint("Valid values are \"[]\", \"[)\", \"(]\", and \"()\".")));
2228 return flags;
2232 * Parse range input.
2234 * Input parameters:
2235 * string: input string to be parsed
2236 * Output parameters:
2237 * *flags: receives flags bitmask
2238 * *lbound_str: receives palloc'd lower bound string, or NULL if none
2239 * *ubound_str: receives palloc'd upper bound string, or NULL if none
2241 * This is modeled somewhat after record_in in rowtypes.c.
2242 * The input syntax is:
2243 * <range> := EMPTY
2244 * | <lb-inc> <string>, <string> <ub-inc>
2245 * <lb-inc> := '[' | '('
2246 * <ub-inc> := ']' | ')'
2248 * Whitespace before or after <range> is ignored. Whitespace within a <string>
2249 * is taken literally and becomes part of the input string for that bound.
2251 * A <string> of length zero is taken as "infinite" (i.e. no bound), unless it
2252 * is surrounded by double-quotes, in which case it is the literal empty
2253 * string.
2255 * Within a <string>, special characters (such as comma, parenthesis, or
2256 * brackets) can be enclosed in double-quotes or escaped with backslash. Within
2257 * double-quotes, a double-quote can be escaped with double-quote or backslash.
2259 * Returns true on success, false on failure (but failures will return only if
2260 * escontext is an ErrorSaveContext).
2262 static bool
2263 range_parse(const char *string, char *flags, char **lbound_str,
2264 char **ubound_str, Node *escontext)
2266 const char *ptr = string;
2267 bool infinite;
2269 *flags = 0;
2271 /* consume whitespace */
2272 while (*ptr != '\0' && isspace((unsigned char) *ptr))
2273 ptr++;
2275 /* check for empty range */
2276 if (pg_strncasecmp(ptr, RANGE_EMPTY_LITERAL,
2277 strlen(RANGE_EMPTY_LITERAL)) == 0)
2279 *flags = RANGE_EMPTY;
2280 *lbound_str = NULL;
2281 *ubound_str = NULL;
2283 ptr += strlen(RANGE_EMPTY_LITERAL);
2285 /* the rest should be whitespace */
2286 while (*ptr != '\0' && isspace((unsigned char) *ptr))
2287 ptr++;
2289 /* should have consumed everything */
2290 if (*ptr != '\0')
2291 ereturn(escontext, false,
2292 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2293 errmsg("malformed range literal: \"%s\"",
2294 string),
2295 errdetail("Junk after \"empty\" key word.")));
2297 return true;
2300 if (*ptr == '[')
2302 *flags |= RANGE_LB_INC;
2303 ptr++;
2305 else if (*ptr == '(')
2306 ptr++;
2307 else
2308 ereturn(escontext, false,
2309 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2310 errmsg("malformed range literal: \"%s\"",
2311 string),
2312 errdetail("Missing left parenthesis or bracket.")));
2314 ptr = range_parse_bound(string, ptr, lbound_str, &infinite, escontext);
2315 if (ptr == NULL)
2316 return false;
2317 if (infinite)
2318 *flags |= RANGE_LB_INF;
2320 if (*ptr == ',')
2321 ptr++;
2322 else
2323 ereturn(escontext, false,
2324 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2325 errmsg("malformed range literal: \"%s\"",
2326 string),
2327 errdetail("Missing comma after lower bound.")));
2329 ptr = range_parse_bound(string, ptr, ubound_str, &infinite, escontext);
2330 if (ptr == NULL)
2331 return false;
2332 if (infinite)
2333 *flags |= RANGE_UB_INF;
2335 if (*ptr == ']')
2337 *flags |= RANGE_UB_INC;
2338 ptr++;
2340 else if (*ptr == ')')
2341 ptr++;
2342 else /* must be a comma */
2343 ereturn(escontext, false,
2344 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2345 errmsg("malformed range literal: \"%s\"",
2346 string),
2347 errdetail("Too many commas.")));
2349 /* consume whitespace */
2350 while (*ptr != '\0' && isspace((unsigned char) *ptr))
2351 ptr++;
2353 if (*ptr != '\0')
2354 ereturn(escontext, false,
2355 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2356 errmsg("malformed range literal: \"%s\"",
2357 string),
2358 errdetail("Junk after right parenthesis or bracket.")));
2360 return true;
2364 * Helper for range_parse: parse and de-quote one bound string.
2366 * We scan until finding comma, right parenthesis, or right bracket.
2368 * Input parameters:
2369 * string: entire input string (used only for error reports)
2370 * ptr: where to start parsing bound
2371 * Output parameters:
2372 * *bound_str: receives palloc'd bound string, or NULL if none
2373 * *infinite: set true if no bound, else false
2375 * The return value is the scan ptr, advanced past the bound string.
2376 * However, if escontext is an ErrorSaveContext, we return NULL on failure.
2378 static const char *
2379 range_parse_bound(const char *string, const char *ptr,
2380 char **bound_str, bool *infinite, Node *escontext)
2382 StringInfoData buf;
2384 /* Check for null: completely empty input means null */
2385 if (*ptr == ',' || *ptr == ')' || *ptr == ']')
2387 *bound_str = NULL;
2388 *infinite = true;
2390 else
2392 /* Extract string for this bound */
2393 bool inquote = false;
2395 initStringInfo(&buf);
2396 while (inquote || !(*ptr == ',' || *ptr == ')' || *ptr == ']'))
2398 char ch = *ptr++;
2400 if (ch == '\0')
2401 ereturn(escontext, NULL,
2402 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2403 errmsg("malformed range literal: \"%s\"",
2404 string),
2405 errdetail("Unexpected end of input.")));
2406 if (ch == '\\')
2408 if (*ptr == '\0')
2409 ereturn(escontext, NULL,
2410 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2411 errmsg("malformed range literal: \"%s\"",
2412 string),
2413 errdetail("Unexpected end of input.")));
2414 appendStringInfoChar(&buf, *ptr++);
2416 else if (ch == '"')
2418 if (!inquote)
2419 inquote = true;
2420 else if (*ptr == '"')
2422 /* doubled quote within quote sequence */
2423 appendStringInfoChar(&buf, *ptr++);
2425 else
2426 inquote = false;
2428 else
2429 appendStringInfoChar(&buf, ch);
2432 *bound_str = buf.data;
2433 *infinite = false;
2436 return ptr;
2440 * Convert a deserialized range value to text form
2442 * Inputs are the flags byte, and the two bound values already converted to
2443 * text (but not yet quoted). If no bound value, pass NULL.
2445 * Result is a palloc'd string
2447 static char *
2448 range_deparse(char flags, const char *lbound_str, const char *ubound_str)
2450 StringInfoData buf;
2452 if (flags & RANGE_EMPTY)
2453 return pstrdup(RANGE_EMPTY_LITERAL);
2455 initStringInfo(&buf);
2457 appendStringInfoChar(&buf, (flags & RANGE_LB_INC) ? '[' : '(');
2459 if (RANGE_HAS_LBOUND(flags))
2460 appendStringInfoString(&buf, range_bound_escape(lbound_str));
2462 appendStringInfoChar(&buf, ',');
2464 if (RANGE_HAS_UBOUND(flags))
2465 appendStringInfoString(&buf, range_bound_escape(ubound_str));
2467 appendStringInfoChar(&buf, (flags & RANGE_UB_INC) ? ']' : ')');
2469 return buf.data;
2473 * Helper for range_deparse: quote a bound value as needed
2475 * Result is a palloc'd string
2477 static char *
2478 range_bound_escape(const char *value)
2480 bool nq;
2481 const char *ptr;
2482 StringInfoData buf;
2484 initStringInfo(&buf);
2486 /* Detect whether we need double quotes for this value */
2487 nq = (value[0] == '\0'); /* force quotes for empty string */
2488 for (ptr = value; *ptr; ptr++)
2490 char ch = *ptr;
2492 if (ch == '"' || ch == '\\' ||
2493 ch == '(' || ch == ')' ||
2494 ch == '[' || ch == ']' ||
2495 ch == ',' ||
2496 isspace((unsigned char) ch))
2498 nq = true;
2499 break;
2503 /* And emit the string */
2504 if (nq)
2505 appendStringInfoChar(&buf, '"');
2506 for (ptr = value; *ptr; ptr++)
2508 char ch = *ptr;
2510 if (ch == '"' || ch == '\\')
2511 appendStringInfoChar(&buf, ch);
2512 appendStringInfoChar(&buf, ch);
2514 if (nq)
2515 appendStringInfoChar(&buf, '"');
2517 return buf.data;
2521 * Test whether range r1 contains range r2.
2523 * Caller has already checked that they are the same range type, and looked up
2524 * the necessary typcache entry.
2526 bool
2527 range_contains_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
2529 RangeBound lower1;
2530 RangeBound upper1;
2531 bool empty1;
2532 RangeBound lower2;
2533 RangeBound upper2;
2534 bool empty2;
2536 /* Different types should be prevented by ANYRANGE matching rules */
2537 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
2538 elog(ERROR, "range types do not match");
2540 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
2541 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
2543 /* If either range is empty, the answer is easy */
2544 if (empty2)
2545 return true;
2546 else if (empty1)
2547 return false;
2549 /* Else we must have lower1 <= lower2 and upper1 >= upper2 */
2550 if (range_cmp_bounds(typcache, &lower1, &lower2) > 0)
2551 return false;
2552 if (range_cmp_bounds(typcache, &upper1, &upper2) < 0)
2553 return false;
2555 return true;
2558 bool
2559 range_contained_by_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
2561 return range_contains_internal(typcache, r2, r1);
2565 * Test whether range r contains a specific element value.
2567 bool
2568 range_contains_elem_internal(TypeCacheEntry *typcache, const RangeType *r, Datum val)
2570 RangeBound lower;
2571 RangeBound upper;
2572 bool empty;
2573 int32 cmp;
2575 range_deserialize(typcache, r, &lower, &upper, &empty);
2577 if (empty)
2578 return false;
2580 if (!lower.infinite)
2582 cmp = DatumGetInt32(FunctionCall2Coll(&typcache->rng_cmp_proc_finfo,
2583 typcache->rng_collation,
2584 lower.val, val));
2585 if (cmp > 0)
2586 return false;
2587 if (cmp == 0 && !lower.inclusive)
2588 return false;
2591 if (!upper.infinite)
2593 cmp = DatumGetInt32(FunctionCall2Coll(&typcache->rng_cmp_proc_finfo,
2594 typcache->rng_collation,
2595 upper.val, val));
2596 if (cmp < 0)
2597 return false;
2598 if (cmp == 0 && !upper.inclusive)
2599 return false;
2602 return true;
2607 * datum_compute_size() and datum_write() are used to insert the bound
2608 * values into a range object. They are modeled after heaptuple.c's
2609 * heap_compute_data_size() and heap_fill_tuple(), but we need not handle
2610 * null values here. TYPE_IS_PACKABLE must test the same conditions as
2611 * heaptuple.c's ATT_IS_PACKABLE macro. See the comments thare for more
2612 * details.
2615 /* Does datatype allow packing into the 1-byte-header varlena format? */
2616 #define TYPE_IS_PACKABLE(typlen, typstorage) \
2617 ((typlen) == -1 && (typstorage) != TYPSTORAGE_PLAIN)
2620 * Increment data_length by the space needed by the datum, including any
2621 * preceding alignment padding.
2623 static Size
2624 datum_compute_size(Size data_length, Datum val, bool typbyval, char typalign,
2625 int16 typlen, char typstorage)
2627 if (TYPE_IS_PACKABLE(typlen, typstorage) &&
2628 VARATT_CAN_MAKE_SHORT(DatumGetPointer(val)))
2631 * we're anticipating converting to a short varlena header, so adjust
2632 * length and don't count any alignment
2634 data_length += VARATT_CONVERTED_SHORT_SIZE(DatumGetPointer(val));
2636 else
2638 data_length = att_align_datum(data_length, typalign, typlen, val);
2639 data_length = att_addlength_datum(data_length, typlen, val);
2642 return data_length;
2646 * Write the given datum beginning at ptr (after advancing to correct
2647 * alignment, if needed). Return the pointer incremented by space used.
2649 static Pointer
2650 datum_write(Pointer ptr, Datum datum, bool typbyval, char typalign,
2651 int16 typlen, char typstorage)
2653 Size data_length;
2655 if (typbyval)
2657 /* pass-by-value */
2658 ptr = (char *) att_align_nominal(ptr, typalign);
2659 store_att_byval(ptr, datum, typlen);
2660 data_length = typlen;
2662 else if (typlen == -1)
2664 /* varlena */
2665 Pointer val = DatumGetPointer(datum);
2667 if (VARATT_IS_EXTERNAL(val))
2670 * Throw error, because we must never put a toast pointer inside a
2671 * range object. Caller should have detoasted it.
2673 elog(ERROR, "cannot store a toast pointer inside a range");
2674 data_length = 0; /* keep compiler quiet */
2676 else if (VARATT_IS_SHORT(val))
2678 /* no alignment for short varlenas */
2679 data_length = VARSIZE_SHORT(val);
2680 memcpy(ptr, val, data_length);
2682 else if (TYPE_IS_PACKABLE(typlen, typstorage) &&
2683 VARATT_CAN_MAKE_SHORT(val))
2685 /* convert to short varlena -- no alignment */
2686 data_length = VARATT_CONVERTED_SHORT_SIZE(val);
2687 SET_VARSIZE_SHORT(ptr, data_length);
2688 memcpy(ptr + 1, VARDATA(val), data_length - 1);
2690 else
2692 /* full 4-byte header varlena */
2693 ptr = (char *) att_align_nominal(ptr, typalign);
2694 data_length = VARSIZE(val);
2695 memcpy(ptr, val, data_length);
2698 else if (typlen == -2)
2700 /* cstring ... never needs alignment */
2701 Assert(typalign == TYPALIGN_CHAR);
2702 data_length = strlen(DatumGetCString(datum)) + 1;
2703 memcpy(ptr, DatumGetPointer(datum), data_length);
2705 else
2707 /* fixed-length pass-by-reference */
2708 ptr = (char *) att_align_nominal(ptr, typalign);
2709 Assert(typlen > 0);
2710 data_length = typlen;
2711 memcpy(ptr, DatumGetPointer(datum), data_length);
2714 ptr += data_length;
2716 return ptr;