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