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