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