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