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