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