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