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