1/*-------------------------------------------------------------------------
2 *
3 * rangetypes.c
4 * I/O functions, operators, and support functions for range types.
5 *
6 * The stored (serialized) format of a range value is:
7 *
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
13 *
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.
20 *
21 *
22 * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
23 * Portions Copyright (c) 1994, Regents of the University of California
24 *
25 *
26 * IDENTIFICATION
27 * src/backend/utils/adt/rangetypes.c
28 *
29 *-------------------------------------------------------------------------
30 */
31#include "postgres.h"
32
33#include "access/tupmacs.h"
34#include "lib/stringinfo.h"
35#include "libpq/pqformat.h"
36#include "miscadmin.h"
37#include "utils/builtins.h"
38#include "utils/date.h"
39#include "utils/hashutils.h"
40#include "utils/int8.h"
41#include "utils/lsyscache.h"
42#include "utils/rangetypes.h"
43#include "utils/timestamp.h"
44
45
46#define RANGE_EMPTY_LITERAL "empty"
47
48/* fn_extra cache entry for one of the range I/O functions */
49typedef struct RangeIOData
50{
51 TypeCacheEntry *typcache; /* range type's typcache entry */
52 Oid typiofunc; /* element type's I/O function */
53 Oid typioparam; /* element type's I/O parameter */
54 FmgrInfo proc; /* lookup result for typiofunc */
55} RangeIOData;
56
57
58static RangeIOData *get_range_io_data(FunctionCallInfo fcinfo, Oid rngtypid,
59 IOFuncSelector func);
60static char range_parse_flags(const char *flags_str);
61static void range_parse(const char *input_str, char *flags, char **lbound_str,
62 char **ubound_str);
63static const char *range_parse_bound(const char *string, const char *ptr,
64 char **bound_str, bool *infinite);
65static char *range_deparse(char flags, const char *lbound_str,
66 const char *ubound_str);
67static char *range_bound_escape(const char *value);
68static Size datum_compute_size(Size sz, Datum datum, bool typbyval,
69 char typalign, int16 typlen, char typstorage);
70static Pointer datum_write(Pointer ptr, Datum datum, bool typbyval,
71 char typalign, int16 typlen, char typstorage);
72
73
74/*
75 *----------------------------------------------------------
76 * I/O FUNCTIONS
77 *----------------------------------------------------------
78 */
79
80Datum
81range_in(PG_FUNCTION_ARGS)
82{
83 char *input_str = PG_GETARG_CSTRING(0);
84 Oid rngtypoid = PG_GETARG_OID(1);
85 Oid typmod = PG_GETARG_INT32(2);
86 RangeType *range;
87 RangeIOData *cache;
88 char flags;
89 char *lbound_str;
90 char *ubound_str;
91 RangeBound lower;
92 RangeBound upper;
93
94 check_stack_depth(); /* recurses when subtype is a range type */
95
96 cache = get_range_io_data(fcinfo, rngtypoid, IOFunc_input);
97
98 /* parse */
99 range_parse(input_str, &flags, &lbound_str, &ubound_str);
100
101 /* call element type's input function */
102 if (RANGE_HAS_LBOUND(flags))
103 lower.val = InputFunctionCall(&cache->proc, lbound_str,
104 cache->typioparam, typmod);
105 if (RANGE_HAS_UBOUND(flags))
106 upper.val = InputFunctionCall(&cache->proc, ubound_str,
107 cache->typioparam, typmod);
108
109 lower.infinite = (flags & RANGE_LB_INF) != 0;
110 lower.inclusive = (flags & RANGE_LB_INC) != 0;
111 lower.lower = true;
112 upper.infinite = (flags & RANGE_UB_INF) != 0;
113 upper.inclusive = (flags & RANGE_UB_INC) != 0;
114 upper.lower = false;
115
116 /* serialize and canonicalize */
117 range = make_range(cache->typcache, &lower, &upper, flags & RANGE_EMPTY);
118
119 PG_RETURN_RANGE_P(range);
120}
121
122Datum
123range_out(PG_FUNCTION_ARGS)
124{
125 RangeType *range = PG_GETARG_RANGE_P(0);
126 char *output_str;
127 RangeIOData *cache;
128 char flags;
129 char *lbound_str = NULL;
130 char *ubound_str = NULL;
131 RangeBound lower;
132 RangeBound upper;
133 bool empty;
134
135 check_stack_depth(); /* recurses when subtype is a range type */
136
137 cache = get_range_io_data(fcinfo, RangeTypeGetOid(range), IOFunc_output);
138
139 /* deserialize */
140 range_deserialize(cache->typcache, range, &lower, &upper, &empty);
141 flags = range_get_flags(range);
142
143 /* call element type's output function */
144 if (RANGE_HAS_LBOUND(flags))
145 lbound_str = OutputFunctionCall(&cache->proc, lower.val);
146 if (RANGE_HAS_UBOUND(flags))
147 ubound_str = OutputFunctionCall(&cache->proc, upper.val);
148
149 /* construct result string */
150 output_str = range_deparse(flags, lbound_str, ubound_str);
151
152 PG_RETURN_CSTRING(output_str);
153}
154
155/*
156 * Binary representation: The first byte is the flags, then the lower bound
157 * (if present), then the upper bound (if present). Each bound is represented
158 * by a 4-byte length header and the binary representation of that bound (as
159 * returned by a call to the send function for the subtype).
160 */
161
162Datum
163range_recv(PG_FUNCTION_ARGS)
164{
165 StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
166 Oid rngtypoid = PG_GETARG_OID(1);
167 int32 typmod = PG_GETARG_INT32(2);
168 RangeType *range;
169 RangeIOData *cache;
170 char flags;
171 RangeBound lower;
172 RangeBound upper;
173
174 check_stack_depth(); /* recurses when subtype is a range type */
175
176 cache = get_range_io_data(fcinfo, rngtypoid, IOFunc_receive);
177
178 /* receive the flags... */
179 flags = (unsigned char) pq_getmsgbyte(buf);
180
181 /*
182 * Mask out any unsupported flags, particularly RANGE_xB_NULL which would
183 * confuse following tests. Note that range_serialize will take care of
184 * cleaning up any inconsistencies in the remaining flags.
185 */
186 flags &= (RANGE_EMPTY |
187 RANGE_LB_INC |
188 RANGE_LB_INF |
189 RANGE_UB_INC |
190 RANGE_UB_INF);
191
192 /* receive the bounds ... */
193 if (RANGE_HAS_LBOUND(flags))
194 {
195 uint32 bound_len = pq_getmsgint(buf, 4);
196 const char *bound_data = pq_getmsgbytes(buf, bound_len);
197 StringInfoData bound_buf;
198
199 initStringInfo(&bound_buf);
200 appendBinaryStringInfo(&bound_buf, bound_data, bound_len);
201
202 lower.val = ReceiveFunctionCall(&cache->proc,
203 &bound_buf,
204 cache->typioparam,
205 typmod);
206 pfree(bound_buf.data);
207 }
208 else
209 lower.val = (Datum) 0;
210
211 if (RANGE_HAS_UBOUND(flags))
212 {
213 uint32 bound_len = pq_getmsgint(buf, 4);
214 const char *bound_data = pq_getmsgbytes(buf, bound_len);
215 StringInfoData bound_buf;
216
217 initStringInfo(&bound_buf);
218 appendBinaryStringInfo(&bound_buf, bound_data, bound_len);
219
220 upper.val = ReceiveFunctionCall(&cache->proc,
221 &bound_buf,
222 cache->typioparam,
223 typmod);
224 pfree(bound_buf.data);
225 }
226 else
227 upper.val = (Datum) 0;
228
229 pq_getmsgend(buf);
230
231 /* finish constructing RangeBound representation */
232 lower.infinite = (flags & RANGE_LB_INF) != 0;
233 lower.inclusive = (flags & RANGE_LB_INC) != 0;
234 lower.lower = true;
235 upper.infinite = (flags & RANGE_UB_INF) != 0;
236 upper.inclusive = (flags & RANGE_UB_INC) != 0;
237 upper.lower = false;
238
239 /* serialize and canonicalize */
240 range = make_range(cache->typcache, &lower, &upper, flags & RANGE_EMPTY);
241
242 PG_RETURN_RANGE_P(range);
243}
244
245Datum
246range_send(PG_FUNCTION_ARGS)
247{
248 RangeType *range = PG_GETARG_RANGE_P(0);
249 StringInfo buf = makeStringInfo();
250 RangeIOData *cache;
251 char flags;
252 RangeBound lower;
253 RangeBound upper;
254 bool empty;
255
256 check_stack_depth(); /* recurses when subtype is a range type */
257
258 cache = get_range_io_data(fcinfo, RangeTypeGetOid(range), IOFunc_send);
259
260 /* deserialize */
261 range_deserialize(cache->typcache, range, &lower, &upper, &empty);
262 flags = range_get_flags(range);
263
264 /* construct output */
265 pq_begintypsend(buf);
266
267 pq_sendbyte(buf, flags);
268
269 if (RANGE_HAS_LBOUND(flags))
270 {
271 Datum bound = PointerGetDatum(SendFunctionCall(&cache->proc,
272 lower.val));
273 uint32 bound_len = VARSIZE(bound) - VARHDRSZ;
274 char *bound_data = VARDATA(bound);
275
276 pq_sendint32(buf, bound_len);
277 pq_sendbytes(buf, bound_data, bound_len);
278 }
279
280 if (RANGE_HAS_UBOUND(flags))
281 {
282 Datum bound = PointerGetDatum(SendFunctionCall(&cache->proc,
283 upper.val));
284 uint32 bound_len = VARSIZE(bound) - VARHDRSZ;
285 char *bound_data = VARDATA(bound);
286
287 pq_sendint32(buf, bound_len);
288 pq_sendbytes(buf, bound_data, bound_len);
289 }
290
291 PG_RETURN_BYTEA_P(pq_endtypsend(buf));
292}
293
294/*
295 * get_range_io_data: get cached information needed for range type I/O
296 *
297 * The range I/O functions need a bit more cached info than other range
298 * functions, so they store a RangeIOData struct in fn_extra, not just a
299 * pointer to a type cache entry.
300 */
301static RangeIOData *
302get_range_io_data(FunctionCallInfo fcinfo, Oid rngtypid, IOFuncSelector func)
303{
304 RangeIOData *cache = (RangeIOData *) fcinfo->flinfo->fn_extra;
305
306 if (cache == NULL || cache->typcache->type_id != rngtypid)
307 {
308 int16 typlen;
309 bool typbyval;
310 char typalign;
311 char typdelim;
312
313 cache = (RangeIOData *) MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
314 sizeof(RangeIOData));
315 cache->typcache = lookup_type_cache(rngtypid, TYPECACHE_RANGE_INFO);
316 if (cache->typcache->rngelemtype == NULL)
317 elog(ERROR, "type %u is not a range type", rngtypid);
318
319 /* get_type_io_data does more than we need, but is convenient */
320 get_type_io_data(cache->typcache->rngelemtype->type_id,
321 func,
322 &typlen,
323 &typbyval,
324 &typalign,
325 &typdelim,
326 &cache->typioparam,
327 &cache->typiofunc);
328
329 if (!OidIsValid(cache->typiofunc))
330 {
331 /* this could only happen for receive or send */
332 if (func == IOFunc_receive)
333 ereport(ERROR,
334 (errcode(ERRCODE_UNDEFINED_FUNCTION),
335 errmsg("no binary input function available for type %s",
336 format_type_be(cache->typcache->rngelemtype->type_id))));
337 else
338 ereport(ERROR,
339 (errcode(ERRCODE_UNDEFINED_FUNCTION),
340 errmsg("no binary output function available for type %s",
341 format_type_be(cache->typcache->rngelemtype->type_id))));
342 }
343 fmgr_info_cxt(cache->typiofunc, &cache->proc,
344 fcinfo->flinfo->fn_mcxt);
345
346 fcinfo->flinfo->fn_extra = (void *) cache;
347 }
348
349 return cache;
350}
351
352
353/*
354 *----------------------------------------------------------
355 * GENERIC FUNCTIONS
356 *----------------------------------------------------------
357 */
358
359/* Construct standard-form range value from two arguments */
360Datum
361range_constructor2(PG_FUNCTION_ARGS)
362{
363 Datum arg1 = PG_GETARG_DATUM(0);
364 Datum arg2 = PG_GETARG_DATUM(1);
365 Oid rngtypid = get_fn_expr_rettype(fcinfo->flinfo);
366 RangeType *range;
367 TypeCacheEntry *typcache;
368 RangeBound lower;
369 RangeBound upper;
370
371 typcache = range_get_typcache(fcinfo, rngtypid);
372
373 lower.val = PG_ARGISNULL(0) ? (Datum) 0 : arg1;
374 lower.infinite = PG_ARGISNULL(0);
375 lower.inclusive = true;
376 lower.lower = true;
377
378 upper.val = PG_ARGISNULL(1) ? (Datum) 0 : arg2;
379 upper.infinite = PG_ARGISNULL(1);
380 upper.inclusive = false;
381 upper.lower = false;
382
383 range = make_range(typcache, &lower, &upper, false);
384
385 PG_RETURN_RANGE_P(range);
386}
387
388/* Construct general range value from three arguments */
389Datum
390range_constructor3(PG_FUNCTION_ARGS)
391{
392 Datum arg1 = PG_GETARG_DATUM(0);
393 Datum arg2 = PG_GETARG_DATUM(1);
394 Oid rngtypid = get_fn_expr_rettype(fcinfo->flinfo);
395 RangeType *range;
396 TypeCacheEntry *typcache;
397 RangeBound lower;
398 RangeBound upper;
399 char flags;
400
401 typcache = range_get_typcache(fcinfo, rngtypid);
402
403 if (PG_ARGISNULL(2))
404 ereport(ERROR,
405 (errcode(ERRCODE_DATA_EXCEPTION),
406 errmsg("range constructor flags argument must not be null")));
407
408 flags = range_parse_flags(text_to_cstring(PG_GETARG_TEXT_PP(2)));
409
410 lower.val = PG_ARGISNULL(0) ? (Datum) 0 : arg1;
411 lower.infinite = PG_ARGISNULL(0);
412 lower.inclusive = (flags & RANGE_LB_INC) != 0;
413 lower.lower = true;
414
415 upper.val = PG_ARGISNULL(1) ? (Datum) 0 : arg2;
416 upper.infinite = PG_ARGISNULL(1);
417 upper.inclusive = (flags & RANGE_UB_INC) != 0;
418 upper.lower = false;
419
420 range = make_range(typcache, &lower, &upper, false);
421
422 PG_RETURN_RANGE_P(range);
423}
424
425
426/* range -> subtype functions */
427
428/* extract lower bound value */
429Datum
430range_lower(PG_FUNCTION_ARGS)
431{
432 RangeType *r1 = PG_GETARG_RANGE_P(0);
433 TypeCacheEntry *typcache;
434 RangeBound lower;
435 RangeBound upper;
436 bool empty;
437
438 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
439
440 range_deserialize(typcache, r1, &lower, &upper, &empty);
441
442 /* Return NULL if there's no finite lower bound */
443 if (empty || lower.infinite)
444 PG_RETURN_NULL();
445
446 PG_RETURN_DATUM(lower.val);
447}
448
449/* extract upper bound value */
450Datum
451range_upper(PG_FUNCTION_ARGS)
452{
453 RangeType *r1 = PG_GETARG_RANGE_P(0);
454 TypeCacheEntry *typcache;
455 RangeBound lower;
456 RangeBound upper;
457 bool empty;
458
459 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
460
461 range_deserialize(typcache, r1, &lower, &upper, &empty);
462
463 /* Return NULL if there's no finite upper bound */
464 if (empty || upper.infinite)
465 PG_RETURN_NULL();
466
467 PG_RETURN_DATUM(upper.val);
468}
469
470
471/* range -> bool functions */
472
473/* is range empty? */
474Datum
475range_empty(PG_FUNCTION_ARGS)
476{
477 RangeType *r1 = PG_GETARG_RANGE_P(0);
478 char flags = range_get_flags(r1);
479
480 PG_RETURN_BOOL(flags & RANGE_EMPTY);
481}
482
483/* is lower bound inclusive? */
484Datum
485range_lower_inc(PG_FUNCTION_ARGS)
486{
487 RangeType *r1 = PG_GETARG_RANGE_P(0);
488 char flags = range_get_flags(r1);
489
490 PG_RETURN_BOOL(flags & RANGE_LB_INC);
491}
492
493/* is upper bound inclusive? */
494Datum
495range_upper_inc(PG_FUNCTION_ARGS)
496{
497 RangeType *r1 = PG_GETARG_RANGE_P(0);
498 char flags = range_get_flags(r1);
499
500 PG_RETURN_BOOL(flags & RANGE_UB_INC);
501}
502
503/* is lower bound infinite? */
504Datum
505range_lower_inf(PG_FUNCTION_ARGS)
506{
507 RangeType *r1 = PG_GETARG_RANGE_P(0);
508 char flags = range_get_flags(r1);
509
510 PG_RETURN_BOOL(flags & RANGE_LB_INF);
511}
512
513/* is upper bound infinite? */
514Datum
515range_upper_inf(PG_FUNCTION_ARGS)
516{
517 RangeType *r1 = PG_GETARG_RANGE_P(0);
518 char flags = range_get_flags(r1);
519
520 PG_RETURN_BOOL(flags & RANGE_UB_INF);
521}
522
523
524/* range, element -> bool functions */
525
526/* contains? */
527Datum
528range_contains_elem(PG_FUNCTION_ARGS)
529{
530 RangeType *r = PG_GETARG_RANGE_P(0);
531 Datum val = PG_GETARG_DATUM(1);
532 TypeCacheEntry *typcache;
533
534 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
535
536 PG_RETURN_BOOL(range_contains_elem_internal(typcache, r, val));
537}
538
539/* contained by? */
540Datum
541elem_contained_by_range(PG_FUNCTION_ARGS)
542{
543 Datum val = PG_GETARG_DATUM(0);
544 RangeType *r = PG_GETARG_RANGE_P(1);
545 TypeCacheEntry *typcache;
546
547 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
548
549 PG_RETURN_BOOL(range_contains_elem_internal(typcache, r, val));
550}
551
552
553/* range, range -> bool functions */
554
555/* equality (internal version) */
556bool
557range_eq_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
558{
559 RangeBound lower1,
560 lower2;
561 RangeBound upper1,
562 upper2;
563 bool empty1,
564 empty2;
565
566 /* Different types should be prevented by ANYRANGE matching rules */
567 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
568 elog(ERROR, "range types do not match");
569
570 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
571 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
572
573 if (empty1 && empty2)
574 return true;
575 if (empty1 != empty2)
576 return false;
577
578 if (range_cmp_bounds(typcache, &lower1, &lower2) != 0)
579 return false;
580
581 if (range_cmp_bounds(typcache, &upper1, &upper2) != 0)
582 return false;
583
584 return true;
585}
586
587/* equality */
588Datum
589range_eq(PG_FUNCTION_ARGS)
590{
591 RangeType *r1 = PG_GETARG_RANGE_P(0);
592 RangeType *r2 = PG_GETARG_RANGE_P(1);
593 TypeCacheEntry *typcache;
594
595 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
596
597 PG_RETURN_BOOL(range_eq_internal(typcache, r1, r2));
598}
599
600/* inequality (internal version) */
601bool
602range_ne_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
603{
604 return (!range_eq_internal(typcache, r1, r2));
605}
606
607/* inequality */
608Datum
609range_ne(PG_FUNCTION_ARGS)
610{
611 RangeType *r1 = PG_GETARG_RANGE_P(0);
612 RangeType *r2 = PG_GETARG_RANGE_P(1);
613 TypeCacheEntry *typcache;
614
615 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
616
617 PG_RETURN_BOOL(range_ne_internal(typcache, r1, r2));
618}
619
620/* contains? */
621Datum
622range_contains(PG_FUNCTION_ARGS)
623{
624 RangeType *r1 = PG_GETARG_RANGE_P(0);
625 RangeType *r2 = PG_GETARG_RANGE_P(1);
626 TypeCacheEntry *typcache;
627
628 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
629
630 PG_RETURN_BOOL(range_contains_internal(typcache, r1, r2));
631}
632
633/* contained by? */
634Datum
635range_contained_by(PG_FUNCTION_ARGS)
636{
637 RangeType *r1 = PG_GETARG_RANGE_P(0);
638 RangeType *r2 = PG_GETARG_RANGE_P(1);
639 TypeCacheEntry *typcache;
640
641 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
642
643 PG_RETURN_BOOL(range_contained_by_internal(typcache, r1, r2));
644}
645
646/* strictly left of? (internal version) */
647bool
648range_before_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
649{
650 RangeBound lower1,
651 lower2;
652 RangeBound upper1,
653 upper2;
654 bool empty1,
655 empty2;
656
657 /* Different types should be prevented by ANYRANGE matching rules */
658 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
659 elog(ERROR, "range types do not match");
660
661 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
662 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
663
664 /* An empty range is neither before nor after any other range */
665 if (empty1 || empty2)
666 return false;
667
668 return (range_cmp_bounds(typcache, &upper1, &lower2) < 0);
669}
670
671/* strictly left of? */
672Datum
673range_before(PG_FUNCTION_ARGS)
674{
675 RangeType *r1 = PG_GETARG_RANGE_P(0);
676 RangeType *r2 = PG_GETARG_RANGE_P(1);
677 TypeCacheEntry *typcache;
678
679 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
680
681 PG_RETURN_BOOL(range_before_internal(typcache, r1, r2));
682}
683
684/* strictly right of? (internal version) */
685bool
686range_after_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
687{
688 RangeBound lower1,
689 lower2;
690 RangeBound upper1,
691 upper2;
692 bool empty1,
693 empty2;
694
695 /* Different types should be prevented by ANYRANGE matching rules */
696 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
697 elog(ERROR, "range types do not match");
698
699 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
700 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
701
702 /* An empty range is neither before nor after any other range */
703 if (empty1 || empty2)
704 return false;
705
706 return (range_cmp_bounds(typcache, &lower1, &upper2) > 0);
707}
708
709/* strictly right of? */
710Datum
711range_after(PG_FUNCTION_ARGS)
712{
713 RangeType *r1 = PG_GETARG_RANGE_P(0);
714 RangeType *r2 = PG_GETARG_RANGE_P(1);
715 TypeCacheEntry *typcache;
716
717 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
718
719 PG_RETURN_BOOL(range_after_internal(typcache, r1, r2));
720}
721
722/*
723 * Check if two bounds A and B are "adjacent", where A is an upper bound and B
724 * is a lower bound. For the bounds to be adjacent, each subtype value must
725 * satisfy strictly one of the bounds: there are no values which satisfy both
726 * bounds (i.e. less than A and greater than B); and there are no values which
727 * satisfy neither bound (i.e. greater than A and less than B).
728 *
729 * For discrete ranges, we rely on the canonicalization function to see if A..B
730 * normalizes to empty. (If there is no canonicalization function, it's
731 * impossible for such a range to normalize to empty, so we needn't bother to
732 * try.)
733 *
734 * If A == B, the ranges are adjacent only if the bounds have different
735 * inclusive flags (i.e., exactly one of the ranges includes the common
736 * boundary point).
737 *
738 * And if A > B then the ranges are not adjacent in this order.
739 */
740bool
741bounds_adjacent(TypeCacheEntry *typcache, RangeBound boundA, RangeBound boundB)
742{
743 int cmp;
744
745 Assert(!boundA.lower && boundB.lower);
746
747 cmp = range_cmp_bound_values(typcache, &boundA, &boundB);
748 if (cmp < 0)
749 {
750 RangeType *r;
751
752 /*
753 * Bounds do not overlap; see if there are points in between.
754 */
755
756 /* in a continuous subtype, there are assumed to be points between */
757 if (!OidIsValid(typcache->rng_canonical_finfo.fn_oid))
758 return false;
759
760 /*
761 * The bounds are of a discrete range type; so make a range A..B and
762 * see if it's empty.
763 */
764
765 /* flip the inclusion flags */
766 boundA.inclusive = !boundA.inclusive;
767 boundB.inclusive = !boundB.inclusive;
768 /* change upper/lower labels to avoid Assert failures */
769 boundA.lower = true;
770 boundB.lower = false;
771 r = make_range(typcache, &boundA, &boundB, false);
772 return RangeIsEmpty(r);
773 }
774 else if (cmp == 0)
775 return boundA.inclusive != boundB.inclusive;
776 else
777 return false; /* bounds overlap */
778}
779
780/* adjacent to (but not overlapping)? (internal version) */
781bool
782range_adjacent_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
783{
784 RangeBound lower1,
785 lower2;
786 RangeBound upper1,
787 upper2;
788 bool empty1,
789 empty2;
790
791 /* Different types should be prevented by ANYRANGE matching rules */
792 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
793 elog(ERROR, "range types do not match");
794
795 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
796 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
797
798 /* An empty range is not adjacent to any other range */
799 if (empty1 || empty2)
800 return false;
801
802 /*
803 * Given two ranges A..B and C..D, the ranges are adjacent if and only if
804 * B is adjacent to C, or D is adjacent to A.
805 */
806 return (bounds_adjacent(typcache, upper1, lower2) ||
807 bounds_adjacent(typcache, upper2, lower1));
808}
809
810/* adjacent to (but not overlapping)? */
811Datum
812range_adjacent(PG_FUNCTION_ARGS)
813{
814 RangeType *r1 = PG_GETARG_RANGE_P(0);
815 RangeType *r2 = PG_GETARG_RANGE_P(1);
816 TypeCacheEntry *typcache;
817
818 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
819
820 PG_RETURN_BOOL(range_adjacent_internal(typcache, r1, r2));
821}
822
823/* overlaps? (internal version) */
824bool
825range_overlaps_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
826{
827 RangeBound lower1,
828 lower2;
829 RangeBound upper1,
830 upper2;
831 bool empty1,
832 empty2;
833
834 /* Different types should be prevented by ANYRANGE matching rules */
835 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
836 elog(ERROR, "range types do not match");
837
838 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
839 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
840
841 /* An empty range does not overlap any other range */
842 if (empty1 || empty2)
843 return false;
844
845 if (range_cmp_bounds(typcache, &lower1, &lower2) >= 0 &&
846 range_cmp_bounds(typcache, &lower1, &upper2) <= 0)
847 return true;
848
849 if (range_cmp_bounds(typcache, &lower2, &lower1) >= 0 &&
850 range_cmp_bounds(typcache, &lower2, &upper1) <= 0)
851 return true;
852
853 return false;
854}
855
856/* overlaps? */
857Datum
858range_overlaps(PG_FUNCTION_ARGS)
859{
860 RangeType *r1 = PG_GETARG_RANGE_P(0);
861 RangeType *r2 = PG_GETARG_RANGE_P(1);
862 TypeCacheEntry *typcache;
863
864 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
865
866 PG_RETURN_BOOL(range_overlaps_internal(typcache, r1, r2));
867}
868
869/* does not extend to right of? (internal version) */
870bool
871range_overleft_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
872{
873 RangeBound lower1,
874 lower2;
875 RangeBound upper1,
876 upper2;
877 bool empty1,
878 empty2;
879
880 /* Different types should be prevented by ANYRANGE matching rules */
881 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
882 elog(ERROR, "range types do not match");
883
884 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
885 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
886
887 /* An empty range is neither before nor after any other range */
888 if (empty1 || empty2)
889 return false;
890
891 if (range_cmp_bounds(typcache, &upper1, &upper2) <= 0)
892 return true;
893
894 return false;
895}
896
897/* does not extend to right of? */
898Datum
899range_overleft(PG_FUNCTION_ARGS)
900{
901 RangeType *r1 = PG_GETARG_RANGE_P(0);
902 RangeType *r2 = PG_GETARG_RANGE_P(1);
903 TypeCacheEntry *typcache;
904
905 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
906
907 PG_RETURN_BOOL(range_overleft_internal(typcache, r1, r2));
908}
909
910/* does not extend to left of? (internal version) */
911bool
912range_overright_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
913{
914 RangeBound lower1,
915 lower2;
916 RangeBound upper1,
917 upper2;
918 bool empty1,
919 empty2;
920
921 /* Different types should be prevented by ANYRANGE matching rules */
922 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
923 elog(ERROR, "range types do not match");
924
925 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
926 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
927
928 /* An empty range is neither before nor after any other range */
929 if (empty1 || empty2)
930 return false;
931
932 if (range_cmp_bounds(typcache, &lower1, &lower2) >= 0)
933 return true;
934
935 return false;
936}
937
938/* does not extend to left of? */
939Datum
940range_overright(PG_FUNCTION_ARGS)
941{
942 RangeType *r1 = PG_GETARG_RANGE_P(0);
943 RangeType *r2 = PG_GETARG_RANGE_P(1);
944 TypeCacheEntry *typcache;
945
946 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
947
948 PG_RETURN_BOOL(range_overright_internal(typcache, r1, r2));
949}
950
951
952/* range, range -> range functions */
953
954/* set difference */
955Datum
956range_minus(PG_FUNCTION_ARGS)
957{
958 RangeType *r1 = PG_GETARG_RANGE_P(0);
959 RangeType *r2 = PG_GETARG_RANGE_P(1);
960 TypeCacheEntry *typcache;
961 RangeBound lower1,
962 lower2;
963 RangeBound upper1,
964 upper2;
965 bool empty1,
966 empty2;
967 int cmp_l1l2,
968 cmp_l1u2,
969 cmp_u1l2,
970 cmp_u1u2;
971
972 /* Different types should be prevented by ANYRANGE matching rules */
973 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
974 elog(ERROR, "range types do not match");
975
976 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
977
978 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
979 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
980
981 /* if either is empty, r1 is the correct answer */
982 if (empty1 || empty2)
983 PG_RETURN_RANGE_P(r1);
984
985 cmp_l1l2 = range_cmp_bounds(typcache, &lower1, &lower2);
986 cmp_l1u2 = range_cmp_bounds(typcache, &lower1, &upper2);
987 cmp_u1l2 = range_cmp_bounds(typcache, &upper1, &lower2);
988 cmp_u1u2 = range_cmp_bounds(typcache, &upper1, &upper2);
989
990 if (cmp_l1l2 < 0 && cmp_u1u2 > 0)
991 ereport(ERROR,
992 (errcode(ERRCODE_DATA_EXCEPTION),
993 errmsg("result of range difference would not be contiguous")));
994
995 if (cmp_l1u2 > 0 || cmp_u1l2 < 0)
996 PG_RETURN_RANGE_P(r1);
997
998 if (cmp_l1l2 >= 0 && cmp_u1u2 <= 0)
999 PG_RETURN_RANGE_P(make_empty_range(typcache));
1000
1001 if (cmp_l1l2 <= 0 && cmp_u1l2 >= 0 && cmp_u1u2 <= 0)
1002 {
1003 lower2.inclusive = !lower2.inclusive;
1004 lower2.lower = false; /* it will become the upper bound */
1005 PG_RETURN_RANGE_P(make_range(typcache, &lower1, &lower2, false));
1006 }
1007
1008 if (cmp_l1l2 >= 0 && cmp_u1u2 >= 0 && cmp_l1u2 <= 0)
1009 {
1010 upper2.inclusive = !upper2.inclusive;
1011 upper2.lower = true; /* it will become the lower bound */
1012 PG_RETURN_RANGE_P(make_range(typcache, &upper2, &upper1, false));
1013 }
1014
1015 elog(ERROR, "unexpected case in range_minus");
1016 PG_RETURN_NULL();
1017}
1018
1019/*
1020 * Set union. If strict is true, it is an error that the two input ranges
1021 * are not adjacent or overlapping.
1022 */
1023static RangeType *
1024range_union_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2,
1025 bool strict)
1026{
1027 RangeBound lower1,
1028 lower2;
1029 RangeBound upper1,
1030 upper2;
1031 bool empty1,
1032 empty2;
1033 RangeBound *result_lower;
1034 RangeBound *result_upper;
1035
1036 /* Different types should be prevented by ANYRANGE matching rules */
1037 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
1038 elog(ERROR, "range types do not match");
1039
1040 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
1041 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
1042
1043 /* if either is empty, the other is the correct answer */
1044 if (empty1)
1045 return r2;
1046 if (empty2)
1047 return r1;
1048
1049 if (strict &&
1050 !DatumGetBool(range_overlaps_internal(typcache, r1, r2)) &&
1051 !DatumGetBool(range_adjacent_internal(typcache, r1, r2)))
1052 ereport(ERROR,
1053 (errcode(ERRCODE_DATA_EXCEPTION),
1054 errmsg("result of range union would not be contiguous")));
1055
1056 if (range_cmp_bounds(typcache, &lower1, &lower2) < 0)
1057 result_lower = &lower1;
1058 else
1059 result_lower = &lower2;
1060
1061 if (range_cmp_bounds(typcache, &upper1, &upper2) > 0)
1062 result_upper = &upper1;
1063 else
1064 result_upper = &upper2;
1065
1066 return make_range(typcache, result_lower, result_upper, false);
1067}
1068
1069Datum
1070range_union(PG_FUNCTION_ARGS)
1071{
1072 RangeType *r1 = PG_GETARG_RANGE_P(0);
1073 RangeType *r2 = PG_GETARG_RANGE_P(1);
1074 TypeCacheEntry *typcache;
1075
1076 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
1077
1078 PG_RETURN_RANGE_P(range_union_internal(typcache, r1, r2, true));
1079}
1080
1081/*
1082 * range merge: like set union, except also allow and account for non-adjacent
1083 * input ranges.
1084 */
1085Datum
1086range_merge(PG_FUNCTION_ARGS)
1087{
1088 RangeType *r1 = PG_GETARG_RANGE_P(0);
1089 RangeType *r2 = PG_GETARG_RANGE_P(1);
1090 TypeCacheEntry *typcache;
1091
1092 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
1093
1094 PG_RETURN_RANGE_P(range_union_internal(typcache, r1, r2, false));
1095}
1096
1097/* set intersection */
1098Datum
1099range_intersect(PG_FUNCTION_ARGS)
1100{
1101 RangeType *r1 = PG_GETARG_RANGE_P(0);
1102 RangeType *r2 = PG_GETARG_RANGE_P(1);
1103 TypeCacheEntry *typcache;
1104 RangeBound lower1,
1105 lower2;
1106 RangeBound upper1,
1107 upper2;
1108 bool empty1,
1109 empty2;
1110 RangeBound *result_lower;
1111 RangeBound *result_upper;
1112
1113 /* Different types should be prevented by ANYRANGE matching rules */
1114 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
1115 elog(ERROR, "range types do not match");
1116
1117 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
1118
1119 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
1120 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
1121
1122 if (empty1 || empty2 || !DatumGetBool(range_overlaps(fcinfo)))
1123 PG_RETURN_RANGE_P(make_empty_range(typcache));
1124
1125 if (range_cmp_bounds(typcache, &lower1, &lower2) >= 0)
1126 result_lower = &lower1;
1127 else
1128 result_lower = &lower2;
1129
1130 if (range_cmp_bounds(typcache, &upper1, &upper2) <= 0)
1131 result_upper = &upper1;
1132 else
1133 result_upper = &upper2;
1134
1135 PG_RETURN_RANGE_P(make_range(typcache, result_lower, result_upper, false));
1136}
1137
1138/* Btree support */
1139
1140/* btree comparator */
1141Datum
1142range_cmp(PG_FUNCTION_ARGS)
1143{
1144 RangeType *r1 = PG_GETARG_RANGE_P(0);
1145 RangeType *r2 = PG_GETARG_RANGE_P(1);
1146 TypeCacheEntry *typcache;
1147 RangeBound lower1,
1148 lower2;
1149 RangeBound upper1,
1150 upper2;
1151 bool empty1,
1152 empty2;
1153 int cmp;
1154
1155 check_stack_depth(); /* recurses when subtype is a range type */
1156
1157 /* Different types should be prevented by ANYRANGE matching rules */
1158 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
1159 elog(ERROR, "range types do not match");
1160
1161 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
1162
1163 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
1164 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
1165
1166 /* For b-tree use, empty ranges sort before all else */
1167 if (empty1 && empty2)
1168 cmp = 0;
1169 else if (empty1)
1170 cmp = -1;
1171 else if (empty2)
1172 cmp = 1;
1173 else
1174 {
1175 cmp = range_cmp_bounds(typcache, &lower1, &lower2);
1176 if (cmp == 0)
1177 cmp = range_cmp_bounds(typcache, &upper1, &upper2);
1178 }
1179
1180 PG_FREE_IF_COPY(r1, 0);
1181 PG_FREE_IF_COPY(r2, 1);
1182
1183 PG_RETURN_INT32(cmp);
1184}
1185
1186/* inequality operators using the range_cmp function */
1187Datum
1188range_lt(PG_FUNCTION_ARGS)
1189{
1190 int cmp = range_cmp(fcinfo);
1191
1192 PG_RETURN_BOOL(cmp < 0);
1193}
1194
1195Datum
1196range_le(PG_FUNCTION_ARGS)
1197{
1198 int cmp = range_cmp(fcinfo);
1199
1200 PG_RETURN_BOOL(cmp <= 0);
1201}
1202
1203Datum
1204range_ge(PG_FUNCTION_ARGS)
1205{
1206 int cmp = range_cmp(fcinfo);
1207
1208 PG_RETURN_BOOL(cmp >= 0);
1209}
1210
1211Datum
1212range_gt(PG_FUNCTION_ARGS)
1213{
1214 int cmp = range_cmp(fcinfo);
1215
1216 PG_RETURN_BOOL(cmp > 0);
1217}
1218
1219/* Hash support */
1220
1221/* hash a range value */
1222Datum
1223hash_range(PG_FUNCTION_ARGS)
1224{
1225 RangeType *r = PG_GETARG_RANGE_P(0);
1226 uint32 result;
1227 TypeCacheEntry *typcache;
1228 TypeCacheEntry *scache;
1229 RangeBound lower;
1230 RangeBound upper;
1231 bool empty;
1232 char flags;
1233 uint32 lower_hash;
1234 uint32 upper_hash;
1235
1236 check_stack_depth(); /* recurses when subtype is a range type */
1237
1238 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1239
1240 /* deserialize */
1241 range_deserialize(typcache, r, &lower, &upper, &empty);
1242 flags = range_get_flags(r);
1243
1244 /*
1245 * Look up the element type's hash function, if not done already.
1246 */
1247 scache = typcache->rngelemtype;
1248 if (!OidIsValid(scache->hash_proc_finfo.fn_oid))
1249 {
1250 scache = lookup_type_cache(scache->type_id, TYPECACHE_HASH_PROC_FINFO);
1251 if (!OidIsValid(scache->hash_proc_finfo.fn_oid))
1252 ereport(ERROR,
1253 (errcode(ERRCODE_UNDEFINED_FUNCTION),
1254 errmsg("could not identify a hash function for type %s",
1255 format_type_be(scache->type_id))));
1256 }
1257
1258 /*
1259 * Apply the hash function to each bound.
1260 */
1261 if (RANGE_HAS_LBOUND(flags))
1262 lower_hash = DatumGetUInt32(FunctionCall1Coll(&scache->hash_proc_finfo,
1263 typcache->rng_collation,
1264 lower.val));
1265 else
1266 lower_hash = 0;
1267
1268 if (RANGE_HAS_UBOUND(flags))
1269 upper_hash = DatumGetUInt32(FunctionCall1Coll(&scache->hash_proc_finfo,
1270 typcache->rng_collation,
1271 upper.val));
1272 else
1273 upper_hash = 0;
1274
1275 /* Merge hashes of flags and bounds */
1276 result = hash_uint32((uint32) flags);
1277 result ^= lower_hash;
1278 result = (result << 1) | (result >> 31);
1279 result ^= upper_hash;
1280
1281 PG_RETURN_INT32(result);
1282}
1283
1284/*
1285 * Returns 64-bit value by hashing a value to a 64-bit value, with a seed.
1286 * Otherwise, similar to hash_range.
1287 */
1288Datum
1289hash_range_extended(PG_FUNCTION_ARGS)
1290{
1291 RangeType *r = PG_GETARG_RANGE_P(0);
1292 Datum seed = PG_GETARG_DATUM(1);
1293 uint64 result;
1294 TypeCacheEntry *typcache;
1295 TypeCacheEntry *scache;
1296 RangeBound lower;
1297 RangeBound upper;
1298 bool empty;
1299 char flags;
1300 uint64 lower_hash;
1301 uint64 upper_hash;
1302
1303 check_stack_depth();
1304
1305 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1306
1307 range_deserialize(typcache, r, &lower, &upper, &empty);
1308 flags = range_get_flags(r);
1309
1310 scache = typcache->rngelemtype;
1311 if (!OidIsValid(scache->hash_extended_proc_finfo.fn_oid))
1312 {
1313 scache = lookup_type_cache(scache->type_id,
1314 TYPECACHE_HASH_EXTENDED_PROC_FINFO);
1315 if (!OidIsValid(scache->hash_extended_proc_finfo.fn_oid))
1316 ereport(ERROR,
1317 (errcode(ERRCODE_UNDEFINED_FUNCTION),
1318 errmsg("could not identify a hash function for type %s",
1319 format_type_be(scache->type_id))));
1320 }
1321
1322 if (RANGE_HAS_LBOUND(flags))
1323 lower_hash = DatumGetUInt64(FunctionCall2Coll(&scache->hash_extended_proc_finfo,
1324 typcache->rng_collation,
1325 lower.val,
1326 seed));
1327 else
1328 lower_hash = 0;
1329
1330 if (RANGE_HAS_UBOUND(flags))
1331 upper_hash = DatumGetUInt64(FunctionCall2Coll(&scache->hash_extended_proc_finfo,
1332 typcache->rng_collation,
1333 upper.val,
1334 seed));
1335 else
1336 upper_hash = 0;
1337
1338 /* Merge hashes of flags and bounds */
1339 result = DatumGetUInt64(hash_uint32_extended((uint32) flags,
1340 DatumGetInt64(seed)));
1341 result ^= lower_hash;
1342 result = ROTATE_HIGH_AND_LOW_32BITS(result);
1343 result ^= upper_hash;
1344
1345 PG_RETURN_UINT64(result);
1346}
1347
1348/*
1349 *----------------------------------------------------------
1350 * CANONICAL FUNCTIONS
1351 *
1352 * Functions for specific built-in range types.
1353 *----------------------------------------------------------
1354 */
1355
1356Datum
1357int4range_canonical(PG_FUNCTION_ARGS)
1358{
1359 RangeType *r = PG_GETARG_RANGE_P(0);
1360 TypeCacheEntry *typcache;
1361 RangeBound lower;
1362 RangeBound upper;
1363 bool empty;
1364
1365 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1366
1367 range_deserialize(typcache, r, &lower, &upper, &empty);
1368
1369 if (empty)
1370 PG_RETURN_RANGE_P(r);
1371
1372 if (!lower.infinite && !lower.inclusive)
1373 {
1374 lower.val = DirectFunctionCall2(int4pl, lower.val, Int32GetDatum(1));
1375 lower.inclusive = true;
1376 }
1377
1378 if (!upper.infinite && upper.inclusive)
1379 {
1380 upper.val = DirectFunctionCall2(int4pl, upper.val, Int32GetDatum(1));
1381 upper.inclusive = false;
1382 }
1383
1384 PG_RETURN_RANGE_P(range_serialize(typcache, &lower, &upper, false));
1385}
1386
1387Datum
1388int8range_canonical(PG_FUNCTION_ARGS)
1389{
1390 RangeType *r = PG_GETARG_RANGE_P(0);
1391 TypeCacheEntry *typcache;
1392 RangeBound lower;
1393 RangeBound upper;
1394 bool empty;
1395
1396 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1397
1398 range_deserialize(typcache, r, &lower, &upper, &empty);
1399
1400 if (empty)
1401 PG_RETURN_RANGE_P(r);
1402
1403 if (!lower.infinite && !lower.inclusive)
1404 {
1405 lower.val = DirectFunctionCall2(int8pl, lower.val, Int64GetDatum(1));
1406 lower.inclusive = true;
1407 }
1408
1409 if (!upper.infinite && upper.inclusive)
1410 {
1411 upper.val = DirectFunctionCall2(int8pl, upper.val, Int64GetDatum(1));
1412 upper.inclusive = false;
1413 }
1414
1415 PG_RETURN_RANGE_P(range_serialize(typcache, &lower, &upper, false));
1416}
1417
1418Datum
1419daterange_canonical(PG_FUNCTION_ARGS)
1420{
1421 RangeType *r = PG_GETARG_RANGE_P(0);
1422 TypeCacheEntry *typcache;
1423 RangeBound lower;
1424 RangeBound upper;
1425 bool empty;
1426
1427 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1428
1429 range_deserialize(typcache, r, &lower, &upper, &empty);
1430
1431 if (empty)
1432 PG_RETURN_RANGE_P(r);
1433
1434 if (!lower.infinite && !DATE_NOT_FINITE(DatumGetDateADT(lower.val)) &&
1435 !lower.inclusive)
1436 {
1437 lower.val = DirectFunctionCall2(date_pli, lower.val, Int32GetDatum(1));
1438 lower.inclusive = true;
1439 }
1440
1441 if (!upper.infinite && !DATE_NOT_FINITE(DatumGetDateADT(upper.val)) &&
1442 upper.inclusive)
1443 {
1444 upper.val = DirectFunctionCall2(date_pli, upper.val, Int32GetDatum(1));
1445 upper.inclusive = false;
1446 }
1447
1448 PG_RETURN_RANGE_P(range_serialize(typcache, &lower, &upper, false));
1449}
1450
1451/*
1452 *----------------------------------------------------------
1453 * SUBTYPE_DIFF FUNCTIONS
1454 *
1455 * Functions for specific built-in range types.
1456 *
1457 * Note that subtype_diff does return the difference, not the absolute value
1458 * of the difference, and it must take care to avoid overflow.
1459 * (numrange_subdiff is at some risk there ...)
1460 *----------------------------------------------------------
1461 */
1462
1463Datum
1464int4range_subdiff(PG_FUNCTION_ARGS)
1465{
1466 int32 v1 = PG_GETARG_INT32(0);
1467 int32 v2 = PG_GETARG_INT32(1);
1468
1469 PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
1470}
1471
1472Datum
1473int8range_subdiff(PG_FUNCTION_ARGS)
1474{
1475 int64 v1 = PG_GETARG_INT64(0);
1476 int64 v2 = PG_GETARG_INT64(1);
1477
1478 PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
1479}
1480
1481Datum
1482numrange_subdiff(PG_FUNCTION_ARGS)
1483{
1484 Datum v1 = PG_GETARG_DATUM(0);
1485 Datum v2 = PG_GETARG_DATUM(1);
1486 Datum numresult;
1487 float8 floatresult;
1488
1489 numresult = DirectFunctionCall2(numeric_sub, v1, v2);
1490
1491 floatresult = DatumGetFloat8(DirectFunctionCall1(numeric_float8,
1492 numresult));
1493
1494 PG_RETURN_FLOAT8(floatresult);
1495}
1496
1497Datum
1498daterange_subdiff(PG_FUNCTION_ARGS)
1499{
1500 int32 v1 = PG_GETARG_INT32(0);
1501 int32 v2 = PG_GETARG_INT32(1);
1502
1503 PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
1504}
1505
1506Datum
1507tsrange_subdiff(PG_FUNCTION_ARGS)
1508{
1509 Timestamp v1 = PG_GETARG_TIMESTAMP(0);
1510 Timestamp v2 = PG_GETARG_TIMESTAMP(1);
1511 float8 result;
1512
1513 result = ((float8) v1 - (float8) v2) / USECS_PER_SEC;
1514 PG_RETURN_FLOAT8(result);
1515}
1516
1517Datum
1518tstzrange_subdiff(PG_FUNCTION_ARGS)
1519{
1520 Timestamp v1 = PG_GETARG_TIMESTAMP(0);
1521 Timestamp v2 = PG_GETARG_TIMESTAMP(1);
1522 float8 result;
1523
1524 result = ((float8) v1 - (float8) v2) / USECS_PER_SEC;
1525 PG_RETURN_FLOAT8(result);
1526}
1527
1528/*
1529 *----------------------------------------------------------
1530 * SUPPORT FUNCTIONS
1531 *
1532 * These functions aren't in pg_proc, but are useful for
1533 * defining new generic range functions in C.
1534 *----------------------------------------------------------
1535 */
1536
1537/*
1538 * range_get_typcache: get cached information about a range type
1539 *
1540 * This is for use by range-related functions that follow the convention
1541 * of using the fn_extra field as a pointer to the type cache entry for
1542 * the range type. Functions that need to cache more information than
1543 * that must fend for themselves.
1544 */
1545TypeCacheEntry *
1546range_get_typcache(FunctionCallInfo fcinfo, Oid rngtypid)
1547{
1548 TypeCacheEntry *typcache = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
1549
1550 if (typcache == NULL ||
1551 typcache->type_id != rngtypid)
1552 {
1553 typcache = lookup_type_cache(rngtypid, TYPECACHE_RANGE_INFO);
1554 if (typcache->rngelemtype == NULL)
1555 elog(ERROR, "type %u is not a range type", rngtypid);
1556 fcinfo->flinfo->fn_extra = (void *) typcache;
1557 }
1558
1559 return typcache;
1560}
1561
1562/*
1563 * range_serialize: construct a range value from bounds and empty-flag
1564 *
1565 * This does not force canonicalization of the range value. In most cases,
1566 * external callers should only be canonicalization functions. Note that
1567 * we perform some datatype-independent canonicalization checks anyway.
1568 */
1569RangeType *
1570range_serialize(TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper,
1571 bool empty)
1572{
1573 RangeType *range;
1574 int cmp;
1575 Size msize;
1576 Pointer ptr;
1577 int16 typlen;
1578 bool typbyval;
1579 char typalign;
1580 char typstorage;
1581 char flags = 0;
1582
1583 /*
1584 * Verify range is not invalid on its face, and construct flags value,
1585 * preventing any non-canonical combinations such as infinite+inclusive.
1586 */
1587 Assert(lower->lower);
1588 Assert(!upper->lower);
1589
1590 if (empty)
1591 flags |= RANGE_EMPTY;
1592 else
1593 {
1594 cmp = range_cmp_bound_values(typcache, lower, upper);
1595
1596 /* error check: if lower bound value is above upper, it's wrong */
1597 if (cmp > 0)
1598 ereport(ERROR,
1599 (errcode(ERRCODE_DATA_EXCEPTION),
1600 errmsg("range lower bound must be less than or equal to range upper bound")));
1601
1602 /* if bounds are equal, and not both inclusive, range is empty */
1603 if (cmp == 0 && !(lower->inclusive && upper->inclusive))
1604 flags |= RANGE_EMPTY;
1605 else
1606 {
1607 /* infinite boundaries are never inclusive */
1608 if (lower->infinite)
1609 flags |= RANGE_LB_INF;
1610 else if (lower->inclusive)
1611 flags |= RANGE_LB_INC;
1612 if (upper->infinite)
1613 flags |= RANGE_UB_INF;
1614 else if (upper->inclusive)
1615 flags |= RANGE_UB_INC;
1616 }
1617 }
1618
1619 /* Fetch information about range's element type */
1620 typlen = typcache->rngelemtype->typlen;
1621 typbyval = typcache->rngelemtype->typbyval;
1622 typalign = typcache->rngelemtype->typalign;
1623 typstorage = typcache->rngelemtype->typstorage;
1624
1625 /* Count space for varlena header and range type's OID */
1626 msize = sizeof(RangeType);
1627 Assert(msize == MAXALIGN(msize));
1628
1629 /* Count space for bounds */
1630 if (RANGE_HAS_LBOUND(flags))
1631 {
1632 /*
1633 * Make sure item to be inserted is not toasted. It is essential that
1634 * we not insert an out-of-line toast value pointer into a range
1635 * object, for the same reasons that arrays and records can't contain
1636 * them. It would work to store a compressed-in-line value, but we
1637 * prefer to decompress and then let compression be applied to the
1638 * whole range object if necessary. But, unlike arrays, we do allow
1639 * short-header varlena objects to stay as-is.
1640 */
1641 if (typlen == -1)
1642 lower->val = PointerGetDatum(PG_DETOAST_DATUM_PACKED(lower->val));
1643
1644 msize = datum_compute_size(msize, lower->val, typbyval, typalign,
1645 typlen, typstorage);
1646 }
1647
1648 if (RANGE_HAS_UBOUND(flags))
1649 {
1650 /* Make sure item to be inserted is not toasted */
1651 if (typlen == -1)
1652 upper->val = PointerGetDatum(PG_DETOAST_DATUM_PACKED(upper->val));
1653
1654 msize = datum_compute_size(msize, upper->val, typbyval, typalign,
1655 typlen, typstorage);
1656 }
1657
1658 /* Add space for flag byte */
1659 msize += sizeof(char);
1660
1661 /* Note: zero-fill is required here, just as in heap tuples */
1662 range = (RangeType *) palloc0(msize);
1663 SET_VARSIZE(range, msize);
1664
1665 /* Now fill in the datum */
1666 range->rangetypid = typcache->type_id;
1667
1668 ptr = (char *) (range + 1);
1669
1670 if (RANGE_HAS_LBOUND(flags))
1671 {
1672 Assert(lower->lower);
1673 ptr = datum_write(ptr, lower->val, typbyval, typalign, typlen,
1674 typstorage);
1675 }
1676
1677 if (RANGE_HAS_UBOUND(flags))
1678 {
1679 Assert(!upper->lower);
1680 ptr = datum_write(ptr, upper->val, typbyval, typalign, typlen,
1681 typstorage);
1682 }
1683
1684 *((char *) ptr) = flags;
1685
1686 return range;
1687}
1688
1689/*
1690 * range_deserialize: deconstruct a range value
1691 *
1692 * NB: the given range object must be fully detoasted; it cannot have a
1693 * short varlena header.
1694 *
1695 * Note that if the element type is pass-by-reference, the datums in the
1696 * RangeBound structs will be pointers into the given range object.
1697 */
1698void
1699range_deserialize(TypeCacheEntry *typcache, RangeType *range,
1700 RangeBound *lower, RangeBound *upper, bool *empty)
1701{
1702 char flags;
1703 int16 typlen;
1704 bool typbyval;
1705 char typalign;
1706 Pointer ptr;
1707 Datum lbound;
1708 Datum ubound;
1709
1710 /* assert caller passed the right typcache entry */
1711 Assert(RangeTypeGetOid(range) == typcache->type_id);
1712
1713 /* fetch the flag byte from datum's last byte */
1714 flags = *((char *) range + VARSIZE(range) - 1);
1715
1716 /* fetch information about range's element type */
1717 typlen = typcache->rngelemtype->typlen;
1718 typbyval = typcache->rngelemtype->typbyval;
1719 typalign = typcache->rngelemtype->typalign;
1720
1721 /* initialize data pointer just after the range OID */
1722 ptr = (Pointer) (range + 1);
1723
1724 /* fetch lower bound, if any */
1725 if (RANGE_HAS_LBOUND(flags))
1726 {
1727 /* att_align_pointer cannot be necessary here */
1728 lbound = fetch_att(ptr, typbyval, typlen);
1729 ptr = (Pointer) att_addlength_pointer(ptr, typlen, ptr);
1730 }
1731 else
1732 lbound = (Datum) 0;
1733
1734 /* fetch upper bound, if any */
1735 if (RANGE_HAS_UBOUND(flags))
1736 {
1737 ptr = (Pointer) att_align_pointer(ptr, typalign, typlen, ptr);
1738 ubound = fetch_att(ptr, typbyval, typlen);
1739 /* no need for att_addlength_pointer */
1740 }
1741 else
1742 ubound = (Datum) 0;
1743
1744 /* emit results */
1745
1746 *empty = (flags & RANGE_EMPTY) != 0;
1747
1748 lower->val = lbound;
1749 lower->infinite = (flags & RANGE_LB_INF) != 0;
1750 lower->inclusive = (flags & RANGE_LB_INC) != 0;
1751 lower->lower = true;
1752
1753 upper->val = ubound;
1754 upper->infinite = (flags & RANGE_UB_INF) != 0;
1755 upper->inclusive = (flags & RANGE_UB_INC) != 0;
1756 upper->lower = false;
1757}
1758
1759/*
1760 * range_get_flags: just get the flags from a RangeType value.
1761 *
1762 * This is frequently useful in places that only need the flags and not
1763 * the full results of range_deserialize.
1764 */
1765char
1766range_get_flags(RangeType *range)
1767{
1768 /* fetch the flag byte from datum's last byte */
1769 return *((char *) range + VARSIZE(range) - 1);
1770}
1771
1772/*
1773 * range_set_contain_empty: set the RANGE_CONTAIN_EMPTY bit in the value.
1774 *
1775 * This is only needed in GiST operations, so we don't include a provision
1776 * for setting it in range_serialize; rather, this function must be applied
1777 * afterwards.
1778 */
1779void
1780range_set_contain_empty(RangeType *range)
1781{
1782 char *flagsp;
1783
1784 /* flag byte is datum's last byte */
1785 flagsp = (char *) range + VARSIZE(range) - 1;
1786
1787 *flagsp |= RANGE_CONTAIN_EMPTY;
1788}
1789
1790/*
1791 * This both serializes and canonicalizes (if applicable) the range.
1792 * This should be used by most callers.
1793 */
1794RangeType *
1795make_range(TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper,
1796 bool empty)
1797{
1798 RangeType *range;
1799
1800 range = range_serialize(typcache, lower, upper, empty);
1801
1802 /* no need to call canonical on empty ranges ... */
1803 if (OidIsValid(typcache->rng_canonical_finfo.fn_oid) &&
1804 !RangeIsEmpty(range))
1805 range = DatumGetRangeTypeP(FunctionCall1(&typcache->rng_canonical_finfo,
1806 RangeTypePGetDatum(range)));
1807
1808 return range;
1809}
1810
1811/*
1812 * Compare two range boundary points, returning <0, 0, or >0 according to
1813 * whether b1 is less than, equal to, or greater than b2.
1814 *
1815 * The boundaries can be any combination of upper and lower; so it's useful
1816 * for a variety of operators.
1817 *
1818 * The simple case is when b1 and b2 are both finite and inclusive, in which
1819 * case the result is just a comparison of the values held in b1 and b2.
1820 *
1821 * If a bound is exclusive, then we need to know whether it's a lower bound,
1822 * in which case we treat the boundary point as "just greater than" the held
1823 * value; or an upper bound, in which case we treat the boundary point as
1824 * "just less than" the held value.
1825 *
1826 * If a bound is infinite, it represents minus infinity (less than every other
1827 * point) if it's a lower bound; or plus infinity (greater than every other
1828 * point) if it's an upper bound.
1829 *
1830 * There is only one case where two boundaries compare equal but are not
1831 * identical: when both bounds are inclusive and hold the same finite value,
1832 * but one is an upper bound and the other a lower bound.
1833 */
1834int
1835range_cmp_bounds(TypeCacheEntry *typcache, RangeBound *b1, RangeBound *b2)
1836{
1837 int32 result;
1838
1839 /*
1840 * First, handle cases involving infinity, which don't require invoking
1841 * the comparison proc.
1842 */
1843 if (b1->infinite && b2->infinite)
1844 {
1845 /*
1846 * Both are infinity, so they are equal unless one is lower and the
1847 * other not.
1848 */
1849 if (b1->lower == b2->lower)
1850 return 0;
1851 else
1852 return b1->lower ? -1 : 1;
1853 }
1854 else if (b1->infinite)
1855 return b1->lower ? -1 : 1;
1856 else if (b2->infinite)
1857 return b2->lower ? 1 : -1;
1858
1859 /*
1860 * Both boundaries are finite, so compare the held values.
1861 */
1862 result = DatumGetInt32(FunctionCall2Coll(&typcache->rng_cmp_proc_finfo,
1863 typcache->rng_collation,
1864 b1->val, b2->val));
1865
1866 /*
1867 * If the comparison is anything other than equal, we're done. If they
1868 * compare equal though, we still have to consider whether the boundaries
1869 * are inclusive or exclusive.
1870 */
1871 if (result == 0)
1872 {
1873 if (!b1->inclusive && !b2->inclusive)
1874 {
1875 /* both are exclusive */
1876 if (b1->lower == b2->lower)
1877 return 0;
1878 else
1879 return b1->lower ? 1 : -1;
1880 }
1881 else if (!b1->inclusive)
1882 return b1->lower ? 1 : -1;
1883 else if (!b2->inclusive)
1884 return b2->lower ? -1 : 1;
1885 else
1886 {
1887 /*
1888 * Both are inclusive and the values held are equal, so they are
1889 * equal regardless of whether they are upper or lower boundaries,
1890 * or a mix.
1891 */
1892 return 0;
1893 }
1894 }
1895
1896 return result;
1897}
1898
1899/*
1900 * Compare two range boundary point values, returning <0, 0, or >0 according
1901 * to whether b1 is less than, equal to, or greater than b2.
1902 *
1903 * This is similar to but simpler than range_cmp_bounds(). We just compare
1904 * the values held in b1 and b2, ignoring inclusive/exclusive flags. The
1905 * lower/upper flags only matter for infinities, where they tell us if the
1906 * infinity is plus or minus.
1907 */
1908int
1909range_cmp_bound_values(TypeCacheEntry *typcache, RangeBound *b1,
1910 RangeBound *b2)
1911{
1912 /*
1913 * First, handle cases involving infinity, which don't require invoking
1914 * the comparison proc.
1915 */
1916 if (b1->infinite && b2->infinite)
1917 {
1918 /*
1919 * Both are infinity, so they are equal unless one is lower and the
1920 * other not.
1921 */
1922 if (b1->lower == b2->lower)
1923 return 0;
1924 else
1925 return b1->lower ? -1 : 1;
1926 }
1927 else if (b1->infinite)
1928 return b1->lower ? -1 : 1;
1929 else if (b2->infinite)
1930 return b2->lower ? 1 : -1;
1931
1932 /*
1933 * Both boundaries are finite, so compare the held values.
1934 */
1935 return DatumGetInt32(FunctionCall2Coll(&typcache->rng_cmp_proc_finfo,
1936 typcache->rng_collation,
1937 b1->val, b2->val));
1938}
1939
1940/*
1941 * Build an empty range value of the type indicated by the typcache entry.
1942 */
1943RangeType *
1944make_empty_range(TypeCacheEntry *typcache)
1945{
1946 RangeBound lower;
1947 RangeBound upper;
1948
1949 lower.val = (Datum) 0;
1950 lower.infinite = false;
1951 lower.inclusive = false;
1952 lower.lower = true;
1953
1954 upper.val = (Datum) 0;
1955 upper.infinite = false;
1956 upper.inclusive = false;
1957 upper.lower = false;
1958
1959 return make_range(typcache, &lower, &upper, true);
1960}
1961
1962
1963/*
1964 *----------------------------------------------------------
1965 * STATIC FUNCTIONS
1966 *----------------------------------------------------------
1967 */
1968
1969/*
1970 * Given a string representing the flags for the range type, return the flags
1971 * represented as a char.
1972 */
1973static char
1974range_parse_flags(const char *flags_str)
1975{
1976 char flags = 0;
1977
1978 if (flags_str[0] == '\0' ||
1979 flags_str[1] == '\0' ||
1980 flags_str[2] != '\0')
1981 ereport(ERROR,
1982 (errcode(ERRCODE_SYNTAX_ERROR),
1983 errmsg("invalid range bound flags"),
1984 errhint("Valid values are \"[]\", \"[)\", \"(]\", and \"()\".")));
1985
1986 switch (flags_str[0])
1987 {
1988 case '[':
1989 flags |= RANGE_LB_INC;
1990 break;
1991 case '(':
1992 break;
1993 default:
1994 ereport(ERROR,
1995 (errcode(ERRCODE_SYNTAX_ERROR),
1996 errmsg("invalid range bound flags"),
1997 errhint("Valid values are \"[]\", \"[)\", \"(]\", and \"()\".")));
1998 }
1999
2000 switch (flags_str[1])
2001 {
2002 case ']':
2003 flags |= RANGE_UB_INC;
2004 break;
2005 case ')':
2006 break;
2007 default:
2008 ereport(ERROR,
2009 (errcode(ERRCODE_SYNTAX_ERROR),
2010 errmsg("invalid range bound flags"),
2011 errhint("Valid values are \"[]\", \"[)\", \"(]\", and \"()\".")));
2012 }
2013
2014 return flags;
2015}
2016
2017/*
2018 * Parse range input.
2019 *
2020 * Input parameters:
2021 * string: input string to be parsed
2022 * Output parameters:
2023 * *flags: receives flags bitmask
2024 * *lbound_str: receives palloc'd lower bound string, or NULL if none
2025 * *ubound_str: receives palloc'd upper bound string, or NULL if none
2026 *
2027 * This is modeled somewhat after record_in in rowtypes.c.
2028 * The input syntax is:
2029 * <range> := EMPTY
2030 * | <lb-inc> <string>, <string> <ub-inc>
2031 * <lb-inc> := '[' | '('
2032 * <ub-inc> := ']' | ')'
2033 *
2034 * Whitespace before or after <range> is ignored. Whitespace within a <string>
2035 * is taken literally and becomes part of the input string for that bound.
2036 *
2037 * A <string> of length zero is taken as "infinite" (i.e. no bound), unless it
2038 * is surrounded by double-quotes, in which case it is the literal empty
2039 * string.
2040 *
2041 * Within a <string>, special characters (such as comma, parenthesis, or
2042 * brackets) can be enclosed in double-quotes or escaped with backslash. Within
2043 * double-quotes, a double-quote can be escaped with double-quote or backslash.
2044 */
2045static void
2046range_parse(const char *string, char *flags, char **lbound_str,
2047 char **ubound_str)
2048{
2049 const char *ptr = string;
2050 bool infinite;
2051
2052 *flags = 0;
2053
2054 /* consume whitespace */
2055 while (*ptr != '\0' && isspace((unsigned char) *ptr))
2056 ptr++;
2057
2058 /* check for empty range */
2059 if (pg_strncasecmp(ptr, RANGE_EMPTY_LITERAL,
2060 strlen(RANGE_EMPTY_LITERAL)) == 0)
2061 {
2062 *flags = RANGE_EMPTY;
2063 *lbound_str = NULL;
2064 *ubound_str = NULL;
2065
2066 ptr += strlen(RANGE_EMPTY_LITERAL);
2067
2068 /* the rest should be whitespace */
2069 while (*ptr != '\0' && isspace((unsigned char) *ptr))
2070 ptr++;
2071
2072 /* should have consumed everything */
2073 if (*ptr != '\0')
2074 ereport(ERROR,
2075 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2076 errmsg("malformed range literal: \"%s\"",
2077 string),
2078 errdetail("Junk after \"empty\" key word.")));
2079
2080 return;
2081 }
2082
2083 if (*ptr == '[')
2084 {
2085 *flags |= RANGE_LB_INC;
2086 ptr++;
2087 }
2088 else if (*ptr == '(')
2089 ptr++;
2090 else
2091 ereport(ERROR,
2092 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2093 errmsg("malformed range literal: \"%s\"",
2094 string),
2095 errdetail("Missing left parenthesis or bracket.")));
2096
2097 ptr = range_parse_bound(string, ptr, lbound_str, &infinite);
2098 if (infinite)
2099 *flags |= RANGE_LB_INF;
2100
2101 if (*ptr == ',')
2102 ptr++;
2103 else
2104 ereport(ERROR,
2105 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2106 errmsg("malformed range literal: \"%s\"",
2107 string),
2108 errdetail("Missing comma after lower bound.")));
2109
2110 ptr = range_parse_bound(string, ptr, ubound_str, &infinite);
2111 if (infinite)
2112 *flags |= RANGE_UB_INF;
2113
2114 if (*ptr == ']')
2115 {
2116 *flags |= RANGE_UB_INC;
2117 ptr++;
2118 }
2119 else if (*ptr == ')')
2120 ptr++;
2121 else /* must be a comma */
2122 ereport(ERROR,
2123 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2124 errmsg("malformed range literal: \"%s\"",
2125 string),
2126 errdetail("Too many commas.")));
2127
2128 /* consume whitespace */
2129 while (*ptr != '\0' && isspace((unsigned char) *ptr))
2130 ptr++;
2131
2132 if (*ptr != '\0')
2133 ereport(ERROR,
2134 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2135 errmsg("malformed range literal: \"%s\"",
2136 string),
2137 errdetail("Junk after right parenthesis or bracket.")));
2138}
2139
2140/*
2141 * Helper for range_parse: parse and de-quote one bound string.
2142 *
2143 * We scan until finding comma, right parenthesis, or right bracket.
2144 *
2145 * Input parameters:
2146 * string: entire input string (used only for error reports)
2147 * ptr: where to start parsing bound
2148 * Output parameters:
2149 * *bound_str: receives palloc'd bound string, or NULL if none
2150 * *infinite: set true if no bound, else false
2151 *
2152 * The return value is the scan ptr, advanced past the bound string.
2153 */
2154static const char *
2155range_parse_bound(const char *string, const char *ptr,
2156 char **bound_str, bool *infinite)
2157{
2158 StringInfoData buf;
2159
2160 /* Check for null: completely empty input means null */
2161 if (*ptr == ',' || *ptr == ')' || *ptr == ']')
2162 {
2163 *bound_str = NULL;
2164 *infinite = true;
2165 }
2166 else
2167 {
2168 /* Extract string for this bound */
2169 bool inquote = false;
2170
2171 initStringInfo(&buf);
2172 while (inquote || !(*ptr == ',' || *ptr == ')' || *ptr == ']'))
2173 {
2174 char ch = *ptr++;
2175
2176 if (ch == '\0')
2177 ereport(ERROR,
2178 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2179 errmsg("malformed range literal: \"%s\"",
2180 string),
2181 errdetail("Unexpected end of input.")));
2182 if (ch == '\\')
2183 {
2184 if (*ptr == '\0')
2185 ereport(ERROR,
2186 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2187 errmsg("malformed range literal: \"%s\"",
2188 string),
2189 errdetail("Unexpected end of input.")));
2190 appendStringInfoChar(&buf, *ptr++);
2191 }
2192 else if (ch == '"')
2193 {
2194 if (!inquote)
2195 inquote = true;
2196 else if (*ptr == '"')
2197 {
2198 /* doubled quote within quote sequence */
2199 appendStringInfoChar(&buf, *ptr++);
2200 }
2201 else
2202 inquote = false;
2203 }
2204 else
2205 appendStringInfoChar(&buf, ch);
2206 }
2207
2208 *bound_str = buf.data;
2209 *infinite = false;
2210 }
2211
2212 return ptr;
2213}
2214
2215/*
2216 * Convert a deserialized range value to text form
2217 *
2218 * Inputs are the flags byte, and the two bound values already converted to
2219 * text (but not yet quoted). If no bound value, pass NULL.
2220 *
2221 * Result is a palloc'd string
2222 */
2223static char *
2224range_deparse(char flags, const char *lbound_str, const char *ubound_str)
2225{
2226 StringInfoData buf;
2227
2228 if (flags & RANGE_EMPTY)
2229 return pstrdup(RANGE_EMPTY_LITERAL);
2230
2231 initStringInfo(&buf);
2232
2233 appendStringInfoChar(&buf, (flags & RANGE_LB_INC) ? '[' : '(');
2234
2235 if (RANGE_HAS_LBOUND(flags))
2236 appendStringInfoString(&buf, range_bound_escape(lbound_str));
2237
2238 appendStringInfoChar(&buf, ',');
2239
2240 if (RANGE_HAS_UBOUND(flags))
2241 appendStringInfoString(&buf, range_bound_escape(ubound_str));
2242
2243 appendStringInfoChar(&buf, (flags & RANGE_UB_INC) ? ']' : ')');
2244
2245 return buf.data;
2246}
2247
2248/*
2249 * Helper for range_deparse: quote a bound value as needed
2250 *
2251 * Result is a palloc'd string
2252 */
2253static char *
2254range_bound_escape(const char *value)
2255{
2256 bool nq;
2257 const char *ptr;
2258 StringInfoData buf;
2259
2260 initStringInfo(&buf);
2261
2262 /* Detect whether we need double quotes for this value */
2263 nq = (value[0] == '\0'); /* force quotes for empty string */
2264 for (ptr = value; *ptr; ptr++)
2265 {
2266 char ch = *ptr;
2267
2268 if (ch == '"' || ch == '\\' ||
2269 ch == '(' || ch == ')' ||
2270 ch == '[' || ch == ']' ||
2271 ch == ',' ||
2272 isspace((unsigned char) ch))
2273 {
2274 nq = true;
2275 break;
2276 }
2277 }
2278
2279 /* And emit the string */
2280 if (nq)
2281 appendStringInfoChar(&buf, '"');
2282 for (ptr = value; *ptr; ptr++)
2283 {
2284 char ch = *ptr;
2285
2286 if (ch == '"' || ch == '\\')
2287 appendStringInfoChar(&buf, ch);
2288 appendStringInfoChar(&buf, ch);
2289 }
2290 if (nq)
2291 appendStringInfoChar(&buf, '"');
2292
2293 return buf.data;
2294}
2295
2296/*
2297 * Test whether range r1 contains range r2.
2298 *
2299 * Caller has already checked that they are the same range type, and looked up
2300 * the necessary typcache entry.
2301 */
2302bool
2303range_contains_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
2304{
2305 RangeBound lower1;
2306 RangeBound upper1;
2307 bool empty1;
2308 RangeBound lower2;
2309 RangeBound upper2;
2310 bool empty2;
2311
2312 /* Different types should be prevented by ANYRANGE matching rules */
2313 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
2314 elog(ERROR, "range types do not match");
2315
2316 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
2317 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
2318
2319 /* If either range is empty, the answer is easy */
2320 if (empty2)
2321 return true;
2322 else if (empty1)
2323 return false;
2324
2325 /* Else we must have lower1 <= lower2 and upper1 >= upper2 */
2326 if (range_cmp_bounds(typcache, &lower1, &lower2) > 0)
2327 return false;
2328 if (range_cmp_bounds(typcache, &upper1, &upper2) < 0)
2329 return false;
2330
2331 return true;
2332}
2333
2334bool
2335range_contained_by_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
2336{
2337 return range_contains_internal(typcache, r2, r1);
2338}
2339
2340/*
2341 * Test whether range r contains a specific element value.
2342 */
2343bool
2344range_contains_elem_internal(TypeCacheEntry *typcache, RangeType *r, Datum val)
2345{
2346 RangeBound lower;
2347 RangeBound upper;
2348 bool empty;
2349 int32 cmp;
2350
2351 range_deserialize(typcache, r, &lower, &upper, &empty);
2352
2353 if (empty)
2354 return false;
2355
2356 if (!lower.infinite)
2357 {
2358 cmp = DatumGetInt32(FunctionCall2Coll(&typcache->rng_cmp_proc_finfo,
2359 typcache->rng_collation,
2360 lower.val, val));
2361 if (cmp > 0)
2362 return false;
2363 if (cmp == 0 && !lower.inclusive)
2364 return false;
2365 }
2366
2367 if (!upper.infinite)
2368 {
2369 cmp = DatumGetInt32(FunctionCall2Coll(&typcache->rng_cmp_proc_finfo,
2370 typcache->rng_collation,
2371 upper.val, val));
2372 if (cmp < 0)
2373 return false;
2374 if (cmp == 0 && !upper.inclusive)
2375 return false;
2376 }
2377
2378 return true;
2379}
2380
2381
2382/*
2383 * datum_compute_size() and datum_write() are used to insert the bound
2384 * values into a range object. They are modeled after heaptuple.c's
2385 * heap_compute_data_size() and heap_fill_tuple(), but we need not handle
2386 * null values here. TYPE_IS_PACKABLE must test the same conditions as
2387 * heaptuple.c's ATT_IS_PACKABLE macro.
2388 */
2389
2390/* Does datatype allow packing into the 1-byte-header varlena format? */
2391#define TYPE_IS_PACKABLE(typlen, typstorage) \
2392 ((typlen) == -1 && (typstorage) != 'p')
2393
2394/*
2395 * Increment data_length by the space needed by the datum, including any
2396 * preceding alignment padding.
2397 */
2398static Size
2399datum_compute_size(Size data_length, Datum val, bool typbyval, char typalign,
2400 int16 typlen, char typstorage)
2401{
2402 if (TYPE_IS_PACKABLE(typlen, typstorage) &&
2403 VARATT_CAN_MAKE_SHORT(DatumGetPointer(val)))
2404 {
2405 /*
2406 * we're anticipating converting to a short varlena header, so adjust
2407 * length and don't count any alignment
2408 */
2409 data_length += VARATT_CONVERTED_SHORT_SIZE(DatumGetPointer(val));
2410 }
2411 else
2412 {
2413 data_length = att_align_datum(data_length, typalign, typlen, val);
2414 data_length = att_addlength_datum(data_length, typlen, val);
2415 }
2416
2417 return data_length;
2418}
2419
2420/*
2421 * Write the given datum beginning at ptr (after advancing to correct
2422 * alignment, if needed). Return the pointer incremented by space used.
2423 */
2424static Pointer
2425datum_write(Pointer ptr, Datum datum, bool typbyval, char typalign,
2426 int16 typlen, char typstorage)
2427{
2428 Size data_length;
2429
2430 if (typbyval)
2431 {
2432 /* pass-by-value */
2433 ptr = (char *) att_align_nominal(ptr, typalign);
2434 store_att_byval(ptr, datum, typlen);
2435 data_length = typlen;
2436 }
2437 else if (typlen == -1)
2438 {
2439 /* varlena */
2440 Pointer val = DatumGetPointer(datum);
2441
2442 if (VARATT_IS_EXTERNAL(val))
2443 {
2444 /*
2445 * Throw error, because we must never put a toast pointer inside a
2446 * range object. Caller should have detoasted it.
2447 */
2448 elog(ERROR, "cannot store a toast pointer inside a range");
2449 data_length = 0; /* keep compiler quiet */
2450 }
2451 else if (VARATT_IS_SHORT(val))
2452 {
2453 /* no alignment for short varlenas */
2454 data_length = VARSIZE_SHORT(val);
2455 memcpy(ptr, val, data_length);
2456 }
2457 else if (TYPE_IS_PACKABLE(typlen, typstorage) &&
2458 VARATT_CAN_MAKE_SHORT(val))
2459 {
2460 /* convert to short varlena -- no alignment */
2461 data_length = VARATT_CONVERTED_SHORT_SIZE(val);
2462 SET_VARSIZE_SHORT(ptr, data_length);
2463 memcpy(ptr + 1, VARDATA(val), data_length - 1);
2464 }
2465 else
2466 {
2467 /* full 4-byte header varlena */
2468 ptr = (char *) att_align_nominal(ptr, typalign);
2469 data_length = VARSIZE(val);
2470 memcpy(ptr, val, data_length);
2471 }
2472 }
2473 else if (typlen == -2)
2474 {
2475 /* cstring ... never needs alignment */
2476 Assert(typalign == 'c');
2477 data_length = strlen(DatumGetCString(datum)) + 1;
2478 memcpy(ptr, DatumGetPointer(datum), data_length);
2479 }
2480 else
2481 {
2482 /* fixed-length pass-by-reference */
2483 ptr = (char *) att_align_nominal(ptr, typalign);
2484 Assert(typlen > 0);
2485 data_length = typlen;
2486 memcpy(ptr, DatumGetPointer(datum), data_length);
2487 }
2488
2489 ptr += data_length;
2490
2491 return ptr;
2492}
2493