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