PostgreSQL Source Code git master
rangetypes.c
Go to the documentation of this file.
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-2025, 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 "common/hashfn.h"
34#include "funcapi.h"
35#include "libpq/pqformat.h"
36#include "miscadmin.h"
37#include "nodes/makefuncs.h"
38#include "nodes/miscnodes.h"
39#include "nodes/supportnodes.h"
40#include "optimizer/clauses.h"
41#include "optimizer/cost.h"
42#include "optimizer/optimizer.h"
43#include "utils/builtins.h"
44#include "utils/date.h"
45#include "utils/lsyscache.h"
46#include "utils/rangetypes.h"
47#include "utils/sortsupport.h"
48#include "utils/timestamp.h"
49#include "varatt.h"
50
51
52/* fn_extra cache entry for one of the range I/O functions */
53typedef struct RangeIOData
54{
55 TypeCacheEntry *typcache; /* range type's typcache entry */
56 FmgrInfo typioproc; /* element type's I/O function */
57 Oid typioparam; /* element type's I/O parameter */
59
60
61static RangeIOData *get_range_io_data(FunctionCallInfo fcinfo, Oid rngtypid,
62 IOFuncSelector func);
63static int range_fast_cmp(Datum a, Datum b, SortSupport ssup);
64static char range_parse_flags(const char *flags_str);
65static bool range_parse(const char *string, char *flags, char **lbound_str,
66 char **ubound_str, Node *escontext);
67static const char *range_parse_bound(const char *string, const char *ptr,
68 char **bound_str, bool *infinite,
69 Node *escontext);
70static char *range_deparse(char flags, const char *lbound_str,
71 const char *ubound_str);
72static char *range_bound_escape(const char *value);
73static Size datum_compute_size(Size data_length, Datum val, bool typbyval,
74 char typalign, int16 typlen, char typstorage);
75static Pointer datum_write(Pointer ptr, Datum datum, bool typbyval,
76 char typalign, int16 typlen, char typstorage);
78 Expr *rangeExpr, Expr *elemExpr);
79static Expr *build_bound_expr(Expr *elemExpr, Datum val,
80 bool isLowerBound, bool isInclusive,
81 TypeCacheEntry *typeCache,
82 Oid opfamily, Oid rng_collation);
83
84
85/*
86 *----------------------------------------------------------
87 * I/O FUNCTIONS
88 *----------------------------------------------------------
89 */
90
93{
94 char *input_str = PG_GETARG_CSTRING(0);
95 Oid rngtypoid = PG_GETARG_OID(1);
96 Oid typmod = PG_GETARG_INT32(2);
97 Node *escontext = fcinfo->context;
99 RangeIOData *cache;
100 char flags;
101 char *lbound_str;
102 char *ubound_str;
105
106 check_stack_depth(); /* recurses when subtype is a range type */
107
108 cache = get_range_io_data(fcinfo, rngtypoid, IOFunc_input);
109
110 /* parse */
111 if (!range_parse(input_str, &flags, &lbound_str, &ubound_str, escontext))
113
114 /* call element type's input function */
115 if (RANGE_HAS_LBOUND(flags))
116 if (!InputFunctionCallSafe(&cache->typioproc, lbound_str,
117 cache->typioparam, typmod,
118 escontext, &lower.val))
120 if (RANGE_HAS_UBOUND(flags))
121 if (!InputFunctionCallSafe(&cache->typioproc, ubound_str,
122 cache->typioparam, typmod,
123 escontext, &upper.val))
125
126 lower.infinite = (flags & RANGE_LB_INF) != 0;
127 lower.inclusive = (flags & RANGE_LB_INC) != 0;
128 lower.lower = true;
129 upper.infinite = (flags & RANGE_UB_INF) != 0;
130 upper.inclusive = (flags & RANGE_UB_INC) != 0;
131 upper.lower = false;
132
133 /* serialize and canonicalize */
134 range = make_range(cache->typcache, &lower, &upper,
135 flags & RANGE_EMPTY, escontext);
136
138}
139
140Datum
142{
144 char *output_str;
145 RangeIOData *cache;
146 char flags;
147 char *lbound_str = NULL;
148 char *ubound_str = NULL;
151 bool empty;
152
153 check_stack_depth(); /* recurses when subtype is a range type */
154
156
157 /* deserialize */
158 range_deserialize(cache->typcache, range, &lower, &upper, &empty);
159 flags = range_get_flags(range);
160
161 /* call element type's output function */
162 if (RANGE_HAS_LBOUND(flags))
163 lbound_str = OutputFunctionCall(&cache->typioproc, lower.val);
164 if (RANGE_HAS_UBOUND(flags))
165 ubound_str = OutputFunctionCall(&cache->typioproc, upper.val);
166
167 /* construct result string */
168 output_str = range_deparse(flags, lbound_str, ubound_str);
169
170 PG_RETURN_CSTRING(output_str);
171}
172
173/*
174 * Binary representation: The first byte is the flags, then the lower bound
175 * (if present), then the upper bound (if present). Each bound is represented
176 * by a 4-byte length header and the binary representation of that bound (as
177 * returned by a call to the send function for the subtype).
178 */
179
180Datum
182{
184 Oid rngtypoid = PG_GETARG_OID(1);
185 int32 typmod = PG_GETARG_INT32(2);
187 RangeIOData *cache;
188 char flags;
191
192 check_stack_depth(); /* recurses when subtype is a range type */
193
194 cache = get_range_io_data(fcinfo, rngtypoid, IOFunc_receive);
195
196 /* receive the flags... */
197 flags = (unsigned char) pq_getmsgbyte(buf);
198
199 /*
200 * Mask out any unsupported flags, particularly RANGE_xB_NULL which would
201 * confuse following tests. Note that range_serialize will take care of
202 * cleaning up any inconsistencies in the remaining flags.
203 */
204 flags &= (RANGE_EMPTY |
209
210 /* receive the bounds ... */
211 if (RANGE_HAS_LBOUND(flags))
212 {
213 uint32 bound_len = pq_getmsgint(buf, 4);
214 const char *bound_data = pq_getmsgbytes(buf, bound_len);
215 StringInfoData bound_buf;
216
217 initStringInfo(&bound_buf);
218 appendBinaryStringInfo(&bound_buf, bound_data, bound_len);
219
220 lower.val = ReceiveFunctionCall(&cache->typioproc,
221 &bound_buf,
222 cache->typioparam,
223 typmod);
224 pfree(bound_buf.data);
225 }
226 else
227 lower.val = (Datum) 0;
228
229 if (RANGE_HAS_UBOUND(flags))
230 {
231 uint32 bound_len = pq_getmsgint(buf, 4);
232 const char *bound_data = pq_getmsgbytes(buf, bound_len);
233 StringInfoData bound_buf;
234
235 initStringInfo(&bound_buf);
236 appendBinaryStringInfo(&bound_buf, bound_data, bound_len);
237
238 upper.val = ReceiveFunctionCall(&cache->typioproc,
239 &bound_buf,
240 cache->typioparam,
241 typmod);
242 pfree(bound_buf.data);
243 }
244 else
245 upper.val = (Datum) 0;
246
248
249 /* finish constructing RangeBound representation */
250 lower.infinite = (flags & RANGE_LB_INF) != 0;
251 lower.inclusive = (flags & RANGE_LB_INC) != 0;
252 lower.lower = true;
253 upper.infinite = (flags & RANGE_UB_INF) != 0;
254 upper.inclusive = (flags & RANGE_UB_INC) != 0;
255 upper.lower = false;
256
257 /* serialize and canonicalize */
258 range = make_range(cache->typcache, &lower, &upper,
259 flags & RANGE_EMPTY, NULL);
260
262}
263
264Datum
266{
269 RangeIOData *cache;
270 char flags;
273 bool empty;
274
275 check_stack_depth(); /* recurses when subtype is a range type */
276
278
280
281 /* deserialize */
282 range_deserialize(cache->typcache, range, &lower, &upper, &empty);
283 flags = range_get_flags(range);
284
285 /* construct output */
287
288 pq_sendbyte(&buf, flags);
289
290 if (RANGE_HAS_LBOUND(flags))
291 {
292 bytea *bound = SendFunctionCall(&cache->typioproc, lower.val);
293 uint32 bound_len = VARSIZE(bound) - VARHDRSZ;
294 char *bound_data = VARDATA(bound);
295
296 pq_sendint32(&buf, bound_len);
297 pq_sendbytes(&buf, bound_data, bound_len);
298 }
299
300 if (RANGE_HAS_UBOUND(flags))
301 {
302 bytea *bound = SendFunctionCall(&cache->typioproc, upper.val);
303 uint32 bound_len = VARSIZE(bound) - VARHDRSZ;
304 char *bound_data = VARDATA(bound);
305
306 pq_sendint32(&buf, bound_len);
307 pq_sendbytes(&buf, bound_data, bound_len);
308 }
309
311}
312
313/*
314 * get_range_io_data: get cached information needed for range type I/O
315 *
316 * The range I/O functions need a bit more cached info than other range
317 * functions, so they store a RangeIOData struct in fn_extra, not just a
318 * pointer to a type cache entry.
319 */
320static RangeIOData *
322{
323 RangeIOData *cache = (RangeIOData *) fcinfo->flinfo->fn_extra;
324
325 if (cache == NULL || cache->typcache->type_id != rngtypid)
326 {
327 int16 typlen;
328 bool typbyval;
329 char typalign;
330 char typdelim;
331 Oid typiofunc;
332
333 cache = (RangeIOData *) MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
334 sizeof(RangeIOData));
336 if (cache->typcache->rngelemtype == NULL)
337 elog(ERROR, "type %u is not a range type", rngtypid);
338
339 /* get_type_io_data does more than we need, but is convenient */
341 func,
342 &typlen,
343 &typbyval,
344 &typalign,
345 &typdelim,
346 &cache->typioparam,
347 &typiofunc);
348
349 if (!OidIsValid(typiofunc))
350 {
351 /* this could only happen for receive or send */
352 if (func == IOFunc_receive)
354 (errcode(ERRCODE_UNDEFINED_FUNCTION),
355 errmsg("no binary input function available for type %s",
357 else
359 (errcode(ERRCODE_UNDEFINED_FUNCTION),
360 errmsg("no binary output function available for type %s",
362 }
363 fmgr_info_cxt(typiofunc, &cache->typioproc,
364 fcinfo->flinfo->fn_mcxt);
365
366 fcinfo->flinfo->fn_extra = cache;
367 }
368
369 return cache;
370}
371
372
373/*
374 *----------------------------------------------------------
375 * GENERIC FUNCTIONS
376 *----------------------------------------------------------
377 */
378
379/* Construct standard-form range value from two arguments */
380Datum
382{
383 Datum arg1 = PG_GETARG_DATUM(0);
384 Datum arg2 = PG_GETARG_DATUM(1);
385 Oid rngtypid = get_fn_expr_rettype(fcinfo->flinfo);
387 TypeCacheEntry *typcache;
390
391 typcache = range_get_typcache(fcinfo, rngtypid);
392
393 lower.val = PG_ARGISNULL(0) ? (Datum) 0 : arg1;
394 lower.infinite = PG_ARGISNULL(0);
395 lower.inclusive = true;
396 lower.lower = true;
397
398 upper.val = PG_ARGISNULL(1) ? (Datum) 0 : arg2;
399 upper.infinite = PG_ARGISNULL(1);
400 upper.inclusive = false;
401 upper.lower = false;
402
403 range = make_range(typcache, &lower, &upper, false, NULL);
404
406}
407
408/* Construct general range value from three arguments */
409Datum
411{
412 Datum arg1 = PG_GETARG_DATUM(0);
413 Datum arg2 = PG_GETARG_DATUM(1);
414 Oid rngtypid = get_fn_expr_rettype(fcinfo->flinfo);
416 TypeCacheEntry *typcache;
419 char flags;
420
421 typcache = range_get_typcache(fcinfo, rngtypid);
422
423 if (PG_ARGISNULL(2))
425 (errcode(ERRCODE_DATA_EXCEPTION),
426 errmsg("range constructor flags argument must not be null")));
427
429
430 lower.val = PG_ARGISNULL(0) ? (Datum) 0 : arg1;
431 lower.infinite = PG_ARGISNULL(0);
432 lower.inclusive = (flags & RANGE_LB_INC) != 0;
433 lower.lower = true;
434
435 upper.val = PG_ARGISNULL(1) ? (Datum) 0 : arg2;
436 upper.infinite = PG_ARGISNULL(1);
437 upper.inclusive = (flags & RANGE_UB_INC) != 0;
438 upper.lower = false;
439
440 range = make_range(typcache, &lower, &upper, false, NULL);
441
443}
444
445
446/* range -> subtype functions */
447
448/* extract lower bound value */
449Datum
451{
453 TypeCacheEntry *typcache;
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 lower bound */
463 if (empty || lower.infinite)
465
467}
468
469/* extract upper bound value */
470Datum
472{
474 TypeCacheEntry *typcache;
477 bool empty;
478
479 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
480
481 range_deserialize(typcache, r1, &lower, &upper, &empty);
482
483 /* Return NULL if there's no finite upper bound */
484 if (empty || upper.infinite)
486
488}
489
490
491/* range -> bool functions */
492
493/* is range empty? */
494Datum
496{
498 char flags = range_get_flags(r1);
499
501}
502
503/* is lower bound inclusive? */
504Datum
506{
508 char flags = range_get_flags(r1);
509
511}
512
513/* is upper bound inclusive? */
514Datum
516{
518 char flags = range_get_flags(r1);
519
521}
522
523/* is lower bound infinite? */
524Datum
526{
528 char flags = range_get_flags(r1);
529
531}
532
533/* is upper bound infinite? */
534Datum
536{
538 char flags = range_get_flags(r1);
539
541}
542
543
544/* range, element -> bool functions */
545
546/* contains? */
547Datum
549{
552 TypeCacheEntry *typcache;
553
554 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
555
557}
558
559/* contained by? */
560Datum
562{
565 TypeCacheEntry *typcache;
566
567 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
568
570}
571
572
573/* range, range -> bool functions */
574
575/* equality (internal version) */
576bool
577range_eq_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
578{
579 RangeBound lower1,
580 lower2;
581 RangeBound upper1,
582 upper2;
583 bool empty1,
584 empty2;
585
586 /* Different types should be prevented by ANYRANGE matching rules */
587 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
588 elog(ERROR, "range types do not match");
589
590 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
591 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
592
593 if (empty1 && empty2)
594 return true;
595 if (empty1 != empty2)
596 return false;
597
598 if (range_cmp_bounds(typcache, &lower1, &lower2) != 0)
599 return false;
600
601 if (range_cmp_bounds(typcache, &upper1, &upper2) != 0)
602 return false;
603
604 return true;
605}
606
607/* equality */
608Datum
610{
613 TypeCacheEntry *typcache;
614
615 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
616
617 PG_RETURN_BOOL(range_eq_internal(typcache, r1, r2));
618}
619
620/* inequality (internal version) */
621bool
622range_ne_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
623{
624 return (!range_eq_internal(typcache, r1, r2));
625}
626
627/* inequality */
628Datum
630{
633 TypeCacheEntry *typcache;
634
635 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
636
637 PG_RETURN_BOOL(range_ne_internal(typcache, r1, r2));
638}
639
640/* contains? */
641Datum
643{
646 TypeCacheEntry *typcache;
647
648 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
649
650 PG_RETURN_BOOL(range_contains_internal(typcache, r1, r2));
651}
652
653/* contained by? */
654Datum
656{
659 TypeCacheEntry *typcache;
660
661 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
662
664}
665
666/* strictly left of? (internal version) */
667bool
669{
670 RangeBound lower1,
671 lower2;
672 RangeBound upper1,
673 upper2;
674 bool empty1,
675 empty2;
676
677 /* Different types should be prevented by ANYRANGE matching rules */
678 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
679 elog(ERROR, "range types do not match");
680
681 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
682 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
683
684 /* An empty range is neither before nor after any other range */
685 if (empty1 || empty2)
686 return false;
687
688 return (range_cmp_bounds(typcache, &upper1, &lower2) < 0);
689}
690
691/* strictly left of? */
692Datum
694{
697 TypeCacheEntry *typcache;
698
699 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
700
701 PG_RETURN_BOOL(range_before_internal(typcache, r1, r2));
702}
703
704/* strictly right of? (internal version) */
705bool
707{
708 RangeBound lower1,
709 lower2;
710 RangeBound upper1,
711 upper2;
712 bool empty1,
713 empty2;
714
715 /* Different types should be prevented by ANYRANGE matching rules */
716 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
717 elog(ERROR, "range types do not match");
718
719 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
720 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
721
722 /* An empty range is neither before nor after any other range */
723 if (empty1 || empty2)
724 return false;
725
726 return (range_cmp_bounds(typcache, &lower1, &upper2) > 0);
727}
728
729/* strictly right of? */
730Datum
732{
735 TypeCacheEntry *typcache;
736
737 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
738
739 PG_RETURN_BOOL(range_after_internal(typcache, r1, r2));
740}
741
742/*
743 * Check if two bounds A and B are "adjacent", where A is an upper bound and B
744 * is a lower bound. For the bounds to be adjacent, each subtype value must
745 * satisfy strictly one of the bounds: there are no values which satisfy both
746 * bounds (i.e. less than A and greater than B); and there are no values which
747 * satisfy neither bound (i.e. greater than A and less than B).
748 *
749 * For discrete ranges, we rely on the canonicalization function to see if A..B
750 * normalizes to empty. (If there is no canonicalization function, it's
751 * impossible for such a range to normalize to empty, so we needn't bother to
752 * try.)
753 *
754 * If A == B, the ranges are adjacent only if the bounds have different
755 * inclusive flags (i.e., exactly one of the ranges includes the common
756 * boundary point).
757 *
758 * And if A > B then the ranges are not adjacent in this order.
759 */
760bool
762{
763 int cmp;
764
765 Assert(!boundA.lower && boundB.lower);
766
767 cmp = range_cmp_bound_values(typcache, &boundA, &boundB);
768 if (cmp < 0)
769 {
770 RangeType *r;
771
772 /*
773 * Bounds do not overlap; see if there are points in between.
774 */
775
776 /* in a continuous subtype, there are assumed to be points between */
777 if (!OidIsValid(typcache->rng_canonical_finfo.fn_oid))
778 return false;
779
780 /*
781 * The bounds are of a discrete range type; so make a range A..B and
782 * see if it's empty.
783 */
784
785 /* flip the inclusion flags */
786 boundA.inclusive = !boundA.inclusive;
787 boundB.inclusive = !boundB.inclusive;
788 /* change upper/lower labels to avoid Assert failures */
789 boundA.lower = true;
790 boundB.lower = false;
791 r = make_range(typcache, &boundA, &boundB, false, NULL);
792 return RangeIsEmpty(r);
793 }
794 else if (cmp == 0)
795 return boundA.inclusive != boundB.inclusive;
796 else
797 return false; /* bounds overlap */
798}
799
800/* adjacent to (but not overlapping)? (internal version) */
801bool
803{
804 RangeBound lower1,
805 lower2;
806 RangeBound upper1,
807 upper2;
808 bool empty1,
809 empty2;
810
811 /* Different types should be prevented by ANYRANGE matching rules */
812 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
813 elog(ERROR, "range types do not match");
814
815 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
816 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
817
818 /* An empty range is not adjacent to any other range */
819 if (empty1 || empty2)
820 return false;
821
822 /*
823 * Given two ranges A..B and C..D, the ranges are adjacent if and only if
824 * B is adjacent to C, or D is adjacent to A.
825 */
826 return (bounds_adjacent(typcache, upper1, lower2) ||
827 bounds_adjacent(typcache, upper2, lower1));
828}
829
830/* adjacent to (but not overlapping)? */
831Datum
833{
836 TypeCacheEntry *typcache;
837
838 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
839
840 PG_RETURN_BOOL(range_adjacent_internal(typcache, r1, r2));
841}
842
843/* overlaps? (internal version) */
844bool
846{
847 RangeBound lower1,
848 lower2;
849 RangeBound upper1,
850 upper2;
851 bool empty1,
852 empty2;
853
854 /* Different types should be prevented by ANYRANGE matching rules */
855 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
856 elog(ERROR, "range types do not match");
857
858 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
859 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
860
861 /* An empty range does not overlap any other range */
862 if (empty1 || empty2)
863 return false;
864
865 if (range_cmp_bounds(typcache, &lower1, &lower2) >= 0 &&
866 range_cmp_bounds(typcache, &lower1, &upper2) <= 0)
867 return true;
868
869 if (range_cmp_bounds(typcache, &lower2, &lower1) >= 0 &&
870 range_cmp_bounds(typcache, &lower2, &upper1) <= 0)
871 return true;
872
873 return false;
874}
875
876/* overlaps? */
877Datum
879{
882 TypeCacheEntry *typcache;
883
884 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
885
886 PG_RETURN_BOOL(range_overlaps_internal(typcache, r1, r2));
887}
888
889/* does not extend to right of? (internal version) */
890bool
892{
893 RangeBound lower1,
894 lower2;
895 RangeBound upper1,
896 upper2;
897 bool empty1,
898 empty2;
899
900 /* Different types should be prevented by ANYRANGE matching rules */
901 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
902 elog(ERROR, "range types do not match");
903
904 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
905 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
906
907 /* An empty range is neither before nor after any other range */
908 if (empty1 || empty2)
909 return false;
910
911 if (range_cmp_bounds(typcache, &upper1, &upper2) <= 0)
912 return true;
913
914 return false;
915}
916
917/* does not extend to right of? */
918Datum
920{
923 TypeCacheEntry *typcache;
924
925 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
926
927 PG_RETURN_BOOL(range_overleft_internal(typcache, r1, r2));
928}
929
930/* does not extend to left of? (internal version) */
931bool
933{
934 RangeBound lower1,
935 lower2;
936 RangeBound upper1,
937 upper2;
938 bool empty1,
939 empty2;
940
941 /* Different types should be prevented by ANYRANGE matching rules */
942 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
943 elog(ERROR, "range types do not match");
944
945 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
946 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
947
948 /* An empty range is neither before nor after any other range */
949 if (empty1 || empty2)
950 return false;
951
952 if (range_cmp_bounds(typcache, &lower1, &lower2) >= 0)
953 return true;
954
955 return false;
956}
957
958/* does not extend to left of? */
959Datum
961{
964 TypeCacheEntry *typcache;
965
966 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
967
968 PG_RETURN_BOOL(range_overright_internal(typcache, r1, r2));
969}
970
971
972/* range, range -> range functions */
973
974/* set difference */
975Datum
977{
980 RangeType *ret;
981 TypeCacheEntry *typcache;
982
983 /* Different types should be prevented by ANYRANGE matching rules */
984 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
985 elog(ERROR, "range types do not match");
986
987 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
988
989 ret = range_minus_internal(typcache, r1, r2);
990 if (ret)
992 else
994}
995
996RangeType *
998{
999 RangeBound lower1,
1000 lower2;
1001 RangeBound upper1,
1002 upper2;
1003 bool empty1,
1004 empty2;
1005 int cmp_l1l2,
1006 cmp_l1u2,
1007 cmp_u1l2,
1008 cmp_u1u2;
1009
1010 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
1011 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
1012
1013 /* if either is empty, r1 is the correct answer */
1014 if (empty1 || empty2)
1015 return r1;
1016
1017 cmp_l1l2 = range_cmp_bounds(typcache, &lower1, &lower2);
1018 cmp_l1u2 = range_cmp_bounds(typcache, &lower1, &upper2);
1019 cmp_u1l2 = range_cmp_bounds(typcache, &upper1, &lower2);
1020 cmp_u1u2 = range_cmp_bounds(typcache, &upper1, &upper2);
1021
1022 if (cmp_l1l2 < 0 && cmp_u1u2 > 0)
1023 ereport(ERROR,
1024 (errcode(ERRCODE_DATA_EXCEPTION),
1025 errmsg("result of range difference would not be contiguous")));
1026
1027 if (cmp_l1u2 > 0 || cmp_u1l2 < 0)
1028 return r1;
1029
1030 if (cmp_l1l2 >= 0 && cmp_u1u2 <= 0)
1031 return make_empty_range(typcache);
1032
1033 if (cmp_l1l2 <= 0 && cmp_u1l2 >= 0 && cmp_u1u2 <= 0)
1034 {
1035 lower2.inclusive = !lower2.inclusive;
1036 lower2.lower = false; /* it will become the upper bound */
1037 return make_range(typcache, &lower1, &lower2, false, NULL);
1038 }
1039
1040 if (cmp_l1l2 >= 0 && cmp_u1u2 >= 0 && cmp_l1u2 <= 0)
1041 {
1042 upper2.inclusive = !upper2.inclusive;
1043 upper2.lower = true; /* it will become the lower bound */
1044 return make_range(typcache, &upper2, &upper1, false, NULL);
1045 }
1046
1047 elog(ERROR, "unexpected case in range_minus");
1048 return NULL;
1049}
1050
1051/*
1052 * Set union. If strict is true, it is an error that the two input ranges
1053 * are not adjacent or overlapping.
1054 */
1055RangeType *
1057 bool strict)
1058{
1059 RangeBound lower1,
1060 lower2;
1061 RangeBound upper1,
1062 upper2;
1063 bool empty1,
1064 empty2;
1065 RangeBound *result_lower;
1066 RangeBound *result_upper;
1067
1068 /* Different types should be prevented by ANYRANGE matching rules */
1069 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
1070 elog(ERROR, "range types do not match");
1071
1072 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
1073 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
1074
1075 /* if either is empty, the other is the correct answer */
1076 if (empty1)
1077 return r2;
1078 if (empty2)
1079 return r1;
1080
1081 if (strict &&
1082 !range_overlaps_internal(typcache, r1, r2) &&
1083 !range_adjacent_internal(typcache, r1, r2))
1084 ereport(ERROR,
1085 (errcode(ERRCODE_DATA_EXCEPTION),
1086 errmsg("result of range union would not be contiguous")));
1087
1088 if (range_cmp_bounds(typcache, &lower1, &lower2) < 0)
1089 result_lower = &lower1;
1090 else
1091 result_lower = &lower2;
1092
1093 if (range_cmp_bounds(typcache, &upper1, &upper2) > 0)
1094 result_upper = &upper1;
1095 else
1096 result_upper = &upper2;
1097
1098 return make_range(typcache, result_lower, result_upper, false, NULL);
1099}
1100
1101Datum
1103{
1106 TypeCacheEntry *typcache;
1107
1108 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
1109
1110 PG_RETURN_RANGE_P(range_union_internal(typcache, r1, r2, true));
1111}
1112
1113/*
1114 * range merge: like set union, except also allow and account for non-adjacent
1115 * input ranges.
1116 */
1117Datum
1119{
1122 TypeCacheEntry *typcache;
1123
1124 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
1125
1126 PG_RETURN_RANGE_P(range_union_internal(typcache, r1, r2, false));
1127}
1128
1129/* set intersection */
1130Datum
1132{
1135 TypeCacheEntry *typcache;
1136
1137 /* Different types should be prevented by ANYRANGE matching rules */
1138 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
1139 elog(ERROR, "range types do not match");
1140
1141 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
1142
1144}
1145
1146RangeType *
1148{
1149 RangeBound lower1,
1150 lower2;
1151 RangeBound upper1,
1152 upper2;
1153 bool empty1,
1154 empty2;
1155 RangeBound *result_lower;
1156 RangeBound *result_upper;
1157
1158 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
1159 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
1160
1161 if (empty1 || empty2 || !range_overlaps_internal(typcache, r1, r2))
1162 return make_empty_range(typcache);
1163
1164 if (range_cmp_bounds(typcache, &lower1, &lower2) >= 0)
1165 result_lower = &lower1;
1166 else
1167 result_lower = &lower2;
1168
1169 if (range_cmp_bounds(typcache, &upper1, &upper2) <= 0)
1170 result_upper = &upper1;
1171 else
1172 result_upper = &upper2;
1173
1174 return make_range(typcache, result_lower, result_upper, false, NULL);
1175}
1176
1177/* range, range -> range, range functions */
1178
1179/*
1180 * range_split_internal - if r2 intersects the middle of r1, leaving non-empty
1181 * ranges on both sides, then return true and set output1 and output2 to the
1182 * results of r1 - r2 (in order). Otherwise return false and don't set output1
1183 * or output2. Neither input range should be empty.
1184 */
1185bool
1187 RangeType **output1, RangeType **output2)
1188{
1189 RangeBound lower1,
1190 lower2;
1191 RangeBound upper1,
1192 upper2;
1193 bool empty1,
1194 empty2;
1195
1196 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
1197 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
1198
1199 if (range_cmp_bounds(typcache, &lower1, &lower2) < 0 &&
1200 range_cmp_bounds(typcache, &upper1, &upper2) > 0)
1201 {
1202 /*
1203 * Need to invert inclusive/exclusive for the lower2 and upper2
1204 * points. They can't be infinite though. We're allowed to overwrite
1205 * these RangeBounds since they only exist locally.
1206 */
1207 lower2.inclusive = !lower2.inclusive;
1208 lower2.lower = false;
1209 upper2.inclusive = !upper2.inclusive;
1210 upper2.lower = true;
1211
1212 *output1 = make_range(typcache, &lower1, &lower2, false, NULL);
1213 *output2 = make_range(typcache, &upper2, &upper1, false, NULL);
1214 return true;
1215 }
1216
1217 return false;
1218}
1219
1220/*
1221 * range_minus_multi - like range_minus but as a SRF to accommodate splits,
1222 * with no result rows if the result would be empty.
1223 */
1224Datum
1226{
1227 struct range_minus_multi_fctx
1228 {
1229 RangeType *rs[2];
1230 int n;
1231 };
1232
1233 FuncCallContext *funcctx;
1234 struct range_minus_multi_fctx *fctx;
1235 MemoryContext oldcontext;
1236
1237 /* stuff done only on the first call of the function */
1238 if (SRF_IS_FIRSTCALL())
1239 {
1240 RangeType *r1;
1241 RangeType *r2;
1242 Oid rngtypid;
1243 TypeCacheEntry *typcache;
1244
1245 /* create a function context for cross-call persistence */
1246 funcctx = SRF_FIRSTCALL_INIT();
1247
1248 /*
1249 * switch to memory context appropriate for multiple function calls
1250 */
1251 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1252
1253 r1 = PG_GETARG_RANGE_P(0);
1254 r2 = PG_GETARG_RANGE_P(1);
1255
1256 /* Different types should be prevented by ANYRANGE matching rules */
1257 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
1258 elog(ERROR, "range types do not match");
1259
1260 /* allocate memory for user context */
1261 fctx = (struct range_minus_multi_fctx *) palloc(sizeof(struct range_minus_multi_fctx));
1262
1263 /*
1264 * Initialize state. We can't store the range typcache in fn_extra
1265 * because the caller uses that for the SRF state.
1266 */
1267 rngtypid = RangeTypeGetOid(r1);
1268 typcache = lookup_type_cache(rngtypid, TYPECACHE_RANGE_INFO);
1269 if (typcache->rngelemtype == NULL)
1270 elog(ERROR, "type %u is not a range type", rngtypid);
1271 range_minus_multi_internal(typcache, r1, r2, fctx->rs, &fctx->n);
1272
1273 funcctx->user_fctx = fctx;
1274 MemoryContextSwitchTo(oldcontext);
1275 }
1276
1277 /* stuff done on every call of the function */
1278 funcctx = SRF_PERCALL_SETUP();
1279 fctx = funcctx->user_fctx;
1280
1281 if (funcctx->call_cntr < fctx->n)
1282 {
1283 /*
1284 * We must keep these on separate lines because SRF_RETURN_NEXT does
1285 * call_cntr++:
1286 */
1287 RangeType *ret = fctx->rs[funcctx->call_cntr];
1288
1289 SRF_RETURN_NEXT(funcctx, RangeTypePGetDatum(ret));
1290 }
1291 else
1292 /* do when there is no more left */
1293 SRF_RETURN_DONE(funcctx);
1294}
1295
1296/*
1297 * range_minus_multi_internal - Subtracts r2 from r1
1298 *
1299 * The subtraction can produce zero, one, or two resulting ranges. We return
1300 * the results by setting outputs and outputn to the ranges remaining and their
1301 * count (respectively). The results will never contain empty ranges and will
1302 * be ordered. Caller should set outputs to a two-element array of RangeType
1303 * pointers.
1304 */
1305void
1307 RangeType *r2, RangeType **outputs, int *outputn)
1308{
1309 int cmp_l1l2,
1310 cmp_l1u2,
1311 cmp_u1l2,
1312 cmp_u1u2;
1313 RangeBound lower1,
1314 lower2;
1315 RangeBound upper1,
1316 upper2;
1317 bool empty1,
1318 empty2;
1319
1320 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
1321 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
1322
1323 if (empty1)
1324 {
1325 /* if r1 is empty then r1 - r2 is empty, so return zero results */
1326 *outputn = 0;
1327 return;
1328 }
1329 else if (empty2)
1330 {
1331 /* r2 is empty so the result is just r1 (which we know is not empty) */
1332 outputs[0] = r1;
1333 *outputn = 1;
1334 return;
1335 }
1336
1337 /*
1338 * Use the same logic as range_minus_internal, but support the split case
1339 */
1340 cmp_l1l2 = range_cmp_bounds(typcache, &lower1, &lower2);
1341 cmp_l1u2 = range_cmp_bounds(typcache, &lower1, &upper2);
1342 cmp_u1l2 = range_cmp_bounds(typcache, &upper1, &lower2);
1343 cmp_u1u2 = range_cmp_bounds(typcache, &upper1, &upper2);
1344
1345 if (cmp_l1l2 < 0 && cmp_u1u2 > 0)
1346 {
1347 lower2.inclusive = !lower2.inclusive;
1348 lower2.lower = false; /* it will become the upper bound */
1349 outputs[0] = make_range(typcache, &lower1, &lower2, false, NULL);
1350
1351 upper2.inclusive = !upper2.inclusive;
1352 upper2.lower = true; /* it will become the lower bound */
1353 outputs[1] = make_range(typcache, &upper2, &upper1, false, NULL);
1354
1355 *outputn = 2;
1356 }
1357 else if (cmp_l1u2 > 0 || cmp_u1l2 < 0)
1358 {
1359 outputs[0] = r1;
1360 *outputn = 1;
1361 }
1362 else if (cmp_l1l2 >= 0 && cmp_u1u2 <= 0)
1363 {
1364 *outputn = 0;
1365 }
1366 else if (cmp_l1l2 <= 0 && cmp_u1l2 >= 0 && cmp_u1u2 <= 0)
1367 {
1368 lower2.inclusive = !lower2.inclusive;
1369 lower2.lower = false; /* it will become the upper bound */
1370 outputs[0] = make_range(typcache, &lower1, &lower2, false, NULL);
1371 *outputn = 1;
1372 }
1373 else if (cmp_l1l2 >= 0 && cmp_u1u2 >= 0 && cmp_l1u2 <= 0)
1374 {
1375 upper2.inclusive = !upper2.inclusive;
1376 upper2.lower = true; /* it will become the lower bound */
1377 outputs[0] = make_range(typcache, &upper2, &upper1, false, NULL);
1378 *outputn = 1;
1379 }
1380 else
1381 {
1382 elog(ERROR, "unexpected case in range_minus_multi");
1383 }
1384}
1385
1386/* range -> range aggregate functions */
1387
1388Datum
1390{
1391 MemoryContext aggContext;
1392 Oid rngtypoid;
1393 TypeCacheEntry *typcache;
1394 RangeType *result;
1395 RangeType *current;
1396
1397 if (!AggCheckCallContext(fcinfo, &aggContext))
1398 elog(ERROR, "range_intersect_agg_transfn called in non-aggregate context");
1399
1400 rngtypoid = get_fn_expr_argtype(fcinfo->flinfo, 1);
1401 if (!type_is_range(rngtypoid))
1402 elog(ERROR, "range_intersect_agg must be called with a range");
1403
1404 typcache = range_get_typcache(fcinfo, rngtypoid);
1405
1406 /* strictness ensures these are non-null */
1407 result = PG_GETARG_RANGE_P(0);
1408 current = PG_GETARG_RANGE_P(1);
1409
1410 result = range_intersect_internal(typcache, result, current);
1411 PG_RETURN_RANGE_P(result);
1412}
1413
1414
1415/* Btree support */
1416
1417/* btree comparator */
1418Datum
1420{
1423 TypeCacheEntry *typcache;
1424 RangeBound lower1,
1425 lower2;
1426 RangeBound upper1,
1427 upper2;
1428 bool empty1,
1429 empty2;
1430 int cmp;
1431
1432 check_stack_depth(); /* recurses when subtype is a range type */
1433
1434 /* Different types should be prevented by ANYRANGE matching rules */
1435 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
1436 elog(ERROR, "range types do not match");
1437
1438 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
1439
1440 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
1441 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
1442
1443 /* For b-tree use, empty ranges sort before all else */
1444 if (empty1 && empty2)
1445 cmp = 0;
1446 else if (empty1)
1447 cmp = -1;
1448 else if (empty2)
1449 cmp = 1;
1450 else
1451 {
1452 cmp = range_cmp_bounds(typcache, &lower1, &lower2);
1453 if (cmp == 0)
1454 cmp = range_cmp_bounds(typcache, &upper1, &upper2);
1455 }
1456
1457 PG_FREE_IF_COPY(r1, 0);
1458 PG_FREE_IF_COPY(r2, 1);
1459
1461}
1462
1463/* Sort support strategy routine */
1464Datum
1466{
1468
1469 ssup->comparator = range_fast_cmp;
1470 ssup->ssup_extra = NULL;
1471
1473}
1474
1475/* like range_cmp, but uses the new sortsupport interface */
1476static int
1478{
1479 RangeType *range_a = DatumGetRangeTypeP(a);
1480 RangeType *range_b = DatumGetRangeTypeP(b);
1481 TypeCacheEntry *typcache;
1482 RangeBound lower1,
1483 lower2;
1484 RangeBound upper1,
1485 upper2;
1486 bool empty1,
1487 empty2;
1488 int cmp;
1489
1490 /* cache the range info between calls */
1491 if (ssup->ssup_extra == NULL)
1492 {
1493 Assert(RangeTypeGetOid(range_a) == RangeTypeGetOid(range_b));
1494 ssup->ssup_extra =
1496 }
1497 typcache = ssup->ssup_extra;
1498
1499 range_deserialize(typcache, range_a, &lower1, &upper1, &empty1);
1500 range_deserialize(typcache, range_b, &lower2, &upper2, &empty2);
1501
1502 /* For b-tree use, empty ranges sort before all else */
1503 if (empty1 && empty2)
1504 cmp = 0;
1505 else if (empty1)
1506 cmp = -1;
1507 else if (empty2)
1508 cmp = 1;
1509 else
1510 {
1511 cmp = range_cmp_bounds(typcache, &lower1, &lower2);
1512 if (cmp == 0)
1513 cmp = range_cmp_bounds(typcache, &upper1, &upper2);
1514 }
1515
1516 if ((Pointer) range_a != DatumGetPointer(a))
1517 pfree(range_a);
1518 if ((Pointer) range_b != DatumGetPointer(b))
1519 pfree(range_b);
1520
1521 return cmp;
1522}
1523
1524
1525/* inequality operators using the range_cmp function */
1526Datum
1528{
1529 int cmp = DatumGetInt32(range_cmp(fcinfo));
1530
1531 PG_RETURN_BOOL(cmp < 0);
1532}
1533
1534Datum
1536{
1537 int cmp = DatumGetInt32(range_cmp(fcinfo));
1538
1539 PG_RETURN_BOOL(cmp <= 0);
1540}
1541
1542Datum
1544{
1545 int cmp = DatumGetInt32(range_cmp(fcinfo));
1546
1547 PG_RETURN_BOOL(cmp >= 0);
1548}
1549
1550Datum
1552{
1553 int cmp = DatumGetInt32(range_cmp(fcinfo));
1554
1555 PG_RETURN_BOOL(cmp > 0);
1556}
1557
1558/* Hash support */
1559
1560/* hash a range value */
1561Datum
1563{
1565 uint32 result;
1566 TypeCacheEntry *typcache;
1567 TypeCacheEntry *scache;
1570 bool empty;
1571 char flags;
1572 uint32 lower_hash;
1573 uint32 upper_hash;
1574
1575 check_stack_depth(); /* recurses when subtype is a range type */
1576
1577 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1578
1579 /* deserialize */
1580 range_deserialize(typcache, r, &lower, &upper, &empty);
1581 flags = range_get_flags(r);
1582
1583 /*
1584 * Look up the element type's hash function, if not done already.
1585 */
1586 scache = typcache->rngelemtype;
1587 if (!OidIsValid(scache->hash_proc_finfo.fn_oid))
1588 {
1590 if (!OidIsValid(scache->hash_proc_finfo.fn_oid))
1591 ereport(ERROR,
1592 (errcode(ERRCODE_UNDEFINED_FUNCTION),
1593 errmsg("could not identify a hash function for type %s",
1594 format_type_be(scache->type_id))));
1595 }
1596
1597 /*
1598 * Apply the hash function to each bound.
1599 */
1600 if (RANGE_HAS_LBOUND(flags))
1601 lower_hash = DatumGetUInt32(FunctionCall1Coll(&scache->hash_proc_finfo,
1602 typcache->rng_collation,
1603 lower.val));
1604 else
1605 lower_hash = 0;
1606
1607 if (RANGE_HAS_UBOUND(flags))
1608 upper_hash = DatumGetUInt32(FunctionCall1Coll(&scache->hash_proc_finfo,
1609 typcache->rng_collation,
1610 upper.val));
1611 else
1612 upper_hash = 0;
1613
1614 /* Merge hashes of flags and bounds */
1615 result = hash_bytes_uint32((uint32) flags);
1616 result ^= lower_hash;
1617 result = pg_rotate_left32(result, 1);
1618 result ^= upper_hash;
1619
1620 PG_RETURN_INT32(result);
1621}
1622
1623/*
1624 * Returns 64-bit value by hashing a value to a 64-bit value, with a seed.
1625 * Otherwise, similar to hash_range.
1626 */
1627Datum
1629{
1631 Datum seed = PG_GETARG_DATUM(1);
1632 uint64 result;
1633 TypeCacheEntry *typcache;
1634 TypeCacheEntry *scache;
1637 bool empty;
1638 char flags;
1639 uint64 lower_hash;
1640 uint64 upper_hash;
1641
1643
1644 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1645
1646 range_deserialize(typcache, r, &lower, &upper, &empty);
1647 flags = range_get_flags(r);
1648
1649 scache = typcache->rngelemtype;
1651 {
1652 scache = lookup_type_cache(scache->type_id,
1655 ereport(ERROR,
1656 (errcode(ERRCODE_UNDEFINED_FUNCTION),
1657 errmsg("could not identify a hash function for type %s",
1658 format_type_be(scache->type_id))));
1659 }
1660
1661 if (RANGE_HAS_LBOUND(flags))
1663 typcache->rng_collation,
1664 lower.val,
1665 seed));
1666 else
1667 lower_hash = 0;
1668
1669 if (RANGE_HAS_UBOUND(flags))
1671 typcache->rng_collation,
1672 upper.val,
1673 seed));
1674 else
1675 upper_hash = 0;
1676
1677 /* Merge hashes of flags and bounds */
1679 DatumGetInt64(seed)));
1680 result ^= lower_hash;
1681 result = ROTATE_HIGH_AND_LOW_32BITS(result);
1682 result ^= upper_hash;
1683
1684 PG_RETURN_UINT64(result);
1685}
1686
1687/*
1688 *----------------------------------------------------------
1689 * CANONICAL FUNCTIONS
1690 *
1691 * Functions for specific built-in range types.
1692 *----------------------------------------------------------
1693 */
1694
1695Datum
1697{
1699 Node *escontext = fcinfo->context;
1700 TypeCacheEntry *typcache;
1703 bool empty;
1704
1705 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1706
1707 range_deserialize(typcache, r, &lower, &upper, &empty);
1708
1709 if (empty)
1711
1712 if (!lower.infinite && !lower.inclusive)
1713 {
1714 int32 bnd = DatumGetInt32(lower.val);
1715
1716 /* Handle possible overflow manually */
1717 if (unlikely(bnd == PG_INT32_MAX))
1718 ereturn(escontext, (Datum) 0,
1719 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1720 errmsg("integer out of range")));
1721 lower.val = Int32GetDatum(bnd + 1);
1722 lower.inclusive = true;
1723 }
1724
1725 if (!upper.infinite && upper.inclusive)
1726 {
1727 int32 bnd = DatumGetInt32(upper.val);
1728
1729 /* Handle possible overflow manually */
1730 if (unlikely(bnd == PG_INT32_MAX))
1731 ereturn(escontext, (Datum) 0,
1732 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1733 errmsg("integer out of range")));
1734 upper.val = Int32GetDatum(bnd + 1);
1735 upper.inclusive = false;
1736 }
1737
1739 false, escontext));
1740}
1741
1742Datum
1744{
1746 Node *escontext = fcinfo->context;
1747 TypeCacheEntry *typcache;
1750 bool empty;
1751
1752 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1753
1754 range_deserialize(typcache, r, &lower, &upper, &empty);
1755
1756 if (empty)
1758
1759 if (!lower.infinite && !lower.inclusive)
1760 {
1761 int64 bnd = DatumGetInt64(lower.val);
1762
1763 /* Handle possible overflow manually */
1764 if (unlikely(bnd == PG_INT64_MAX))
1765 ereturn(escontext, (Datum) 0,
1766 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1767 errmsg("bigint out of range")));
1768 lower.val = Int64GetDatum(bnd + 1);
1769 lower.inclusive = true;
1770 }
1771
1772 if (!upper.infinite && upper.inclusive)
1773 {
1774 int64 bnd = DatumGetInt64(upper.val);
1775
1776 /* Handle possible overflow manually */
1777 if (unlikely(bnd == PG_INT64_MAX))
1778 ereturn(escontext, (Datum) 0,
1779 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1780 errmsg("bigint out of range")));
1781 upper.val = Int64GetDatum(bnd + 1);
1782 upper.inclusive = false;
1783 }
1784
1786 false, escontext));
1787}
1788
1789Datum
1791{
1793 Node *escontext = fcinfo->context;
1794 TypeCacheEntry *typcache;
1797 bool empty;
1798
1799 typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1800
1801 range_deserialize(typcache, r, &lower, &upper, &empty);
1802
1803 if (empty)
1805
1806 if (!lower.infinite && !DATE_NOT_FINITE(DatumGetDateADT(lower.val)) &&
1807 !lower.inclusive)
1808 {
1809 DateADT bnd = DatumGetDateADT(lower.val);
1810
1811 /* Check for overflow -- note we already eliminated PG_INT32_MAX */
1812 bnd++;
1813 if (unlikely(!IS_VALID_DATE(bnd)))
1814 ereturn(escontext, (Datum) 0,
1815 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1816 errmsg("date out of range")));
1817 lower.val = DateADTGetDatum(bnd);
1818 lower.inclusive = true;
1819 }
1820
1821 if (!upper.infinite && !DATE_NOT_FINITE(DatumGetDateADT(upper.val)) &&
1822 upper.inclusive)
1823 {
1824 DateADT bnd = DatumGetDateADT(upper.val);
1825
1826 /* Check for overflow -- note we already eliminated PG_INT32_MAX */
1827 bnd++;
1828 if (unlikely(!IS_VALID_DATE(bnd)))
1829 ereturn(escontext, (Datum) 0,
1830 (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1831 errmsg("date out of range")));
1832 upper.val = DateADTGetDatum(bnd);
1833 upper.inclusive = false;
1834 }
1835
1837 false, escontext));
1838}
1839
1840/*
1841 *----------------------------------------------------------
1842 * SUBTYPE_DIFF FUNCTIONS
1843 *
1844 * Functions for specific built-in range types.
1845 *
1846 * Note that subtype_diff does return the difference, not the absolute value
1847 * of the difference, and it must take care to avoid overflow.
1848 * (numrange_subdiff is at some risk there ...)
1849 *----------------------------------------------------------
1850 */
1851
1852Datum
1854{
1855 int32 v1 = PG_GETARG_INT32(0);
1856 int32 v2 = PG_GETARG_INT32(1);
1857
1858 PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
1859}
1860
1861Datum
1863{
1864 int64 v1 = PG_GETARG_INT64(0);
1865 int64 v2 = PG_GETARG_INT64(1);
1866
1867 PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
1868}
1869
1870Datum
1872{
1873 Datum v1 = PG_GETARG_DATUM(0);
1874 Datum v2 = PG_GETARG_DATUM(1);
1875 Datum numresult;
1876 float8 floatresult;
1877
1878 numresult = DirectFunctionCall2(numeric_sub, v1, v2);
1879
1881 numresult));
1882
1883 PG_RETURN_FLOAT8(floatresult);
1884}
1885
1886Datum
1888{
1889 int32 v1 = PG_GETARG_INT32(0);
1890 int32 v2 = PG_GETARG_INT32(1);
1891
1892 PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
1893}
1894
1895Datum
1897{
1900 float8 result;
1901
1902 result = ((float8) v1 - (float8) v2) / USECS_PER_SEC;
1903 PG_RETURN_FLOAT8(result);
1904}
1905
1906Datum
1908{
1911 float8 result;
1912
1913 result = ((float8) v1 - (float8) v2) / USECS_PER_SEC;
1914 PG_RETURN_FLOAT8(result);
1915}
1916
1917/*
1918 *----------------------------------------------------------
1919 * SUPPORT FUNCTIONS
1920 *
1921 * These functions aren't in pg_proc, but are useful for
1922 * defining new generic range functions in C.
1923 *----------------------------------------------------------
1924 */
1925
1926/*
1927 * range_get_typcache: get cached information about a range type
1928 *
1929 * This is for use by range-related functions that follow the convention
1930 * of using the fn_extra field as a pointer to the type cache entry for
1931 * the range type. Functions that need to cache more information than
1932 * that must fend for themselves.
1933 */
1936{
1937 TypeCacheEntry *typcache = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
1938
1939 if (typcache == NULL ||
1940 typcache->type_id != rngtypid)
1941 {
1942 typcache = lookup_type_cache(rngtypid, TYPECACHE_RANGE_INFO);
1943 if (typcache->rngelemtype == NULL)
1944 elog(ERROR, "type %u is not a range type", rngtypid);
1945 fcinfo->flinfo->fn_extra = typcache;
1946 }
1947
1948 return typcache;
1949}
1950
1951/*
1952 * range_serialize: construct a range value from bounds and empty-flag
1953 *
1954 * This does not force canonicalization of the range value. In most cases,
1955 * external callers should only be canonicalization functions. Note that
1956 * we perform some datatype-independent canonicalization checks anyway.
1957 */
1958RangeType *
1960 bool empty, struct Node *escontext)
1961{
1963 int cmp;
1964 Size msize;
1965 Pointer ptr;
1966 int16 typlen;
1967 bool typbyval;
1968 char typalign;
1969 char typstorage;
1970 char flags = 0;
1971
1972 /*
1973 * Verify range is not invalid on its face, and construct flags value,
1974 * preventing any non-canonical combinations such as infinite+inclusive.
1975 */
1976 Assert(lower->lower);
1977 Assert(!upper->lower);
1978
1979 if (empty)
1980 flags |= RANGE_EMPTY;
1981 else
1982 {
1983 cmp = range_cmp_bound_values(typcache, lower, upper);
1984
1985 /* error check: if lower bound value is above upper, it's wrong */
1986 if (cmp > 0)
1987 ereturn(escontext, NULL,
1988 (errcode(ERRCODE_DATA_EXCEPTION),
1989 errmsg("range lower bound must be less than or equal to range upper bound")));
1990
1991 /* if bounds are equal, and not both inclusive, range is empty */
1992 if (cmp == 0 && !(lower->inclusive && upper->inclusive))
1993 flags |= RANGE_EMPTY;
1994 else
1995 {
1996 /* infinite boundaries are never inclusive */
1997 if (lower->infinite)
1998 flags |= RANGE_LB_INF;
1999 else if (lower->inclusive)
2000 flags |= RANGE_LB_INC;
2001 if (upper->infinite)
2002 flags |= RANGE_UB_INF;
2003 else if (upper->inclusive)
2004 flags |= RANGE_UB_INC;
2005 }
2006 }
2007
2008 /* Fetch information about range's element type */
2009 typlen = typcache->rngelemtype->typlen;
2010 typbyval = typcache->rngelemtype->typbyval;
2011 typalign = typcache->rngelemtype->typalign;
2012 typstorage = typcache->rngelemtype->typstorage;
2013
2014 /* Count space for varlena header and range type's OID */
2015 msize = sizeof(RangeType);
2016 Assert(msize == MAXALIGN(msize));
2017
2018 /* Count space for bounds */
2019 if (RANGE_HAS_LBOUND(flags))
2020 {
2021 /*
2022 * Make sure item to be inserted is not toasted. It is essential that
2023 * we not insert an out-of-line toast value pointer into a range
2024 * object, for the same reasons that arrays and records can't contain
2025 * them. It would work to store a compressed-in-line value, but we
2026 * prefer to decompress and then let compression be applied to the
2027 * whole range object if necessary. But, unlike arrays, we do allow
2028 * short-header varlena objects to stay as-is.
2029 */
2030 if (typlen == -1)
2032
2033 msize = datum_compute_size(msize, lower->val, typbyval, typalign,
2034 typlen, typstorage);
2035 }
2036
2037 if (RANGE_HAS_UBOUND(flags))
2038 {
2039 /* Make sure item to be inserted is not toasted */
2040 if (typlen == -1)
2042
2043 msize = datum_compute_size(msize, upper->val, typbyval, typalign,
2044 typlen, typstorage);
2045 }
2046
2047 /* Add space for flag byte */
2048 msize += sizeof(char);
2049
2050 /* Note: zero-fill is required here, just as in heap tuples */
2051 range = (RangeType *) palloc0(msize);
2052 SET_VARSIZE(range, msize);
2053
2054 /* Now fill in the datum */
2055 range->rangetypid = typcache->type_id;
2056
2057 ptr = (char *) (range + 1);
2058
2059 if (RANGE_HAS_LBOUND(flags))
2060 {
2061 Assert(lower->lower);
2062 ptr = datum_write(ptr, lower->val, typbyval, typalign, typlen,
2063 typstorage);
2064 }
2065
2066 if (RANGE_HAS_UBOUND(flags))
2067 {
2068 Assert(!upper->lower);
2069 ptr = datum_write(ptr, upper->val, typbyval, typalign, typlen,
2070 typstorage);
2071 }
2072
2073 *((char *) ptr) = flags;
2074
2075 return range;
2076}
2077
2078/*
2079 * range_deserialize: deconstruct a range value
2080 *
2081 * NB: the given range object must be fully detoasted; it cannot have a
2082 * short varlena header.
2083 *
2084 * Note that if the element type is pass-by-reference, the datums in the
2085 * RangeBound structs will be pointers into the given range object.
2086 */
2087void
2089 RangeBound *lower, RangeBound *upper, bool *empty)
2090{
2091 char flags;
2092 int16 typlen;
2093 bool typbyval;
2094 char typalign;
2095 Pointer ptr;
2096 Datum lbound;
2097 Datum ubound;
2098
2099 /* assert caller passed the right typcache entry */
2100 Assert(RangeTypeGetOid(range) == typcache->type_id);
2101
2102 /* fetch the flag byte from datum's last byte */
2103 flags = *((const char *) range + VARSIZE(range) - 1);
2104
2105 /* fetch information about range's element type */
2106 typlen = typcache->rngelemtype->typlen;
2107 typbyval = typcache->rngelemtype->typbyval;
2108 typalign = typcache->rngelemtype->typalign;
2109
2110 /* initialize data pointer just after the range OID */
2111 ptr = (Pointer) (range + 1);
2112
2113 /* fetch lower bound, if any */
2114 if (RANGE_HAS_LBOUND(flags))
2115 {
2116 /* att_align_pointer cannot be necessary here */
2117 lbound = fetch_att(ptr, typbyval, typlen);
2118 ptr = (Pointer) att_addlength_pointer(ptr, typlen, ptr);
2119 }
2120 else
2121 lbound = (Datum) 0;
2122
2123 /* fetch upper bound, if any */
2124 if (RANGE_HAS_UBOUND(flags))
2125 {
2126 ptr = (Pointer) att_align_pointer(ptr, typalign, typlen, ptr);
2127 ubound = fetch_att(ptr, typbyval, typlen);
2128 /* no need for att_addlength_pointer */
2129 }
2130 else
2131 ubound = (Datum) 0;
2132
2133 /* emit results */
2134
2135 *empty = (flags & RANGE_EMPTY) != 0;
2136
2137 lower->val = lbound;
2138 lower->infinite = (flags & RANGE_LB_INF) != 0;
2139 lower->inclusive = (flags & RANGE_LB_INC) != 0;
2140 lower->lower = true;
2141
2142 upper->val = ubound;
2143 upper->infinite = (flags & RANGE_UB_INF) != 0;
2144 upper->inclusive = (flags & RANGE_UB_INC) != 0;
2145 upper->lower = false;
2146}
2147
2148/*
2149 * range_get_flags: just get the flags from a RangeType value.
2150 *
2151 * This is frequently useful in places that only need the flags and not
2152 * the full results of range_deserialize.
2153 */
2154char
2156{
2157 /* fetch the flag byte from datum's last byte */
2158 return *((char *) range + VARSIZE(range) - 1);
2159}
2160
2161/*
2162 * range_set_contain_empty: set the RANGE_CONTAIN_EMPTY bit in the value.
2163 *
2164 * This is only needed in GiST operations, so we don't include a provision
2165 * for setting it in range_serialize; rather, this function must be applied
2166 * afterwards.
2167 */
2168void
2170{
2171 char *flagsp;
2172
2173 /* flag byte is datum's last byte */
2174 flagsp = (char *) range + VARSIZE(range) - 1;
2175
2176 *flagsp |= RANGE_CONTAIN_EMPTY;
2177}
2178
2179/*
2180 * This both serializes and canonicalizes (if applicable) the range.
2181 * This should be used by most callers.
2182 */
2183RangeType *
2185 bool empty, struct Node *escontext)
2186{
2188
2189 range = range_serialize(typcache, lower, upper, empty, escontext);
2190
2191 if (SOFT_ERROR_OCCURRED(escontext))
2192 return NULL;
2193
2194 /* no need to call canonical on empty ranges ... */
2195 if (OidIsValid(typcache->rng_canonical_finfo.fn_oid) &&
2197 {
2198 /* Do this the hard way so that we can pass escontext */
2199 LOCAL_FCINFO(fcinfo, 1);
2200 Datum result;
2201
2202 InitFunctionCallInfoData(*fcinfo, &typcache->rng_canonical_finfo, 1,
2203 InvalidOid, escontext, NULL);
2204
2205 fcinfo->args[0].value = RangeTypePGetDatum(range);
2206 fcinfo->args[0].isnull = false;
2207
2208 result = FunctionCallInvoke(fcinfo);
2209
2210 if (SOFT_ERROR_OCCURRED(escontext))
2211 return NULL;
2212
2213 /* Should not get a null result if there was no error */
2214 if (fcinfo->isnull)
2215 elog(ERROR, "function %u returned NULL",
2216 typcache->rng_canonical_finfo.fn_oid);
2217
2218 range = DatumGetRangeTypeP(result);
2219 }
2220
2221 return range;
2222}
2223
2224/*
2225 * Compare two range boundary points, returning <0, 0, or >0 according to
2226 * whether b1 is less than, equal to, or greater than b2.
2227 *
2228 * The boundaries can be any combination of upper and lower; so it's useful
2229 * for a variety of operators.
2230 *
2231 * The simple case is when b1 and b2 are both finite and inclusive, in which
2232 * case the result is just a comparison of the values held in b1 and b2.
2233 *
2234 * If a bound is exclusive, then we need to know whether it's a lower bound,
2235 * in which case we treat the boundary point as "just greater than" the held
2236 * value; or an upper bound, in which case we treat the boundary point as
2237 * "just less than" the held value.
2238 *
2239 * If a bound is infinite, it represents minus infinity (less than every other
2240 * point) if it's a lower bound; or plus infinity (greater than every other
2241 * point) if it's an upper bound.
2242 *
2243 * There is only one case where two boundaries compare equal but are not
2244 * identical: when both bounds are inclusive and hold the same finite value,
2245 * but one is an upper bound and the other a lower bound.
2246 */
2247int
2249{
2250 int32 result;
2251
2252 /*
2253 * First, handle cases involving infinity, which don't require invoking
2254 * the comparison proc.
2255 */
2256 if (b1->infinite && b2->infinite)
2257 {
2258 /*
2259 * Both are infinity, so they are equal unless one is lower and the
2260 * other not.
2261 */
2262 if (b1->lower == b2->lower)
2263 return 0;
2264 else
2265 return b1->lower ? -1 : 1;
2266 }
2267 else if (b1->infinite)
2268 return b1->lower ? -1 : 1;
2269 else if (b2->infinite)
2270 return b2->lower ? 1 : -1;
2271
2272 /*
2273 * Both boundaries are finite, so compare the held values.
2274 */
2276 typcache->rng_collation,
2277 b1->val, b2->val));
2278
2279 /*
2280 * If the comparison is anything other than equal, we're done. If they
2281 * compare equal though, we still have to consider whether the boundaries
2282 * are inclusive or exclusive.
2283 */
2284 if (result == 0)
2285 {
2286 if (!b1->inclusive && !b2->inclusive)
2287 {
2288 /* both are exclusive */
2289 if (b1->lower == b2->lower)
2290 return 0;
2291 else
2292 return b1->lower ? 1 : -1;
2293 }
2294 else if (!b1->inclusive)
2295 return b1->lower ? 1 : -1;
2296 else if (!b2->inclusive)
2297 return b2->lower ? -1 : 1;
2298 else
2299 {
2300 /*
2301 * Both are inclusive and the values held are equal, so they are
2302 * equal regardless of whether they are upper or lower boundaries,
2303 * or a mix.
2304 */
2305 return 0;
2306 }
2307 }
2308
2309 return result;
2310}
2311
2312/*
2313 * Compare two range boundary point values, returning <0, 0, or >0 according
2314 * to whether b1 is less than, equal to, or greater than b2.
2315 *
2316 * This is similar to but simpler than range_cmp_bounds(). We just compare
2317 * the values held in b1 and b2, ignoring inclusive/exclusive flags. The
2318 * lower/upper flags only matter for infinities, where they tell us if the
2319 * infinity is plus or minus.
2320 */
2321int
2323 const RangeBound *b2)
2324{
2325 /*
2326 * First, handle cases involving infinity, which don't require invoking
2327 * the comparison proc.
2328 */
2329 if (b1->infinite && b2->infinite)
2330 {
2331 /*
2332 * Both are infinity, so they are equal unless one is lower and the
2333 * other not.
2334 */
2335 if (b1->lower == b2->lower)
2336 return 0;
2337 else
2338 return b1->lower ? -1 : 1;
2339 }
2340 else if (b1->infinite)
2341 return b1->lower ? -1 : 1;
2342 else if (b2->infinite)
2343 return b2->lower ? 1 : -1;
2344
2345 /*
2346 * Both boundaries are finite, so compare the held values.
2347 */
2349 typcache->rng_collation,
2350 b1->val, b2->val));
2351}
2352
2353/*
2354 * qsort callback for sorting ranges.
2355 *
2356 * Two empty ranges compare equal; an empty range sorts to the left of any
2357 * non-empty range. Two non-empty ranges are sorted by lower bound first
2358 * and by upper bound next.
2359 */
2360int
2361range_compare(const void *key1, const void *key2, void *arg)
2362{
2363 RangeType *r1 = *(RangeType **) key1;
2364 RangeType *r2 = *(RangeType **) key2;
2365 TypeCacheEntry *typcache = (TypeCacheEntry *) arg;
2366 RangeBound lower1;
2367 RangeBound upper1;
2368 RangeBound lower2;
2369 RangeBound upper2;
2370 bool empty1;
2371 bool empty2;
2372 int cmp;
2373
2374 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
2375 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
2376
2377 if (empty1 && empty2)
2378 cmp = 0;
2379 else if (empty1)
2380 cmp = -1;
2381 else if (empty2)
2382 cmp = 1;
2383 else
2384 {
2385 cmp = range_cmp_bounds(typcache, &lower1, &lower2);
2386 if (cmp == 0)
2387 cmp = range_cmp_bounds(typcache, &upper1, &upper2);
2388 }
2389
2390 return cmp;
2391}
2392
2393/*
2394 * Build an empty range value of the type indicated by the typcache entry.
2395 */
2396RangeType *
2398{
2401
2402 lower.val = (Datum) 0;
2403 lower.infinite = false;
2404 lower.inclusive = false;
2405 lower.lower = true;
2406
2407 upper.val = (Datum) 0;
2408 upper.infinite = false;
2409 upper.inclusive = false;
2410 upper.lower = false;
2411
2412 return make_range(typcache, &lower, &upper, true, NULL);
2413}
2414
2415/*
2416 * Planner support function for elem_contained_by_range (<@ operator).
2417 */
2418Datum
2420{
2421 Node *rawreq = (Node *) PG_GETARG_POINTER(0);
2422 Node *ret = NULL;
2423
2424 if (IsA(rawreq, SupportRequestSimplify))
2425 {
2427 FuncExpr *fexpr = req->fcall;
2428 Expr *leftop,
2429 *rightop;
2430
2431 Assert(list_length(fexpr->args) == 2);
2432 leftop = linitial(fexpr->args);
2433 rightop = lsecond(fexpr->args);
2434
2435 ret = find_simplified_clause(req->root, rightop, leftop);
2436 }
2437
2438 PG_RETURN_POINTER(ret);
2439}
2440
2441/*
2442 * Planner support function for range_contains_elem (@> operator).
2443 */
2444Datum
2446{
2447 Node *rawreq = (Node *) PG_GETARG_POINTER(0);
2448 Node *ret = NULL;
2449
2450 if (IsA(rawreq, SupportRequestSimplify))
2451 {
2453 FuncExpr *fexpr = req->fcall;
2454 Expr *leftop,
2455 *rightop;
2456
2457 Assert(list_length(fexpr->args) == 2);
2458 leftop = linitial(fexpr->args);
2459 rightop = lsecond(fexpr->args);
2460
2461 ret = find_simplified_clause(req->root, leftop, rightop);
2462 }
2463
2464 PG_RETURN_POINTER(ret);
2465}
2466
2467
2468/*
2469 *----------------------------------------------------------
2470 * STATIC FUNCTIONS
2471 *----------------------------------------------------------
2472 */
2473
2474/*
2475 * Given a string representing the flags for the range type, return the flags
2476 * represented as a char.
2477 */
2478static char
2479range_parse_flags(const char *flags_str)
2480{
2481 char flags = 0;
2482
2483 if (flags_str[0] == '\0' ||
2484 flags_str[1] == '\0' ||
2485 flags_str[2] != '\0')
2486 ereport(ERROR,
2487 (errcode(ERRCODE_SYNTAX_ERROR),
2488 errmsg("invalid range bound flags"),
2489 errhint("Valid values are \"[]\", \"[)\", \"(]\", and \"()\".")));
2490
2491 switch (flags_str[0])
2492 {
2493 case '[':
2494 flags |= RANGE_LB_INC;
2495 break;
2496 case '(':
2497 break;
2498 default:
2499 ereport(ERROR,
2500 (errcode(ERRCODE_SYNTAX_ERROR),
2501 errmsg("invalid range bound flags"),
2502 errhint("Valid values are \"[]\", \"[)\", \"(]\", and \"()\".")));
2503 }
2504
2505 switch (flags_str[1])
2506 {
2507 case ']':
2508 flags |= RANGE_UB_INC;
2509 break;
2510 case ')':
2511 break;
2512 default:
2513 ereport(ERROR,
2514 (errcode(ERRCODE_SYNTAX_ERROR),
2515 errmsg("invalid range bound flags"),
2516 errhint("Valid values are \"[]\", \"[)\", \"(]\", and \"()\".")));
2517 }
2518
2519 return flags;
2520}
2521
2522/*
2523 * Parse range input.
2524 *
2525 * Input parameters:
2526 * string: input string to be parsed
2527 * Output parameters:
2528 * *flags: receives flags bitmask
2529 * *lbound_str: receives palloc'd lower bound string, or NULL if none
2530 * *ubound_str: receives palloc'd upper bound string, or NULL if none
2531 *
2532 * This is modeled somewhat after record_in in rowtypes.c.
2533 * The input syntax is:
2534 * <range> := EMPTY
2535 * | <lb-inc> <string>, <string> <ub-inc>
2536 * <lb-inc> := '[' | '('
2537 * <ub-inc> := ']' | ')'
2538 *
2539 * Whitespace before or after <range> is ignored. Whitespace within a <string>
2540 * is taken literally and becomes part of the input string for that bound.
2541 *
2542 * A <string> of length zero is taken as "infinite" (i.e. no bound), unless it
2543 * is surrounded by double-quotes, in which case it is the literal empty
2544 * string.
2545 *
2546 * Within a <string>, special characters (such as comma, parenthesis, or
2547 * brackets) can be enclosed in double-quotes or escaped with backslash. Within
2548 * double-quotes, a double-quote can be escaped with double-quote or backslash.
2549 *
2550 * Returns true on success, false on failure (but failures will return only if
2551 * escontext is an ErrorSaveContext).
2552 */
2553static bool
2554range_parse(const char *string, char *flags, char **lbound_str,
2555 char **ubound_str, Node *escontext)
2556{
2557 const char *ptr = string;
2558 bool infinite;
2559
2560 *flags = 0;
2561
2562 /* consume whitespace */
2563 while (*ptr != '\0' && isspace((unsigned char) *ptr))
2564 ptr++;
2565
2566 /* check for empty range */
2568 strlen(RANGE_EMPTY_LITERAL)) == 0)
2569 {
2570 *flags = RANGE_EMPTY;
2571 *lbound_str = NULL;
2572 *ubound_str = NULL;
2573
2574 ptr += strlen(RANGE_EMPTY_LITERAL);
2575
2576 /* the rest should be whitespace */
2577 while (*ptr != '\0' && isspace((unsigned char) *ptr))
2578 ptr++;
2579
2580 /* should have consumed everything */
2581 if (*ptr != '\0')
2582 ereturn(escontext, false,
2583 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2584 errmsg("malformed range literal: \"%s\"",
2585 string),
2586 errdetail("Junk after \"empty\" key word.")));
2587
2588 return true;
2589 }
2590
2591 if (*ptr == '[')
2592 {
2593 *flags |= RANGE_LB_INC;
2594 ptr++;
2595 }
2596 else if (*ptr == '(')
2597 ptr++;
2598 else
2599 ereturn(escontext, false,
2600 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2601 errmsg("malformed range literal: \"%s\"",
2602 string),
2603 errdetail("Missing left parenthesis or bracket.")));
2604
2605 ptr = range_parse_bound(string, ptr, lbound_str, &infinite, escontext);
2606 if (ptr == NULL)
2607 return false;
2608 if (infinite)
2609 *flags |= RANGE_LB_INF;
2610
2611 if (*ptr == ',')
2612 ptr++;
2613 else
2614 ereturn(escontext, false,
2615 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2616 errmsg("malformed range literal: \"%s\"",
2617 string),
2618 errdetail("Missing comma after lower bound.")));
2619
2620 ptr = range_parse_bound(string, ptr, ubound_str, &infinite, escontext);
2621 if (ptr == NULL)
2622 return false;
2623 if (infinite)
2624 *flags |= RANGE_UB_INF;
2625
2626 if (*ptr == ']')
2627 {
2628 *flags |= RANGE_UB_INC;
2629 ptr++;
2630 }
2631 else if (*ptr == ')')
2632 ptr++;
2633 else /* must be a comma */
2634 ereturn(escontext, false,
2635 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2636 errmsg("malformed range literal: \"%s\"",
2637 string),
2638 errdetail("Too many commas.")));
2639
2640 /* consume whitespace */
2641 while (*ptr != '\0' && isspace((unsigned char) *ptr))
2642 ptr++;
2643
2644 if (*ptr != '\0')
2645 ereturn(escontext, false,
2646 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2647 errmsg("malformed range literal: \"%s\"",
2648 string),
2649 errdetail("Junk after right parenthesis or bracket.")));
2650
2651 return true;
2652}
2653
2654/*
2655 * Helper for range_parse: parse and de-quote one bound string.
2656 *
2657 * We scan until finding comma, right parenthesis, or right bracket.
2658 *
2659 * Input parameters:
2660 * string: entire input string (used only for error reports)
2661 * ptr: where to start parsing bound
2662 * Output parameters:
2663 * *bound_str: receives palloc'd bound string, or NULL if none
2664 * *infinite: set true if no bound, else false
2665 *
2666 * The return value is the scan ptr, advanced past the bound string.
2667 * However, if escontext is an ErrorSaveContext, we return NULL on failure.
2668 */
2669static const char *
2670range_parse_bound(const char *string, const char *ptr,
2671 char **bound_str, bool *infinite, Node *escontext)
2672{
2674
2675 /* Check for null: completely empty input means null */
2676 if (*ptr == ',' || *ptr == ')' || *ptr == ']')
2677 {
2678 *bound_str = NULL;
2679 *infinite = true;
2680 }
2681 else
2682 {
2683 /* Extract string for this bound */
2684 bool inquote = false;
2685
2687 while (inquote || !(*ptr == ',' || *ptr == ')' || *ptr == ']'))
2688 {
2689 char ch = *ptr++;
2690
2691 if (ch == '\0')
2692 ereturn(escontext, NULL,
2693 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2694 errmsg("malformed range literal: \"%s\"",
2695 string),
2696 errdetail("Unexpected end of input.")));
2697 if (ch == '\\')
2698 {
2699 if (*ptr == '\0')
2700 ereturn(escontext, NULL,
2701 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2702 errmsg("malformed range literal: \"%s\"",
2703 string),
2704 errdetail("Unexpected end of input.")));
2705 appendStringInfoChar(&buf, *ptr++);
2706 }
2707 else if (ch == '"')
2708 {
2709 if (!inquote)
2710 inquote = true;
2711 else if (*ptr == '"')
2712 {
2713 /* doubled quote within quote sequence */
2714 appendStringInfoChar(&buf, *ptr++);
2715 }
2716 else
2717 inquote = false;
2718 }
2719 else
2721 }
2722
2723 *bound_str = buf.data;
2724 *infinite = false;
2725 }
2726
2727 return ptr;
2728}
2729
2730/*
2731 * Convert a deserialized range value to text form
2732 *
2733 * Inputs are the flags byte, and the two bound values already converted to
2734 * text (but not yet quoted). If no bound value, pass NULL.
2735 *
2736 * Result is a palloc'd string
2737 */
2738static char *
2739range_deparse(char flags, const char *lbound_str, const char *ubound_str)
2740{
2742
2743 if (flags & RANGE_EMPTY)
2745
2747
2748 appendStringInfoChar(&buf, (flags & RANGE_LB_INC) ? '[' : '(');
2749
2750 if (RANGE_HAS_LBOUND(flags))
2752
2754
2755 if (RANGE_HAS_UBOUND(flags))
2757
2758 appendStringInfoChar(&buf, (flags & RANGE_UB_INC) ? ']' : ')');
2759
2760 return buf.data;
2761}
2762
2763/*
2764 * Helper for range_deparse: quote a bound value as needed
2765 *
2766 * Result is a palloc'd string
2767 */
2768static char *
2770{
2771 bool nq;
2772 const char *ptr;
2774
2776
2777 /* Detect whether we need double quotes for this value */
2778 nq = (value[0] == '\0'); /* force quotes for empty string */
2779 for (ptr = value; *ptr; ptr++)
2780 {
2781 char ch = *ptr;
2782
2783 if (ch == '"' || ch == '\\' ||
2784 ch == '(' || ch == ')' ||
2785 ch == '[' || ch == ']' ||
2786 ch == ',' ||
2787 isspace((unsigned char) ch))
2788 {
2789 nq = true;
2790 break;
2791 }
2792 }
2793
2794 /* And emit the string */
2795 if (nq)
2797 for (ptr = value; *ptr; ptr++)
2798 {
2799 char ch = *ptr;
2800
2801 if (ch == '"' || ch == '\\')
2804 }
2805 if (nq)
2807
2808 return buf.data;
2809}
2810
2811/*
2812 * Test whether range r1 contains range r2.
2813 *
2814 * Caller has already checked that they are the same range type, and looked up
2815 * the necessary typcache entry.
2816 */
2817bool
2819{
2820 RangeBound lower1;
2821 RangeBound upper1;
2822 bool empty1;
2823 RangeBound lower2;
2824 RangeBound upper2;
2825 bool empty2;
2826
2827 /* Different types should be prevented by ANYRANGE matching rules */
2828 if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
2829 elog(ERROR, "range types do not match");
2830
2831 range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
2832 range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
2833
2834 /* If either range is empty, the answer is easy */
2835 if (empty2)
2836 return true;
2837 else if (empty1)
2838 return false;
2839
2840 /* Else we must have lower1 <= lower2 and upper1 >= upper2 */
2841 if (range_cmp_bounds(typcache, &lower1, &lower2) > 0)
2842 return false;
2843 if (range_cmp_bounds(typcache, &upper1, &upper2) < 0)
2844 return false;
2845
2846 return true;
2847}
2848
2849bool
2851{
2852 return range_contains_internal(typcache, r2, r1);
2853}
2854
2855/*
2856 * Test whether range r contains a specific element value.
2857 */
2858bool
2860{
2863 bool empty;
2864 int32 cmp;
2865
2866 range_deserialize(typcache, r, &lower, &upper, &empty);
2867
2868 if (empty)
2869 return false;
2870
2871 if (!lower.infinite)
2872 {
2874 typcache->rng_collation,
2875 lower.val, val));
2876 if (cmp > 0)
2877 return false;
2878 if (cmp == 0 && !lower.inclusive)
2879 return false;
2880 }
2881
2882 if (!upper.infinite)
2883 {
2885 typcache->rng_collation,
2886 upper.val, val));
2887 if (cmp < 0)
2888 return false;
2889 if (cmp == 0 && !upper.inclusive)
2890 return false;
2891 }
2892
2893 return true;
2894}
2895
2896
2897/*
2898 * datum_compute_size() and datum_write() are used to insert the bound
2899 * values into a range object. They are modeled after heaptuple.c's
2900 * heap_compute_data_size() and heap_fill_tuple(), but we need not handle
2901 * null values here. TYPE_IS_PACKABLE must test the same conditions as
2902 * heaptuple.c's ATT_IS_PACKABLE macro. See the comments there for more
2903 * details.
2904 */
2905
2906/* Does datatype allow packing into the 1-byte-header varlena format? */
2907#define TYPE_IS_PACKABLE(typlen, typstorage) \
2908 ((typlen) == -1 && (typstorage) != TYPSTORAGE_PLAIN)
2909
2910/*
2911 * Increment data_length by the space needed by the datum, including any
2912 * preceding alignment padding.
2913 */
2914static Size
2915datum_compute_size(Size data_length, Datum val, bool typbyval, char typalign,
2916 int16 typlen, char typstorage)
2917{
2918 if (TYPE_IS_PACKABLE(typlen, typstorage) &&
2920 {
2921 /*
2922 * we're anticipating converting to a short varlena header, so adjust
2923 * length and don't count any alignment
2924 */
2926 }
2927 else
2928 {
2929 data_length = att_align_datum(data_length, typalign, typlen, val);
2930 data_length = att_addlength_datum(data_length, typlen, val);
2931 }
2932
2933 return data_length;
2934}
2935
2936/*
2937 * Write the given datum beginning at ptr (after advancing to correct
2938 * alignment, if needed). Return the pointer incremented by space used.
2939 */
2940static Pointer
2941datum_write(Pointer ptr, Datum datum, bool typbyval, char typalign,
2942 int16 typlen, char typstorage)
2943{
2944 Size data_length;
2945
2946 if (typbyval)
2947 {
2948 /* pass-by-value */
2949 ptr = (char *) att_align_nominal(ptr, typalign);
2950 store_att_byval(ptr, datum, typlen);
2951 data_length = typlen;
2952 }
2953 else if (typlen == -1)
2954 {
2955 /* varlena */
2956 Pointer val = DatumGetPointer(datum);
2957
2959 {
2960 /*
2961 * Throw error, because we must never put a toast pointer inside a
2962 * range object. Caller should have detoasted it.
2963 */
2964 elog(ERROR, "cannot store a toast pointer inside a range");
2965 data_length = 0; /* keep compiler quiet */
2966 }
2967 else if (VARATT_IS_SHORT(val))
2968 {
2969 /* no alignment for short varlenas */
2970 data_length = VARSIZE_SHORT(val);
2971 memcpy(ptr, val, data_length);
2972 }
2973 else if (TYPE_IS_PACKABLE(typlen, typstorage) &&
2975 {
2976 /* convert to short varlena -- no alignment */
2977 data_length = VARATT_CONVERTED_SHORT_SIZE(val);
2978 SET_VARSIZE_SHORT(ptr, data_length);
2979 memcpy(ptr + 1, VARDATA(val), data_length - 1);
2980 }
2981 else
2982 {
2983 /* full 4-byte header varlena */
2984 ptr = (char *) att_align_nominal(ptr, typalign);
2985 data_length = VARSIZE(val);
2986 memcpy(ptr, val, data_length);
2987 }
2988 }
2989 else if (typlen == -2)
2990 {
2991 /* cstring ... never needs alignment */
2992 Assert(typalign == TYPALIGN_CHAR);
2993 data_length = strlen(DatumGetCString(datum)) + 1;
2994 memcpy(ptr, DatumGetPointer(datum), data_length);
2995 }
2996 else
2997 {
2998 /* fixed-length pass-by-reference */
2999 ptr = (char *) att_align_nominal(ptr, typalign);
3000 Assert(typlen > 0);
3001 data_length = typlen;
3002 memcpy(ptr, DatumGetPointer(datum), data_length);
3003 }
3004
3005 ptr += data_length;
3006
3007 return ptr;
3008}
3009
3010/*
3011 * Common code for the elem_contained_by_range and range_contains_elem
3012 * support functions. The caller has extracted the function argument
3013 * expressions, and swapped them if necessary to pass the range first.
3014 *
3015 * Returns a simplified replacement expression, or NULL if we can't simplify.
3016 */
3017static Node *
3019{
3021 TypeCacheEntry *rangetypcache;
3024 bool empty;
3025
3026 /* can't do anything unless the range is a non-null constant */
3027 if (!IsA(rangeExpr, Const) || ((Const *) rangeExpr)->constisnull)
3028 return NULL;
3029 range = DatumGetRangeTypeP(((Const *) rangeExpr)->constvalue);
3030
3031 rangetypcache = lookup_type_cache(RangeTypeGetOid(range),
3033 if (rangetypcache->rngelemtype == NULL)
3034 elog(ERROR, "type %u is not a range type", RangeTypeGetOid(range));
3035
3036 range_deserialize(rangetypcache, range, &lower, &upper, &empty);
3037
3038 if (empty)
3039 {
3040 /* if the range is empty, then there can be no matches */
3041 return makeBoolConst(false, false);
3042 }
3043 else if (lower.infinite && upper.infinite)
3044 {
3045 /* the range has infinite bounds, so it matches everything */
3046 return makeBoolConst(true, false);
3047 }
3048 else
3049 {
3050 /* at least one bound is available, we have something to work with */
3051 TypeCacheEntry *elemTypcache = rangetypcache->rngelemtype;
3052 Oid opfamily = rangetypcache->rng_opfamily;
3053 Oid rng_collation = rangetypcache->rng_collation;
3054 Expr *lowerExpr = NULL;
3055 Expr *upperExpr = NULL;
3056
3057 if (!lower.infinite && !upper.infinite)
3058 {
3059 /*
3060 * When both bounds are present, we have a problem: the
3061 * "simplified" clause would need to evaluate the elemExpr twice.
3062 * That's definitely not okay if the elemExpr is volatile, and
3063 * it's also unattractive if the elemExpr is expensive.
3064 */
3065 QualCost eval_cost;
3066
3067 if (contain_volatile_functions((Node *) elemExpr))
3068 return NULL;
3069
3070 /*
3071 * We define "expensive" as "contains any subplan or more than 10
3072 * operators". Note that the subplan search has to be done
3073 * explicitly, since cost_qual_eval() will barf on unplanned
3074 * subselects.
3075 */
3076 if (contain_subplans((Node *) elemExpr))
3077 return NULL;
3078 cost_qual_eval_node(&eval_cost, (Node *) elemExpr, root);
3079 if (eval_cost.startup + eval_cost.per_tuple >
3080 10 * cpu_operator_cost)
3081 return NULL;
3082 }
3083
3084 /* Okay, try to build boundary comparison expressions */
3085 if (!lower.infinite)
3086 {
3087 lowerExpr = build_bound_expr(elemExpr,
3088 lower.val,
3089 true,
3090 lower.inclusive,
3091 elemTypcache,
3092 opfamily,
3093 rng_collation);
3094 if (lowerExpr == NULL)
3095 return NULL;
3096 }
3097
3098 if (!upper.infinite)
3099 {
3100 /* Copy the elemExpr if we need two copies */
3101 if (!lower.infinite)
3102 elemExpr = copyObject(elemExpr);
3103 upperExpr = build_bound_expr(elemExpr,
3104 upper.val,
3105 false,
3106 upper.inclusive,
3107 elemTypcache,
3108 opfamily,
3109 rng_collation);
3110 if (upperExpr == NULL)
3111 return NULL;
3112 }
3113
3114 if (lowerExpr != NULL && upperExpr != NULL)
3115 return (Node *) make_andclause(list_make2(lowerExpr, upperExpr));
3116 else if (lowerExpr != NULL)
3117 return (Node *) lowerExpr;
3118 else if (upperExpr != NULL)
3119 return (Node *) upperExpr;
3120 else
3121 {
3122 Assert(false);
3123 return NULL;
3124 }
3125 }
3126}
3127
3128/*
3129 * Helper function for find_simplified_clause().
3130 *
3131 * Build the expression (elemExpr Operator val), where the operator is
3132 * the appropriate member of the given opfamily depending on
3133 * isLowerBound and isInclusive. typeCache is the typcache entry for
3134 * the "val" value (presently, this will be the same type as elemExpr).
3135 * rng_collation is the collation to use in the comparison.
3136 *
3137 * Return NULL on failure (if, for some reason, we can't find the operator).
3138 */
3139static Expr *
3141 bool isLowerBound, bool isInclusive,
3142 TypeCacheEntry *typeCache,
3143 Oid opfamily, Oid rng_collation)
3144{
3145 Oid elemType = typeCache->type_id;
3146 int16 elemTypeLen = typeCache->typlen;
3147 bool elemByValue = typeCache->typbyval;
3148 Oid elemCollation = typeCache->typcollation;
3149 int16 strategy;
3150 Oid oproid;
3151 Expr *constExpr;
3152
3153 /* Identify the comparison operator to use */
3154 if (isLowerBound)
3155 strategy = isInclusive ? BTGreaterEqualStrategyNumber : BTGreaterStrategyNumber;
3156 else
3157 strategy = isInclusive ? BTLessEqualStrategyNumber : BTLessStrategyNumber;
3158
3159 /*
3160 * We could use exprType(elemExpr) here, if it ever becomes possible that
3161 * elemExpr is not the exact same type as the range elements.
3162 */
3163 oproid = get_opfamily_member(opfamily, elemType, elemType, strategy);
3164
3165 /* We don't really expect failure here, but just in case ... */
3166 if (!OidIsValid(oproid))
3167 return NULL;
3168
3169 /* OK, convert "val" to a full-fledged Const node, and make the OpExpr */
3170 constExpr = (Expr *) makeConst(elemType,
3171 -1,
3172 elemCollation,
3173 elemTypeLen,
3174 val,
3175 false,
3176 elemByValue);
3177
3178 return make_opclause(oproid,
3179 BOOLOID,
3180 false,
3181 elemExpr,
3182 constExpr,
3183 InvalidOid,
3184 rng_collation);
3185}
Datum numeric_sub(PG_FUNCTION_ARGS)
Definition: numeric.c:2940
Datum numeric_float8(PG_FUNCTION_ARGS)
Definition: numeric.c:4557
#define PG_INT32_MAX
Definition: c.h:599
#define MAXALIGN(LEN)
Definition: c.h:815
char * Pointer
Definition: c.h:534
#define VARHDRSZ
Definition: c.h:702
int64_t int64
Definition: c.h:540
double float8
Definition: c.h:640
int16_t int16
Definition: c.h:538
int32_t int32
Definition: c.h:539
#define PG_INT64_MAX
Definition: c.h:602
uint64_t uint64
Definition: c.h:544
#define unlikely(x)
Definition: c.h:407
uint32_t uint32
Definition: c.h:543
#define OidIsValid(objectId)
Definition: c.h:779
size_t Size
Definition: c.h:615
bool contain_subplans(Node *clause)
Definition: clauses.c:342
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:550
double cpu_operator_cost
Definition: costsize.c:134
void cost_qual_eval_node(QualCost *cost, Node *qual, PlannerInfo *root)
Definition: costsize.c:4807
int64 Timestamp
Definition: timestamp.h:38
#define IS_VALID_DATE(d)
Definition: timestamp.h:262
#define USECS_PER_SEC
Definition: timestamp.h:134
static Datum DateADTGetDatum(DateADT X)
Definition: date.h:72
#define DATE_NOT_FINITE(j)
Definition: date.h:43
int32 DateADT
Definition: date.h:23
static DateADT DatumGetDateADT(Datum X)
Definition: date.h:54
int errdetail(const char *fmt,...)
Definition: elog.c:1216
int errhint(const char *fmt,...)
Definition: elog.c:1330
int errcode(int sqlerrcode)
Definition: elog.c:863
int errmsg(const char *fmt,...)
Definition: elog.c:1080
#define ereturn(context, dummy_value,...)
Definition: elog.h:278
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:226
#define ereport(elevel,...)
Definition: elog.h:150
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Definition: fmgr.c:1150
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:138
bytea * SendFunctionCall(FmgrInfo *flinfo, Datum val)
Definition: fmgr.c:1744
bool InputFunctionCallSafe(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod, Node *escontext, Datum *result)
Definition: fmgr.c:1585
char * OutputFunctionCall(FmgrInfo *flinfo, Datum val)
Definition: fmgr.c:1683
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1875
Datum FunctionCall1Coll(FmgrInfo *flinfo, Oid collation, Datum arg1)
Definition: fmgr.c:1130
Oid get_fn_expr_rettype(FmgrInfo *flinfo)
Definition: fmgr.c:1853
Datum ReceiveFunctionCall(FmgrInfo *flinfo, StringInfo buf, Oid typioparam, int32 typmod)
Definition: fmgr.c:1697
#define PG_RETURN_VOID()
Definition: fmgr.h:349
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:260
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:371
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:684
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:367
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition: fmgr.h:150
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:362
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:682
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:268
#define LOCAL_FCINFO(name, nargs)
Definition: fmgr.h:110
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:277
#define PG_RETURN_NULL()
Definition: fmgr.h:345
#define PG_GETARG_INT64(n)
Definition: fmgr.h:283
#define PG_DETOAST_DATUM_PACKED(datum)
Definition: fmgr.h:248
#define PG_RETURN_UINT64(x)
Definition: fmgr.h:369
#define FunctionCallInvoke(fcinfo)
Definition: fmgr.h:172
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354
#define PG_GETARG_INT32(n)
Definition: fmgr.h:269
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:353
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:361
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
char * format_type_be(Oid type_oid)
Definition: format_type.c:343
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:304
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:308
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:310
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:306
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:328
uint32 hash_bytes_uint32(uint32 k)
Definition: hashfn.c:610
#define ROTATE_HIGH_AND_LOW_32BITS(v)
Definition: hashfn.h:18
static Datum hash_uint32_extended(uint32 k, uint64 seed)
Definition: hashfn.h:49
Assert(PointerIsAligned(start, uint64))
long val
Definition: informix.c:689
static struct @171 value
int b
Definition: isn.c:74
int a
Definition: isn.c:73
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:81
bool type_is_range(Oid typid)
Definition: lsyscache.c:2855
Oid get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype, int16 strategy)
Definition: lsyscache.c:168
void get_type_io_data(Oid typid, IOFuncSelector which_func, int16 *typlen, bool *typbyval, char *typalign, char *typdelim, Oid *typioparam, Oid *func)
Definition: lsyscache.c:2492
IOFuncSelector
Definition: lsyscache.h:35
@ IOFunc_output
Definition: lsyscache.h:37
@ IOFunc_input
Definition: lsyscache.h:36
@ IOFunc_send
Definition: lsyscache.h:39
@ IOFunc_receive
Definition: lsyscache.h:38
Node * makeBoolConst(bool value, bool isnull)
Definition: makefuncs.c:408
Expr * make_andclause(List *andclauses)
Definition: makefuncs.c:727
Expr * make_opclause(Oid opno, Oid opresulttype, bool opretset, Expr *leftop, Expr *rightop, Oid opcollid, Oid inputcollid)
Definition: makefuncs.c:701
Const * makeConst(Oid consttype, int32 consttypmod, Oid constcollid, int constlen, Datum constvalue, bool constisnull, bool constbyval)
Definition: makefuncs.c:350
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1229
char * pstrdup(const char *in)
Definition: mcxt.c:1759
void pfree(void *pointer)
Definition: mcxt.c:1594
void * palloc0(Size size)
Definition: mcxt.c:1395
void * palloc(Size size)
Definition: mcxt.c:1365
#define SOFT_ERROR_OCCURRED(escontext)
Definition: miscnodes.h:53
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4613
#define IsA(nodeptr, _type_)
Definition: nodes.h:164
#define copyObject(obj)
Definition: nodes.h:232
Datum lower(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:49
Datum upper(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:80
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
void * arg
static uint32 pg_rotate_left32(uint32 word, int n)
Definition: pg_bitutils.h:428
static int list_length(const List *l)
Definition: pg_list.h:152
#define linitial(l)
Definition: pg_list.h:178
#define lsecond(l)
Definition: pg_list.h:183
#define list_make2(x1, x2)
Definition: pg_list.h:214
static char * buf
Definition: pg_test_fsync.c:72
char typalign
Definition: pg_type.h:176
int pg_strncasecmp(const char *s1, const char *s2, size_t n)
Definition: pgstrcasecmp.c:65
static uint32 DatumGetUInt32(Datum X)
Definition: postgres.h:232
static Datum Int64GetDatum(int64 X)
Definition: postgres.h:403
static uint64 DatumGetUInt64(Datum X)
Definition: postgres.h:413
static int64 DatumGetInt64(Datum X)
Definition: postgres.h:393
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:332
static float8 DatumGetFloat8(Datum X)
Definition: postgres.h:475
static char * DatumGetCString(Datum X)
Definition: postgres.h:345
uint64_t Datum
Definition: postgres.h:70
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:322
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:222
static int32 DatumGetInt32(Datum X)
Definition: postgres.h:212
#define InvalidOid
Definition: postgres_ext.h:37
unsigned int Oid
Definition: postgres_ext.h:32
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition: pqformat.c:415
void pq_sendbytes(StringInfo buf, const void *data, int datalen)
Definition: pqformat.c:126
void pq_getmsgend(StringInfo msg)
Definition: pqformat.c:635
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:326
int pq_getmsgbyte(StringInfo msg)
Definition: pqformat.c:399
const char * pq_getmsgbytes(StringInfo msg, int datalen)
Definition: pqformat.c:508
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:346
static void pq_sendint32(StringInfo buf, uint32 i)
Definition: pqformat.h:144
static void pq_sendbyte(StringInfo buf, uint8 byt)
Definition: pqformat.h:160
char string[11]
Definition: preproc-type.c:52
tree ctl root
Definition: radixtree.h:1857
Datum range_empty(PG_FUNCTION_ARGS)
Definition: rangetypes.c:495
Datum range_out(PG_FUNCTION_ARGS)
Definition: rangetypes.c:141
Datum tstzrange_subdiff(PG_FUNCTION_ARGS)
Definition: rangetypes.c:1907
Datum range_lower(PG_FUNCTION_ARGS)
Definition: rangetypes.c:450
bool range_ne_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:622
int range_cmp_bounds(TypeCacheEntry *typcache, const RangeBound *b1, const RangeBound *b2)
Definition: rangetypes.c:2248
Datum hash_range(PG_FUNCTION_ARGS)
Definition: rangetypes.c:1562
Datum range_cmp(PG_FUNCTION_ARGS)
Definition: rangetypes.c:1419
Datum range_in(PG_FUNCTION_ARGS)
Definition: rangetypes.c:92
Datum range_sortsupport(PG_FUNCTION_ARGS)
Definition: rangetypes.c:1465
bool range_split_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2, RangeType **output1, RangeType **output2)
Definition: rangetypes.c:1186
static int range_fast_cmp(Datum a, Datum b, SortSupport ssup)
Definition: rangetypes.c:1477
Datum daterange_canonical(PG_FUNCTION_ARGS)
Definition: rangetypes.c:1790
Datum range_le(PG_FUNCTION_ARGS)
Definition: rangetypes.c:1535
Datum range_before(PG_FUNCTION_ARGS)
Definition: rangetypes.c:693
RangeType * range_serialize(TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper, bool empty, struct Node *escontext)
Definition: rangetypes.c:1959
Datum int4range_subdiff(PG_FUNCTION_ARGS)
Definition: rangetypes.c:1853
Datum int8range_canonical(PG_FUNCTION_ARGS)
Definition: rangetypes.c:1743
bool range_contained_by_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:2850
#define TYPE_IS_PACKABLE(typlen, typstorage)
Definition: rangetypes.c:2907
RangeType * make_range(TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper, bool empty, struct Node *escontext)
Definition: rangetypes.c:2184
Datum range_lower_inc(PG_FUNCTION_ARGS)
Definition: rangetypes.c:505
Datum range_intersect_agg_transfn(PG_FUNCTION_ARGS)
Definition: rangetypes.c:1389
bool range_contains_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:2818
bool range_after_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:706
static bool range_parse(const char *string, char *flags, char **lbound_str, char **ubound_str, Node *escontext)
Definition: rangetypes.c:2554
static char * range_deparse(char flags, const char *lbound_str, const char *ubound_str)
Definition: rangetypes.c:2739
bool bounds_adjacent(TypeCacheEntry *typcache, RangeBound boundA, RangeBound boundB)
Definition: rangetypes.c:761
bool range_overlaps_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:845
Datum range_minus_multi(PG_FUNCTION_ARGS)
Definition: rangetypes.c:1225
Datum range_lower_inf(PG_FUNCTION_ARGS)
Definition: rangetypes.c:525
Datum range_upper_inc(PG_FUNCTION_ARGS)
Definition: rangetypes.c:515
bool range_before_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:668
Datum elem_contained_by_range(PG_FUNCTION_ARGS)
Definition: rangetypes.c:561
static RangeIOData * get_range_io_data(FunctionCallInfo fcinfo, Oid rngtypid, IOFuncSelector func)
Definition: rangetypes.c:321
Datum range_overleft(PG_FUNCTION_ARGS)
Definition: rangetypes.c:919
Datum range_contained_by(PG_FUNCTION_ARGS)
Definition: rangetypes.c:655
static Pointer datum_write(Pointer ptr, Datum datum, bool typbyval, char typalign, int16 typlen, char typstorage)
Definition: rangetypes.c:2941
Datum range_constructor2(PG_FUNCTION_ARGS)
Definition: rangetypes.c:381
Datum range_adjacent(PG_FUNCTION_ARGS)
Definition: rangetypes.c:832
Datum range_gt(PG_FUNCTION_ARGS)
Definition: rangetypes.c:1551
bool range_overright_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:932
bool range_contains_elem_internal(TypeCacheEntry *typcache, const RangeType *r, Datum val)
Definition: rangetypes.c:2859
Datum range_overright(PG_FUNCTION_ARGS)
Definition: rangetypes.c:960
Datum range_contains(PG_FUNCTION_ARGS)
Definition: rangetypes.c:642
Datum range_intersect(PG_FUNCTION_ARGS)
Definition: rangetypes.c:1131
Datum range_eq(PG_FUNCTION_ARGS)
Definition: rangetypes.c:609
RangeType * range_intersect_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:1147
Datum range_recv(PG_FUNCTION_ARGS)
Definition: rangetypes.c:181
RangeType * range_minus_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
Definition: rangetypes.c:997
void range_deserialize(TypeCacheEntry *typcache, const RangeType *range, RangeBound *lower, RangeBound *upper, bool *empty)
Definition: rangetypes.c:2088
Datum daterange_subdiff(PG_FUNCTION_ARGS)
Definition: rangetypes.c:1887
static char * range_bound_escape(const char *value)
Definition: rangetypes.c:2769
RangeType * range_union_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2, bool strict)
Definition: rangetypes.c:1056
Datum range_lt(PG_FUNCTION_ARGS)
Definition: rangetypes.c:1527
static Size datum_compute_size(Size data_length, Datum val, bool typbyval, char typalign, int16 typlen, char typstorage)
Definition: rangetypes.c:2915
Datum int8range_subdiff(PG_FUNCTION_ARGS)
Definition: rangetypes.c:1862
bool range_eq_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:577
Datum range_upper_inf(PG_FUNCTION_ARGS)
Definition: rangetypes.c:535
Datum int4range_canonical(PG_FUNCTION_ARGS)
Definition: rangetypes.c:1696
Datum range_ge(PG_FUNCTION_ARGS)
Definition: rangetypes.c:1543
Datum range_overlaps(PG_FUNCTION_ARGS)
Definition: rangetypes.c:878
Datum range_contains_elem_support(PG_FUNCTION_ARGS)
Definition: rangetypes.c:2445
Datum range_upper(PG_FUNCTION_ARGS)
Definition: rangetypes.c:471
bool range_adjacent_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:802
Datum elem_contained_by_range_support(PG_FUNCTION_ARGS)
Definition: rangetypes.c:2419
void range_set_contain_empty(RangeType *range)
Definition: rangetypes.c:2169
Datum range_constructor3(PG_FUNCTION_ARGS)
Definition: rangetypes.c:410
TypeCacheEntry * range_get_typcache(FunctionCallInfo fcinfo, Oid rngtypid)
Definition: rangetypes.c:1935
static Expr * build_bound_expr(Expr *elemExpr, Datum val, bool isLowerBound, bool isInclusive, TypeCacheEntry *typeCache, Oid opfamily, Oid rng_collation)
Definition: rangetypes.c:3140
char range_get_flags(const RangeType *range)
Definition: rangetypes.c:2155
Datum hash_range_extended(PG_FUNCTION_ARGS)
Definition: rangetypes.c:1628
static const char * range_parse_bound(const char *string, const char *ptr, char **bound_str, bool *infinite, Node *escontext)
Definition: rangetypes.c:2670
static char range_parse_flags(const char *flags_str)
Definition: rangetypes.c:2479
Datum tsrange_subdiff(PG_FUNCTION_ARGS)
Definition: rangetypes.c:1896
bool range_overleft_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:891
int range_compare(const void *key1, const void *key2, void *arg)
Definition: rangetypes.c:2361
struct RangeIOData RangeIOData
Datum range_after(PG_FUNCTION_ARGS)
Definition: rangetypes.c:731
static Node * find_simplified_clause(PlannerInfo *root, Expr *rangeExpr, Expr *elemExpr)
Definition: rangetypes.c:3018
Datum range_union(PG_FUNCTION_ARGS)
Definition: rangetypes.c:1102
Datum range_minus(PG_FUNCTION_ARGS)
Definition: rangetypes.c:976
void range_minus_multi_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2, RangeType **outputs, int *outputn)
Definition: rangetypes.c:1306
RangeType * make_empty_range(TypeCacheEntry *typcache)
Definition: rangetypes.c:2397
Datum range_ne(PG_FUNCTION_ARGS)
Definition: rangetypes.c:629
int range_cmp_bound_values(TypeCacheEntry *typcache, const RangeBound *b1, const RangeBound *b2)
Definition: rangetypes.c:2322
Datum range_merge(PG_FUNCTION_ARGS)
Definition: rangetypes.c:1118
Datum range_send(PG_FUNCTION_ARGS)
Definition: rangetypes.c:265
Datum range_contains_elem(PG_FUNCTION_ARGS)
Definition: rangetypes.c:548
Datum numrange_subdiff(PG_FUNCTION_ARGS)
Definition: rangetypes.c:1871
static RangeType * DatumGetRangeTypeP(Datum X)
Definition: rangetypes.h:73
#define RANGE_CONTAIN_EMPTY
Definition: rangetypes.h:45
#define RANGE_HAS_UBOUND(flags)
Definition: rangetypes.h:51
#define RANGE_UB_INC
Definition: rangetypes.h:40
#define RangeIsEmpty(r)
Definition: rangetypes.h:55
static Datum RangeTypePGetDatum(const RangeType *X)
Definition: rangetypes.h:85
#define RANGE_LB_INC
Definition: rangetypes.h:39
#define RANGE_UB_INF
Definition: rangetypes.h:42
#define PG_RETURN_RANGE_P(x)
Definition: rangetypes.h:92
#define RANGE_EMPTY
Definition: rangetypes.h:38
#define RANGE_HAS_LBOUND(flags)
Definition: rangetypes.h:47
#define PG_GETARG_RANGE_P(n)
Definition: rangetypes.h:90
#define RANGE_EMPTY_LITERAL
Definition: rangetypes.h:32
#define RANGE_LB_INF
Definition: rangetypes.h:41
#define RangeTypeGetOid(r)
Definition: rangetypes.h:35
static int cmp(const chr *x, const chr *y, size_t len)
Definition: regc_locale.c:743
static struct cvec * range(struct vars *v, chr a, chr b, int cases)
Definition: regc_locale.c:412
struct SortSupportData * SortSupport
Definition: sortsupport.h:58
void check_stack_depth(void)
Definition: stack_depth.c:95
#define BTGreaterStrategyNumber
Definition: stratnum.h:33
#define BTLessStrategyNumber
Definition: stratnum.h:29
#define BTLessEqualStrategyNumber
Definition: stratnum.h:30
#define BTGreaterEqualStrategyNumber
Definition: stratnum.h:32
struct StringInfoData * StringInfo
Definition: string.h:15
void appendBinaryStringInfo(StringInfo str, const void *data, int datalen)
Definition: stringinfo.c:281
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:230
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:242
void initStringInfo(StringInfo str)
Definition: stringinfo.c:97
Definition: fmgr.h:57
void * fn_extra
Definition: fmgr.h:64
MemoryContext fn_mcxt
Definition: fmgr.h:65
Oid fn_oid
Definition: fmgr.h:59
void * user_fctx
Definition: funcapi.h:82
uint64 call_cntr
Definition: funcapi.h:65
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:101
List * args
Definition: primnodes.h:800
FmgrInfo * flinfo
Definition: fmgr.h:87
Definition: nodes.h:135
Cost per_tuple
Definition: pathnodes.h:48
Cost startup
Definition: pathnodes.h:47
bool lower
Definition: rangetypes.h:66
bool infinite
Definition: rangetypes.h:64
bool inclusive
Definition: rangetypes.h:65
Datum val
Definition: rangetypes.h:63
TypeCacheEntry * typcache
Definition: rangetypes.c:55
FmgrInfo typioproc
Definition: rangetypes.c:56
Oid typioparam
Definition: rangetypes.c:57
int(* comparator)(Datum x, Datum y, SortSupport ssup)
Definition: sortsupport.h:106
void * ssup_extra
Definition: sortsupport.h:87
PlannerInfo * root
Definition: supportnodes.h:70
FmgrInfo hash_proc_finfo
Definition: typcache.h:78
FmgrInfo rng_cmp_proc_finfo
Definition: typcache.h:102
Oid rng_collation
Definition: typcache.h:101
char typalign
Definition: typcache.h:41
struct TypeCacheEntry * rngelemtype
Definition: typcache.h:99
FmgrInfo hash_extended_proc_finfo
Definition: typcache.h:79
bool typbyval
Definition: typcache.h:40
FmgrInfo rng_canonical_finfo
Definition: typcache.h:103
int16 typlen
Definition: typcache.h:39
Oid typcollation
Definition: typcache.h:48
char typstorage
Definition: typcache.h:42
Oid rng_opfamily
Definition: typcache.h:100
Definition: c.h:697
#define att_align_pointer(cur_offset, attalign, attlen, attptr)
Definition: tupmacs.h:113
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:145
#define att_align_datum(cur_offset, attalign, attlen, attdatum)
Definition: tupmacs.h:82
#define att_addlength_pointer(cur_offset, attlen, attptr)
Definition: tupmacs.h:180
static Datum fetch_att(const void *T, bool attbyval, int attlen)
Definition: tupmacs.h:50
#define att_addlength_datum(cur_offset, attlen, attdatum)
Definition: tupmacs.h:168
static void store_att_byval(void *T, Datum newdatum, int attlen)
Definition: tupmacs.h:206
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:386
#define TYPECACHE_HASH_PROC_FINFO
Definition: typcache.h:145
#define TYPECACHE_RANGE_INFO
Definition: typcache.h:149
#define TYPECACHE_HASH_EXTENDED_PROC_FINFO
Definition: typcache.h:153
#define PG_GETARG_TIMESTAMP(n)
Definition: timestamp.h:63
static bool VARATT_IS_SHORT(const void *PTR)
Definition: varatt.h:403
static bool VARATT_CAN_MAKE_SHORT(const void *PTR)
Definition: varatt.h:417
static bool VARATT_IS_EXTERNAL(const void *PTR)
Definition: varatt.h:354
static Size VARSIZE(const void *PTR)
Definition: varatt.h:298
static char * VARDATA(const void *PTR)
Definition: varatt.h:305
static Size VARATT_CONVERTED_SHORT_SIZE(const void *PTR)
Definition: varatt.h:425
static void SET_VARSIZE_SHORT(void *PTR, Size len)
Definition: varatt.h:439
static void SET_VARSIZE(void *PTR, Size len)
Definition: varatt.h:432
static Size VARSIZE_SHORT(const void *PTR)
Definition: varatt.h:312
char * text_to_cstring(const text *t)
Definition: varlena.c:214