]> granicus.if.org Git - postgresql/blob - src/backend/utils/adt/rangetypes.c
5c16ca1b19e9d9b7b3c64182317902bff4387244
[postgresql] / src / backend / utils / adt / rangetypes.c
1 /*-------------------------------------------------------------------------
2  *
3  * rangetypes.c
4  *        I/O functions, operators, and support functions for range types.
5  *
6  * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        src/backend/utils/adt/rangetypes.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16
17 #include "access/hash.h"
18 #include "access/nbtree.h"
19 #include "catalog/pg_opclass.h"
20 #include "catalog/pg_range.h"
21 #include "catalog/pg_type.h"
22 #include "fmgr.h"
23 #include "lib/stringinfo.h"
24 #include "libpq/pqformat.h"
25 #include "utils/builtins.h"
26 #include "utils/date.h"
27 #include "utils/fmgroids.h"
28 #include "utils/int8.h"
29 #include "utils/lsyscache.h"
30 #include "utils/rangetypes.h"
31 #include "utils/syscache.h"
32 #include "utils/timestamp.h"
33 #include "utils/typcache.h"
34
35
36 #define TYPE_IS_PACKABLE(typlen, typstorage) \
37         (typlen == -1 && typstorage != 'p')
38
39 /* flags */
40 #define RANGE_EMPTY             0x01
41 #define RANGE_LB_INC    0x02
42 #define RANGE_LB_NULL   0x04    /* NOT USED */
43 #define RANGE_LB_INF    0x08
44 #define RANGE_UB_INC    0x10
45 #define RANGE_UB_NULL   0x20    /* NOT USED */
46 #define RANGE_UB_INF    0x40
47
48 #define RANGE_HAS_LBOUND(flags) (!(flags & (RANGE_EMPTY |       \
49                                                                                         RANGE_LB_NULL | \
50                                                                                         RANGE_LB_INF)))
51
52 #define RANGE_HAS_UBOUND(flags) (!(flags & (RANGE_EMPTY |       \
53                                                                                         RANGE_UB_NULL | \
54                                                                                         RANGE_UB_INF)))
55
56 #define RANGE_EMPTY_LITERAL "empty"
57
58 #define RANGE_DEFAULT_FLAGS             "[)"
59
60
61 static char range_parse_flags(const char *flags_str);
62 static void range_parse(char *input_str, char *flags, char **lbound_str,
63                         char **ubound_str);
64 static char *range_parse_bound(char *string, char *ptr, char **bound_str,
65                                   bool *infinite);
66 static char *range_deparse(char flags, char *lbound_str, char *ubound_str);
67 static char *range_bound_escape(char *in_str);
68 static bool range_contains_internal(FunctionCallInfo fcinfo, RangeType *r1,
69                                                 RangeType *r2);
70 static Size datum_compute_size(Size sz, Datum datum, bool typbyval,
71                                    char typalign, int16 typlen, char typstorage);
72 static Pointer datum_write(Pointer ptr, Datum datum, bool typbyval,
73                         char typalign, int16 typlen, char typstorage);
74
75
76 /*
77  *----------------------------------------------------------
78  * I/O FUNCTIONS
79  *----------------------------------------------------------
80  */
81
82 Datum
83 range_in(PG_FUNCTION_ARGS)
84 {
85         char       *input_str = PG_GETARG_CSTRING(0);
86         Oid                     rngtypoid = PG_GETARG_OID(1);
87         Oid                     typmod = PG_GETARG_INT32(2);
88         Datum           range;
89         char            flags;
90         char       *lbound_str;
91         char       *ubound_str;
92         regproc         subInput;
93         FmgrInfo        subInputFn;
94         Oid                     ioParam;
95         RangeTypeInfo rngtypinfo;
96         RangeBound      lower;
97         RangeBound      upper;
98
99         if (rngtypoid == ANYRANGEOID)
100                 ereport(ERROR,
101                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
102                                  errmsg("cannot accept a value of type anyrange")));
103
104         range_gettypinfo(fcinfo, rngtypoid, &rngtypinfo);
105
106         /* parse */
107         range_parse(input_str, &flags, &lbound_str, &ubound_str);
108
109         /* input */
110         getTypeInputInfo(rngtypinfo.subtype, &subInput, &ioParam);
111         fmgr_info(subInput, &subInputFn);
112
113         lower.rngtypid = rngtypoid;
114         lower.infinite = (flags & RANGE_LB_INF) != 0;
115         lower.inclusive = (flags & RANGE_LB_INC) != 0;
116         lower.lower = true;
117         upper.rngtypid = rngtypoid;
118         upper.infinite = (flags & RANGE_UB_INF) != 0;
119         upper.inclusive = (flags & RANGE_UB_INC) != 0;
120         upper.lower = false;
121
122         if (RANGE_HAS_LBOUND(flags))
123                 lower.val = InputFunctionCall(&subInputFn, lbound_str,
124                                                                           ioParam, typmod);
125         if (RANGE_HAS_UBOUND(flags))
126                 upper.val = InputFunctionCall(&subInputFn, ubound_str,
127                                                                           ioParam, typmod);
128
129         /* serialize and canonicalize */
130         range = make_range(fcinfo, &lower, &upper, flags & RANGE_EMPTY);
131
132         PG_RETURN_RANGE(range);
133 }
134
135 Datum
136 range_out(PG_FUNCTION_ARGS)
137 {
138         RangeType  *range = PG_GETARG_RANGE(0);
139         char       *output_str;
140         regproc         subOutput;
141         FmgrInfo        subOutputFn;
142         bool            isVarlena;
143         char            flags = 0;
144         char       *lbound_str = NULL;
145         char       *ubound_str = NULL;
146         bool            empty;
147         RangeTypeInfo rngtypinfo;
148         RangeBound      lower;
149         RangeBound      upper;
150
151         /* deserialize */
152         range_deserialize(fcinfo, range, &lower, &upper, &empty);
153
154         if (lower.rngtypid != upper.rngtypid)
155                 elog(ERROR, "range types do not match");
156
157         range_gettypinfo(fcinfo, lower.rngtypid, &rngtypinfo);
158
159         if (empty)
160                 flags |= RANGE_EMPTY;
161
162         flags |= (lower.inclusive) ? RANGE_LB_INC : 0;
163         flags |= (lower.infinite) ? RANGE_LB_INF : 0;
164         flags |= (upper.inclusive) ? RANGE_UB_INC : 0;
165         flags |= (upper.infinite) ? RANGE_UB_INF : 0;
166
167         /* output */
168         getTypeOutputInfo(rngtypinfo.subtype, &subOutput, &isVarlena);
169         fmgr_info(subOutput, &subOutputFn);
170
171         if (RANGE_HAS_LBOUND(flags))
172                 lbound_str = OutputFunctionCall(&subOutputFn, lower.val);
173         if (RANGE_HAS_UBOUND(flags))
174                 ubound_str = OutputFunctionCall(&subOutputFn, upper.val);
175
176         /* deparse */
177         output_str = range_deparse(flags, lbound_str, ubound_str);
178
179         PG_RETURN_CSTRING(output_str);
180 }
181
182 /*
183  * Binary representation: The first byte is the flags, then 4 bytes are the
184  * range type Oid, then the lower bound (if present) then the upper bound (if
185  * present). Each bound is represented by a 4-byte length header and the binary
186  * representation of that bound (as returned by a call to the send function for
187  * the subtype).
188  */
189
190 Datum
191 range_recv(PG_FUNCTION_ARGS)
192 {
193         StringInfo      buf = (StringInfo) PG_GETARG_POINTER(0);
194         Oid                     rngtypid = PG_GETARG_OID(1);
195         int32           typmod = PG_GETARG_INT32(2);
196         Datum           range;
197         Oid                     subrecv;
198         Oid                     ioparam;
199         char            flags;
200         RangeBound      lower;
201         RangeBound      upper;
202         RangeTypeInfo rngtypinfo;
203
204         flags = (unsigned char) pq_getmsgbyte(buf);
205
206         range_gettypinfo(fcinfo, rngtypid, &rngtypinfo);
207
208         getTypeBinaryInputInfo(rngtypinfo.subtype, &subrecv, &ioparam);
209
210         if (RANGE_HAS_LBOUND(flags))
211         {
212                 uint32          bound_len = pq_getmsgint(buf, 4);
213                 const char *bound_data = pq_getmsgbytes(buf, bound_len);
214                 StringInfoData bound_buf;
215
216                 initStringInfo(&bound_buf);
217                 appendBinaryStringInfo(&bound_buf, bound_data, bound_len);
218
219                 lower.val = OidReceiveFunctionCall(subrecv,
220                                                                                    &bound_buf,
221                                                                                    ioparam,
222                                                                                    typmod);
223                 pfree(bound_buf.data);
224         }
225         else
226                 lower.val = (Datum) 0;
227
228         if (RANGE_HAS_UBOUND(flags))
229         {
230                 uint32          bound_len = pq_getmsgint(buf, 4);
231                 const char *bound_data = pq_getmsgbytes(buf, bound_len);
232                 StringInfoData bound_buf;
233
234                 initStringInfo(&bound_buf);
235                 appendBinaryStringInfo(&bound_buf, bound_data, bound_len);
236
237                 upper.val = OidReceiveFunctionCall(subrecv,
238                                                                                    &bound_buf,
239                                                                                    ioparam,
240                                                                                    typmod);
241                 pfree(bound_buf.data);
242         }
243         else
244                 upper.val = (Datum) 0;
245
246         pq_getmsgend(buf);
247
248         lower.rngtypid = rngtypid;
249         lower.infinite = (flags & RANGE_LB_INF) != 0;
250         lower.inclusive = (flags & RANGE_LB_INC) != 0;
251         lower.lower = true;
252         upper.rngtypid = rngtypid;
253         upper.infinite = (flags & RANGE_UB_INF) != 0;
254         upper.inclusive = (flags & RANGE_UB_INC) != 0;
255         upper.lower = false;
256
257         /* serialize and canonicalize */
258         range = make_range(fcinfo, &lower, &upper, flags & RANGE_EMPTY);
259
260         PG_RETURN_RANGE(range);
261 }
262
263 Datum
264 range_send(PG_FUNCTION_ARGS)
265 {
266         RangeType  *range = PG_GETARG_RANGE(0);
267         StringInfo      buf = makeStringInfo();
268         char            flags = 0;
269         RangeBound      lower;
270         RangeBound      upper;
271         bool            empty;
272         Oid                     subsend;
273         bool            typIsVarlena;
274         RangeTypeInfo rngtypinfo;
275
276         pq_begintypsend(buf);
277
278         range_deserialize(fcinfo, range, &lower, &upper, &empty);
279
280         if (empty)
281                 flags |= RANGE_EMPTY;
282
283         flags |= (lower.inclusive) ? RANGE_LB_INC : 0;
284         flags |= (lower.infinite) ? RANGE_LB_INF : 0;
285         flags |= (upper.inclusive) ? RANGE_UB_INC : 0;
286         flags |= (upper.infinite) ? RANGE_UB_INF : 0;
287
288         range_gettypinfo(fcinfo, lower.rngtypid, &rngtypinfo);
289
290         getTypeBinaryOutputInfo(rngtypinfo.subtype,
291                                                         &subsend, &typIsVarlena);
292
293         pq_sendbyte(buf, flags);
294
295         if (RANGE_HAS_LBOUND(flags))
296         {
297                 Datum           bound = PointerGetDatum(OidSendFunctionCall(subsend,
298                                                                                                                                 lower.val));
299                 uint32          bound_len = VARSIZE(bound) - VARHDRSZ;
300                 char       *bound_data = VARDATA(bound);
301
302                 pq_sendint(buf, bound_len, 4);
303                 pq_sendbytes(buf, bound_data, bound_len);
304         }
305
306         if (RANGE_HAS_UBOUND(flags))
307         {
308                 Datum           bound = PointerGetDatum(OidSendFunctionCall(subsend,
309                                                                                                                                 upper.val));
310                 uint32          bound_len = VARSIZE(bound) - VARHDRSZ;
311                 char       *bound_data = VARDATA(bound);
312
313                 pq_sendint(buf, bound_len, 4);
314                 pq_sendbytes(buf, bound_data, bound_len);
315         }
316
317         PG_RETURN_BYTEA_P(pq_endtypsend(buf));
318 }
319
320
321 /*
322  *----------------------------------------------------------
323  * GENERIC FUNCTIONS
324  *----------------------------------------------------------
325  */
326
327 Datum
328 range_constructor0(PG_FUNCTION_ARGS)
329 {
330         Oid                     rngtypid = get_fn_expr_rettype(fcinfo->flinfo);
331         RangeType  *range;
332         RangeBound      lower;
333         RangeBound      upper;
334
335         lower.rngtypid = rngtypid;
336         lower.val = (Datum) 0;
337         lower.inclusive = false;
338         lower.infinite = false;
339         lower.lower = true;
340
341         upper.rngtypid = rngtypid;
342         upper.val = (Datum) 0;
343         upper.inclusive = false;
344         upper.infinite = false;
345         upper.lower = false;
346
347         range = DatumGetRangeType(make_range(fcinfo, &lower, &upper, true));
348
349         PG_RETURN_RANGE(range);
350 }
351
352 Datum
353 range_constructor1(PG_FUNCTION_ARGS)
354 {
355         Datum           arg1 = PG_GETARG_DATUM(0);
356         Oid                     rngtypid = get_fn_expr_rettype(fcinfo->flinfo);
357         RangeType  *range;
358         RangeBound      lower;
359         RangeBound      upper;
360
361         if (PG_ARGISNULL(0))
362                 ereport(ERROR,
363                                 (errcode(ERRCODE_DATA_EXCEPTION),
364                                  errmsg("argument must not be NULL")));
365
366         lower.rngtypid = rngtypid;
367         lower.val = arg1;
368         lower.inclusive = true;
369         lower.infinite = false;
370         lower.lower = true;
371
372         upper.rngtypid = rngtypid;
373         upper.val = arg1;
374         upper.inclusive = true;
375         upper.infinite = false;
376         upper.lower = false;
377
378         range = DatumGetRangeType(make_range(fcinfo, &lower, &upper, false));
379
380         PG_RETURN_RANGE(range);
381 }
382
383 Datum
384 range_constructor2(PG_FUNCTION_ARGS)
385 {
386         Datum           arg1 = PG_GETARG_DATUM(0);
387         Datum           arg2 = PG_GETARG_DATUM(1);
388         Oid                     rngtypid = get_fn_expr_rettype(fcinfo->flinfo);
389         RangeType  *range;
390         RangeBound      lower;
391         RangeBound      upper;
392         char            flags;
393
394         flags = range_parse_flags(RANGE_DEFAULT_FLAGS);
395
396         lower.rngtypid = rngtypid;
397         lower.val = PG_ARGISNULL(0) ? (Datum) 0 : arg1;
398         lower.inclusive = flags & RANGE_LB_INC;
399         lower.infinite = PG_ARGISNULL(0);
400         lower.lower = true;
401
402         upper.rngtypid = rngtypid;
403         upper.val = PG_ARGISNULL(1) ? (Datum) 0 : arg2;
404         upper.inclusive = flags & RANGE_UB_INC;
405         upper.infinite = PG_ARGISNULL(1);
406         upper.lower = false;
407
408         range = DatumGetRangeType(make_range(fcinfo, &lower, &upper, false));
409
410         PG_RETURN_RANGE(range);
411 }
412
413 Datum
414 range_constructor3(PG_FUNCTION_ARGS)
415 {
416         Datum           arg1 = PG_GETARG_DATUM(0);
417         Datum           arg2 = PG_GETARG_DATUM(1);
418         Oid                     rngtypid = get_fn_expr_rettype(fcinfo->flinfo);
419         RangeType  *range;
420         RangeBound      lower;
421         RangeBound      upper;
422         char            flags;
423
424         if (PG_ARGISNULL(2))
425                 ereport(ERROR,
426                                 (errcode(ERRCODE_DATA_EXCEPTION),
427                                  errmsg("flags argument must not be NULL")));
428
429         flags = range_parse_flags(text_to_cstring(PG_GETARG_TEXT_P(2)));
430
431         lower.rngtypid = rngtypid;
432         lower.val = PG_ARGISNULL(0) ? (Datum) 0 : arg1;
433         lower.inclusive = flags & RANGE_LB_INC;
434         lower.infinite = PG_ARGISNULL(0);
435         lower.lower = true;
436
437         upper.rngtypid = rngtypid;
438         upper.val = PG_ARGISNULL(1) ? (Datum) 0 : arg2;
439         upper.inclusive = flags & RANGE_UB_INC;
440         upper.infinite = PG_ARGISNULL(1);
441         upper.lower = false;
442
443         range = DatumGetRangeType(make_range(fcinfo, &lower, &upper, false));
444
445         PG_RETURN_RANGE(range);
446 }
447
448 /* range -> subtype */
449 Datum
450 range_lower(PG_FUNCTION_ARGS)
451 {
452         RangeType  *r1 = PG_GETARG_RANGE(0);
453         RangeBound      lower;
454         RangeBound      upper;
455         bool            empty;
456
457         range_deserialize(fcinfo, r1, &lower, &upper, &empty);
458
459         if (empty)
460                 ereport(ERROR,
461                                 (errcode(ERRCODE_DATA_EXCEPTION),
462                                  errmsg("empty range has no lower bound")));
463         if (lower.infinite)
464                 ereport(ERROR,
465                                 (errcode(ERRCODE_DATA_EXCEPTION),
466                                  errmsg("range lower bound is infinite")));
467
468         PG_RETURN_DATUM(lower.val);
469 }
470
471 Datum
472 range_upper(PG_FUNCTION_ARGS)
473 {
474         RangeType  *r1 = PG_GETARG_RANGE(0);
475         RangeBound      lower;
476         RangeBound      upper;
477         bool            empty;
478
479         range_deserialize(fcinfo, r1, &lower, &upper, &empty);
480
481         if (empty)
482                 ereport(ERROR,
483                                 (errcode(ERRCODE_DATA_EXCEPTION),
484                                  errmsg("empty range has no upper bound")));
485         if (upper.infinite)
486                 ereport(ERROR,
487                                 (errcode(ERRCODE_DATA_EXCEPTION),
488                                  errmsg("range upper bound is infinite")));
489
490         PG_RETURN_DATUM(upper.val);
491 }
492
493
494 /* range -> bool */
495 Datum
496 range_empty(PG_FUNCTION_ARGS)
497 {
498         RangeType  *r1 = PG_GETARG_RANGE(0);
499         RangeBound      lower;
500         RangeBound      upper;
501         bool            empty;
502
503         range_deserialize(fcinfo, r1, &lower, &upper, &empty);
504
505         PG_RETURN_BOOL(empty);
506 }
507
508 Datum
509 range_lower_inc(PG_FUNCTION_ARGS)
510 {
511         RangeType  *r1 = PG_GETARG_RANGE(0);
512         RangeBound      lower;
513         RangeBound      upper;
514         bool            empty;
515
516         range_deserialize(fcinfo, r1, &lower, &upper, &empty);
517
518         PG_RETURN_BOOL(lower.inclusive);
519 }
520
521 Datum
522 range_upper_inc(PG_FUNCTION_ARGS)
523 {
524         RangeType  *r1 = PG_GETARG_RANGE(0);
525         RangeBound      lower;
526         RangeBound      upper;
527         bool            empty;
528
529         range_deserialize(fcinfo, r1, &lower, &upper, &empty);
530
531         PG_RETURN_BOOL(upper.inclusive);
532 }
533
534 Datum
535 range_lower_inf(PG_FUNCTION_ARGS)
536 {
537         RangeType  *r1 = PG_GETARG_RANGE(0);
538         RangeBound      lower;
539         RangeBound      upper;
540         bool            empty;
541
542         range_deserialize(fcinfo, r1, &lower, &upper, &empty);
543
544         PG_RETURN_BOOL(lower.infinite);
545 }
546
547 Datum
548 range_upper_inf(PG_FUNCTION_ARGS)
549 {
550         RangeType  *r1 = PG_GETARG_RANGE(0);
551         RangeBound      lower;
552         RangeBound      upper;
553         bool            empty;
554
555         range_deserialize(fcinfo, r1, &lower, &upper, &empty);
556
557         PG_RETURN_BOOL(upper.infinite);
558 }
559
560
561 /* range, range -> bool */
562 Datum
563 range_eq(PG_FUNCTION_ARGS)
564 {
565         RangeType  *r1 = PG_GETARG_RANGE(0);
566         RangeType  *r2 = PG_GETARG_RANGE(1);
567         RangeBound      lower1,
568                                 lower2;
569         RangeBound      upper1,
570                                 upper2;
571         bool            empty1,
572                                 empty2;
573
574         range_deserialize(fcinfo, r1, &lower1, &upper1, &empty1);
575         range_deserialize(fcinfo, r2, &lower2, &upper2, &empty2);
576
577         if (lower1.rngtypid != upper1.rngtypid ||
578                 lower1.rngtypid != lower2.rngtypid ||
579                 lower1.rngtypid != upper2.rngtypid)
580                 elog(ERROR, "range types do not match");
581
582         if (empty1 && empty2)
583                 PG_RETURN_BOOL(true);
584         if (empty1 != empty2)
585                 PG_RETURN_BOOL(false);
586
587         if (range_cmp_bounds(fcinfo, &lower1, &lower2) != 0)
588                 PG_RETURN_BOOL(false);
589
590         if (range_cmp_bounds(fcinfo, &upper1, &upper2) != 0)
591                 PG_RETURN_BOOL(false);
592
593         PG_RETURN_BOOL(true);
594 }
595
596 Datum
597 range_ne(PG_FUNCTION_ARGS)
598 {
599         bool            eq = DatumGetBool(range_eq(fcinfo));
600
601         PG_RETURN_BOOL(!eq);
602 }
603
604 Datum
605 range_contains_elem(PG_FUNCTION_ARGS)
606 {
607         RangeType  *r1 = PG_GETARG_RANGE(0);
608         Datum           val = PG_GETARG_DATUM(1);
609         RangeType  *r2;
610         RangeBound      lower1,
611                                 lower2;
612         RangeBound      upper1,
613                                 upper2;
614         bool            empty1;
615
616         range_deserialize(fcinfo, r1, &lower1, &upper1, &empty1);
617
618         lower2.rngtypid = lower1.rngtypid;
619         lower2.inclusive = true;
620         lower2.infinite = false;
621         lower2.lower = true;
622         lower2.val = val;
623
624         upper2.rngtypid = lower1.rngtypid;
625         upper2.inclusive = true;
626         upper2.infinite = false;
627         upper2.lower = false;
628         upper2.val = val;
629
630         r2 = DatumGetRangeType(make_range(fcinfo, &lower2, &upper2, false));
631
632         PG_RETURN_BOOL(range_contains_internal(fcinfo, r1, r2));
633 }
634
635 Datum
636 range_contains(PG_FUNCTION_ARGS)
637 {
638         RangeType  *r1 = PG_GETARG_RANGE(0);
639         RangeType  *r2 = PG_GETARG_RANGE(1);
640
641         PG_RETURN_BOOL(range_contains_internal(fcinfo, r1, r2));
642 }
643
644 Datum
645 elem_contained_by_range(PG_FUNCTION_ARGS)
646 {
647         RangeType  *r1 = PG_GETARG_RANGE(1);
648         Datum           val = PG_GETARG_DATUM(0);
649         RangeType  *r2;
650         RangeBound      lower1,
651                                 lower2;
652         RangeBound      upper1,
653                                 upper2;
654         bool            empty1;
655
656         range_deserialize(fcinfo, r1, &lower1, &upper1, &empty1);
657
658         lower2.rngtypid = lower1.rngtypid;
659         lower2.inclusive = true;
660         lower2.infinite = false;
661         lower2.lower = true;
662         lower2.val = val;
663
664         upper2.rngtypid = lower1.rngtypid;
665         upper2.inclusive = true;
666         upper2.infinite = false;
667         upper2.lower = false;
668         upper2.val = val;
669
670         r2 = DatumGetRangeType(make_range(fcinfo, &lower2, &upper2, false));
671
672         PG_RETURN_BOOL(range_contains_internal(fcinfo, r1, r2));
673 }
674
675 Datum
676 range_contained_by(PG_FUNCTION_ARGS)
677 {
678         RangeType  *r1 = PG_GETARG_RANGE(0);
679         RangeType  *r2 = PG_GETARG_RANGE(1);
680
681         PG_RETURN_BOOL(range_contains_internal(fcinfo, r2, r1));
682 }
683
684 Datum
685 range_before(PG_FUNCTION_ARGS)
686 {
687         RangeType  *r1 = PG_GETARG_RANGE(0);
688         RangeType  *r2 = PG_GETARG_RANGE(1);
689         RangeBound      lower1,
690                                 lower2;
691         RangeBound      upper1,
692                                 upper2;
693         bool            empty1,
694                                 empty2;
695
696         range_deserialize(fcinfo, r1, &lower1, &upper1, &empty1);
697         range_deserialize(fcinfo, r2, &lower2, &upper2, &empty2);
698
699         if (lower1.rngtypid != upper1.rngtypid ||
700                 lower1.rngtypid != lower2.rngtypid ||
701                 lower1.rngtypid != upper2.rngtypid)
702                 elog(ERROR, "range types do not match");
703
704         /* An empty range is neither before nor after any other range */
705         if (empty1 || empty2)
706                 PG_RETURN_BOOL(false);
707
708         PG_RETURN_BOOL(range_cmp_bounds(fcinfo, &upper1, &lower2) < 0);
709 }
710
711 Datum
712 range_after(PG_FUNCTION_ARGS)
713 {
714         RangeType  *r1 = PG_GETARG_RANGE(0);
715         RangeType  *r2 = PG_GETARG_RANGE(1);
716         RangeBound      lower1,
717                                 lower2;
718         RangeBound      upper1,
719                                 upper2;
720         bool            empty1,
721                                 empty2;
722
723         range_deserialize(fcinfo, r1, &lower1, &upper1, &empty1);
724         range_deserialize(fcinfo, r2, &lower2, &upper2, &empty2);
725
726         if (lower1.rngtypid != upper1.rngtypid ||
727                 lower1.rngtypid != lower2.rngtypid ||
728                 lower1.rngtypid != upper2.rngtypid)
729                 elog(ERROR, "range types do not match");
730
731         /* An empty range is neither before nor after any other range */
732         if (empty1 || empty2)
733                 PG_RETURN_BOOL(false);
734
735         PG_RETURN_BOOL(range_cmp_bounds(fcinfo, &lower1, &upper2) > 0);
736 }
737
738 Datum
739 range_adjacent(PG_FUNCTION_ARGS)
740 {
741         RangeType  *r1 = PG_GETARG_RANGE(0);
742         RangeType  *r2 = PG_GETARG_RANGE(1);
743         RangeTypeInfo rngtypinfo;
744         RangeBound      lower1,
745                                 lower2;
746         RangeBound      upper1,
747                                 upper2;
748         bool            empty1,
749                                 empty2;
750
751         range_deserialize(fcinfo, r1, &lower1, &upper1, &empty1);
752         range_deserialize(fcinfo, r2, &lower2, &upper2, &empty2);
753
754         if (lower1.rngtypid != upper1.rngtypid ||
755                 lower1.rngtypid != lower2.rngtypid ||
756                 lower1.rngtypid != upper2.rngtypid)
757                 elog(ERROR, "range types do not match");
758
759         /* An empty range is not adjacent to any other range */
760         if (empty1 || empty2)
761                 PG_RETURN_BOOL(false);
762
763         /*
764          * For two ranges to be adjacent, the lower boundary of one range has to
765          * match the upper boundary of the other. However, the inclusivity of
766          * those two boundaries must also be different.
767          *
768          * The semantics for range_cmp_bounds aren't quite what we need here, so
769          * we do the comparison more directly.
770          */
771
772         range_gettypinfo(fcinfo, lower1.rngtypid, &rngtypinfo);
773
774         if (lower1.inclusive != upper2.inclusive)
775         {
776                 if (DatumGetInt32(FunctionCall2Coll(&rngtypinfo.cmpFn,
777                                                                                         rngtypinfo.collation,
778                                                                                         lower1.val, upper2.val)) == 0)
779                         PG_RETURN_BOOL(true);
780         }
781
782         if (upper1.inclusive != lower2.inclusive)
783         {
784                 if (DatumGetInt32(FunctionCall2Coll(&rngtypinfo.cmpFn,
785                                                                                         rngtypinfo.collation,
786                                                                                         upper1.val, lower2.val)) == 0)
787                         PG_RETURN_BOOL(true);
788         }
789
790         PG_RETURN_BOOL(false);
791 }
792
793 Datum
794 range_overlaps(PG_FUNCTION_ARGS)
795 {
796         RangeType  *r1 = PG_GETARG_RANGE(0);
797         RangeType  *r2 = PG_GETARG_RANGE(1);
798         RangeBound      lower1,
799                                 lower2;
800         RangeBound      upper1,
801                                 upper2;
802         bool            empty1,
803                                 empty2;
804
805         range_deserialize(fcinfo, r1, &lower1, &upper1, &empty1);
806         range_deserialize(fcinfo, r2, &lower2, &upper2, &empty2);
807
808         if (lower1.rngtypid != upper1.rngtypid ||
809                 lower1.rngtypid != lower2.rngtypid ||
810                 lower1.rngtypid != upper2.rngtypid)
811                 elog(ERROR, "range types do not match");
812
813         /* An empty range does not overlap any other range */
814         if (empty1 || empty2)
815                 PG_RETURN_BOOL(false);
816
817         if (range_cmp_bounds(fcinfo, &lower1, &lower2) >= 0 &&
818                 range_cmp_bounds(fcinfo, &lower1, &upper2) <= 0)
819                 PG_RETURN_BOOL(true);
820
821         if (range_cmp_bounds(fcinfo, &lower2, &lower1) >= 0 &&
822                 range_cmp_bounds(fcinfo, &lower2, &upper1) <= 0)
823                 PG_RETURN_BOOL(true);
824
825         PG_RETURN_BOOL(false);
826 }
827
828 Datum
829 range_overleft(PG_FUNCTION_ARGS)
830 {
831         RangeType  *r1 = PG_GETARG_RANGE(0);
832         RangeType  *r2 = PG_GETARG_RANGE(1);
833         RangeBound      lower1,
834                                 lower2;
835         RangeBound      upper1,
836                                 upper2;
837         bool            empty1,
838                                 empty2;
839
840         range_deserialize(fcinfo, r1, &lower1, &upper1, &empty1);
841         range_deserialize(fcinfo, r2, &lower2, &upper2, &empty2);
842
843         if (lower1.rngtypid != upper1.rngtypid ||
844                 lower1.rngtypid != lower2.rngtypid ||
845                 lower1.rngtypid != upper2.rngtypid)
846                 elog(ERROR, "range types do not match");
847
848         /* An empty range is neither before nor after any other range */
849         if (empty1 || empty2)
850                 PG_RETURN_BOOL(false);
851
852         if (range_cmp_bounds(fcinfo, &upper1, &upper2) <= 0)
853                 PG_RETURN_BOOL(true);
854
855         PG_RETURN_BOOL(false);
856 }
857
858 Datum
859 range_overright(PG_FUNCTION_ARGS)
860 {
861         RangeType  *r1 = PG_GETARG_RANGE(0);
862         RangeType  *r2 = PG_GETARG_RANGE(1);
863         RangeBound      lower1,
864                                 lower2;
865         RangeBound      upper1,
866                                 upper2;
867         bool            empty1,
868                                 empty2;
869
870         range_deserialize(fcinfo, r1, &lower1, &upper1, &empty1);
871         range_deserialize(fcinfo, r2, &lower2, &upper2, &empty2);
872
873         if (lower1.rngtypid != upper1.rngtypid ||
874                 lower1.rngtypid != lower2.rngtypid ||
875                 lower1.rngtypid != upper2.rngtypid)
876                 elog(ERROR, "range types do not match");
877
878         /* An empty range is neither before nor after any other range */
879         if (empty1 || empty2)
880                 PG_RETURN_BOOL(false);
881
882         if (range_cmp_bounds(fcinfo, &lower1, &lower2) >= 0)
883                 PG_RETURN_BOOL(true);
884
885         PG_RETURN_BOOL(false);
886 }
887
888
889 /* range, range -> range */
890 Datum
891 range_minus(PG_FUNCTION_ARGS)
892 {
893         RangeType  *r1 = PG_GETARG_RANGE(0);
894         RangeType  *r2 = PG_GETARG_RANGE(1);
895         RangeBound      lower1,
896                                 lower2;
897         RangeBound      upper1,
898                                 upper2;
899         bool            empty1,
900                                 empty2;
901         int                     cmp_l1l2,
902                                 cmp_l1u2,
903                                 cmp_u1l2,
904                                 cmp_u1u2;
905
906         range_deserialize(fcinfo, r1, &lower1, &upper1, &empty1);
907         range_deserialize(fcinfo, r2, &lower2, &upper2, &empty2);
908
909         if (lower1.rngtypid != upper1.rngtypid ||
910                 lower1.rngtypid != lower2.rngtypid ||
911                 lower1.rngtypid != upper2.rngtypid)
912                 elog(ERROR, "range types do not match");
913
914         /* if either is empty, r1 is the correct answer */
915         if (empty1 || empty2)
916                 PG_RETURN_RANGE(r1);
917
918         cmp_l1l2 = range_cmp_bounds(fcinfo, &lower1, &lower2);
919         cmp_l1u2 = range_cmp_bounds(fcinfo, &lower1, &upper2);
920         cmp_u1l2 = range_cmp_bounds(fcinfo, &upper1, &lower2);
921         cmp_u1u2 = range_cmp_bounds(fcinfo, &upper1, &upper2);
922
923         if (cmp_l1l2 < 0 && cmp_u1u2 > 0)
924                 ereport(ERROR,
925                                 (errcode(ERRCODE_DATA_EXCEPTION),
926                                  errmsg("result of range difference would not be contiguous")));
927
928         if (cmp_l1u2 > 0 || cmp_u1l2 < 0)
929                 PG_RETURN_RANGE(r1);
930
931         if (cmp_l1l2 >= 0 && cmp_u1u2 <= 0)
932                 PG_RETURN_RANGE(make_empty_range(fcinfo, lower1.rngtypid));
933
934         if (cmp_l1l2 <= 0 && cmp_u1l2 >= 0 && cmp_u1u2 <= 0)
935         {
936                 lower2.inclusive = !lower2.inclusive;
937                 lower2.lower = false;   /* it will become the upper bound */
938                 PG_RETURN_RANGE(make_range(fcinfo, &lower1, &lower2, false));
939         }
940
941         if (cmp_l1l2 >= 0 && cmp_u1u2 >= 0 && cmp_l1u2 <= 0)
942         {
943                 upper2.inclusive = !upper2.inclusive;
944                 upper2.lower = true;    /* it will become the lower bound */
945                 PG_RETURN_RANGE(make_range(fcinfo, &upper2, &upper1, false));
946         }
947
948         elog(ERROR, "unexpected case in range_minus");
949         PG_RETURN_NULL();
950 }
951
952 Datum
953 range_union(PG_FUNCTION_ARGS)
954 {
955         RangeType  *r1 = PG_GETARG_RANGE(0);
956         RangeType  *r2 = PG_GETARG_RANGE(1);
957         RangeBound      lower1,
958                                 lower2;
959         RangeBound      upper1,
960                                 upper2;
961         bool            empty1,
962                                 empty2;
963         RangeBound *result_lower;
964         RangeBound *result_upper;
965
966         range_deserialize(fcinfo, r1, &lower1, &upper1, &empty1);
967         range_deserialize(fcinfo, r2, &lower2, &upper2, &empty2);
968
969         /* if either is empty, the other is the correct answer */
970         if (empty1)
971                 PG_RETURN_RANGE(r2);
972         if (empty2)
973                 PG_RETURN_RANGE(r1);
974
975         if (!DatumGetBool(range_overlaps(fcinfo)) &&
976                 !DatumGetBool(range_adjacent(fcinfo)))
977                 ereport(ERROR,
978                                 (errcode(ERRCODE_DATA_EXCEPTION),
979                                  errmsg("result of range union would not be contiguous")));
980
981         if (range_cmp_bounds(fcinfo, &lower1, &lower2) < 0)
982                 result_lower = &lower1;
983         else
984                 result_lower = &lower2;
985
986         if (range_cmp_bounds(fcinfo, &upper1, &upper2) > 0)
987                 result_upper = &upper1;
988         else
989                 result_upper = &upper2;
990
991         PG_RETURN_RANGE(make_range(fcinfo, result_lower, result_upper, false));
992 }
993
994 Datum
995 range_intersect(PG_FUNCTION_ARGS)
996 {
997         RangeType  *r1 = PG_GETARG_RANGE(0);
998         RangeType  *r2 = PG_GETARG_RANGE(1);
999         RangeBound      lower1,
1000                                 lower2;
1001         RangeBound      upper1,
1002                                 upper2;
1003         bool            empty1,
1004                                 empty2;
1005         RangeBound *result_lower;
1006         RangeBound *result_upper;
1007
1008         range_deserialize(fcinfo, r1, &lower1, &upper1, &empty1);
1009         range_deserialize(fcinfo, r2, &lower2, &upper2, &empty2);
1010
1011         if (empty1 || empty2 || !DatumGetBool(range_overlaps(fcinfo)))
1012                 PG_RETURN_RANGE(make_empty_range(fcinfo, lower1.rngtypid));
1013
1014         if (range_cmp_bounds(fcinfo, &lower1, &lower2) >= 0)
1015                 result_lower = &lower1;
1016         else
1017                 result_lower = &lower2;
1018
1019         if (range_cmp_bounds(fcinfo, &upper1, &upper2) <= 0)
1020                 result_upper = &upper1;
1021         else
1022                 result_upper = &upper2;
1023
1024         PG_RETURN_RANGE(make_range(fcinfo, result_lower, result_upper, false));
1025 }
1026
1027 /* Btree support */
1028
1029 Datum
1030 range_cmp(PG_FUNCTION_ARGS)
1031 {
1032         RangeType  *r1 = PG_GETARG_RANGE(0);
1033         RangeType  *r2 = PG_GETARG_RANGE(1);
1034         RangeBound      lower1,
1035                                 lower2;
1036         RangeBound      upper1,
1037                                 upper2;
1038         bool            empty1,
1039                                 empty2;
1040         int                     cmp;
1041
1042         range_deserialize(fcinfo, r1, &lower1, &upper1, &empty1);
1043         range_deserialize(fcinfo, r2, &lower2, &upper2, &empty2);
1044
1045         if (lower1.rngtypid != upper1.rngtypid ||
1046                 lower1.rngtypid != lower2.rngtypid ||
1047                 lower1.rngtypid != upper2.rngtypid)
1048                 elog(ERROR, "range types do not match");
1049
1050         /* For b-tree use, empty ranges sort before all else */
1051         if (empty1 && empty2)
1052                 PG_RETURN_INT32(0);
1053         else if (empty1)
1054                 PG_RETURN_INT32(-1);
1055         else if (empty2)
1056                 PG_RETURN_INT32(1);
1057
1058         if ((cmp = range_cmp_bounds(fcinfo, &lower1, &lower2)) != 0)
1059                 PG_RETURN_INT32(cmp);
1060
1061         PG_RETURN_INT32(range_cmp_bounds(fcinfo, &upper1, &upper2));
1062 }
1063
1064 Datum
1065 range_lt(PG_FUNCTION_ARGS)
1066 {
1067         int                     cmp = range_cmp(fcinfo);
1068
1069         PG_RETURN_BOOL(cmp < 0);
1070 }
1071
1072 Datum
1073 range_le(PG_FUNCTION_ARGS)
1074 {
1075         int                     cmp = range_cmp(fcinfo);
1076
1077         PG_RETURN_BOOL(cmp <= 0);
1078 }
1079
1080 Datum
1081 range_ge(PG_FUNCTION_ARGS)
1082 {
1083         int                     cmp = range_cmp(fcinfo);
1084
1085         PG_RETURN_BOOL(cmp >= 0);
1086 }
1087
1088 Datum
1089 range_gt(PG_FUNCTION_ARGS)
1090 {
1091         int                     cmp = range_cmp(fcinfo);
1092
1093         PG_RETURN_BOOL(cmp > 0);
1094 }
1095
1096 /* Hash support */
1097
1098 Datum
1099 hash_range(PG_FUNCTION_ARGS)
1100 {
1101         RangeType  *r = PG_GETARG_RANGE(0);
1102         RangeBound      lower;
1103         RangeBound      upper;
1104         bool            empty;
1105         char            flags = 0;
1106         uint32          lower_hash = 0;
1107         uint32          upper_hash = 0;
1108         uint32          result = 0;
1109         RangeTypeInfo rngtypinfo;
1110         TypeCacheEntry *typentry;
1111         Oid                     subtype;
1112         FunctionCallInfoData locfcinfo;
1113
1114         range_deserialize(fcinfo, r, &lower, &upper, &empty);
1115
1116         if (lower.rngtypid != upper.rngtypid)
1117                 elog(ERROR, "range types do not match");
1118
1119         if (empty)
1120                 flags |= RANGE_EMPTY;
1121
1122         flags |= (lower.inclusive) ? RANGE_LB_INC : 0;
1123         flags |= (lower.infinite) ? RANGE_LB_INF : 0;
1124         flags |= (upper.inclusive) ? RANGE_UB_INC : 0;
1125         flags |= (upper.infinite) ? RANGE_UB_INF : 0;
1126
1127         range_gettypinfo(fcinfo, lower.rngtypid, &rngtypinfo);
1128         subtype = rngtypinfo.subtype;
1129
1130         /*
1131          * We arrange to look up the hash function only once per series of calls,
1132          * assuming the subtype doesn't change underneath us.  The typcache is
1133          * used so that we have no memory leakage when being used as an index
1134          * support function.
1135          */
1136         typentry = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
1137         if (typentry == NULL || typentry->type_id != subtype)
1138         {
1139                 typentry = lookup_type_cache(subtype, TYPECACHE_HASH_PROC_FINFO);
1140                 if (!OidIsValid(typentry->hash_proc_finfo.fn_oid))
1141                         ereport(ERROR,
1142                                         (errcode(ERRCODE_UNDEFINED_FUNCTION),
1143                                          errmsg("could not identify a hash function for type %s",
1144                                                         format_type_be(subtype))));
1145                 fcinfo->flinfo->fn_extra = (void *) typentry;
1146         }
1147
1148         /*
1149          * Apply the hash function to each bound (the hash function shouldn't care
1150          * about the collation).
1151          */
1152         InitFunctionCallInfoData(locfcinfo, &typentry->hash_proc_finfo, 1,
1153                                                          InvalidOid, NULL, NULL);
1154
1155         if (RANGE_HAS_LBOUND(flags))
1156         {
1157                 locfcinfo.arg[0] = lower.val;
1158                 locfcinfo.argnull[0] = false;
1159                 locfcinfo.isnull = false;
1160                 lower_hash = DatumGetUInt32(FunctionCallInvoke(&locfcinfo));
1161         }
1162         if (RANGE_HAS_UBOUND(flags))
1163         {
1164                 locfcinfo.arg[0] = upper.val;
1165                 locfcinfo.argnull[0] = false;
1166                 locfcinfo.isnull = false;
1167                 upper_hash = DatumGetUInt32(FunctionCallInvoke(&locfcinfo));
1168         }
1169
1170         result = hash_uint32((uint32) flags);
1171         result ^= lower_hash;
1172         result = (result << 1) | (result >> 31);
1173         result ^= upper_hash;
1174
1175         PG_RETURN_INT32(result);
1176 }
1177
1178 /*
1179  *----------------------------------------------------------
1180  * CANONICAL FUNCTIONS
1181  *
1182  *       Functions for specific built-in range types.
1183  *----------------------------------------------------------
1184  */
1185
1186 Datum
1187 int4range_canonical(PG_FUNCTION_ARGS)
1188 {
1189         RangeType  *r = PG_GETARG_RANGE(0);
1190         RangeBound      lower;
1191         RangeBound      upper;
1192         bool            empty;
1193
1194         range_deserialize(fcinfo, r, &lower, &upper, &empty);
1195
1196         if (empty)
1197                 PG_RETURN_RANGE(r);
1198
1199         if (!lower.infinite && !lower.inclusive)
1200         {
1201                 lower.val = DirectFunctionCall2(int4pl, lower.val, Int32GetDatum(1));
1202                 lower.inclusive = true;
1203         }
1204
1205         if (!upper.infinite && upper.inclusive)
1206         {
1207                 upper.val = DirectFunctionCall2(int4pl, upper.val, Int32GetDatum(1));
1208                 upper.inclusive = false;
1209         }
1210
1211         PG_RETURN_RANGE(range_serialize(fcinfo, &lower, &upper, false));
1212 }
1213
1214 Datum
1215 int8range_canonical(PG_FUNCTION_ARGS)
1216 {
1217         RangeType  *r = PG_GETARG_RANGE(0);
1218         RangeBound      lower;
1219         RangeBound      upper;
1220         bool            empty;
1221
1222         range_deserialize(fcinfo, r, &lower, &upper, &empty);
1223
1224         if (empty)
1225                 PG_RETURN_RANGE(r);
1226
1227         if (!lower.infinite && !lower.inclusive)
1228         {
1229                 lower.val = DirectFunctionCall2(int8pl, lower.val, Int64GetDatum(1));
1230                 lower.inclusive = true;
1231         }
1232
1233         if (!upper.infinite && upper.inclusive)
1234         {
1235                 upper.val = DirectFunctionCall2(int8pl, upper.val, Int64GetDatum(1));
1236                 upper.inclusive = false;
1237         }
1238
1239         PG_RETURN_RANGE(range_serialize(fcinfo, &lower, &upper, false));
1240 }
1241
1242 Datum
1243 daterange_canonical(PG_FUNCTION_ARGS)
1244 {
1245         RangeType  *r = PG_GETARG_RANGE(0);
1246         RangeBound      lower;
1247         RangeBound      upper;
1248         bool            empty;
1249
1250         range_deserialize(fcinfo, r, &lower, &upper, &empty);
1251
1252         if (empty)
1253                 PG_RETURN_RANGE(r);
1254
1255         if (!lower.infinite && !lower.inclusive)
1256         {
1257                 lower.val = DirectFunctionCall2(date_pli, lower.val, Int32GetDatum(1));
1258                 lower.inclusive = true;
1259         }
1260
1261         if (!upper.infinite && upper.inclusive)
1262         {
1263                 upper.val = DirectFunctionCall2(date_pli, upper.val, Int32GetDatum(1));
1264                 upper.inclusive = false;
1265         }
1266
1267         PG_RETURN_RANGE(range_serialize(fcinfo, &lower, &upper, false));
1268 }
1269
1270 /*
1271  *----------------------------------------------------------
1272  * SUBTYPE_DIFF FUNCTIONS
1273  *
1274  *       Functions for specific built-in range types.
1275  *----------------------------------------------------------
1276  */
1277
1278 Datum
1279 int4range_subdiff(PG_FUNCTION_ARGS)
1280 {
1281         int32           v1 = PG_GETARG_INT32(0);
1282         int32           v2 = PG_GETARG_INT32(1);
1283
1284         PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
1285 }
1286
1287 Datum
1288 int8range_subdiff(PG_FUNCTION_ARGS)
1289 {
1290         int64           v1 = PG_GETARG_INT64(0);
1291         int64           v2 = PG_GETARG_INT64(1);
1292
1293         PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
1294 }
1295
1296 Datum
1297 numrange_subdiff(PG_FUNCTION_ARGS)
1298 {
1299         Datum           v1 = PG_GETARG_DATUM(0);
1300         Datum           v2 = PG_GETARG_DATUM(1);
1301         Datum           numresult;
1302         float8          floatresult;
1303
1304         numresult = DirectFunctionCall2(numeric_sub, v1, v2);
1305
1306         floatresult = DatumGetFloat8(DirectFunctionCall1(numeric_float8,
1307                                                                                                          numresult));
1308
1309         PG_RETURN_FLOAT8(floatresult);
1310 }
1311
1312 Datum
1313 daterange_subdiff(PG_FUNCTION_ARGS)
1314 {
1315         int32           v1 = PG_GETARG_INT32(0);
1316         int32           v2 = PG_GETARG_INT32(1);
1317
1318         PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
1319 }
1320
1321 Datum
1322 tsrange_subdiff(PG_FUNCTION_ARGS)
1323 {
1324         Timestamp       v1 = PG_GETARG_TIMESTAMP(0);
1325         Timestamp       v2 = PG_GETARG_TIMESTAMP(1);
1326         float8          result;
1327
1328 #ifdef HAVE_INT64_TIMESTAMP
1329         result = ((float8) v1 - (float8) v2) / USECS_PER_SEC;
1330 #else
1331         result = v1 - v2;
1332 #endif
1333
1334         PG_RETURN_FLOAT8(result);
1335 }
1336
1337 Datum
1338 tstzrange_subdiff(PG_FUNCTION_ARGS)
1339 {
1340         Timestamp       v1 = PG_GETARG_TIMESTAMP(0);
1341         Timestamp       v2 = PG_GETARG_TIMESTAMP(1);
1342         float8          result;
1343
1344 #ifdef HAVE_INT64_TIMESTAMP
1345         result = ((float8) v1 - (float8) v2) / USECS_PER_SEC;
1346 #else
1347         result = v1 - v2;
1348 #endif
1349
1350         PG_RETURN_FLOAT8(result);
1351 }
1352
1353 /*
1354  *----------------------------------------------------------
1355  * SUPPORT FUNCTIONS
1356  *
1357  *       These functions aren't in pg_proc, but are useful for
1358  *       defining new generic range functions in C.
1359  *----------------------------------------------------------
1360  */
1361
1362 /*
1363  * Serialized format is:
1364  *
1365  *      4 bytes: Range type Oid
1366  *      Lower boundary, if any, aligned according to subtype's typalign
1367  *      Upper boundary, if any, aligned according to subtype's typalign
1368  *      1 byte for flags
1369  *
1370  * This representation is chosen to be compact when the boundary
1371  * values need to be MAXALIGNed. A palloc chunk always starts out
1372  * MAXALIGNed, and the first 4 bytes will be the length header (range
1373  * types are always variable-length), then the next 4 bytes will be
1374  * the range type Oid. That leaves the first boundary item MAXALIGNed
1375  * without the need for padding.
1376  *
1377  * However, it requires a slightly odd deserialization strategy,
1378  * because we have to read the flags byte before we know whether to
1379  * read a boundary value.
1380  */
1381
1382 /*
1383  * This serializes a range, but does not canonicalize it. This should
1384  * only be called by a canonicalization function.
1385  */
1386 Datum
1387 range_serialize(FunctionCallInfo fcinfo, RangeBound *lower, RangeBound *upper,
1388                                 bool empty)
1389 {
1390         Datum           range;
1391         size_t          msize;
1392         Pointer         ptr;
1393         int16           typlen;
1394         char            typalign;
1395         bool            typbyval;
1396         char            typstorage;
1397         char            flags = 0;
1398         RangeTypeInfo rngtypinfo;
1399
1400         if (lower->rngtypid != upper->rngtypid)
1401                 elog(ERROR, "range types do not match");
1402
1403         range_gettypinfo(fcinfo, lower->rngtypid, &rngtypinfo);
1404
1405         typlen = rngtypinfo.subtyplen;
1406         typalign = rngtypinfo.subtypalign;
1407         typbyval = rngtypinfo.subtypbyval;
1408         typstorage = rngtypinfo.subtypstorage;
1409
1410         if (empty)
1411                 flags |= RANGE_EMPTY;
1412         else if (range_cmp_bounds(fcinfo, lower, upper) > 0)
1413                 ereport(ERROR,
1414                                 (errcode(ERRCODE_DATA_EXCEPTION),
1415                                  errmsg("range lower bound must be less than or equal to range upper bound")));
1416
1417         flags |= (lower->inclusive) ? RANGE_LB_INC : 0;
1418         flags |= (lower->infinite) ? RANGE_LB_INF : 0;
1419         flags |= (upper->inclusive) ? RANGE_UB_INC : 0;
1420         flags |= (upper->infinite) ? RANGE_UB_INF : 0;
1421
1422         msize = VARHDRSZ;
1423         msize += sizeof(Oid);
1424
1425         if (RANGE_HAS_LBOUND(flags))
1426         {
1427                 msize = datum_compute_size(msize, lower->val, typbyval, typalign,
1428                                                                    typlen, typstorage);
1429         }
1430
1431         if (RANGE_HAS_UBOUND(flags))
1432         {
1433                 msize = datum_compute_size(msize, upper->val, typbyval, typalign,
1434                                                                    typlen, typstorage);
1435         }
1436
1437         msize += sizeof(char);
1438
1439         ptr = palloc0(msize);
1440         range = (Datum) ptr;
1441
1442         ptr += VARHDRSZ;
1443
1444         memcpy(ptr, &lower->rngtypid, sizeof(Oid));
1445         ptr += sizeof(Oid);
1446
1447         if (RANGE_HAS_LBOUND(flags))
1448         {
1449                 Assert(lower->lower);
1450                 ptr = datum_write(ptr, lower->val, typbyval, typalign, typlen,
1451                                                   typstorage);
1452         }
1453
1454         if (RANGE_HAS_UBOUND(flags))
1455         {
1456                 Assert(!upper->lower);
1457                 ptr = datum_write(ptr, upper->val, typbyval, typalign, typlen,
1458                                                   typstorage);
1459         }
1460
1461         memcpy(ptr, &flags, sizeof(char));
1462         ptr += sizeof(char);
1463
1464         SET_VARSIZE(range, msize);
1465         PG_RETURN_RANGE(range);
1466 }
1467
1468 void
1469 range_deserialize(FunctionCallInfo fcinfo, RangeType *range, RangeBound *lower,
1470                                   RangeBound *upper, bool *empty)
1471 {
1472         Pointer         ptr = VARDATA(range);
1473         char            typalign;
1474         int16           typlen;
1475         int16           typbyval;
1476         char            flags;
1477         Oid                     rngtypid;
1478         Datum           lbound;
1479         Datum           ubound;
1480         Pointer         flags_ptr;
1481         RangeTypeInfo rngtypinfo;
1482
1483         memset(lower, 0, sizeof(RangeBound));
1484         memset(upper, 0, sizeof(RangeBound));
1485
1486         /* peek at last byte to read the flag byte */
1487         flags_ptr = ptr + VARSIZE(range) - VARHDRSZ - 1;
1488         memcpy(&flags, flags_ptr, sizeof(char));
1489
1490         memcpy(&rngtypid, ptr, sizeof(Oid));
1491         ptr += sizeof(Oid);
1492
1493         if (rngtypid == ANYRANGEOID)
1494                 ereport(ERROR,
1495                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1496                                  errmsg("cannot output a value of type anyrange")));
1497
1498         range_gettypinfo(fcinfo, rngtypid, &rngtypinfo);
1499
1500         typalign = rngtypinfo.subtypalign;
1501         typlen = rngtypinfo.subtyplen;
1502         typbyval = rngtypinfo.subtypbyval;
1503
1504         if (RANGE_HAS_LBOUND(flags))
1505         {
1506                 ptr = (Pointer) att_align_pointer(ptr, typalign, typlen, ptr);
1507                 lbound = fetch_att(ptr, typbyval, typlen);
1508                 ptr = (Pointer) att_addlength_datum(ptr, typlen, PointerGetDatum(ptr));
1509                 if (typlen == -1)
1510                         lbound = PointerGetDatum(PG_DETOAST_DATUM(lbound));
1511         }
1512         else
1513                 lbound = (Datum) 0;
1514
1515         if (RANGE_HAS_UBOUND(flags))
1516         {
1517                 ptr = (Pointer) att_align_pointer(ptr, typalign, typlen, ptr);
1518                 ubound = fetch_att(ptr, typbyval, typlen);
1519                 ptr = (Pointer) att_addlength_datum(ptr, typlen, PointerGetDatum(ptr));
1520                 if (typlen == -1)
1521                         ubound = PointerGetDatum(PG_DETOAST_DATUM(ubound));
1522         }
1523         else
1524                 ubound = (Datum) 0;
1525
1526         *empty = flags & RANGE_EMPTY;
1527
1528         lower->rngtypid = rngtypid;
1529         lower->val = lbound;
1530         lower->inclusive = flags & RANGE_LB_INC;
1531         lower->infinite = flags & RANGE_LB_INF;
1532         lower->lower = true;
1533
1534         upper->rngtypid = rngtypid;
1535         upper->val = ubound;
1536         upper->inclusive = flags & RANGE_UB_INC;
1537         upper->infinite = flags & RANGE_UB_INF;
1538         upper->lower = false;
1539 }
1540
1541 /*
1542  * This both serializes and canonicalizes (if applicable) the range.
1543  * This should be used by most callers.
1544  */
1545 Datum
1546 make_range(FunctionCallInfo fcinfo, RangeBound *lower, RangeBound *upper,
1547                    bool empty)
1548 {
1549         Datum           range;
1550         RangeTypeInfo rngtypinfo;
1551
1552         range_gettypinfo(fcinfo, lower->rngtypid, &rngtypinfo);
1553
1554         if (lower->rngtypid != upper->rngtypid)
1555                 elog(ERROR, "range types do not match");
1556
1557         range = range_serialize(fcinfo, lower, upper, empty);
1558
1559         if (rngtypinfo.canonicalFn.fn_addr != NULL)
1560                 range = FunctionCall1(&rngtypinfo.canonicalFn, range);
1561
1562         PG_RETURN_RANGE(range);
1563 }
1564
1565 int
1566 range_cmp_bounds(FunctionCallInfo fcinfo, RangeBound *b1, RangeBound *b2)
1567 {
1568         int                     result;
1569         RangeTypeInfo rngtypinfo;
1570
1571         if (b1->infinite && b2->infinite)
1572         {
1573                 if (b1->lower == b2->lower)
1574                         return 0;
1575                 else
1576                         return (b1->lower) ? -1 : 1;
1577         }
1578         else if (b1->infinite && !b2->infinite)
1579                 return (b1->lower) ? -1 : 1;
1580         else if (!b1->infinite && b2->infinite)
1581                 return (b2->lower) ? 1 : -1;
1582
1583         range_gettypinfo(fcinfo, b1->rngtypid, &rngtypinfo);
1584
1585         result = DatumGetInt32(FunctionCall2Coll(&rngtypinfo.cmpFn,
1586                                                                                          rngtypinfo.collation,
1587                                                                                          b1->val, b2->val));
1588
1589         if (result == 0)
1590         {
1591                 if (b1->inclusive && !b2->inclusive)
1592                         return (b2->lower) ? -1 : 1;
1593                 else if (!b1->inclusive && b2->inclusive)
1594                         return (b1->lower) ? 1 : -1;
1595         }
1596
1597         return result;
1598 }
1599
1600 RangeType *
1601 make_empty_range(FunctionCallInfo fcinfo, Oid rngtypid)
1602 {
1603         RangeBound      lower;
1604         RangeBound      upper;
1605
1606         memset(&lower, 0, sizeof(RangeBound));
1607         memset(&upper, 0, sizeof(RangeBound));
1608
1609         lower.rngtypid = rngtypid;
1610         lower.lower = true;
1611         upper.rngtypid = rngtypid;
1612         upper.lower = false;
1613
1614         return DatumGetRangeType(make_range(fcinfo, &lower, &upper, true));
1615 }
1616
1617 /*
1618  * Fills in rngtypinfo, from a cached copy if available.
1619  */
1620 void
1621 range_gettypinfo(FunctionCallInfo fcinfo, Oid rngtypid,
1622                                  RangeTypeInfo *rngtypinfo)
1623 {
1624         RangeTypeInfo *cached = (RangeTypeInfo *) fcinfo->flinfo->fn_extra;
1625
1626         if (cached == NULL)
1627         {
1628                 fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
1629                                                                                                           sizeof(RangeTypeInfo));
1630                 cached = (RangeTypeInfo *) fcinfo->flinfo->fn_extra;
1631                 cached->rngtypid = ~rngtypid;
1632         }
1633
1634         if (cached->rngtypid != rngtypid)
1635         {
1636                 Form_pg_range pg_range;
1637                 Form_pg_opclass pg_opclass;
1638                 Form_pg_type pg_type;
1639                 HeapTuple       tup;
1640                 Oid                     subtypeOid;
1641                 Oid                     collationOid;
1642                 Oid                     canonicalOid;
1643                 Oid                     subdiffOid;
1644                 Oid                     opclassOid;
1645                 Oid                     cmpFnOid;
1646                 Oid                     opfamilyOid;
1647                 Oid                     opcintype;
1648                 int16           subtyplen;
1649                 char            subtypalign;
1650                 char            subtypstorage;
1651                 bool            subtypbyval;
1652
1653                 /* get information from pg_range */
1654                 tup = SearchSysCache1(RANGETYPE, ObjectIdGetDatum(rngtypid));
1655                 if (!HeapTupleIsValid(tup))
1656                         elog(ERROR, "cache lookup failed for range type %u", rngtypid);
1657
1658                 pg_range = (Form_pg_range) GETSTRUCT(tup);
1659
1660                 subtypeOid = pg_range->rngsubtype;
1661                 collationOid = pg_range->rngcollation;
1662                 canonicalOid = pg_range->rngcanonical;
1663                 opclassOid = pg_range->rngsubopc;
1664                 subdiffOid = pg_range->rngsubdiff;
1665
1666                 ReleaseSysCache(tup);
1667
1668                 /* get information from pg_opclass */
1669                 tup = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclassOid));
1670                 if (!HeapTupleIsValid(tup))
1671                         ereport(ERROR,
1672                                         (errcode(ERRCODE_UNDEFINED_OBJECT),
1673                                          errmsg("operator class with OID %u does not exist",
1674                                                         opclassOid)));
1675
1676                 pg_opclass = (Form_pg_opclass) GETSTRUCT(tup);
1677
1678                 opfamilyOid = pg_opclass->opcfamily;
1679                 opcintype = pg_opclass->opcintype;
1680
1681                 ReleaseSysCache(tup);
1682
1683                 cmpFnOid = get_opfamily_proc(opfamilyOid, opcintype, opcintype,
1684                                                                          BTORDER_PROC);
1685                 if (!RegProcedureIsValid(cmpFnOid))
1686                         elog(ERROR, "missing support function %d(%u,%u) in opfamily %u",
1687                                  BTORDER_PROC, opcintype, opcintype, opfamilyOid);
1688
1689                 /* get information from pg_type */
1690                 tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(subtypeOid));
1691                 if (!HeapTupleIsValid(tup))
1692                         elog(ERROR, "cache lookup failed for type %u", subtypeOid);
1693
1694                 pg_type = (Form_pg_type) GETSTRUCT(tup);
1695
1696                 subtyplen = pg_type->typlen;
1697                 subtypalign = pg_type->typalign;
1698                 subtypstorage = pg_type->typstorage;
1699                 subtypbyval = pg_type->typbyval;
1700
1701                 ReleaseSysCache(tup);
1702
1703                 /* set up the cache */
1704
1705                 if (OidIsValid(canonicalOid))
1706                         fmgr_info(canonicalOid, &cached->canonicalFn);
1707                 else
1708                         cached->canonicalFn.fn_addr = NULL;
1709
1710                 if (OidIsValid(subdiffOid))
1711                         fmgr_info(subdiffOid, &cached->subdiffFn);
1712                 else
1713                         cached->subdiffFn.fn_addr = NULL;
1714
1715                 fmgr_info(cmpFnOid, &cached->cmpFn);
1716                 cached->subtype = subtypeOid;
1717                 cached->collation = collationOid;
1718                 cached->subtyplen = subtyplen;
1719                 cached->subtypalign = subtypalign;
1720                 cached->subtypstorage = subtypstorage;
1721                 cached->subtypbyval = subtypbyval;
1722                 cached->rngtypid = rngtypid;
1723         }
1724
1725         memcpy(rngtypinfo, cached, sizeof(RangeTypeInfo));
1726 }
1727
1728 /*
1729  *----------------------------------------------------------
1730  * STATIC FUNCTIONS
1731  *----------------------------------------------------------
1732  */
1733
1734 /*
1735  * Given a string representing the flags for the range type, return the flags
1736  * represented as a char.
1737  */
1738 static char
1739 range_parse_flags(const char *flags_str)
1740 {
1741         char            flags = 0;
1742
1743         if (flags_str[0] == '\0' ||
1744                 flags_str[1] == '\0' ||
1745                 flags_str[2] != '\0')
1746                 ereport(ERROR,
1747                                 (errcode(ERRCODE_SYNTAX_ERROR),
1748                                  errmsg("invalid range bound flags"),
1749                                  errhint("Valid values are '[]', '[)', '(]', and '()'.")));
1750
1751         switch (flags_str[0])
1752         {
1753                 case '[':
1754                         flags |= RANGE_LB_INC;
1755                         break;
1756                 case '(':
1757                         break;
1758                 default:
1759                         ereport(ERROR,
1760                                         (errcode(ERRCODE_SYNTAX_ERROR),
1761                                          errmsg("invalid range bound flags"),
1762                                    errhint("Valid values are '[]', '[)', '(]', and '()'.")));
1763         }
1764
1765         switch (flags_str[1])
1766         {
1767                 case ']':
1768                         flags |= RANGE_UB_INC;
1769                         break;
1770                 case ')':
1771                         break;
1772                 default:
1773                         ereport(ERROR,
1774                                         (errcode(ERRCODE_SYNTAX_ERROR),
1775                                          errmsg("invalid range bound flags"),
1776                                    errhint("Valid values are '[]', '[)', '(]', and '()'.")));
1777         }
1778
1779         return flags;
1780 }
1781
1782 /*
1783  * Parse range input, modeled after record_in in rowtypes.c.
1784  *
1785  *      <range>   := EMPTY
1786  *                         | <lb-inc> <string>, <string> <ub-inc>
1787  *      <lb-inc>  := '[' | '('
1788  *      <ub-inc>  := ']' | ')'
1789  *
1790  * Whitespace before or after <range> is ignored. Whitespace within a <string>
1791  * is taken literally and becomes the input string for that bound.
1792  *
1793  * A <string> of length zero is taken as "infinite" (i.e. no bound); unless it
1794  * is surrounded by double-quotes, in which case it is the literal empty
1795  * string.
1796  *
1797  * Within a <string>, special characters (such as comma, parenthesis, or
1798  * brackets) can be enclosed in double-quotes or escaped with backslash. Within
1799  * double-quotes, a double-quote can be escaped with double-quote or backslash.
1800  */
1801 static void
1802 range_parse(char *string, char *flags, char **lbound_str,
1803                         char **ubound_str)
1804 {
1805         char       *ptr = string;
1806         bool            infinite;
1807
1808         *flags = 0;
1809
1810         /* consume whitespace */
1811         while (*ptr != '\0' && isspace(*ptr))
1812                 ptr++;
1813
1814         /* check for empty range */
1815         if (pg_strncasecmp(ptr, RANGE_EMPTY_LITERAL,
1816                                            strlen(RANGE_EMPTY_LITERAL)) == 0)
1817         {
1818                 *flags = RANGE_EMPTY;
1819
1820                 ptr += strlen(RANGE_EMPTY_LITERAL);
1821
1822                 /* the rest should be whitespace */
1823                 while (*ptr != '\0' && isspace(*ptr))
1824                         ptr++;
1825
1826                 /* should have consumed everything */
1827                 if (*ptr != '\0')
1828                         ereport(ERROR,
1829                                         (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1830                                          errmsg("malformed range literal: \"%s\"",
1831                                                         string),
1832                                          errdetail("Unexpected end of input.")));
1833
1834                 return;
1835         }
1836
1837         if (*ptr == '[' || *ptr == '(')
1838         {
1839                 if (*ptr == '[')
1840                         *flags |= RANGE_LB_INC;
1841                 ptr++;
1842         }
1843         else
1844         {
1845                 ereport(ERROR,
1846                                 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1847                                  errmsg("malformed range literal: \"%s\"",
1848                                                 string),
1849                                  errdetail("Missing left parenthesis or bracket.")));
1850         }
1851
1852         ptr = range_parse_bound(string, ptr, lbound_str, &infinite);
1853         if (infinite)
1854         {
1855                 *flags |= RANGE_LB_INF;
1856                 *flags &= ~RANGE_LB_INC;
1857         }
1858
1859         if (*ptr != ',')
1860                 ereport(ERROR,
1861                                 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1862                                  errmsg("malformed range literal: \"%s\"",
1863                                                 string),
1864                                  errdetail("Missing upper bound.")));
1865         ptr++;
1866
1867         ptr = range_parse_bound(string, ptr, ubound_str, &infinite);
1868
1869         if (*ptr == ')' || *ptr == ']')
1870         {
1871                 if (*ptr == ']')
1872                         *flags |= RANGE_UB_INC;
1873         }
1874         else
1875         {
1876                 ereport(ERROR,
1877                                 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1878                                  errmsg("malformed range literal: \"%s\"",
1879                                                 string),
1880                                  errdetail("Too many boundaries.")));
1881         }
1882
1883         ptr++;
1884
1885         if (infinite)
1886         {
1887                 *flags |= RANGE_UB_INF;
1888                 *flags &= ~RANGE_UB_INC;
1889         }
1890
1891         /* consume whitespace */
1892         while (*ptr != '\0' && isspace(*ptr))
1893                 ptr++;
1894
1895         if (*ptr != '\0')
1896                 ereport(ERROR,
1897                                 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1898                                  errmsg("malformed range literal: \"%s\"",
1899                                                 string),
1900                                  errdetail("Junk after right parenthesis or bracket.")));
1901
1902         return;
1903 }
1904
1905 static char *
1906 range_parse_bound(char *string, char *ptr, char **bound_str, bool *infinite)
1907 {
1908         StringInfoData buf;
1909
1910         /* Check for null: completely empty input means null */
1911         if (*ptr == ',' || *ptr == ')' || *ptr == ']')
1912         {
1913                 *bound_str = NULL;
1914                 *infinite = true;
1915         }
1916         else
1917         {
1918                 /* Extract string for this column */
1919                 bool            inquote = false;
1920
1921                 initStringInfo(&buf);
1922                 while (inquote || !(*ptr == ',' || *ptr == ')' || *ptr == ']'))
1923                 {
1924                         char            ch = *ptr++;
1925
1926                         if (ch == '\0')
1927                                 ereport(ERROR,
1928                                                 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1929                                                  errmsg("malformed range literal: \"%s\"",
1930                                                                 string),
1931                                                  errdetail("Unexpected end of input.")));
1932                         if (ch == '\\')
1933                         {
1934                                 if (*ptr == '\0')
1935                                         ereport(ERROR,
1936                                                         (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
1937                                                          errmsg("malformed range literal: \"%s\"",
1938                                                                         string),
1939                                                          errdetail("Unexpected end of input.")));
1940                                 appendStringInfoChar(&buf, *ptr++);
1941                         }
1942                         else if (ch == '\"')
1943                         {
1944                                 if (!inquote)
1945                                         inquote = true;
1946                                 else if (*ptr == '\"')
1947                                 {
1948                                         /* doubled quote within quote sequence */
1949                                         appendStringInfoChar(&buf, *ptr++);
1950                                 }
1951                                 else
1952                                         inquote = false;
1953                         }
1954                         else
1955                                 appendStringInfoChar(&buf, ch);
1956                 }
1957
1958                 *bound_str = buf.data;
1959                 *infinite = false;
1960         }
1961
1962         return ptr;
1963 }
1964
1965 static char *
1966 range_deparse(char flags, char *lbound_str, char *ubound_str)
1967 {
1968         StringInfoData buf;
1969
1970         initStringInfo(&buf);
1971
1972         if (flags & RANGE_EMPTY)
1973                 return pstrdup(RANGE_EMPTY_LITERAL);
1974
1975         appendStringInfoString(&buf, (flags & RANGE_LB_INC) ? "[" : "(");
1976
1977         if (RANGE_HAS_LBOUND(flags))
1978                 appendStringInfoString(&buf, range_bound_escape(lbound_str));
1979
1980         appendStringInfoString(&buf, ",");
1981
1982         if (RANGE_HAS_UBOUND(flags))
1983                 appendStringInfoString(&buf, range_bound_escape(ubound_str));
1984
1985         appendStringInfoString(&buf, (flags & RANGE_UB_INC) ? "]" : ")");
1986
1987         return buf.data;
1988 }
1989
1990 static char *
1991 range_bound_escape(char *value)
1992 {
1993         bool            nq;
1994         char       *tmp;
1995         StringInfoData buf;
1996
1997         initStringInfo(&buf);
1998
1999         /* Detect whether we need double quotes for this value */
2000         nq = (value[0] == '\0');        /* force quotes for empty string */
2001         for (tmp = value; *tmp; tmp++)
2002         {
2003                 char            ch = *tmp;
2004
2005                 if (ch == '"' || ch == '\\' ||
2006                         ch == '(' || ch == ')' ||
2007                         ch == '[' || ch == ']' ||
2008                         ch == ',' ||
2009                         isspace((unsigned char) ch))
2010                 {
2011                         nq = true;
2012                         break;
2013                 }
2014         }
2015
2016         /* And emit the string */
2017         if (nq)
2018                 appendStringInfoChar(&buf, '"');
2019         for (tmp = value; *tmp; tmp++)
2020         {
2021                 char            ch = *tmp;
2022
2023                 if (ch == '"' || ch == '\\')
2024                         appendStringInfoChar(&buf, ch);
2025                 appendStringInfoChar(&buf, ch);
2026         }
2027         if (nq)
2028                 appendStringInfoChar(&buf, '"');
2029
2030         return buf.data;
2031 }
2032
2033 static bool
2034 range_contains_internal(FunctionCallInfo fcinfo, RangeType *r1, RangeType *r2)
2035 {
2036         RangeBound      lower1;
2037         RangeBound      upper1;
2038         bool            empty1;
2039         RangeBound      lower2;
2040         RangeBound      upper2;
2041         bool            empty2;
2042
2043         range_deserialize(fcinfo, r1, &lower1, &upper1, &empty1);
2044         range_deserialize(fcinfo, r2, &lower2, &upper2, &empty2);
2045
2046         if (lower1.rngtypid != upper1.rngtypid ||
2047                 lower1.rngtypid != lower2.rngtypid ||
2048                 lower1.rngtypid != upper2.rngtypid)
2049                 elog(ERROR, "range types do not match");
2050
2051         if (empty2)
2052                 return true;
2053         else if (empty1)
2054                 return false;
2055
2056         if (range_cmp_bounds(fcinfo, &lower1, &lower2) > 0)
2057                 return false;
2058         if (range_cmp_bounds(fcinfo, &upper1, &upper2) < 0)
2059                 return false;
2060
2061         return true;
2062 }
2063
2064 /*
2065  * datum_compute_size() and datum_write() are modeled after
2066  * heap_compute_data_size() and heap_fill_tuple().
2067  */
2068
2069 static Size
2070 datum_compute_size(Size data_length, Datum val, bool typbyval, char typalign,
2071                                    int16 typlen, char typstorage)
2072 {
2073         if (TYPE_IS_PACKABLE(typlen, typstorage) &&
2074                 VARATT_CAN_MAKE_SHORT(DatumGetPointer(val)))
2075         {
2076                 /*
2077                  * we're anticipating converting to a short varlena header, so adjust
2078                  * length and don't count any alignment
2079                  */
2080                 data_length += VARATT_CONVERTED_SHORT_SIZE(DatumGetPointer(val));
2081         }
2082         else
2083         {
2084                 data_length = att_align_datum(data_length, typalign, typlen, val);
2085                 data_length = att_addlength_datum(data_length, typlen, val);
2086         }
2087
2088         return data_length;
2089 }
2090
2091 /*
2092  * Modified version of the code in heap_fill_tuple(). Writes the datum to ptr
2093  * using the correct alignment, and also uses short varlena header if
2094  * applicable.
2095  */
2096 static Pointer
2097 datum_write(Pointer ptr, Datum datum, bool typbyval, char typalign,
2098                         int16 typlen, char typstorage)
2099 {
2100         Size            data_length;
2101
2102         if (typbyval)
2103         {
2104                 /* pass-by-value */
2105                 ptr = (char *) att_align_nominal(ptr, typalign);
2106                 store_att_byval(ptr, datum, typlen);
2107                 data_length = typlen;
2108         }
2109         else if (typlen == -1)
2110         {
2111                 /* varlena */
2112                 Pointer         val = DatumGetPointer(datum);
2113
2114                 if (VARATT_IS_EXTERNAL(val))
2115                 {
2116                         /* no alignment, since it's short by definition */
2117                         data_length = VARSIZE_EXTERNAL(val);
2118                         memcpy(ptr, val, data_length);
2119                 }
2120                 else if (VARATT_IS_SHORT(val))
2121                 {
2122                         /* no alignment for short varlenas */
2123                         data_length = VARSIZE_SHORT(val);
2124                         memcpy(ptr, val, data_length);
2125                 }
2126                 else if (TYPE_IS_PACKABLE(typlen, typstorage) &&
2127                                  VARATT_CAN_MAKE_SHORT(val))
2128                 {
2129                         /* convert to short varlena -- no alignment */
2130                         data_length = VARATT_CONVERTED_SHORT_SIZE(val);
2131                         SET_VARSIZE_SHORT(ptr, data_length);
2132                         memcpy(ptr + 1, VARDATA(val), data_length - 1);
2133                 }
2134                 else
2135                 {
2136                         /* full 4-byte header varlena */
2137                         ptr = (char *) att_align_nominal(ptr, typalign);
2138                         data_length = VARSIZE(val);
2139                         memcpy(ptr, val, data_length);
2140                 }
2141         }
2142         else if (typlen == -2)
2143         {
2144                 /* cstring ... never needs alignment */
2145                 Assert(typalign == 'c');
2146                 data_length = strlen(DatumGetCString(datum)) + 1;
2147                 memcpy(ptr, DatumGetPointer(datum), data_length);
2148         }
2149         else
2150         {
2151                 /* fixed-length pass-by-reference */
2152                 ptr = (char *) att_align_nominal(ptr, typalign);
2153                 Assert(typlen > 0);
2154                 data_length = typlen;
2155                 memcpy(ptr, DatumGetPointer(datum), data_length);
2156         }
2157
2158         ptr += data_length;
2159
2160         return ptr;
2161 }