PostgreSQL Source Code  git master
rangetypes.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * rangetypes.c
4  * I/O functions, operators, and support functions for range types.
5  *
6  * The stored (serialized) format of a range value is:
7  *
8  * 4 bytes: varlena header
9  * 4 bytes: range type's OID
10  * Lower boundary value, if any, aligned according to subtype's typalign
11  * Upper boundary value, if any, aligned according to subtype's typalign
12  * 1 byte for flags
13  *
14  * This representation is chosen to avoid needing any padding before the
15  * lower boundary value, even when it requires double alignment. We can
16  * expect that the varlena header is presented to us on a suitably aligned
17  * boundary (possibly after detoasting), and then the lower boundary is too.
18  * Note that this means we can't work with a packed (short varlena header)
19  * value; we must detoast it first.
20  *
21  *
22  * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
23  * Portions Copyright (c) 1994, Regents of the University of California
24  *
25  *
26  * IDENTIFICATION
27  * src/backend/utils/adt/rangetypes.c
28  *
29  *-------------------------------------------------------------------------
30  */
31 #include "postgres.h"
32 
33 #include "access/tupmacs.h"
34 #include "common/hashfn.h"
35 #include "lib/stringinfo.h"
36 #include "libpq/pqformat.h"
37 #include "miscadmin.h"
38 #include "utils/builtins.h"
39 #include "utils/date.h"
40 #include "utils/int8.h"
41 #include "utils/lsyscache.h"
42 #include "utils/rangetypes.h"
43 #include "utils/timestamp.h"
44 
45 
46 /* fn_extra cache entry for one of the range I/O functions */
47 typedef struct RangeIOData
48 {
49  TypeCacheEntry *typcache; /* range type's typcache entry */
50  FmgrInfo typioproc; /* element type's I/O function */
51  Oid typioparam; /* element type's I/O parameter */
52 } RangeIOData;
53 
54 
55 static RangeIOData *get_range_io_data(FunctionCallInfo fcinfo, Oid rngtypid,
56  IOFuncSelector func);
57 static char range_parse_flags(const char *flags_str);
58 static void range_parse(const char *input_str, char *flags, char **lbound_str,
59  char **ubound_str);
60 static const char *range_parse_bound(const char *string, const char *ptr,
61  char **bound_str, bool *infinite);
62 static char *range_deparse(char flags, const char *lbound_str,
63  const char *ubound_str);
64 static char *range_bound_escape(const char *value);
65 static Size datum_compute_size(Size sz, Datum datum, bool typbyval,
66  char typalign, int16 typlen, char typstorage);
67 static Pointer datum_write(Pointer ptr, Datum datum, bool typbyval,
68  char typalign, int16 typlen, char typstorage);
69 
70 
71 /*
72  *----------------------------------------------------------
73  * I/O FUNCTIONS
74  *----------------------------------------------------------
75  */
76 
77 Datum
79 {
80  char *input_str = PG_GETARG_CSTRING(0);
81  Oid rngtypoid = PG_GETARG_OID(1);
82  Oid typmod = PG_GETARG_INT32(2);
84  RangeIOData *cache;
85  char flags;
86  char *lbound_str;
87  char *ubound_str;
90 
91  check_stack_depth(); /* recurses when subtype is a range type */
92 
93  cache = get_range_io_data(fcinfo, rngtypoid, IOFunc_input);
94 
95  /* parse */
96  range_parse(input_str, &flags, &lbound_str, &ubound_str);
97 
98  /* call element type's input function */
99  if (RANGE_HAS_LBOUND(flags))
100  lower.val = InputFunctionCall(&cache->typioproc, lbound_str,
101  cache->typioparam, typmod);
102  if (RANGE_HAS_UBOUND(flags))
103  upper.val = InputFunctionCall(&cache->typioproc, ubound_str,
104  cache->typioparam, typmod);
105 
106  lower.infinite = (flags & RANGE_LB_INF) != 0;
107  lower.inclusive = (flags & RANGE_LB_INC) != 0;
108  lower.lower = true;
109  upper.infinite = (flags & RANGE_UB_INF) != 0;
110  upper.inclusive = (flags & RANGE_UB_INC) != 0;
111  upper.lower = false;
112 
113  /* serialize and canonicalize */
114  range = make_range(cache->typcache, &lower, &upper, flags & RANGE_EMPTY);
115 
116  PG_RETURN_RANGE_P(range);
117 }
118 
119 Datum
121 {
123  char *output_str;
124  RangeIOData *cache;
125  char flags;
126  char *lbound_str = NULL;
127  char *ubound_str = NULL;
130  bool empty;
131 
132  check_stack_depth(); /* recurses when subtype is a range type */
133 
134  cache = get_range_io_data(fcinfo, RangeTypeGetOid(range), IOFunc_output);
135 
136  /* deserialize */
137  range_deserialize(cache->typcache, range, &lower, &upper, &empty);
138  flags = range_get_flags(range);
139 
140  /* call element type's output function */
141  if (RANGE_HAS_LBOUND(flags))
142  lbound_str = OutputFunctionCall(&cache->typioproc, lower.val);
143  if (RANGE_HAS_UBOUND(flags))
144  ubound_str = OutputFunctionCall(&cache->typioproc, upper.val);
145 
146  /* construct result string */
147  output_str = range_deparse(flags, lbound_str, ubound_str);
148 
149  PG_RETURN_CSTRING(output_str);
150 }
151 
152 /*
153  * Binary representation: The first byte is the flags, then the lower bound
154  * (if present), then the upper bound (if present). Each bound is represented
155  * by a 4-byte length header and the binary representation of that bound (as
156  * returned by a call to the send function for the subtype).
157  */
158 
159 Datum
161 {
163  Oid rngtypoid = PG_GETARG_OID(1);
164  int32 typmod = PG_GETARG_INT32(2);
165  RangeType *range;
166  RangeIOData *cache;
167  char flags;
170 
171  check_stack_depth(); /* recurses when subtype is a range type */
172 
173  cache = get_range_io_data(fcinfo, rngtypoid, IOFunc_receive);
174 
175  /* receive the flags... */
176  flags = (unsigned char) pq_getmsgbyte(buf);
177 
178  /*
179  * Mask out any unsupported flags, particularly RANGE_xB_NULL which would
180  * confuse following tests. Note that range_serialize will take care of
181  * cleaning up any inconsistencies in the remaining flags.
182  */
183  flags &= (RANGE_EMPTY |
184  RANGE_LB_INC |
185  RANGE_LB_INF |
186  RANGE_UB_INC |
187  RANGE_UB_INF);
188 
189  /* receive the bounds ... */
190  if (RANGE_HAS_LBOUND(flags))
191  {
192  uint32 bound_len = pq_getmsgint(buf, 4);
193  const char *bound_data = pq_getmsgbytes(buf, bound_len);
194  StringInfoData bound_buf;
195 
196  initStringInfo(&bound_buf);
197  appendBinaryStringInfo(&bound_buf, bound_data, bound_len);
198 
199  lower.val = ReceiveFunctionCall(&cache->typioproc,
200  &bound_buf,
201  cache->typioparam,
202  typmod);
203  pfree(bound_buf.data);
204  }
205  else
206  lower.val = (Datum) 0;
207 
208  if (RANGE_HAS_UBOUND(flags))
209  {
210  uint32 bound_len = pq_getmsgint(buf, 4);
211  const char *bound_data = pq_getmsgbytes(buf, bound_len);
212  StringInfoData bound_buf;
213 
214  initStringInfo(&bound_buf);
215  appendBinaryStringInfo(&bound_buf, bound_data, bound_len);
216 
217  upper.val = ReceiveFunctionCall(&cache->typioproc,
218  &bound_buf,
219  cache->typioparam,
220  typmod);
221  pfree(bound_buf.data);
222  }
223  else
224  upper.val = (Datum) 0;
225 
226  pq_getmsgend(buf);
227 
228  /* finish constructing RangeBound representation */
229  lower.infinite = (flags & RANGE_LB_INF) != 0;
230  lower.inclusive = (flags & RANGE_LB_INC) != 0;
231  lower.lower = true;
232  upper.infinite = (flags & RANGE_UB_INF) != 0;
233  upper.inclusive = (flags & RANGE_UB_INC) != 0;
234  upper.lower = false;
235 
236  /* serialize and canonicalize */
237  range = make_range(cache->typcache, &lower, &upper, flags & RANGE_EMPTY);
238 
239  PG_RETURN_RANGE_P(range);
240 }
241 
242 Datum
244 {
247  RangeIOData *cache;
248  char flags;
251  bool empty;
252 
253  check_stack_depth(); /* recurses when subtype is a range type */
254 
255  cache = get_range_io_data(fcinfo, RangeTypeGetOid(range), IOFunc_send);
256 
257  /* deserialize */
258  range_deserialize(cache->typcache, range, &lower, &upper, &empty);
259  flags = range_get_flags(range);
260 
261  /* construct output */
262  pq_begintypsend(buf);
263 
264  pq_sendbyte(buf, flags);
265 
266  if (RANGE_HAS_LBOUND(flags))
267  {
269  lower.val));
270  uint32 bound_len = VARSIZE(bound) - VARHDRSZ;
271  char *bound_data = VARDATA(bound);
272 
273  pq_sendint32(buf, bound_len);
274  pq_sendbytes(buf, bound_data, bound_len);
275  }
276 
277  if (RANGE_HAS_UBOUND(flags))
278  {
280  upper.val));
281  uint32 bound_len = VARSIZE(bound) - VARHDRSZ;
282  char *bound_data = VARDATA(bound);
283 
284  pq_sendint32(buf, bound_len);
285  pq_sendbytes(buf, bound_data, bound_len);
286  }
287 
289 }
290 
291 /*
292  * get_range_io_data: get cached information needed for range type I/O
293  *
294  * The range I/O functions need a bit more cached info than other range
295  * functions, so they store a RangeIOData struct in fn_extra, not just a
296  * pointer to a type cache entry.
297  */
298 static RangeIOData *
300 {
301  RangeIOData *cache = (RangeIOData *) fcinfo->flinfo->fn_extra;
302 
303  if (cache == NULL || cache->typcache->type_id != rngtypid)
304  {
305  int16 typlen;
306  bool typbyval;
307  char typalign;
308  char typdelim;
309  Oid typiofunc;
310 
311  cache = (RangeIOData *) MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
312  sizeof(RangeIOData));
313  cache->typcache = lookup_type_cache(rngtypid, TYPECACHE_RANGE_INFO);
314  if (cache->typcache->rngelemtype == NULL)
315  elog(ERROR, "type %u is not a range type", rngtypid);
316 
317  /* get_type_io_data does more than we need, but is convenient */
319  func,
320  &typlen,
321  &typbyval,
322  &typalign,
323  &typdelim,
324  &cache->typioparam,
325  &typiofunc);
326 
327  if (!OidIsValid(typiofunc))
328  {
329  /* this could only happen for receive or send */
330  if (func == IOFunc_receive)
331  ereport(ERROR,
332  (errcode(ERRCODE_UNDEFINED_FUNCTION),
333  errmsg("no binary input function available for type %s",
335  else
336  ereport(ERROR,
337  (errcode(ERRCODE_UNDEFINED_FUNCTION),
338  errmsg("no binary output function available for type %s",
340  }
341  fmgr_info_cxt(typiofunc, &cache->typioproc,
342  fcinfo->flinfo->fn_mcxt);
343 
344  fcinfo->flinfo->fn_extra = (void *) cache;
345  }
346 
347  return cache;
348 }
349 
350 
351 /*
352  *----------------------------------------------------------
353  * GENERIC FUNCTIONS
354  *----------------------------------------------------------
355  */
356 
357 /* Construct standard-form range value from two arguments */
358 Datum
360 {
361  Datum arg1 = PG_GETARG_DATUM(0);
362  Datum arg2 = PG_GETARG_DATUM(1);
363  Oid rngtypid = get_fn_expr_rettype(fcinfo->flinfo);
364  RangeType *range;
368 
369  typcache = range_get_typcache(fcinfo, rngtypid);
370 
371  lower.val = PG_ARGISNULL(0) ? (Datum) 0 : arg1;
372  lower.infinite = PG_ARGISNULL(0);
373  lower.inclusive = true;
374  lower.lower = true;
375 
376  upper.val = PG_ARGISNULL(1) ? (Datum) 0 : arg2;
377  upper.infinite = PG_ARGISNULL(1);
378  upper.inclusive = false;
379  upper.lower = false;
380 
381  range = make_range(typcache, &lower, &upper, false);
382 
383  PG_RETURN_RANGE_P(range);
384 }
385 
386 /* Construct general range value from three arguments */
387 Datum
389 {
390  Datum arg1 = PG_GETARG_DATUM(0);
391  Datum arg2 = PG_GETARG_DATUM(1);
392  Oid rngtypid = get_fn_expr_rettype(fcinfo->flinfo);
393  RangeType *range;
397  char flags;
398 
399  typcache = range_get_typcache(fcinfo, rngtypid);
400 
401  if (PG_ARGISNULL(2))
402  ereport(ERROR,
403  (errcode(ERRCODE_DATA_EXCEPTION),
404  errmsg("range constructor flags argument must not be null")));
405 
407 
408  lower.val = PG_ARGISNULL(0) ? (Datum) 0 : arg1;
409  lower.infinite = PG_ARGISNULL(0);
410  lower.inclusive = (flags & RANGE_LB_INC) != 0;
411  lower.lower = true;
412 
413  upper.val = PG_ARGISNULL(1) ? (Datum) 0 : arg2;
414  upper.infinite = PG_ARGISNULL(1);
415  upper.inclusive = (flags & RANGE_UB_INC) != 0;
416  upper.lower = false;
417 
418  range = make_range(typcache, &lower, &upper, false);
419 
420  PG_RETURN_RANGE_P(range);
421 }
422 
423 
424 /* range -> subtype functions */
425 
426 /* extract lower bound value */
427 Datum
429 {
430  RangeType *r1 = PG_GETARG_RANGE_P(0);
434  bool empty;
435 
436  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
437 
438  range_deserialize(typcache, r1, &lower, &upper, &empty);
439 
440  /* Return NULL if there's no finite lower bound */
441  if (empty || lower.infinite)
442  PG_RETURN_NULL();
443 
444  PG_RETURN_DATUM(lower.val);
445 }
446 
447 /* extract upper bound value */
448 Datum
450 {
451  RangeType *r1 = PG_GETARG_RANGE_P(0);
455  bool empty;
456 
457  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
458 
459  range_deserialize(typcache, r1, &lower, &upper, &empty);
460 
461  /* Return NULL if there's no finite upper bound */
462  if (empty || upper.infinite)
463  PG_RETURN_NULL();
464 
465  PG_RETURN_DATUM(upper.val);
466 }
467 
468 
469 /* range -> bool functions */
470 
471 /* is range empty? */
472 Datum
474 {
475  RangeType *r1 = PG_GETARG_RANGE_P(0);
476  char flags = range_get_flags(r1);
477 
478  PG_RETURN_BOOL(flags & RANGE_EMPTY);
479 }
480 
481 /* is lower bound inclusive? */
482 Datum
484 {
485  RangeType *r1 = PG_GETARG_RANGE_P(0);
486  char flags = range_get_flags(r1);
487 
488  PG_RETURN_BOOL(flags & RANGE_LB_INC);
489 }
490 
491 /* is upper bound inclusive? */
492 Datum
494 {
495  RangeType *r1 = PG_GETARG_RANGE_P(0);
496  char flags = range_get_flags(r1);
497 
498  PG_RETURN_BOOL(flags & RANGE_UB_INC);
499 }
500 
501 /* is lower bound infinite? */
502 Datum
504 {
505  RangeType *r1 = PG_GETARG_RANGE_P(0);
506  char flags = range_get_flags(r1);
507 
508  PG_RETURN_BOOL(flags & RANGE_LB_INF);
509 }
510 
511 /* is upper bound infinite? */
512 Datum
514 {
515  RangeType *r1 = PG_GETARG_RANGE_P(0);
516  char flags = range_get_flags(r1);
517 
518  PG_RETURN_BOOL(flags & RANGE_UB_INF);
519 }
520 
521 
522 /* range, element -> bool functions */
523 
524 /* contains? */
525 Datum
527 {
531 
532  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
533 
534  PG_RETURN_BOOL(range_contains_elem_internal(typcache, r, val));
535 }
536 
537 /* contained by? */
538 Datum
540 {
544 
545  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
546 
547  PG_RETURN_BOOL(range_contains_elem_internal(typcache, r, val));
548 }
549 
550 
551 /* range, range -> bool functions */
552 
553 /* equality (internal version) */
554 bool
556 {
557  RangeBound lower1,
558  lower2;
559  RangeBound upper1,
560  upper2;
561  bool empty1,
562  empty2;
563 
564  /* Different types should be prevented by ANYRANGE matching rules */
565  if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
566  elog(ERROR, "range types do not match");
567 
568  range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
569  range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
570 
571  if (empty1 && empty2)
572  return true;
573  if (empty1 != empty2)
574  return false;
575 
576  if (range_cmp_bounds(typcache, &lower1, &lower2) != 0)
577  return false;
578 
579  if (range_cmp_bounds(typcache, &upper1, &upper2) != 0)
580  return false;
581 
582  return true;
583 }
584 
585 /* equality */
586 Datum
588 {
589  RangeType *r1 = PG_GETARG_RANGE_P(0);
590  RangeType *r2 = PG_GETARG_RANGE_P(1);
592 
593  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
594 
595  PG_RETURN_BOOL(range_eq_internal(typcache, r1, r2));
596 }
597 
598 /* inequality (internal version) */
599 bool
601 {
602  return (!range_eq_internal(typcache, r1, r2));
603 }
604 
605 /* inequality */
606 Datum
608 {
609  RangeType *r1 = PG_GETARG_RANGE_P(0);
610  RangeType *r2 = PG_GETARG_RANGE_P(1);
612 
613  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
614 
615  PG_RETURN_BOOL(range_ne_internal(typcache, r1, r2));
616 }
617 
618 /* contains? */
619 Datum
621 {
622  RangeType *r1 = PG_GETARG_RANGE_P(0);
623  RangeType *r2 = PG_GETARG_RANGE_P(1);
625 
626  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
627 
628  PG_RETURN_BOOL(range_contains_internal(typcache, r1, r2));
629 }
630 
631 /* contained by? */
632 Datum
634 {
635  RangeType *r1 = PG_GETARG_RANGE_P(0);
636  RangeType *r2 = PG_GETARG_RANGE_P(1);
638 
639  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
640 
641  PG_RETURN_BOOL(range_contained_by_internal(typcache, r1, r2));
642 }
643 
644 /* strictly left of? (internal version) */
645 bool
647 {
648  RangeBound lower1,
649  lower2;
650  RangeBound upper1,
651  upper2;
652  bool empty1,
653  empty2;
654 
655  /* Different types should be prevented by ANYRANGE matching rules */
656  if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
657  elog(ERROR, "range types do not match");
658 
659  range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
660  range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
661 
662  /* An empty range is neither before nor after any other range */
663  if (empty1 || empty2)
664  return false;
665 
666  return (range_cmp_bounds(typcache, &upper1, &lower2) < 0);
667 }
668 
669 /* strictly left of? */
670 Datum
672 {
673  RangeType *r1 = PG_GETARG_RANGE_P(0);
674  RangeType *r2 = PG_GETARG_RANGE_P(1);
676 
677  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
678 
679  PG_RETURN_BOOL(range_before_internal(typcache, r1, r2));
680 }
681 
682 /* strictly right of? (internal version) */
683 bool
685 {
686  RangeBound lower1,
687  lower2;
688  RangeBound upper1,
689  upper2;
690  bool empty1,
691  empty2;
692 
693  /* Different types should be prevented by ANYRANGE matching rules */
694  if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
695  elog(ERROR, "range types do not match");
696 
697  range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
698  range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
699 
700  /* An empty range is neither before nor after any other range */
701  if (empty1 || empty2)
702  return false;
703 
704  return (range_cmp_bounds(typcache, &lower1, &upper2) > 0);
705 }
706 
707 /* strictly right of? */
708 Datum
710 {
711  RangeType *r1 = PG_GETARG_RANGE_P(0);
712  RangeType *r2 = PG_GETARG_RANGE_P(1);
714 
715  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
716 
717  PG_RETURN_BOOL(range_after_internal(typcache, r1, r2));
718 }
719 
720 /*
721  * Check if two bounds A and B are "adjacent", where A is an upper bound and B
722  * is a lower bound. For the bounds to be adjacent, each subtype value must
723  * satisfy strictly one of the bounds: there are no values which satisfy both
724  * bounds (i.e. less than A and greater than B); and there are no values which
725  * satisfy neither bound (i.e. greater than A and less than B).
726  *
727  * For discrete ranges, we rely on the canonicalization function to see if A..B
728  * normalizes to empty. (If there is no canonicalization function, it's
729  * impossible for such a range to normalize to empty, so we needn't bother to
730  * try.)
731  *
732  * If A == B, the ranges are adjacent only if the bounds have different
733  * inclusive flags (i.e., exactly one of the ranges includes the common
734  * boundary point).
735  *
736  * And if A > B then the ranges are not adjacent in this order.
737  */
738 bool
740 {
741  int cmp;
742 
743  Assert(!boundA.lower && boundB.lower);
744 
745  cmp = range_cmp_bound_values(typcache, &boundA, &boundB);
746  if (cmp < 0)
747  {
748  RangeType *r;
749 
750  /*
751  * Bounds do not overlap; see if there are points in between.
752  */
753 
754  /* in a continuous subtype, there are assumed to be points between */
755  if (!OidIsValid(typcache->rng_canonical_finfo.fn_oid))
756  return false;
757 
758  /*
759  * The bounds are of a discrete range type; so make a range A..B and
760  * see if it's empty.
761  */
762 
763  /* flip the inclusion flags */
764  boundA.inclusive = !boundA.inclusive;
765  boundB.inclusive = !boundB.inclusive;
766  /* change upper/lower labels to avoid Assert failures */
767  boundA.lower = true;
768  boundB.lower = false;
769  r = make_range(typcache, &boundA, &boundB, false);
770  return RangeIsEmpty(r);
771  }
772  else if (cmp == 0)
773  return boundA.inclusive != boundB.inclusive;
774  else
775  return false; /* bounds overlap */
776 }
777 
778 /* adjacent to (but not overlapping)? (internal version) */
779 bool
781 {
782  RangeBound lower1,
783  lower2;
784  RangeBound upper1,
785  upper2;
786  bool empty1,
787  empty2;
788 
789  /* Different types should be prevented by ANYRANGE matching rules */
790  if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
791  elog(ERROR, "range types do not match");
792 
793  range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
794  range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
795 
796  /* An empty range is not adjacent to any other range */
797  if (empty1 || empty2)
798  return false;
799 
800  /*
801  * Given two ranges A..B and C..D, the ranges are adjacent if and only if
802  * B is adjacent to C, or D is adjacent to A.
803  */
804  return (bounds_adjacent(typcache, upper1, lower2) ||
805  bounds_adjacent(typcache, upper2, lower1));
806 }
807 
808 /* adjacent to (but not overlapping)? */
809 Datum
811 {
812  RangeType *r1 = PG_GETARG_RANGE_P(0);
813  RangeType *r2 = PG_GETARG_RANGE_P(1);
815 
816  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
817 
818  PG_RETURN_BOOL(range_adjacent_internal(typcache, r1, r2));
819 }
820 
821 /* overlaps? (internal version) */
822 bool
824 {
825  RangeBound lower1,
826  lower2;
827  RangeBound upper1,
828  upper2;
829  bool empty1,
830  empty2;
831 
832  /* Different types should be prevented by ANYRANGE matching rules */
833  if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
834  elog(ERROR, "range types do not match");
835 
836  range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
837  range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
838 
839  /* An empty range does not overlap any other range */
840  if (empty1 || empty2)
841  return false;
842 
843  if (range_cmp_bounds(typcache, &lower1, &lower2) >= 0 &&
844  range_cmp_bounds(typcache, &lower1, &upper2) <= 0)
845  return true;
846 
847  if (range_cmp_bounds(typcache, &lower2, &lower1) >= 0 &&
848  range_cmp_bounds(typcache, &lower2, &upper1) <= 0)
849  return true;
850 
851  return false;
852 }
853 
854 /* overlaps? */
855 Datum
857 {
858  RangeType *r1 = PG_GETARG_RANGE_P(0);
859  RangeType *r2 = PG_GETARG_RANGE_P(1);
861 
862  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
863 
864  PG_RETURN_BOOL(range_overlaps_internal(typcache, r1, r2));
865 }
866 
867 /* does not extend to right of? (internal version) */
868 bool
870 {
871  RangeBound lower1,
872  lower2;
873  RangeBound upper1,
874  upper2;
875  bool empty1,
876  empty2;
877 
878  /* Different types should be prevented by ANYRANGE matching rules */
879  if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
880  elog(ERROR, "range types do not match");
881 
882  range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
883  range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
884 
885  /* An empty range is neither before nor after any other range */
886  if (empty1 || empty2)
887  return false;
888 
889  if (range_cmp_bounds(typcache, &upper1, &upper2) <= 0)
890  return true;
891 
892  return false;
893 }
894 
895 /* does not extend to right of? */
896 Datum
898 {
899  RangeType *r1 = PG_GETARG_RANGE_P(0);
900  RangeType *r2 = PG_GETARG_RANGE_P(1);
902 
903  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
904 
905  PG_RETURN_BOOL(range_overleft_internal(typcache, r1, r2));
906 }
907 
908 /* does not extend to left of? (internal version) */
909 bool
911 {
912  RangeBound lower1,
913  lower2;
914  RangeBound upper1,
915  upper2;
916  bool empty1,
917  empty2;
918 
919  /* Different types should be prevented by ANYRANGE matching rules */
920  if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
921  elog(ERROR, "range types do not match");
922 
923  range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
924  range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
925 
926  /* An empty range is neither before nor after any other range */
927  if (empty1 || empty2)
928  return false;
929 
930  if (range_cmp_bounds(typcache, &lower1, &lower2) >= 0)
931  return true;
932 
933  return false;
934 }
935 
936 /* does not extend to left of? */
937 Datum
939 {
940  RangeType *r1 = PG_GETARG_RANGE_P(0);
941  RangeType *r2 = PG_GETARG_RANGE_P(1);
943 
944  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
945 
946  PG_RETURN_BOOL(range_overright_internal(typcache, r1, r2));
947 }
948 
949 
950 /* range, range -> range functions */
951 
952 /* set difference */
953 Datum
955 {
956  RangeType *r1 = PG_GETARG_RANGE_P(0);
957  RangeType *r2 = PG_GETARG_RANGE_P(1);
958  RangeType *ret;
960 
961  /* Different types should be prevented by ANYRANGE matching rules */
962  if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
963  elog(ERROR, "range types do not match");
964 
965  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
966 
967  ret = range_minus_internal(typcache, r1, r2);
968  if (ret)
969  PG_RETURN_RANGE_P(ret);
970  else
971  PG_RETURN_NULL();
972 }
973 
974 RangeType *
976 {
977  RangeBound lower1,
978  lower2;
979  RangeBound upper1,
980  upper2;
981  bool empty1,
982  empty2;
983  int cmp_l1l2,
984  cmp_l1u2,
985  cmp_u1l2,
986  cmp_u1u2;
987 
988  range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
989  range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
990 
991  /* if either is empty, r1 is the correct answer */
992  if (empty1 || empty2)
993  return r1;
994 
995  cmp_l1l2 = range_cmp_bounds(typcache, &lower1, &lower2);
996  cmp_l1u2 = range_cmp_bounds(typcache, &lower1, &upper2);
997  cmp_u1l2 = range_cmp_bounds(typcache, &upper1, &lower2);
998  cmp_u1u2 = range_cmp_bounds(typcache, &upper1, &upper2);
999 
1000  if (cmp_l1l2 < 0 && cmp_u1u2 > 0)
1001  ereport(ERROR,
1002  (errcode(ERRCODE_DATA_EXCEPTION),
1003  errmsg("result of range difference would not be contiguous")));
1004 
1005  if (cmp_l1u2 > 0 || cmp_u1l2 < 0)
1006  return r1;
1007 
1008  if (cmp_l1l2 >= 0 && cmp_u1u2 <= 0)
1009  return make_empty_range(typcache);
1010 
1011  if (cmp_l1l2 <= 0 && cmp_u1l2 >= 0 && cmp_u1u2 <= 0)
1012  {
1013  lower2.inclusive = !lower2.inclusive;
1014  lower2.lower = false; /* it will become the upper bound */
1015  return make_range(typcache, &lower1, &lower2, false);
1016  }
1017 
1018  if (cmp_l1l2 >= 0 && cmp_u1u2 >= 0 && cmp_l1u2 <= 0)
1019  {
1020  upper2.inclusive = !upper2.inclusive;
1021  upper2.lower = true; /* it will become the lower bound */
1022  return make_range(typcache, &upper2, &upper1, false);
1023  }
1024 
1025  elog(ERROR, "unexpected case in range_minus");
1026  return NULL;
1027 }
1028 
1029 /*
1030  * Set union. If strict is true, it is an error that the two input ranges
1031  * are not adjacent or overlapping.
1032  */
1033 RangeType *
1035  bool strict)
1036 {
1037  RangeBound lower1,
1038  lower2;
1039  RangeBound upper1,
1040  upper2;
1041  bool empty1,
1042  empty2;
1043  RangeBound *result_lower;
1044  RangeBound *result_upper;
1045 
1046  /* Different types should be prevented by ANYRANGE matching rules */
1047  if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
1048  elog(ERROR, "range types do not match");
1049 
1050  range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
1051  range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
1052 
1053  /* if either is empty, the other is the correct answer */
1054  if (empty1)
1055  return r2;
1056  if (empty2)
1057  return r1;
1058 
1059  if (strict &&
1060  !DatumGetBool(range_overlaps_internal(typcache, r1, r2)) &&
1061  !DatumGetBool(range_adjacent_internal(typcache, r1, r2)))
1062  ereport(ERROR,
1063  (errcode(ERRCODE_DATA_EXCEPTION),
1064  errmsg("result of range union would not be contiguous")));
1065 
1066  if (range_cmp_bounds(typcache, &lower1, &lower2) < 0)
1067  result_lower = &lower1;
1068  else
1069  result_lower = &lower2;
1070 
1071  if (range_cmp_bounds(typcache, &upper1, &upper2) > 0)
1072  result_upper = &upper1;
1073  else
1074  result_upper = &upper2;
1075 
1076  return make_range(typcache, result_lower, result_upper, false);
1077 }
1078 
1079 Datum
1081 {
1082  RangeType *r1 = PG_GETARG_RANGE_P(0);
1083  RangeType *r2 = PG_GETARG_RANGE_P(1);
1085 
1086  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
1087 
1088  PG_RETURN_RANGE_P(range_union_internal(typcache, r1, r2, true));
1089 }
1090 
1091 /*
1092  * range merge: like set union, except also allow and account for non-adjacent
1093  * input ranges.
1094  */
1095 Datum
1097 {
1098  RangeType *r1 = PG_GETARG_RANGE_P(0);
1099  RangeType *r2 = PG_GETARG_RANGE_P(1);
1101 
1102  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
1103 
1104  PG_RETURN_RANGE_P(range_union_internal(typcache, r1, r2, false));
1105 }
1106 
1107 /* set intersection */
1108 Datum
1110 {
1111  RangeType *r1 = PG_GETARG_RANGE_P(0);
1112  RangeType *r2 = PG_GETARG_RANGE_P(1);
1114 
1115  /* Different types should be prevented by ANYRANGE matching rules */
1116  if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
1117  elog(ERROR, "range types do not match");
1118 
1119  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
1120 
1121  PG_RETURN_RANGE_P(range_intersect_internal(typcache, r1, r2));
1122 }
1123 
1124 RangeType *
1126 {
1127  RangeBound lower1,
1128  lower2;
1129  RangeBound upper1,
1130  upper2;
1131  bool empty1,
1132  empty2;
1133  RangeBound *result_lower;
1134  RangeBound *result_upper;
1135 
1136  range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
1137  range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
1138 
1139  if (empty1 || empty2 || !range_overlaps_internal(typcache, r1, r2))
1140  return make_empty_range(typcache);
1141 
1142  if (range_cmp_bounds(typcache, &lower1, &lower2) >= 0)
1143  result_lower = &lower1;
1144  else
1145  result_lower = &lower2;
1146 
1147  if (range_cmp_bounds(typcache, &upper1, &upper2) <= 0)
1148  result_upper = &upper1;
1149  else
1150  result_upper = &upper2;
1151 
1152  return make_range(typcache, result_lower, result_upper, false);
1153 }
1154 
1155 /* range, range -> range, range functions */
1156 
1157 /*
1158  * range_split_internal - if r2 intersects the middle of r1, leaving non-empty
1159  * ranges on both sides, then return true and set output1 and output2 to the
1160  * results of r1 - r2 (in order). Otherwise return false and don't set output1
1161  * or output2. Neither input range should be empty.
1162  */
1163 bool
1165  RangeType **output1, RangeType **output2)
1166 {
1167  RangeBound lower1,
1168  lower2;
1169  RangeBound upper1,
1170  upper2;
1171  bool empty1,
1172  empty2;
1173 
1174  range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
1175  range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
1176 
1177  if (range_cmp_bounds(typcache, &lower1, &lower2) < 0 &&
1178  range_cmp_bounds(typcache, &upper1, &upper2) > 0)
1179  {
1180  /*
1181  * Need to invert inclusive/exclusive for the lower2 and upper2
1182  * points. They can't be infinite though. We're allowed to overwrite
1183  * these RangeBounds since they only exist locally.
1184  */
1185  lower2.inclusive = !lower2.inclusive;
1186  lower2.lower = false;
1187  upper2.inclusive = !upper2.inclusive;
1188  upper2.lower = true;
1189 
1190  *output1 = make_range(typcache, &lower1, &lower2, false);
1191  *output2 = make_range(typcache, &upper2, &upper1, false);
1192  return true;
1193  }
1194 
1195  return false;
1196 }
1197 
1198 /* range -> range aggregate functions */
1199 
1200 Datum
1202 {
1203  MemoryContext aggContext;
1204  Oid rngtypoid;
1206  RangeType *result;
1207  RangeType *current;
1208 
1209  if (!AggCheckCallContext(fcinfo, &aggContext))
1210  elog(ERROR, "range_intersect_agg_transfn called in non-aggregate context");
1211 
1212  rngtypoid = get_fn_expr_argtype(fcinfo->flinfo, 1);
1213  if (!type_is_range(rngtypoid))
1214  ereport(ERROR, (errmsg("range_intersect_agg must be called with a range")));
1215 
1216  typcache = range_get_typcache(fcinfo, rngtypoid);
1217 
1218  /* strictness ensures these are non-null */
1219  result = PG_GETARG_RANGE_P(0);
1220  current = PG_GETARG_RANGE_P(1);
1221 
1222  result = range_intersect_internal(typcache, result, current);
1223  PG_RETURN_RANGE_P(result);
1224 }
1225 
1226 
1227 /* Btree support */
1228 
1229 /* btree comparator */
1230 Datum
1232 {
1233  RangeType *r1 = PG_GETARG_RANGE_P(0);
1234  RangeType *r2 = PG_GETARG_RANGE_P(1);
1236  RangeBound lower1,
1237  lower2;
1238  RangeBound upper1,
1239  upper2;
1240  bool empty1,
1241  empty2;
1242  int cmp;
1243 
1244  check_stack_depth(); /* recurses when subtype is a range type */
1245 
1246  /* Different types should be prevented by ANYRANGE matching rules */
1247  if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
1248  elog(ERROR, "range types do not match");
1249 
1250  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
1251 
1252  range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
1253  range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
1254 
1255  /* For b-tree use, empty ranges sort before all else */
1256  if (empty1 && empty2)
1257  cmp = 0;
1258  else if (empty1)
1259  cmp = -1;
1260  else if (empty2)
1261  cmp = 1;
1262  else
1263  {
1264  cmp = range_cmp_bounds(typcache, &lower1, &lower2);
1265  if (cmp == 0)
1266  cmp = range_cmp_bounds(typcache, &upper1, &upper2);
1267  }
1268 
1269  PG_FREE_IF_COPY(r1, 0);
1270  PG_FREE_IF_COPY(r2, 1);
1271 
1272  PG_RETURN_INT32(cmp);
1273 }
1274 
1275 /* inequality operators using the range_cmp function */
1276 Datum
1278 {
1279  int cmp = range_cmp(fcinfo);
1280 
1281  PG_RETURN_BOOL(cmp < 0);
1282 }
1283 
1284 Datum
1286 {
1287  int cmp = range_cmp(fcinfo);
1288 
1289  PG_RETURN_BOOL(cmp <= 0);
1290 }
1291 
1292 Datum
1294 {
1295  int cmp = range_cmp(fcinfo);
1296 
1297  PG_RETURN_BOOL(cmp >= 0);
1298 }
1299 
1300 Datum
1302 {
1303  int cmp = range_cmp(fcinfo);
1304 
1305  PG_RETURN_BOOL(cmp > 0);
1306 }
1307 
1308 /* Hash support */
1309 
1310 /* hash a range value */
1311 Datum
1313 {
1314  RangeType *r = PG_GETARG_RANGE_P(0);
1315  uint32 result;
1317  TypeCacheEntry *scache;
1318  RangeBound lower;
1319  RangeBound upper;
1320  bool empty;
1321  char flags;
1322  uint32 lower_hash;
1323  uint32 upper_hash;
1324 
1325  check_stack_depth(); /* recurses when subtype is a range type */
1326 
1327  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1328 
1329  /* deserialize */
1330  range_deserialize(typcache, r, &lower, &upper, &empty);
1331  flags = range_get_flags(r);
1332 
1333  /*
1334  * Look up the element type's hash function, if not done already.
1335  */
1336  scache = typcache->rngelemtype;
1337  if (!OidIsValid(scache->hash_proc_finfo.fn_oid))
1338  {
1340  if (!OidIsValid(scache->hash_proc_finfo.fn_oid))
1341  ereport(ERROR,
1342  (errcode(ERRCODE_UNDEFINED_FUNCTION),
1343  errmsg("could not identify a hash function for type %s",
1344  format_type_be(scache->type_id))));
1345  }
1346 
1347  /*
1348  * Apply the hash function to each bound.
1349  */
1350  if (RANGE_HAS_LBOUND(flags))
1351  lower_hash = DatumGetUInt32(FunctionCall1Coll(&scache->hash_proc_finfo,
1352  typcache->rng_collation,
1353  lower.val));
1354  else
1355  lower_hash = 0;
1356 
1357  if (RANGE_HAS_UBOUND(flags))
1358  upper_hash = DatumGetUInt32(FunctionCall1Coll(&scache->hash_proc_finfo,
1359  typcache->rng_collation,
1360  upper.val));
1361  else
1362  upper_hash = 0;
1363 
1364  /* Merge hashes of flags and bounds */
1365  result = hash_uint32((uint32) flags);
1366  result ^= lower_hash;
1367  result = (result << 1) | (result >> 31);
1368  result ^= upper_hash;
1369 
1370  PG_RETURN_INT32(result);
1371 }
1372 
1373 /*
1374  * Returns 64-bit value by hashing a value to a 64-bit value, with a seed.
1375  * Otherwise, similar to hash_range.
1376  */
1377 Datum
1379 {
1380  RangeType *r = PG_GETARG_RANGE_P(0);
1381  Datum seed = PG_GETARG_DATUM(1);
1382  uint64 result;
1384  TypeCacheEntry *scache;
1385  RangeBound lower;
1386  RangeBound upper;
1387  bool empty;
1388  char flags;
1389  uint64 lower_hash;
1390  uint64 upper_hash;
1391 
1393 
1394  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1395 
1396  range_deserialize(typcache, r, &lower, &upper, &empty);
1397  flags = range_get_flags(r);
1398 
1399  scache = typcache->rngelemtype;
1401  {
1402  scache = lookup_type_cache(scache->type_id,
1405  ereport(ERROR,
1406  (errcode(ERRCODE_UNDEFINED_FUNCTION),
1407  errmsg("could not identify a hash function for type %s",
1408  format_type_be(scache->type_id))));
1409  }
1410 
1411  if (RANGE_HAS_LBOUND(flags))
1413  typcache->rng_collation,
1414  lower.val,
1415  seed));
1416  else
1417  lower_hash = 0;
1418 
1419  if (RANGE_HAS_UBOUND(flags))
1421  typcache->rng_collation,
1422  upper.val,
1423  seed));
1424  else
1425  upper_hash = 0;
1426 
1427  /* Merge hashes of flags and bounds */
1428  result = DatumGetUInt64(hash_uint32_extended((uint32) flags,
1429  DatumGetInt64(seed)));
1430  result ^= lower_hash;
1431  result = ROTATE_HIGH_AND_LOW_32BITS(result);
1432  result ^= upper_hash;
1433 
1434  PG_RETURN_UINT64(result);
1435 }
1436 
1437 /*
1438  *----------------------------------------------------------
1439  * CANONICAL FUNCTIONS
1440  *
1441  * Functions for specific built-in range types.
1442  *----------------------------------------------------------
1443  */
1444 
1445 Datum
1447 {
1448  RangeType *r = PG_GETARG_RANGE_P(0);
1450  RangeBound lower;
1451  RangeBound upper;
1452  bool empty;
1453 
1454  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1455 
1456  range_deserialize(typcache, r, &lower, &upper, &empty);
1457 
1458  if (empty)
1459  PG_RETURN_RANGE_P(r);
1460 
1461  if (!lower.infinite && !lower.inclusive)
1462  {
1463  lower.val = DirectFunctionCall2(int4pl, lower.val, Int32GetDatum(1));
1464  lower.inclusive = true;
1465  }
1466 
1467  if (!upper.infinite && upper.inclusive)
1468  {
1469  upper.val = DirectFunctionCall2(int4pl, upper.val, Int32GetDatum(1));
1470  upper.inclusive = false;
1471  }
1472 
1473  PG_RETURN_RANGE_P(range_serialize(typcache, &lower, &upper, false));
1474 }
1475 
1476 Datum
1478 {
1479  RangeType *r = PG_GETARG_RANGE_P(0);
1481  RangeBound lower;
1482  RangeBound upper;
1483  bool empty;
1484 
1485  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1486 
1487  range_deserialize(typcache, r, &lower, &upper, &empty);
1488 
1489  if (empty)
1490  PG_RETURN_RANGE_P(r);
1491 
1492  if (!lower.infinite && !lower.inclusive)
1493  {
1494  lower.val = DirectFunctionCall2(int8pl, lower.val, Int64GetDatum(1));
1495  lower.inclusive = true;
1496  }
1497 
1498  if (!upper.infinite && upper.inclusive)
1499  {
1500  upper.val = DirectFunctionCall2(int8pl, upper.val, Int64GetDatum(1));
1501  upper.inclusive = false;
1502  }
1503 
1504  PG_RETURN_RANGE_P(range_serialize(typcache, &lower, &upper, false));
1505 }
1506 
1507 Datum
1509 {
1510  RangeType *r = PG_GETARG_RANGE_P(0);
1512  RangeBound lower;
1513  RangeBound upper;
1514  bool empty;
1515 
1516  typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1517 
1518  range_deserialize(typcache, r, &lower, &upper, &empty);
1519 
1520  if (empty)
1521  PG_RETURN_RANGE_P(r);
1522 
1523  if (!lower.infinite && !DATE_NOT_FINITE(DatumGetDateADT(lower.val)) &&
1524  !lower.inclusive)
1525  {
1526  lower.val = DirectFunctionCall2(date_pli, lower.val, Int32GetDatum(1));
1527  lower.inclusive = true;
1528  }
1529 
1530  if (!upper.infinite && !DATE_NOT_FINITE(DatumGetDateADT(upper.val)) &&
1531  upper.inclusive)
1532  {
1533  upper.val = DirectFunctionCall2(date_pli, upper.val, Int32GetDatum(1));
1534  upper.inclusive = false;
1535  }
1536 
1537  PG_RETURN_RANGE_P(range_serialize(typcache, &lower, &upper, false));
1538 }
1539 
1540 /*
1541  *----------------------------------------------------------
1542  * SUBTYPE_DIFF FUNCTIONS
1543  *
1544  * Functions for specific built-in range types.
1545  *
1546  * Note that subtype_diff does return the difference, not the absolute value
1547  * of the difference, and it must take care to avoid overflow.
1548  * (numrange_subdiff is at some risk there ...)
1549  *----------------------------------------------------------
1550  */
1551 
1552 Datum
1554 {
1555  int32 v1 = PG_GETARG_INT32(0);
1556  int32 v2 = PG_GETARG_INT32(1);
1557 
1558  PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
1559 }
1560 
1561 Datum
1563 {
1564  int64 v1 = PG_GETARG_INT64(0);
1565  int64 v2 = PG_GETARG_INT64(1);
1566 
1567  PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
1568 }
1569 
1570 Datum
1572 {
1573  Datum v1 = PG_GETARG_DATUM(0);
1574  Datum v2 = PG_GETARG_DATUM(1);
1575  Datum numresult;
1576  float8 floatresult;
1577 
1578  numresult = DirectFunctionCall2(numeric_sub, v1, v2);
1579 
1581  numresult));
1582 
1583  PG_RETURN_FLOAT8(floatresult);
1584 }
1585 
1586 Datum
1588 {
1589  int32 v1 = PG_GETARG_INT32(0);
1590  int32 v2 = PG_GETARG_INT32(1);
1591 
1592  PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
1593 }
1594 
1595 Datum
1597 {
1600  float8 result;
1601 
1602  result = ((float8) v1 - (float8) v2) / USECS_PER_SEC;
1603  PG_RETURN_FLOAT8(result);
1604 }
1605 
1606 Datum
1608 {
1611  float8 result;
1612 
1613  result = ((float8) v1 - (float8) v2) / USECS_PER_SEC;
1614  PG_RETURN_FLOAT8(result);
1615 }
1616 
1617 /*
1618  *----------------------------------------------------------
1619  * SUPPORT FUNCTIONS
1620  *
1621  * These functions aren't in pg_proc, but are useful for
1622  * defining new generic range functions in C.
1623  *----------------------------------------------------------
1624  */
1625 
1626 /*
1627  * range_get_typcache: get cached information about a range type
1628  *
1629  * This is for use by range-related functions that follow the convention
1630  * of using the fn_extra field as a pointer to the type cache entry for
1631  * the range type. Functions that need to cache more information than
1632  * that must fend for themselves.
1633  */
1636 {
1638 
1639  if (typcache == NULL ||
1640  typcache->type_id != rngtypid)
1641  {
1642  typcache = lookup_type_cache(rngtypid, TYPECACHE_RANGE_INFO);
1643  if (typcache->rngelemtype == NULL)
1644  elog(ERROR, "type %u is not a range type", rngtypid);
1645  fcinfo->flinfo->fn_extra = (void *) typcache;
1646  }
1647 
1648  return typcache;
1649 }
1650 
1651 /*
1652  * range_serialize: construct a range value from bounds and empty-flag
1653  *
1654  * This does not force canonicalization of the range value. In most cases,
1655  * external callers should only be canonicalization functions. Note that
1656  * we perform some datatype-independent canonicalization checks anyway.
1657  */
1658 RangeType *
1660  bool empty)
1661 {
1662  RangeType *range;
1663  int cmp;
1664  Size msize;
1665  Pointer ptr;
1666  int16 typlen;
1667  bool typbyval;
1668  char typalign;
1669  char typstorage;
1670  char flags = 0;
1671 
1672  /*
1673  * Verify range is not invalid on its face, and construct flags value,
1674  * preventing any non-canonical combinations such as infinite+inclusive.
1675  */
1676  Assert(lower->lower);
1677  Assert(!upper->lower);
1678 
1679  if (empty)
1680  flags |= RANGE_EMPTY;
1681  else
1682  {
1683  cmp = range_cmp_bound_values(typcache, lower, upper);
1684 
1685  /* error check: if lower bound value is above upper, it's wrong */
1686  if (cmp > 0)
1687  ereport(ERROR,
1688  (errcode(ERRCODE_DATA_EXCEPTION),
1689  errmsg("range lower bound must be less than or equal to range upper bound")));
1690 
1691  /* if bounds are equal, and not both inclusive, range is empty */
1692  if (cmp == 0 && !(lower->inclusive && upper->inclusive))
1693  flags |= RANGE_EMPTY;
1694  else
1695  {
1696  /* infinite boundaries are never inclusive */
1697  if (lower->infinite)
1698  flags |= RANGE_LB_INF;
1699  else if (lower->inclusive)
1700  flags |= RANGE_LB_INC;
1701  if (upper->infinite)
1702  flags |= RANGE_UB_INF;
1703  else if (upper->inclusive)
1704  flags |= RANGE_UB_INC;
1705  }
1706  }
1707 
1708  /* Fetch information about range's element type */
1709  typlen = typcache->rngelemtype->typlen;
1710  typbyval = typcache->rngelemtype->typbyval;
1711  typalign = typcache->rngelemtype->typalign;
1712  typstorage = typcache->rngelemtype->typstorage;
1713 
1714  /* Count space for varlena header and range type's OID */
1715  msize = sizeof(RangeType);
1716  Assert(msize == MAXALIGN(msize));
1717 
1718  /* Count space for bounds */
1719  if (RANGE_HAS_LBOUND(flags))
1720  {
1721  /*
1722  * Make sure item to be inserted is not toasted. It is essential that
1723  * we not insert an out-of-line toast value pointer into a range
1724  * object, for the same reasons that arrays and records can't contain
1725  * them. It would work to store a compressed-in-line value, but we
1726  * prefer to decompress and then let compression be applied to the
1727  * whole range object if necessary. But, unlike arrays, we do allow
1728  * short-header varlena objects to stay as-is.
1729  */
1730  if (typlen == -1)
1731  lower->val = PointerGetDatum(PG_DETOAST_DATUM_PACKED(lower->val));
1732 
1733  msize = datum_compute_size(msize, lower->val, typbyval, typalign,
1734  typlen, typstorage);
1735  }
1736 
1737  if (RANGE_HAS_UBOUND(flags))
1738  {
1739  /* Make sure item to be inserted is not toasted */
1740  if (typlen == -1)
1741  upper->val = PointerGetDatum(PG_DETOAST_DATUM_PACKED(upper->val));
1742 
1743  msize = datum_compute_size(msize, upper->val, typbyval, typalign,
1744  typlen, typstorage);
1745  }
1746 
1747  /* Add space for flag byte */
1748  msize += sizeof(char);
1749 
1750  /* Note: zero-fill is required here, just as in heap tuples */
1751  range = (RangeType *) palloc0(msize);
1752  SET_VARSIZE(range, msize);
1753 
1754  /* Now fill in the datum */
1755  range->rangetypid = typcache->type_id;
1756 
1757  ptr = (char *) (range + 1);
1758 
1759  if (RANGE_HAS_LBOUND(flags))
1760  {
1761  Assert(lower->lower);
1762  ptr = datum_write(ptr, lower->val, typbyval, typalign, typlen,
1763  typstorage);
1764  }
1765 
1766  if (RANGE_HAS_UBOUND(flags))
1767  {
1768  Assert(!upper->lower);
1769  ptr = datum_write(ptr, upper->val, typbyval, typalign, typlen,
1770  typstorage);
1771  }
1772 
1773  *((char *) ptr) = flags;
1774 
1775  return range;
1776 }
1777 
1778 /*
1779  * range_deserialize: deconstruct a range value
1780  *
1781  * NB: the given range object must be fully detoasted; it cannot have a
1782  * short varlena header.
1783  *
1784  * Note that if the element type is pass-by-reference, the datums in the
1785  * RangeBound structs will be pointers into the given range object.
1786  */
1787 void
1789  RangeBound *lower, RangeBound *upper, bool *empty)
1790 {
1791  char flags;
1792  int16 typlen;
1793  bool typbyval;
1794  char typalign;
1795  Pointer ptr;
1796  Datum lbound;
1797  Datum ubound;
1798 
1799  /* assert caller passed the right typcache entry */
1800  Assert(RangeTypeGetOid(range) == typcache->type_id);
1801 
1802  /* fetch the flag byte from datum's last byte */
1803  flags = *((const char *) range + VARSIZE(range) - 1);
1804 
1805  /* fetch information about range's element type */
1806  typlen = typcache->rngelemtype->typlen;
1807  typbyval = typcache->rngelemtype->typbyval;
1808  typalign = typcache->rngelemtype->typalign;
1809 
1810  /* initialize data pointer just after the range OID */
1811  ptr = (Pointer) (range + 1);
1812 
1813  /* fetch lower bound, if any */
1814  if (RANGE_HAS_LBOUND(flags))
1815  {
1816  /* att_align_pointer cannot be necessary here */
1817  lbound = fetch_att(ptr, typbyval, typlen);
1818  ptr = (Pointer) att_addlength_pointer(ptr, typlen, ptr);
1819  }
1820  else
1821  lbound = (Datum) 0;
1822 
1823  /* fetch upper bound, if any */
1824  if (RANGE_HAS_UBOUND(flags))
1825  {
1826  ptr = (Pointer) att_align_pointer(ptr, typalign, typlen, ptr);
1827  ubound = fetch_att(ptr, typbyval, typlen);
1828  /* no need for att_addlength_pointer */
1829  }
1830  else
1831  ubound = (Datum) 0;
1832 
1833  /* emit results */
1834 
1835  *empty = (flags & RANGE_EMPTY) != 0;
1836 
1837  lower->val = lbound;
1838  lower->infinite = (flags & RANGE_LB_INF) != 0;
1839  lower->inclusive = (flags & RANGE_LB_INC) != 0;
1840  lower->lower = true;
1841 
1842  upper->val = ubound;
1843  upper->infinite = (flags & RANGE_UB_INF) != 0;
1844  upper->inclusive = (flags & RANGE_UB_INC) != 0;
1845  upper->lower = false;
1846 }
1847 
1848 /*
1849  * range_get_flags: just get the flags from a RangeType value.
1850  *
1851  * This is frequently useful in places that only need the flags and not
1852  * the full results of range_deserialize.
1853  */
1854 char
1856 {
1857  /* fetch the flag byte from datum's last byte */
1858  return *((char *) range + VARSIZE(range) - 1);
1859 }
1860 
1861 /*
1862  * range_set_contain_empty: set the RANGE_CONTAIN_EMPTY bit in the value.
1863  *
1864  * This is only needed in GiST operations, so we don't include a provision
1865  * for setting it in range_serialize; rather, this function must be applied
1866  * afterwards.
1867  */
1868 void
1870 {
1871  char *flagsp;
1872 
1873  /* flag byte is datum's last byte */
1874  flagsp = (char *) range + VARSIZE(range) - 1;
1875 
1876  *flagsp |= RANGE_CONTAIN_EMPTY;
1877 }
1878 
1879 /*
1880  * This both serializes and canonicalizes (if applicable) the range.
1881  * This should be used by most callers.
1882  */
1883 RangeType *
1885  bool empty)
1886 {
1887  RangeType *range;
1888 
1889  range = range_serialize(typcache, lower, upper, empty);
1890 
1891  /* no need to call canonical on empty ranges ... */
1892  if (OidIsValid(typcache->rng_canonical_finfo.fn_oid) &&
1893  !RangeIsEmpty(range))
1895  RangeTypePGetDatum(range)));
1896 
1897  return range;
1898 }
1899 
1900 /*
1901  * Compare two range boundary points, returning <0, 0, or >0 according to
1902  * whether b1 is less than, equal to, or greater than b2.
1903  *
1904  * The boundaries can be any combination of upper and lower; so it's useful
1905  * for a variety of operators.
1906  *
1907  * The simple case is when b1 and b2 are both finite and inclusive, in which
1908  * case the result is just a comparison of the values held in b1 and b2.
1909  *
1910  * If a bound is exclusive, then we need to know whether it's a lower bound,
1911  * in which case we treat the boundary point as "just greater than" the held
1912  * value; or an upper bound, in which case we treat the boundary point as
1913  * "just less than" the held value.
1914  *
1915  * If a bound is infinite, it represents minus infinity (less than every other
1916  * point) if it's a lower bound; or plus infinity (greater than every other
1917  * point) if it's an upper bound.
1918  *
1919  * There is only one case where two boundaries compare equal but are not
1920  * identical: when both bounds are inclusive and hold the same finite value,
1921  * but one is an upper bound and the other a lower bound.
1922  */
1923 int
1925 {
1926  int32 result;
1927 
1928  /*
1929  * First, handle cases involving infinity, which don't require invoking
1930  * the comparison proc.
1931  */
1932  if (b1->infinite && b2->infinite)
1933  {
1934  /*
1935  * Both are infinity, so they are equal unless one is lower and the
1936  * other not.
1937  */
1938  if (b1->lower == b2->lower)
1939  return 0;
1940  else
1941  return b1->lower ? -1 : 1;
1942  }
1943  else if (b1->infinite)
1944  return b1->lower ? -1 : 1;
1945  else if (b2->infinite)
1946  return b2->lower ? 1 : -1;
1947 
1948  /*
1949  * Both boundaries are finite, so compare the held values.
1950  */
1952  typcache->rng_collation,
1953  b1->val, b2->val));
1954 
1955  /*
1956  * If the comparison is anything other than equal, we're done. If they
1957  * compare equal though, we still have to consider whether the boundaries
1958  * are inclusive or exclusive.
1959  */
1960  if (result == 0)
1961  {
1962  if (!b1->inclusive && !b2->inclusive)
1963  {
1964  /* both are exclusive */
1965  if (b1->lower == b2->lower)
1966  return 0;
1967  else
1968  return b1->lower ? 1 : -1;
1969  }
1970  else if (!b1->inclusive)
1971  return b1->lower ? 1 : -1;
1972  else if (!b2->inclusive)
1973  return b2->lower ? -1 : 1;
1974  else
1975  {
1976  /*
1977  * Both are inclusive and the values held are equal, so they are
1978  * equal regardless of whether they are upper or lower boundaries,
1979  * or a mix.
1980  */
1981  return 0;
1982  }
1983  }
1984 
1985  return result;
1986 }
1987 
1988 /*
1989  * Compare two range boundary point values, returning <0, 0, or >0 according
1990  * to whether b1 is less than, equal to, or greater than b2.
1991  *
1992  * This is similar to but simpler than range_cmp_bounds(). We just compare
1993  * the values held in b1 and b2, ignoring inclusive/exclusive flags. The
1994  * lower/upper flags only matter for infinities, where they tell us if the
1995  * infinity is plus or minus.
1996  */
1997 int
1999  const RangeBound *b2)
2000 {
2001  /*
2002  * First, handle cases involving infinity, which don't require invoking
2003  * the comparison proc.
2004  */
2005  if (b1->infinite && b2->infinite)
2006  {
2007  /*
2008  * Both are infinity, so they are equal unless one is lower and the
2009  * other not.
2010  */
2011  if (b1->lower == b2->lower)
2012  return 0;
2013  else
2014  return b1->lower ? -1 : 1;
2015  }
2016  else if (b1->infinite)
2017  return b1->lower ? -1 : 1;
2018  else if (b2->infinite)
2019  return b2->lower ? 1 : -1;
2020 
2021  /*
2022  * Both boundaries are finite, so compare the held values.
2023  */
2025  typcache->rng_collation,
2026  b1->val, b2->val));
2027 }
2028 
2029 /*
2030  * qsort callback for sorting ranges.
2031  *
2032  * Two empty ranges compare equal; an empty range sorts to the left of any
2033  * non-empty range. Two non-empty ranges are sorted by lower bound first
2034  * and by upper bound next.
2035  */
2036 int
2037 range_compare(const void *key1, const void *key2, void *arg)
2038 {
2039  RangeType *r1 = *(RangeType **) key1;
2040  RangeType *r2 = *(RangeType **) key2;
2042  RangeBound lower1;
2043  RangeBound upper1;
2044  RangeBound lower2;
2045  RangeBound upper2;
2046  bool empty1;
2047  bool empty2;
2048  int cmp;
2049 
2050  range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
2051  range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
2052 
2053  if (empty1 && empty2)
2054  cmp = 0;
2055  else if (empty1)
2056  cmp = -1;
2057  else if (empty2)
2058  cmp = 1;
2059  else
2060  {
2061  cmp = range_cmp_bounds(typcache, &lower1, &lower2);
2062  if (cmp == 0)
2063  cmp = range_cmp_bounds(typcache, &upper1, &upper2);
2064  }
2065 
2066  return cmp;
2067 }
2068 
2069 /*
2070  * Build an empty range value of the type indicated by the typcache entry.
2071  */
2072 RangeType *
2074 {
2075  RangeBound lower;
2076  RangeBound upper;
2077 
2078  lower.val = (Datum) 0;
2079  lower.infinite = false;
2080  lower.inclusive = false;
2081  lower.lower = true;
2082 
2083  upper.val = (Datum) 0;
2084  upper.infinite = false;
2085  upper.inclusive = false;
2086  upper.lower = false;
2087 
2088  return make_range(typcache, &lower, &upper, true);
2089 }
2090 
2091 
2092 /*
2093  *----------------------------------------------------------
2094  * STATIC FUNCTIONS
2095  *----------------------------------------------------------
2096  */
2097 
2098 /*
2099  * Given a string representing the flags for the range type, return the flags
2100  * represented as a char.
2101  */
2102 static char
2103 range_parse_flags(const char *flags_str)
2104 {
2105  char flags = 0;
2106 
2107  if (flags_str[0] == '\0' ||
2108  flags_str[1] == '\0' ||
2109  flags_str[2] != '\0')
2110  ereport(ERROR,
2111  (errcode(ERRCODE_SYNTAX_ERROR),
2112  errmsg("invalid range bound flags"),
2113  errhint("Valid values are \"[]\", \"[)\", \"(]\", and \"()\".")));
2114 
2115  switch (flags_str[0])
2116  {
2117  case '[':
2118  flags |= RANGE_LB_INC;
2119  break;
2120  case '(':
2121  break;
2122  default:
2123  ereport(ERROR,
2124  (errcode(ERRCODE_SYNTAX_ERROR),
2125  errmsg("invalid range bound flags"),
2126  errhint("Valid values are \"[]\", \"[)\", \"(]\", and \"()\".")));
2127  }
2128 
2129  switch (flags_str[1])
2130  {
2131  case ']':
2132  flags |= RANGE_UB_INC;
2133  break;
2134  case ')':
2135  break;
2136  default:
2137  ereport(ERROR,
2138  (errcode(ERRCODE_SYNTAX_ERROR),
2139  errmsg("invalid range bound flags"),
2140  errhint("Valid values are \"[]\", \"[)\", \"(]\", and \"()\".")));
2141  }
2142 
2143  return flags;
2144 }
2145 
2146 /*
2147  * Parse range input.
2148  *
2149  * Input parameters:
2150  * string: input string to be parsed
2151  * Output parameters:
2152  * *flags: receives flags bitmask
2153  * *lbound_str: receives palloc'd lower bound string, or NULL if none
2154  * *ubound_str: receives palloc'd upper bound string, or NULL if none
2155  *
2156  * This is modeled somewhat after record_in in rowtypes.c.
2157  * The input syntax is:
2158  * <range> := EMPTY
2159  * | <lb-inc> <string>, <string> <ub-inc>
2160  * <lb-inc> := '[' | '('
2161  * <ub-inc> := ']' | ')'
2162  *
2163  * Whitespace before or after <range> is ignored. Whitespace within a <string>
2164  * is taken literally and becomes part of the input string for that bound.
2165  *
2166  * A <string> of length zero is taken as "infinite" (i.e. no bound), unless it
2167  * is surrounded by double-quotes, in which case it is the literal empty
2168  * string.
2169  *
2170  * Within a <string>, special characters (such as comma, parenthesis, or
2171  * brackets) can be enclosed in double-quotes or escaped with backslash. Within
2172  * double-quotes, a double-quote can be escaped with double-quote or backslash.
2173  */
2174 static void
2175 range_parse(const char *string, char *flags, char **lbound_str,
2176  char **ubound_str)
2177 {
2178  const char *ptr = string;
2179  bool infinite;
2180 
2181  *flags = 0;
2182 
2183  /* consume whitespace */
2184  while (*ptr != '\0' && isspace((unsigned char) *ptr))
2185  ptr++;
2186 
2187  /* check for empty range */
2189  strlen(RANGE_EMPTY_LITERAL)) == 0)
2190  {
2191  *flags = RANGE_EMPTY;
2192  *lbound_str = NULL;
2193  *ubound_str = NULL;
2194 
2195  ptr += strlen(RANGE_EMPTY_LITERAL);
2196 
2197  /* the rest should be whitespace */
2198  while (*ptr != '\0' && isspace((unsigned char) *ptr))
2199  ptr++;
2200 
2201  /* should have consumed everything */
2202  if (*ptr != '\0')
2203  ereport(ERROR,
2204  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2205  errmsg("malformed range literal: \"%s\"",
2206  string),
2207  errdetail("Junk after \"empty\" key word.")));
2208 
2209  return;
2210  }
2211 
2212  if (*ptr == '[')
2213  {
2214  *flags |= RANGE_LB_INC;
2215  ptr++;
2216  }
2217  else if (*ptr == '(')
2218  ptr++;
2219  else
2220  ereport(ERROR,
2221  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2222  errmsg("malformed range literal: \"%s\"",
2223  string),
2224  errdetail("Missing left parenthesis or bracket.")));
2225 
2226  ptr = range_parse_bound(string, ptr, lbound_str, &infinite);
2227  if (infinite)
2228  *flags |= RANGE_LB_INF;
2229 
2230  if (*ptr == ',')
2231  ptr++;
2232  else
2233  ereport(ERROR,
2234  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2235  errmsg("malformed range literal: \"%s\"",
2236  string),
2237  errdetail("Missing comma after lower bound.")));
2238 
2239  ptr = range_parse_bound(string, ptr, ubound_str, &infinite);
2240  if (infinite)
2241  *flags |= RANGE_UB_INF;
2242 
2243  if (*ptr == ']')
2244  {
2245  *flags |= RANGE_UB_INC;
2246  ptr++;
2247  }
2248  else if (*ptr == ')')
2249  ptr++;
2250  else /* must be a comma */
2251  ereport(ERROR,
2252  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2253  errmsg("malformed range literal: \"%s\"",
2254  string),
2255  errdetail("Too many commas.")));
2256 
2257  /* consume whitespace */
2258  while (*ptr != '\0' && isspace((unsigned char) *ptr))
2259  ptr++;
2260 
2261  if (*ptr != '\0')
2262  ereport(ERROR,
2263  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2264  errmsg("malformed range literal: \"%s\"",
2265  string),
2266  errdetail("Junk after right parenthesis or bracket.")));
2267 }
2268 
2269 /*
2270  * Helper for range_parse: parse and de-quote one bound string.
2271  *
2272  * We scan until finding comma, right parenthesis, or right bracket.
2273  *
2274  * Input parameters:
2275  * string: entire input string (used only for error reports)
2276  * ptr: where to start parsing bound
2277  * Output parameters:
2278  * *bound_str: receives palloc'd bound string, or NULL if none
2279  * *infinite: set true if no bound, else false
2280  *
2281  * The return value is the scan ptr, advanced past the bound string.
2282  */
2283 static const char *
2284 range_parse_bound(const char *string, const char *ptr,
2285  char **bound_str, bool *infinite)
2286 {
2288 
2289  /* Check for null: completely empty input means null */
2290  if (*ptr == ',' || *ptr == ')' || *ptr == ']')
2291  {
2292  *bound_str = NULL;
2293  *infinite = true;
2294  }
2295  else
2296  {
2297  /* Extract string for this bound */
2298  bool inquote = false;
2299 
2300  initStringInfo(&buf);
2301  while (inquote || !(*ptr == ',' || *ptr == ')' || *ptr == ']'))
2302  {
2303  char ch = *ptr++;
2304 
2305  if (ch == '\0')
2306  ereport(ERROR,
2307  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2308  errmsg("malformed range literal: \"%s\"",
2309  string),
2310  errdetail("Unexpected end of input.")));
2311  if (ch == '\\')
2312  {
2313  if (*ptr == '\0')
2314  ereport(ERROR,
2315  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2316  errmsg("malformed range literal: \"%s\"",
2317  string),
2318  errdetail("Unexpected end of input.")));
2319  appendStringInfoChar(&buf, *ptr++);
2320  }
2321  else if (ch == '"')
2322  {
2323  if (!inquote)
2324  inquote = true;
2325  else if (*ptr == '"')
2326  {
2327  /* doubled quote within quote sequence */
2328  appendStringInfoChar(&buf, *ptr++);
2329  }
2330  else
2331  inquote = false;
2332  }
2333  else
2334  appendStringInfoChar(&buf, ch);
2335  }
2336 
2337  *bound_str = buf.data;
2338  *infinite = false;
2339  }
2340 
2341  return ptr;
2342 }
2343 
2344 /*
2345  * Convert a deserialized range value to text form
2346  *
2347  * Inputs are the flags byte, and the two bound values already converted to
2348  * text (but not yet quoted). If no bound value, pass NULL.
2349  *
2350  * Result is a palloc'd string
2351  */
2352 static char *
2353 range_deparse(char flags, const char *lbound_str, const char *ubound_str)
2354 {
2356 
2357  if (flags & RANGE_EMPTY)
2358  return pstrdup(RANGE_EMPTY_LITERAL);
2359 
2360  initStringInfo(&buf);
2361 
2362  appendStringInfoChar(&buf, (flags & RANGE_LB_INC) ? '[' : '(');
2363 
2364  if (RANGE_HAS_LBOUND(flags))
2365  appendStringInfoString(&buf, range_bound_escape(lbound_str));
2366 
2367  appendStringInfoChar(&buf, ',');
2368 
2369  if (RANGE_HAS_UBOUND(flags))
2370  appendStringInfoString(&buf, range_bound_escape(ubound_str));
2371 
2372  appendStringInfoChar(&buf, (flags & RANGE_UB_INC) ? ']' : ')');
2373 
2374  return buf.data;
2375 }
2376 
2377 /*
2378  * Helper for range_deparse: quote a bound value as needed
2379  *
2380  * Result is a palloc'd string
2381  */
2382 static char *
2384 {
2385  bool nq;
2386  const char *ptr;
2388 
2389  initStringInfo(&buf);
2390 
2391  /* Detect whether we need double quotes for this value */
2392  nq = (value[0] == '\0'); /* force quotes for empty string */
2393  for (ptr = value; *ptr; ptr++)
2394  {
2395  char ch = *ptr;
2396 
2397  if (ch == '"' || ch == '\\' ||
2398  ch == '(' || ch == ')' ||
2399  ch == '[' || ch == ']' ||
2400  ch == ',' ||
2401  isspace((unsigned char) ch))
2402  {
2403  nq = true;
2404  break;
2405  }
2406  }
2407 
2408  /* And emit the string */
2409  if (nq)
2410  appendStringInfoChar(&buf, '"');
2411  for (ptr = value; *ptr; ptr++)
2412  {
2413  char ch = *ptr;
2414 
2415  if (ch == '"' || ch == '\\')
2416  appendStringInfoChar(&buf, ch);
2417  appendStringInfoChar(&buf, ch);
2418  }
2419  if (nq)
2420  appendStringInfoChar(&buf, '"');
2421 
2422  return buf.data;
2423 }
2424 
2425 /*
2426  * Test whether range r1 contains range r2.
2427  *
2428  * Caller has already checked that they are the same range type, and looked up
2429  * the necessary typcache entry.
2430  */
2431 bool
2433 {
2434  RangeBound lower1;
2435  RangeBound upper1;
2436  bool empty1;
2437  RangeBound lower2;
2438  RangeBound upper2;
2439  bool empty2;
2440 
2441  /* Different types should be prevented by ANYRANGE matching rules */
2442  if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
2443  elog(ERROR, "range types do not match");
2444 
2445  range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
2446  range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
2447 
2448  /* If either range is empty, the answer is easy */
2449  if (empty2)
2450  return true;
2451  else if (empty1)
2452  return false;
2453 
2454  /* Else we must have lower1 <= lower2 and upper1 >= upper2 */
2455  if (range_cmp_bounds(typcache, &lower1, &lower2) > 0)
2456  return false;
2457  if (range_cmp_bounds(typcache, &upper1, &upper2) < 0)
2458  return false;
2459 
2460  return true;
2461 }
2462 
2463 bool
2465 {
2466  return range_contains_internal(typcache, r2, r1);
2467 }
2468 
2469 /*
2470  * Test whether range r contains a specific element value.
2471  */
2472 bool
2474 {
2475  RangeBound lower;
2476  RangeBound upper;
2477  bool empty;
2478  int32 cmp;
2479 
2480  range_deserialize(typcache, r, &lower, &upper, &empty);
2481 
2482  if (empty)
2483  return false;
2484 
2485  if (!lower.infinite)
2486  {
2488  typcache->rng_collation,
2489  lower.val, val));
2490  if (cmp > 0)
2491  return false;
2492  if (cmp == 0 && !lower.inclusive)
2493  return false;
2494  }
2495 
2496  if (!upper.infinite)
2497  {
2499  typcache->rng_collation,
2500  upper.val, val));
2501  if (cmp < 0)
2502  return false;
2503  if (cmp == 0 && !upper.inclusive)
2504  return false;
2505  }
2506 
2507  return true;
2508 }
2509 
2510 
2511 /*
2512  * datum_compute_size() and datum_write() are used to insert the bound
2513  * values into a range object. They are modeled after heaptuple.c's
2514  * heap_compute_data_size() and heap_fill_tuple(), but we need not handle
2515  * null values here. TYPE_IS_PACKABLE must test the same conditions as
2516  * heaptuple.c's ATT_IS_PACKABLE macro.
2517  */
2518 
2519 /* Does datatype allow packing into the 1-byte-header varlena format? */
2520 #define TYPE_IS_PACKABLE(typlen, typstorage) \
2521  ((typlen) == -1 && (typstorage) != TYPSTORAGE_PLAIN)
2522 
2523 /*
2524  * Increment data_length by the space needed by the datum, including any
2525  * preceding alignment padding.
2526  */
2527 static Size
2528 datum_compute_size(Size data_length, Datum val, bool typbyval, char typalign,
2529  int16 typlen, char typstorage)
2530 {
2531  if (TYPE_IS_PACKABLE(typlen, typstorage) &&
2533  {
2534  /*
2535  * we're anticipating converting to a short varlena header, so adjust
2536  * length and don't count any alignment
2537  */
2538  data_length += VARATT_CONVERTED_SHORT_SIZE(DatumGetPointer(val));
2539  }
2540  else
2541  {
2542  data_length = att_align_datum(data_length, typalign, typlen, val);
2543  data_length = att_addlength_datum(data_length, typlen, val);
2544  }
2545 
2546  return data_length;
2547 }
2548 
2549 /*
2550  * Write the given datum beginning at ptr (after advancing to correct
2551  * alignment, if needed). Return the pointer incremented by space used.
2552  */
2553 static Pointer
2554 datum_write(Pointer ptr, Datum datum, bool typbyval, char typalign,
2555  int16 typlen, char typstorage)
2556 {
2557  Size data_length;
2558 
2559  if (typbyval)
2560  {
2561  /* pass-by-value */
2562  ptr = (char *) att_align_nominal(ptr, typalign);
2563  store_att_byval(ptr, datum, typlen);
2564  data_length = typlen;
2565  }
2566  else if (typlen == -1)
2567  {
2568  /* varlena */
2569  Pointer val = DatumGetPointer(datum);
2570 
2571  if (VARATT_IS_EXTERNAL(val))
2572  {
2573  /*
2574  * Throw error, because we must never put a toast pointer inside a
2575  * range object. Caller should have detoasted it.
2576  */
2577  elog(ERROR, "cannot store a toast pointer inside a range");
2578  data_length = 0; /* keep compiler quiet */
2579  }
2580  else if (VARATT_IS_SHORT(val))
2581  {
2582  /* no alignment for short varlenas */
2583  data_length = VARSIZE_SHORT(val);
2584  memcpy(ptr, val, data_length);
2585  }
2586  else if (TYPE_IS_PACKABLE(typlen, typstorage) &&
2587  VARATT_CAN_MAKE_SHORT(val))
2588  {
2589  /* convert to short varlena -- no alignment */
2590  data_length = VARATT_CONVERTED_SHORT_SIZE(val);
2591  SET_VARSIZE_SHORT(ptr, data_length);
2592  memcpy(ptr + 1, VARDATA(val), data_length - 1);
2593  }
2594  else
2595  {
2596  /* full 4-byte header varlena */
2597  ptr = (char *) att_align_nominal(ptr, typalign);
2598  data_length = VARSIZE(val);
2599  memcpy(ptr, val, data_length);
2600  }
2601  }
2602  else if (typlen == -2)
2603  {
2604  /* cstring ... never needs alignment */
2605  Assert(typalign == TYPALIGN_CHAR);
2606  data_length = strlen(DatumGetCString(datum)) + 1;
2607  memcpy(ptr, DatumGetPointer(datum), data_length);
2608  }
2609  else
2610  {
2611  /* fixed-length pass-by-reference */
2612  ptr = (char *) att_align_nominal(ptr, typalign);
2613  Assert(typlen > 0);
2614  data_length = typlen;
2615  memcpy(ptr, DatumGetPointer(datum), data_length);
2616  }
2617 
2618  ptr += data_length;
2619 
2620  return ptr;
2621 }
#define RANGE_HAS_UBOUND(flags)
Definition: rangetypes.h:52
RangeType * make_range(TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper, bool empty)
Definition: rangetypes.c:1884
Datum range_in(PG_FUNCTION_ARGS)
Definition: rangetypes.c:78
signed short int16
Definition: c.h:428
#define DatumGetUInt32(X)
Definition: postgres.h:486
Datum range_upper(PG_FUNCTION_ARGS)
Definition: rangetypes.c:449
#define SET_VARSIZE_SHORT(PTR, len)
Definition: postgres.h:330
#define PG_GETARG_INT32(n)
Definition: fmgr.h:269
Definition: fmgr.h:56
Datum tsrange_subdiff(PG_FUNCTION_ARGS)
Definition: rangetypes.c:1596
FmgrInfo rng_cmp_proc_finfo
Definition: typcache.h:100
Datum int4range_subdiff(PG_FUNCTION_ARGS)
Definition: rangetypes.c:1553
#define RangeIsEmpty(r)
Definition: rangetypes.h:56
void range_deserialize(TypeCacheEntry *typcache, const RangeType *range, RangeBound *lower, RangeBound *upper, bool *empty)
Definition: rangetypes.c:1788
#define DatumGetDateADT(X)
Definition: date.h:53
#define RANGE_HAS_LBOUND(flags)
Definition: rangetypes.h:48
static char range_parse_flags(const char *flags_str)
Definition: rangetypes.c:2103
Datum range_lower_inc(PG_FUNCTION_ARGS)
Definition: rangetypes.c:483
int errhint(const char *fmt,...)
Definition: elog.c:1152
#define TYPECACHE_RANGE_INFO
Definition: typcache.h:147
RangeType * range_minus_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
Definition: rangetypes.c:975
bool range_overlaps_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:823
#define VARDATA(PTR)
Definition: postgres.h:302
#define RANGE_EMPTY_LITERAL
Definition: rangetypes.h:32
#define RANGE_EMPTY
Definition: rangetypes.h:38
MemoryContext fn_mcxt
Definition: fmgr.h:65
#define att_align_nominal(cur_offset, attalign)
Definition: tupmacs.h:148
TypeCacheEntry * range_get_typcache(FunctionCallInfo fcinfo, Oid rngtypid)
Definition: rangetypes.c:1635
#define TYPECACHE_HASH_EXTENDED_PROC_FINFO
Definition: typcache.h:151
#define RangeTypeGetOid(r)
Definition: rangetypes.h:35
Datum range_empty(PG_FUNCTION_ARGS)
Definition: rangetypes.c:473
#define DatumGetInt32(X)
Definition: postgres.h:472
Datum range_overleft(PG_FUNCTION_ARGS)
Definition: rangetypes.c:897
#define USECS_PER_SEC
Definition: timestamp.h:94
Datum lower(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:46
Datum tstzrange_subdiff(PG_FUNCTION_ARGS)
Definition: rangetypes.c:1607
#define VARSIZE(PTR)
Definition: postgres.h:303
#define PointerGetDatum(X)
Definition: postgres.h:556
#define PG_GETARG_TIMESTAMP(n)
Definition: timestamp.h:35
int range_cmp_bound_values(TypeCacheEntry *typcache, const RangeBound *b1, const RangeBound *b2)
Definition: rangetypes.c:1998
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:268
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:328
#define VARHDRSZ
Definition: c.h:627
char * pstrdup(const char *in)
Definition: mcxt.c:1187
Datum int8pl(PG_FUNCTION_ARGS)
Definition: int8.c:548
bool range_after_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:684
Datum range_lower(PG_FUNCTION_ARGS)
Definition: rangetypes.c:428
StringInfo makeStringInfo(void)
Definition: stringinfo.c:41
StringInfoData * StringInfo
Definition: stringinfo.h:44
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:367
#define TYPECACHE_HASH_PROC_FINFO
Definition: typcache.h:143
bool range_contains_elem_internal(TypeCacheEntry *typcache, const RangeType *r, Datum val)
Definition: rangetypes.c:2473
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354
Datum val
Definition: rangetypes.h:64
static void range_parse(const char *input_str, char *flags, char **lbound_str, char **ubound_str)
Definition: rangetypes.c:2175
int errcode(int sqlerrcode)
Definition: elog.c:694
TypeCacheEntry * typcache
Definition: rangetypes.c:49
char range_get_flags(const RangeType *range)
Definition: rangetypes.c:1855
Datum range_minus(PG_FUNCTION_ARGS)
Definition: rangetypes.c:954
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
bool type_is_range(Oid typid)
Definition: lsyscache.c:2635
Datum range_after(PG_FUNCTION_ARGS)
Definition: rangetypes.c:709
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
Datum range_overlaps(PG_FUNCTION_ARGS)
Definition: rangetypes.c:856
RangeType * make_empty_range(TypeCacheEntry *typcache)
Definition: rangetypes.c:2073
Datum range_before(PG_FUNCTION_ARGS)
Definition: rangetypes.c:671
bool bounds_adjacent(TypeCacheEntry *typcache, RangeBound boundA, RangeBound boundB)
Definition: rangetypes.c:739
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:626
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:371
Datum upper(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:77
IOFuncSelector
Definition: lsyscache.h:33
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Definition: fmgr.c:1151
#define TYPE_IS_PACKABLE(typlen, typstorage)
Definition: rangetypes.c:2520
unsigned int Oid
Definition: postgres_ext.h:31
int16 typlen
Definition: typcache.h:39
bool range_ne_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:600
Datum range_lower_inf(PG_FUNCTION_ARGS)
Definition: rangetypes.c:503
#define PG_RETURN_UINT64(x)
Definition: fmgr.h:369
#define RANGE_LB_INF
Definition: rangetypes.h:41
bool typbyval
Definition: typcache.h:40
#define OidIsValid(objectId)
Definition: c.h:710
struct RangeIOData RangeIOData
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:348
Datum range_upper_inf(PG_FUNCTION_ARGS)
Definition: rangetypes.c:513
#define RangeTypePGetDatum(X)
Definition: rangetypes.h:75
Oid rangetypid
Definition: rangetypes.h:28
Datum int4pl(PG_FUNCTION_ARGS)
Definition: int.c:770
Datum int8range_canonical(PG_FUNCTION_ARGS)
Definition: rangetypes.c:1477
const char * pq_getmsgbytes(StringInfo msg, int datalen)
Definition: pqformat.c:510
signed int int32
Definition: c.h:429
void range_set_contain_empty(RangeType *range)
Definition: rangetypes.c:1869
Datum daterange_canonical(PG_FUNCTION_ARGS)
Definition: rangetypes.c:1508
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
char * OutputFunctionCall(FmgrInfo *flinfo, Datum val)
Definition: fmgr.c:1576
#define att_align_datum(cur_offset, attalign, attlen, attdatum)
Definition: tupmacs.h:105
static void pq_sendbyte(StringInfo buf, uint8 byt)
Definition: pqformat.h:161
static struct @141 value
static void pq_sendint32(StringInfo buf, uint32 i)
Definition: pqformat.h:145
#define VARATT_IS_EXTERNAL(PTR)
Definition: postgres.h:313
int pg_strncasecmp(const char *s1, const char *s2, size_t n)
Definition: pgstrcasecmp.c:69
void pfree(void *pointer)
Definition: mcxt.c:1057
char * Pointer
Definition: c.h:418
char typalign
Definition: pg_type.h:176
bool inclusive
Definition: rangetypes.h:66
static char * range_deparse(char flags, const char *lbound_str, const char *ubound_str)
Definition: rangetypes.c:2353
#define ERROR
Definition: elog.h:45
double float8
Definition: c.h:565
Datum range_contains(PG_FUNCTION_ARGS)
Definition: rangetypes.c:620
#define DatumGetCString(X)
Definition: postgres.h:566
#define VARATT_IS_SHORT(PTR)
Definition: postgres.h:326
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1803
Datum ReceiveFunctionCall(FmgrInfo *flinfo, StringInfo buf, Oid typioparam, int32 typmod)
Definition: fmgr.c:1590
#define DATE_NOT_FINITE(j)
Definition: date.h:43
#define VARATT_CAN_MAKE_SHORT(PTR)
Definition: postgres.h:270
Datum range_gt(PG_FUNCTION_ARGS)
Definition: rangetypes.c:1301
#define DatumGetInt64(X)
Definition: postgres.h:607
#define PG_DETOAST_DATUM_PACKED(datum)
Definition: fmgr.h:248
static Size datum_compute_size(Size sz, Datum datum, bool typbyval, char typalign, int16 typlen, char typstorage)
Definition: rangetypes.c:2528
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
Datum int4range_canonical(PG_FUNCTION_ARGS)
Definition: rangetypes.c:1446
Datum range_overright(PG_FUNCTION_ARGS)
Definition: rangetypes.c:938
static char * buf
Definition: pg_test_fsync.c:68
char typstorage
Definition: typcache.h:42
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
void check_stack_depth(void)
Definition: postgres.c:3310
Datum numeric_float8(PG_FUNCTION_ARGS)
Definition: numeric.c:4306
#define RANGE_UB_INC
Definition: rangetypes.h:40
int errdetail(const char *fmt,...)
Definition: elog.c:1038
char string[11]
Definition: preproc-type.c:46
#define DatumGetBool(X)
Definition: postgres.h:393
Datum range_eq(PG_FUNCTION_ARGS)
Definition: rangetypes.c:587
unsigned int uint32
Definition: c.h:441
bytea * SendFunctionCall(FmgrInfo *flinfo, Datum val)
Definition: fmgr.c:1637
FmgrInfo hash_proc_finfo
Definition: typcache.h:77
FmgrInfo typioproc
Definition: rangetypes.c:50
Datum range_constructor2(PG_FUNCTION_ARGS)
Definition: rangetypes.c:359
Datum range_upper_inc(PG_FUNCTION_ARGS)
Definition: rangetypes.c:493
static struct cvec * range(struct vars *v, chr a, chr b, int cases)
Definition: regc_locale.c:412
Datum Int64GetDatum(int64 X)
Definition: fmgr.c:1700
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:136
#define att_addlength_pointer(cur_offset, attlen, attptr)
Definition: tupmacs.h:176
Datum range_constructor3(PG_FUNCTION_ARGS)
Definition: rangetypes.c:388
RangeType * range_serialize(TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper, bool empty)
Definition: rangetypes.c:1659
bool lower
Definition: rangetypes.h:67
#define VARSIZE_SHORT(PTR)
Definition: postgres.h:305
#define PG_RETURN_RANGE_P(x)
Definition: rangetypes.h:78
FmgrInfo rng_canonical_finfo
Definition: typcache.h:101
Datum range_ne(PG_FUNCTION_ARGS)
Definition: rangetypes.c:607
struct TypeCacheEntry * rngelemtype
Definition: typcache.h:98
int64 Timestamp
Definition: timestamp.h:38
bool range_contains_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:2432
Datum range_merge(PG_FUNCTION_ARGS)
Definition: rangetypes.c:1096
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
Datum int8range_subdiff(PG_FUNCTION_ARGS)
Definition: rangetypes.c:1562
#define VARATT_CONVERTED_SHORT_SIZE(PTR)
Definition: postgres.h:273
#define store_att_byval(T, newdatum, attlen)
Definition: tupmacs.h:226
Datum range_recv(PG_FUNCTION_ARGS)
Definition: rangetypes.c:160
FmgrInfo hash_extended_proc_finfo
Definition: typcache.h:78
#define ROTATE_HIGH_AND_LOW_32BITS(v)
Definition: hashfn.h:18
void * palloc0(Size size)
Definition: mcxt.c:981
#define DatumGetFloat8(X)
Definition: postgres.h:714
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
uintptr_t Datum
Definition: postgres.h:367
Oid get_fn_expr_rettype(FmgrInfo *flinfo)
Definition: fmgr.c:1781
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:353
Datum numeric_sub(PG_FUNCTION_ARGS)
Definition: numeric.c:2788
Datum elem_contained_by_range(PG_FUNCTION_ARGS)
Definition: rangetypes.c:539
FmgrInfo * flinfo
Definition: fmgr.h:87
Datum FunctionCall1Coll(FmgrInfo *flinfo, Oid collation, Datum arg1)
Definition: fmgr.c:1131
RangeType * range_union_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2, bool strict)
Definition: rangetypes.c:1034
static Pointer datum_write(Pointer ptr, Datum datum, bool typbyval, char typalign, int16 typlen, char typstorage)
Definition: rangetypes.c:2554
Datum range_out(PG_FUNCTION_ARGS)
Definition: rangetypes.c:120
#define att_align_pointer(cur_offset, attalign, attlen, attptr)
Definition: tupmacs.h:126
static const char * range_parse_bound(const char *string, const char *ptr, char **bound_str, bool *infinite)
Definition: rangetypes.c:2284
#define RANGE_LB_INC
Definition: rangetypes.h:39
Datum range_le(PG_FUNCTION_ARGS)
Definition: rangetypes.c:1285
Datum InputFunctionCall(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod)
Definition: fmgr.c:1532
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:338
bool range_overleft_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:869
Oid fn_oid
Definition: fmgr.h:59
#define ereport(elevel,...)
Definition: elog.h:155
Datum range_contained_by(PG_FUNCTION_ARGS)
Definition: rangetypes.c:633
#define RANGE_CONTAIN_EMPTY
Definition: rangetypes.h:45
Datum range_lt(PG_FUNCTION_ARGS)
Definition: rangetypes.c:1277
int pq_getmsgbyte(StringInfo msg)
Definition: pqformat.c:401
#define DatumGetUInt64(X)
Definition: postgres.h:634
Datum hash_range_extended(PG_FUNCTION_ARGS)
Definition: rangetypes.c:1378
Datum range_intersect_agg_transfn(PG_FUNCTION_ARGS)
Definition: rangetypes.c:1201
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
#define Assert(condition)
Definition: c.h:804
RangeType * range_intersect_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:1125
bool range_before_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:646
static Datum hash_uint32(uint32 k)
Definition: hashfn.h:43
Datum range_ge(PG_FUNCTION_ARGS)
Definition: rangetypes.c:1293
Datum range_union(PG_FUNCTION_ARGS)
Definition: rangetypes.c:1080
bool range_contained_by_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:2464
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:362
size_t Size
Definition: c.h:540
#define PG_GETARG_RANGE_P(n)
Definition: rangetypes.h:76
#define DatumGetRangeTypeP(X)
Definition: rangetypes.h:73
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4587
bool infinite
Definition: rangetypes.h:65
#define MAXALIGN(LEN)
Definition: c.h:757
Oid rng_collation
Definition: typcache.h:99
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:260
void * fn_extra
Definition: fmgr.h:64
#define DatumGetPointer(X)
Definition: postgres.h:549
#define RANGE_UB_INF
Definition: rangetypes.h:42
Datum hash_range(PG_FUNCTION_ARGS)
Definition: rangetypes.c:1312
char * text_to_cstring(const text *t)
Definition: varlena.c:222
#define Int32GetDatum(X)
Definition: postgres.h:479
#define att_addlength_datum(cur_offset, attlen, attdatum)
Definition: tupmacs.h:164
bool range_overright_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:910
void pq_sendbytes(StringInfo buf, const char *data, int datalen)
Definition: pqformat.c:125
char typalign
Definition: typcache.h:41
Datum range_contains_elem(PG_FUNCTION_ARGS)
Definition: rangetypes.c:526
int errmsg(const char *fmt,...)
Definition: elog.c:905
#define fetch_att(T, attbyval, attlen)
Definition: tupmacs.h:75
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:797
Datum range_intersect(PG_FUNCTION_ARGS)
Definition: rangetypes.c:1109
#define elog(elevel,...)
Definition: elog.h:227
#define FunctionCall1(flinfo, arg1)
Definition: fmgr.h:644
bool range_adjacent_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:780
void * arg
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:277
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition: pqformat.c:417
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:329
void pq_getmsgend(StringInfo msg)
Definition: pqformat.c:637
static RangeIOData * get_range_io_data(FunctionCallInfo fcinfo, Oid rngtypid, IOFuncSelector func)
Definition: rangetypes.c:299
bool range_split_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2, RangeType **output1, RangeType **output2)
Definition: rangetypes.c:1164
Datum range_send(PG_FUNCTION_ARGS)
Definition: rangetypes.c:243
Datum range_cmp(PG_FUNCTION_ARGS)
Definition: rangetypes.c:1231
#define PG_GETARG_INT64(n)
Definition: fmgr.h:283
Datum daterange_subdiff(PG_FUNCTION_ARGS)
Definition: rangetypes.c:1587
int range_compare(const void *key1, const void *key2, void *arg)
Definition: rangetypes.c:2037
Datum numrange_subdiff(PG_FUNCTION_ARGS)
Definition: rangetypes.c:1571
static Datum hash_uint32_extended(uint32 k, uint64 seed)
Definition: hashfn.h:49
bool range_eq_internal(TypeCacheEntry *typcache, const RangeType *r1, const RangeType *r2)
Definition: rangetypes.c:555
void appendBinaryStringInfo(StringInfo str, const char *data, int datalen)
Definition: stringinfo.c:227
long val
Definition: informix.c:664
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:628
#define PG_RETURN_NULL()
Definition: fmgr.h:345
int range_cmp_bounds(TypeCacheEntry *typcache, const RangeBound *b1, const RangeBound *b2)
Definition: rangetypes.c:1924
Oid typioparam
Definition: rangetypes.c:51
static int cmp(const chr *x, const chr *y, size_t len)
Definition: regc_locale.c:747
Datum range_adjacent(PG_FUNCTION_ARGS)
Definition: rangetypes.c:810
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:2272
static char * range_bound_escape(const char *value)
Definition: rangetypes.c:2383
Datum date_pli(PG_FUNCTION_ARGS)
Definition: date.c:508