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