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