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-2019, 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 "access/tupmacs.h"
34 #include "lib/stringinfo.h"
35 #include "libpq/pqformat.h"
36 #include "miscadmin.h"
37 #include "utils/builtins.h"
38 #include "utils/date.h"
39 #include "utils/hashutils.h"
40 #include "utils/int8.h"
41 #include "utils/lsyscache.h"
42 #include "utils/rangetypes.h"
43 #include "utils/timestamp.h"
44 
45 
46 #define RANGE_EMPTY_LITERAL "empty"
47 
48 /* fn_extra cache entry for one of the range I/O functions */
49 typedef struct RangeIOData
50 {
51 	TypeCacheEntry *typcache;	/* range type's typcache entry */
52 	Oid			typiofunc;		/* element type's I/O function */
53 	Oid			typioparam;		/* element type's I/O parameter */
54 	FmgrInfo	proc;			/* lookup result for typiofunc */
55 } RangeIOData;
56 
57 
58 static RangeIOData *get_range_io_data(FunctionCallInfo fcinfo, Oid rngtypid,
59 									  IOFuncSelector func);
60 static char range_parse_flags(const char *flags_str);
61 static void range_parse(const char *input_str, char *flags, char **lbound_str,
62 						char **ubound_str);
63 static const char *range_parse_bound(const char *string, const char *ptr,
64 									 char **bound_str, bool *infinite);
65 static char *range_deparse(char flags, const char *lbound_str,
66 						   const char *ubound_str);
67 static char *range_bound_escape(const char *value);
68 static Size datum_compute_size(Size sz, Datum datum, bool typbyval,
69 							   char typalign, int16 typlen, char typstorage);
70 static Pointer datum_write(Pointer ptr, Datum datum, bool typbyval,
71 						   char typalign, int16 typlen, char typstorage);
72 
73 
74 /*
75  *----------------------------------------------------------
76  * I/O FUNCTIONS
77  *----------------------------------------------------------
78  */
79 
80 Datum
range_in(PG_FUNCTION_ARGS)81 range_in(PG_FUNCTION_ARGS)
82 {
83 	char	   *input_str = PG_GETARG_CSTRING(0);
84 	Oid			rngtypoid = PG_GETARG_OID(1);
85 	Oid			typmod = PG_GETARG_INT32(2);
86 	RangeType  *range;
87 	RangeIOData *cache;
88 	char		flags;
89 	char	   *lbound_str;
90 	char	   *ubound_str;
91 	RangeBound	lower;
92 	RangeBound	upper;
93 
94 	check_stack_depth();		/* recurses when subtype is a range type */
95 
96 	cache = get_range_io_data(fcinfo, rngtypoid, IOFunc_input);
97 
98 	/* parse */
99 	range_parse(input_str, &flags, &lbound_str, &ubound_str);
100 
101 	/* call element type's input function */
102 	if (RANGE_HAS_LBOUND(flags))
103 		lower.val = InputFunctionCall(&cache->proc, lbound_str,
104 									  cache->typioparam, typmod);
105 	if (RANGE_HAS_UBOUND(flags))
106 		upper.val = InputFunctionCall(&cache->proc, ubound_str,
107 									  cache->typioparam, typmod);
108 
109 	lower.infinite = (flags & RANGE_LB_INF) != 0;
110 	lower.inclusive = (flags & RANGE_LB_INC) != 0;
111 	lower.lower = true;
112 	upper.infinite = (flags & RANGE_UB_INF) != 0;
113 	upper.inclusive = (flags & RANGE_UB_INC) != 0;
114 	upper.lower = false;
115 
116 	/* serialize and canonicalize */
117 	range = make_range(cache->typcache, &lower, &upper, flags & RANGE_EMPTY);
118 
119 	PG_RETURN_RANGE_P(range);
120 }
121 
122 Datum
range_out(PG_FUNCTION_ARGS)123 range_out(PG_FUNCTION_ARGS)
124 {
125 	RangeType  *range = PG_GETARG_RANGE_P(0);
126 	char	   *output_str;
127 	RangeIOData *cache;
128 	char		flags;
129 	char	   *lbound_str = NULL;
130 	char	   *ubound_str = NULL;
131 	RangeBound	lower;
132 	RangeBound	upper;
133 	bool		empty;
134 
135 	check_stack_depth();		/* recurses when subtype is a range type */
136 
137 	cache = get_range_io_data(fcinfo, RangeTypeGetOid(range), IOFunc_output);
138 
139 	/* deserialize */
140 	range_deserialize(cache->typcache, range, &lower, &upper, &empty);
141 	flags = range_get_flags(range);
142 
143 	/* call element type's output function */
144 	if (RANGE_HAS_LBOUND(flags))
145 		lbound_str = OutputFunctionCall(&cache->proc, lower.val);
146 	if (RANGE_HAS_UBOUND(flags))
147 		ubound_str = OutputFunctionCall(&cache->proc, upper.val);
148 
149 	/* construct result string */
150 	output_str = range_deparse(flags, lbound_str, ubound_str);
151 
152 	PG_RETURN_CSTRING(output_str);
153 }
154 
155 /*
156  * Binary representation: The first byte is the flags, then the lower bound
157  * (if present), then the upper bound (if present).  Each bound is represented
158  * by a 4-byte length header and the binary representation of that bound (as
159  * returned by a call to the send function for the subtype).
160  */
161 
162 Datum
range_recv(PG_FUNCTION_ARGS)163 range_recv(PG_FUNCTION_ARGS)
164 {
165 	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);
166 	Oid			rngtypoid = PG_GETARG_OID(1);
167 	int32		typmod = PG_GETARG_INT32(2);
168 	RangeType  *range;
169 	RangeIOData *cache;
170 	char		flags;
171 	RangeBound	lower;
172 	RangeBound	upper;
173 
174 	check_stack_depth();		/* recurses when subtype is a range type */
175 
176 	cache = get_range_io_data(fcinfo, rngtypoid, IOFunc_receive);
177 
178 	/* receive the flags... */
179 	flags = (unsigned char) pq_getmsgbyte(buf);
180 
181 	/*
182 	 * Mask out any unsupported flags, particularly RANGE_xB_NULL which would
183 	 * confuse following tests.  Note that range_serialize will take care of
184 	 * cleaning up any inconsistencies in the remaining flags.
185 	 */
186 	flags &= (RANGE_EMPTY |
187 			  RANGE_LB_INC |
188 			  RANGE_LB_INF |
189 			  RANGE_UB_INC |
190 			  RANGE_UB_INF);
191 
192 	/* receive the bounds ... */
193 	if (RANGE_HAS_LBOUND(flags))
194 	{
195 		uint32		bound_len = pq_getmsgint(buf, 4);
196 		const char *bound_data = pq_getmsgbytes(buf, bound_len);
197 		StringInfoData bound_buf;
198 
199 		initStringInfo(&bound_buf);
200 		appendBinaryStringInfo(&bound_buf, bound_data, bound_len);
201 
202 		lower.val = ReceiveFunctionCall(&cache->proc,
203 										&bound_buf,
204 										cache->typioparam,
205 										typmod);
206 		pfree(bound_buf.data);
207 	}
208 	else
209 		lower.val = (Datum) 0;
210 
211 	if (RANGE_HAS_UBOUND(flags))
212 	{
213 		uint32		bound_len = pq_getmsgint(buf, 4);
214 		const char *bound_data = pq_getmsgbytes(buf, bound_len);
215 		StringInfoData bound_buf;
216 
217 		initStringInfo(&bound_buf);
218 		appendBinaryStringInfo(&bound_buf, bound_data, bound_len);
219 
220 		upper.val = ReceiveFunctionCall(&cache->proc,
221 										&bound_buf,
222 										cache->typioparam,
223 										typmod);
224 		pfree(bound_buf.data);
225 	}
226 	else
227 		upper.val = (Datum) 0;
228 
229 	pq_getmsgend(buf);
230 
231 	/* finish constructing RangeBound representation */
232 	lower.infinite = (flags & RANGE_LB_INF) != 0;
233 	lower.inclusive = (flags & RANGE_LB_INC) != 0;
234 	lower.lower = true;
235 	upper.infinite = (flags & RANGE_UB_INF) != 0;
236 	upper.inclusive = (flags & RANGE_UB_INC) != 0;
237 	upper.lower = false;
238 
239 	/* serialize and canonicalize */
240 	range = make_range(cache->typcache, &lower, &upper, flags & RANGE_EMPTY);
241 
242 	PG_RETURN_RANGE_P(range);
243 }
244 
245 Datum
range_send(PG_FUNCTION_ARGS)246 range_send(PG_FUNCTION_ARGS)
247 {
248 	RangeType  *range = PG_GETARG_RANGE_P(0);
249 	StringInfo	buf = makeStringInfo();
250 	RangeIOData *cache;
251 	char		flags;
252 	RangeBound	lower;
253 	RangeBound	upper;
254 	bool		empty;
255 
256 	check_stack_depth();		/* recurses when subtype is a range type */
257 
258 	cache = get_range_io_data(fcinfo, RangeTypeGetOid(range), IOFunc_send);
259 
260 	/* deserialize */
261 	range_deserialize(cache->typcache, range, &lower, &upper, &empty);
262 	flags = range_get_flags(range);
263 
264 	/* construct output */
265 	pq_begintypsend(buf);
266 
267 	pq_sendbyte(buf, flags);
268 
269 	if (RANGE_HAS_LBOUND(flags))
270 	{
271 		Datum		bound = PointerGetDatum(SendFunctionCall(&cache->proc,
272 															 lower.val));
273 		uint32		bound_len = VARSIZE(bound) - VARHDRSZ;
274 		char	   *bound_data = VARDATA(bound);
275 
276 		pq_sendint32(buf, bound_len);
277 		pq_sendbytes(buf, bound_data, bound_len);
278 	}
279 
280 	if (RANGE_HAS_UBOUND(flags))
281 	{
282 		Datum		bound = PointerGetDatum(SendFunctionCall(&cache->proc,
283 															 upper.val));
284 		uint32		bound_len = VARSIZE(bound) - VARHDRSZ;
285 		char	   *bound_data = VARDATA(bound);
286 
287 		pq_sendint32(buf, bound_len);
288 		pq_sendbytes(buf, bound_data, bound_len);
289 	}
290 
291 	PG_RETURN_BYTEA_P(pq_endtypsend(buf));
292 }
293 
294 /*
295  * get_range_io_data: get cached information needed for range type I/O
296  *
297  * The range I/O functions need a bit more cached info than other range
298  * functions, so they store a RangeIOData struct in fn_extra, not just a
299  * pointer to a type cache entry.
300  */
301 static RangeIOData *
get_range_io_data(FunctionCallInfo fcinfo,Oid rngtypid,IOFuncSelector func)302 get_range_io_data(FunctionCallInfo fcinfo, Oid rngtypid, IOFuncSelector func)
303 {
304 	RangeIOData *cache = (RangeIOData *) fcinfo->flinfo->fn_extra;
305 
306 	if (cache == NULL || cache->typcache->type_id != rngtypid)
307 	{
308 		int16		typlen;
309 		bool		typbyval;
310 		char		typalign;
311 		char		typdelim;
312 
313 		cache = (RangeIOData *) MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
314 												   sizeof(RangeIOData));
315 		cache->typcache = lookup_type_cache(rngtypid, TYPECACHE_RANGE_INFO);
316 		if (cache->typcache->rngelemtype == NULL)
317 			elog(ERROR, "type %u is not a range type", rngtypid);
318 
319 		/* get_type_io_data does more than we need, but is convenient */
320 		get_type_io_data(cache->typcache->rngelemtype->type_id,
321 						 func,
322 						 &typlen,
323 						 &typbyval,
324 						 &typalign,
325 						 &typdelim,
326 						 &cache->typioparam,
327 						 &cache->typiofunc);
328 
329 		if (!OidIsValid(cache->typiofunc))
330 		{
331 			/* this could only happen for receive or send */
332 			if (func == IOFunc_receive)
333 				ereport(ERROR,
334 						(errcode(ERRCODE_UNDEFINED_FUNCTION),
335 						 errmsg("no binary input function available for type %s",
336 								format_type_be(cache->typcache->rngelemtype->type_id))));
337 			else
338 				ereport(ERROR,
339 						(errcode(ERRCODE_UNDEFINED_FUNCTION),
340 						 errmsg("no binary output function available for type %s",
341 								format_type_be(cache->typcache->rngelemtype->type_id))));
342 		}
343 		fmgr_info_cxt(cache->typiofunc, &cache->proc,
344 					  fcinfo->flinfo->fn_mcxt);
345 
346 		fcinfo->flinfo->fn_extra = (void *) cache;
347 	}
348 
349 	return cache;
350 }
351 
352 
353 /*
354  *----------------------------------------------------------
355  * GENERIC FUNCTIONS
356  *----------------------------------------------------------
357  */
358 
359 /* Construct standard-form range value from two arguments */
360 Datum
range_constructor2(PG_FUNCTION_ARGS)361 range_constructor2(PG_FUNCTION_ARGS)
362 {
363 	Datum		arg1 = PG_GETARG_DATUM(0);
364 	Datum		arg2 = PG_GETARG_DATUM(1);
365 	Oid			rngtypid = get_fn_expr_rettype(fcinfo->flinfo);
366 	RangeType  *range;
367 	TypeCacheEntry *typcache;
368 	RangeBound	lower;
369 	RangeBound	upper;
370 
371 	typcache = range_get_typcache(fcinfo, rngtypid);
372 
373 	lower.val = PG_ARGISNULL(0) ? (Datum) 0 : arg1;
374 	lower.infinite = PG_ARGISNULL(0);
375 	lower.inclusive = true;
376 	lower.lower = true;
377 
378 	upper.val = PG_ARGISNULL(1) ? (Datum) 0 : arg2;
379 	upper.infinite = PG_ARGISNULL(1);
380 	upper.inclusive = false;
381 	upper.lower = false;
382 
383 	range = make_range(typcache, &lower, &upper, false);
384 
385 	PG_RETURN_RANGE_P(range);
386 }
387 
388 /* Construct general range value from three arguments */
389 Datum
range_constructor3(PG_FUNCTION_ARGS)390 range_constructor3(PG_FUNCTION_ARGS)
391 {
392 	Datum		arg1 = PG_GETARG_DATUM(0);
393 	Datum		arg2 = PG_GETARG_DATUM(1);
394 	Oid			rngtypid = get_fn_expr_rettype(fcinfo->flinfo);
395 	RangeType  *range;
396 	TypeCacheEntry *typcache;
397 	RangeBound	lower;
398 	RangeBound	upper;
399 	char		flags;
400 
401 	typcache = range_get_typcache(fcinfo, rngtypid);
402 
403 	if (PG_ARGISNULL(2))
404 		ereport(ERROR,
405 				(errcode(ERRCODE_DATA_EXCEPTION),
406 				 errmsg("range constructor flags argument must not be null")));
407 
408 	flags = range_parse_flags(text_to_cstring(PG_GETARG_TEXT_PP(2)));
409 
410 	lower.val = PG_ARGISNULL(0) ? (Datum) 0 : arg1;
411 	lower.infinite = PG_ARGISNULL(0);
412 	lower.inclusive = (flags & RANGE_LB_INC) != 0;
413 	lower.lower = true;
414 
415 	upper.val = PG_ARGISNULL(1) ? (Datum) 0 : arg2;
416 	upper.infinite = PG_ARGISNULL(1);
417 	upper.inclusive = (flags & RANGE_UB_INC) != 0;
418 	upper.lower = false;
419 
420 	range = make_range(typcache, &lower, &upper, false);
421 
422 	PG_RETURN_RANGE_P(range);
423 }
424 
425 
426 /* range -> subtype functions */
427 
428 /* extract lower bound value */
429 Datum
range_lower(PG_FUNCTION_ARGS)430 range_lower(PG_FUNCTION_ARGS)
431 {
432 	RangeType  *r1 = PG_GETARG_RANGE_P(0);
433 	TypeCacheEntry *typcache;
434 	RangeBound	lower;
435 	RangeBound	upper;
436 	bool		empty;
437 
438 	typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
439 
440 	range_deserialize(typcache, r1, &lower, &upper, &empty);
441 
442 	/* Return NULL if there's no finite lower bound */
443 	if (empty || lower.infinite)
444 		PG_RETURN_NULL();
445 
446 	PG_RETURN_DATUM(lower.val);
447 }
448 
449 /* extract upper bound value */
450 Datum
range_upper(PG_FUNCTION_ARGS)451 range_upper(PG_FUNCTION_ARGS)
452 {
453 	RangeType  *r1 = PG_GETARG_RANGE_P(0);
454 	TypeCacheEntry *typcache;
455 	RangeBound	lower;
456 	RangeBound	upper;
457 	bool		empty;
458 
459 	typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
460 
461 	range_deserialize(typcache, r1, &lower, &upper, &empty);
462 
463 	/* Return NULL if there's no finite upper bound */
464 	if (empty || upper.infinite)
465 		PG_RETURN_NULL();
466 
467 	PG_RETURN_DATUM(upper.val);
468 }
469 
470 
471 /* range -> bool functions */
472 
473 /* is range empty? */
474 Datum
range_empty(PG_FUNCTION_ARGS)475 range_empty(PG_FUNCTION_ARGS)
476 {
477 	RangeType  *r1 = PG_GETARG_RANGE_P(0);
478 	char		flags = range_get_flags(r1);
479 
480 	PG_RETURN_BOOL(flags & RANGE_EMPTY);
481 }
482 
483 /* is lower bound inclusive? */
484 Datum
range_lower_inc(PG_FUNCTION_ARGS)485 range_lower_inc(PG_FUNCTION_ARGS)
486 {
487 	RangeType  *r1 = PG_GETARG_RANGE_P(0);
488 	char		flags = range_get_flags(r1);
489 
490 	PG_RETURN_BOOL(flags & RANGE_LB_INC);
491 }
492 
493 /* is upper bound inclusive? */
494 Datum
range_upper_inc(PG_FUNCTION_ARGS)495 range_upper_inc(PG_FUNCTION_ARGS)
496 {
497 	RangeType  *r1 = PG_GETARG_RANGE_P(0);
498 	char		flags = range_get_flags(r1);
499 
500 	PG_RETURN_BOOL(flags & RANGE_UB_INC);
501 }
502 
503 /* is lower bound infinite? */
504 Datum
range_lower_inf(PG_FUNCTION_ARGS)505 range_lower_inf(PG_FUNCTION_ARGS)
506 {
507 	RangeType  *r1 = PG_GETARG_RANGE_P(0);
508 	char		flags = range_get_flags(r1);
509 
510 	PG_RETURN_BOOL(flags & RANGE_LB_INF);
511 }
512 
513 /* is upper bound infinite? */
514 Datum
range_upper_inf(PG_FUNCTION_ARGS)515 range_upper_inf(PG_FUNCTION_ARGS)
516 {
517 	RangeType  *r1 = PG_GETARG_RANGE_P(0);
518 	char		flags = range_get_flags(r1);
519 
520 	PG_RETURN_BOOL(flags & RANGE_UB_INF);
521 }
522 
523 
524 /* range, element -> bool functions */
525 
526 /* contains? */
527 Datum
range_contains_elem(PG_FUNCTION_ARGS)528 range_contains_elem(PG_FUNCTION_ARGS)
529 {
530 	RangeType  *r = PG_GETARG_RANGE_P(0);
531 	Datum		val = PG_GETARG_DATUM(1);
532 	TypeCacheEntry *typcache;
533 
534 	typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
535 
536 	PG_RETURN_BOOL(range_contains_elem_internal(typcache, r, val));
537 }
538 
539 /* contained by? */
540 Datum
elem_contained_by_range(PG_FUNCTION_ARGS)541 elem_contained_by_range(PG_FUNCTION_ARGS)
542 {
543 	Datum		val = PG_GETARG_DATUM(0);
544 	RangeType  *r = PG_GETARG_RANGE_P(1);
545 	TypeCacheEntry *typcache;
546 
547 	typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
548 
549 	PG_RETURN_BOOL(range_contains_elem_internal(typcache, r, val));
550 }
551 
552 
553 /* range, range -> bool functions */
554 
555 /* equality (internal version) */
556 bool
range_eq_internal(TypeCacheEntry * typcache,RangeType * r1,RangeType * r2)557 range_eq_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
558 {
559 	RangeBound	lower1,
560 				lower2;
561 	RangeBound	upper1,
562 				upper2;
563 	bool		empty1,
564 				empty2;
565 
566 	/* Different types should be prevented by ANYRANGE matching rules */
567 	if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
568 		elog(ERROR, "range types do not match");
569 
570 	range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
571 	range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
572 
573 	if (empty1 && empty2)
574 		return true;
575 	if (empty1 != empty2)
576 		return false;
577 
578 	if (range_cmp_bounds(typcache, &lower1, &lower2) != 0)
579 		return false;
580 
581 	if (range_cmp_bounds(typcache, &upper1, &upper2) != 0)
582 		return false;
583 
584 	return true;
585 }
586 
587 /* equality */
588 Datum
range_eq(PG_FUNCTION_ARGS)589 range_eq(PG_FUNCTION_ARGS)
590 {
591 	RangeType  *r1 = PG_GETARG_RANGE_P(0);
592 	RangeType  *r2 = PG_GETARG_RANGE_P(1);
593 	TypeCacheEntry *typcache;
594 
595 	typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
596 
597 	PG_RETURN_BOOL(range_eq_internal(typcache, r1, r2));
598 }
599 
600 /* inequality (internal version) */
601 bool
range_ne_internal(TypeCacheEntry * typcache,RangeType * r1,RangeType * r2)602 range_ne_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
603 {
604 	return (!range_eq_internal(typcache, r1, r2));
605 }
606 
607 /* inequality */
608 Datum
range_ne(PG_FUNCTION_ARGS)609 range_ne(PG_FUNCTION_ARGS)
610 {
611 	RangeType  *r1 = PG_GETARG_RANGE_P(0);
612 	RangeType  *r2 = PG_GETARG_RANGE_P(1);
613 	TypeCacheEntry *typcache;
614 
615 	typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
616 
617 	PG_RETURN_BOOL(range_ne_internal(typcache, r1, r2));
618 }
619 
620 /* contains? */
621 Datum
range_contains(PG_FUNCTION_ARGS)622 range_contains(PG_FUNCTION_ARGS)
623 {
624 	RangeType  *r1 = PG_GETARG_RANGE_P(0);
625 	RangeType  *r2 = PG_GETARG_RANGE_P(1);
626 	TypeCacheEntry *typcache;
627 
628 	typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
629 
630 	PG_RETURN_BOOL(range_contains_internal(typcache, r1, r2));
631 }
632 
633 /* contained by? */
634 Datum
range_contained_by(PG_FUNCTION_ARGS)635 range_contained_by(PG_FUNCTION_ARGS)
636 {
637 	RangeType  *r1 = PG_GETARG_RANGE_P(0);
638 	RangeType  *r2 = PG_GETARG_RANGE_P(1);
639 	TypeCacheEntry *typcache;
640 
641 	typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
642 
643 	PG_RETURN_BOOL(range_contained_by_internal(typcache, r1, r2));
644 }
645 
646 /* strictly left of? (internal version) */
647 bool
range_before_internal(TypeCacheEntry * typcache,RangeType * r1,RangeType * r2)648 range_before_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
649 {
650 	RangeBound	lower1,
651 				lower2;
652 	RangeBound	upper1,
653 				upper2;
654 	bool		empty1,
655 				empty2;
656 
657 	/* Different types should be prevented by ANYRANGE matching rules */
658 	if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
659 		elog(ERROR, "range types do not match");
660 
661 	range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
662 	range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
663 
664 	/* An empty range is neither before nor after any other range */
665 	if (empty1 || empty2)
666 		return false;
667 
668 	return (range_cmp_bounds(typcache, &upper1, &lower2) < 0);
669 }
670 
671 /* strictly left of? */
672 Datum
range_before(PG_FUNCTION_ARGS)673 range_before(PG_FUNCTION_ARGS)
674 {
675 	RangeType  *r1 = PG_GETARG_RANGE_P(0);
676 	RangeType  *r2 = PG_GETARG_RANGE_P(1);
677 	TypeCacheEntry *typcache;
678 
679 	typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
680 
681 	PG_RETURN_BOOL(range_before_internal(typcache, r1, r2));
682 }
683 
684 /* strictly right of? (internal version) */
685 bool
range_after_internal(TypeCacheEntry * typcache,RangeType * r1,RangeType * r2)686 range_after_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
687 {
688 	RangeBound	lower1,
689 				lower2;
690 	RangeBound	upper1,
691 				upper2;
692 	bool		empty1,
693 				empty2;
694 
695 	/* Different types should be prevented by ANYRANGE matching rules */
696 	if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
697 		elog(ERROR, "range types do not match");
698 
699 	range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
700 	range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
701 
702 	/* An empty range is neither before nor after any other range */
703 	if (empty1 || empty2)
704 		return false;
705 
706 	return (range_cmp_bounds(typcache, &lower1, &upper2) > 0);
707 }
708 
709 /* strictly right of? */
710 Datum
range_after(PG_FUNCTION_ARGS)711 range_after(PG_FUNCTION_ARGS)
712 {
713 	RangeType  *r1 = PG_GETARG_RANGE_P(0);
714 	RangeType  *r2 = PG_GETARG_RANGE_P(1);
715 	TypeCacheEntry *typcache;
716 
717 	typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
718 
719 	PG_RETURN_BOOL(range_after_internal(typcache, r1, r2));
720 }
721 
722 /*
723  * Check if two bounds A and B are "adjacent", where A is an upper bound and B
724  * is a lower bound. For the bounds to be adjacent, each subtype value must
725  * satisfy strictly one of the bounds: there are no values which satisfy both
726  * bounds (i.e. less than A and greater than B); and there are no values which
727  * satisfy neither bound (i.e. greater than A and less than B).
728  *
729  * For discrete ranges, we rely on the canonicalization function to see if A..B
730  * normalizes to empty. (If there is no canonicalization function, it's
731  * impossible for such a range to normalize to empty, so we needn't bother to
732  * try.)
733  *
734  * If A == B, the ranges are adjacent only if the bounds have different
735  * inclusive flags (i.e., exactly one of the ranges includes the common
736  * boundary point).
737  *
738  * And if A > B then the ranges are not adjacent in this order.
739  */
740 bool
bounds_adjacent(TypeCacheEntry * typcache,RangeBound boundA,RangeBound boundB)741 bounds_adjacent(TypeCacheEntry *typcache, RangeBound boundA, RangeBound boundB)
742 {
743 	int			cmp;
744 
745 	Assert(!boundA.lower && boundB.lower);
746 
747 	cmp = range_cmp_bound_values(typcache, &boundA, &boundB);
748 	if (cmp < 0)
749 	{
750 		RangeType  *r;
751 
752 		/*
753 		 * Bounds do not overlap; see if there are points in between.
754 		 */
755 
756 		/* in a continuous subtype, there are assumed to be points between */
757 		if (!OidIsValid(typcache->rng_canonical_finfo.fn_oid))
758 			return false;
759 
760 		/*
761 		 * The bounds are of a discrete range type; so make a range A..B and
762 		 * see if it's empty.
763 		 */
764 
765 		/* flip the inclusion flags */
766 		boundA.inclusive = !boundA.inclusive;
767 		boundB.inclusive = !boundB.inclusive;
768 		/* change upper/lower labels to avoid Assert failures */
769 		boundA.lower = true;
770 		boundB.lower = false;
771 		r = make_range(typcache, &boundA, &boundB, false);
772 		return RangeIsEmpty(r);
773 	}
774 	else if (cmp == 0)
775 		return boundA.inclusive != boundB.inclusive;
776 	else
777 		return false;			/* bounds overlap */
778 }
779 
780 /* adjacent to (but not overlapping)? (internal version) */
781 bool
range_adjacent_internal(TypeCacheEntry * typcache,RangeType * r1,RangeType * r2)782 range_adjacent_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
783 {
784 	RangeBound	lower1,
785 				lower2;
786 	RangeBound	upper1,
787 				upper2;
788 	bool		empty1,
789 				empty2;
790 
791 	/* Different types should be prevented by ANYRANGE matching rules */
792 	if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
793 		elog(ERROR, "range types do not match");
794 
795 	range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
796 	range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
797 
798 	/* An empty range is not adjacent to any other range */
799 	if (empty1 || empty2)
800 		return false;
801 
802 	/*
803 	 * Given two ranges A..B and C..D, the ranges are adjacent if and only if
804 	 * B is adjacent to C, or D is adjacent to A.
805 	 */
806 	return (bounds_adjacent(typcache, upper1, lower2) ||
807 			bounds_adjacent(typcache, upper2, lower1));
808 }
809 
810 /* adjacent to (but not overlapping)? */
811 Datum
range_adjacent(PG_FUNCTION_ARGS)812 range_adjacent(PG_FUNCTION_ARGS)
813 {
814 	RangeType  *r1 = PG_GETARG_RANGE_P(0);
815 	RangeType  *r2 = PG_GETARG_RANGE_P(1);
816 	TypeCacheEntry *typcache;
817 
818 	typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
819 
820 	PG_RETURN_BOOL(range_adjacent_internal(typcache, r1, r2));
821 }
822 
823 /* overlaps? (internal version) */
824 bool
range_overlaps_internal(TypeCacheEntry * typcache,RangeType * r1,RangeType * r2)825 range_overlaps_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
826 {
827 	RangeBound	lower1,
828 				lower2;
829 	RangeBound	upper1,
830 				upper2;
831 	bool		empty1,
832 				empty2;
833 
834 	/* Different types should be prevented by ANYRANGE matching rules */
835 	if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
836 		elog(ERROR, "range types do not match");
837 
838 	range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
839 	range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
840 
841 	/* An empty range does not overlap any other range */
842 	if (empty1 || empty2)
843 		return false;
844 
845 	if (range_cmp_bounds(typcache, &lower1, &lower2) >= 0 &&
846 		range_cmp_bounds(typcache, &lower1, &upper2) <= 0)
847 		return true;
848 
849 	if (range_cmp_bounds(typcache, &lower2, &lower1) >= 0 &&
850 		range_cmp_bounds(typcache, &lower2, &upper1) <= 0)
851 		return true;
852 
853 	return false;
854 }
855 
856 /* overlaps? */
857 Datum
range_overlaps(PG_FUNCTION_ARGS)858 range_overlaps(PG_FUNCTION_ARGS)
859 {
860 	RangeType  *r1 = PG_GETARG_RANGE_P(0);
861 	RangeType  *r2 = PG_GETARG_RANGE_P(1);
862 	TypeCacheEntry *typcache;
863 
864 	typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
865 
866 	PG_RETURN_BOOL(range_overlaps_internal(typcache, r1, r2));
867 }
868 
869 /* does not extend to right of? (internal version) */
870 bool
range_overleft_internal(TypeCacheEntry * typcache,RangeType * r1,RangeType * r2)871 range_overleft_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
872 {
873 	RangeBound	lower1,
874 				lower2;
875 	RangeBound	upper1,
876 				upper2;
877 	bool		empty1,
878 				empty2;
879 
880 	/* Different types should be prevented by ANYRANGE matching rules */
881 	if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
882 		elog(ERROR, "range types do not match");
883 
884 	range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
885 	range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
886 
887 	/* An empty range is neither before nor after any other range */
888 	if (empty1 || empty2)
889 		return false;
890 
891 	if (range_cmp_bounds(typcache, &upper1, &upper2) <= 0)
892 		return true;
893 
894 	return false;
895 }
896 
897 /* does not extend to right of? */
898 Datum
range_overleft(PG_FUNCTION_ARGS)899 range_overleft(PG_FUNCTION_ARGS)
900 {
901 	RangeType  *r1 = PG_GETARG_RANGE_P(0);
902 	RangeType  *r2 = PG_GETARG_RANGE_P(1);
903 	TypeCacheEntry *typcache;
904 
905 	typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
906 
907 	PG_RETURN_BOOL(range_overleft_internal(typcache, r1, r2));
908 }
909 
910 /* does not extend to left of? (internal version) */
911 bool
range_overright_internal(TypeCacheEntry * typcache,RangeType * r1,RangeType * r2)912 range_overright_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
913 {
914 	RangeBound	lower1,
915 				lower2;
916 	RangeBound	upper1,
917 				upper2;
918 	bool		empty1,
919 				empty2;
920 
921 	/* Different types should be prevented by ANYRANGE matching rules */
922 	if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
923 		elog(ERROR, "range types do not match");
924 
925 	range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
926 	range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
927 
928 	/* An empty range is neither before nor after any other range */
929 	if (empty1 || empty2)
930 		return false;
931 
932 	if (range_cmp_bounds(typcache, &lower1, &lower2) >= 0)
933 		return true;
934 
935 	return false;
936 }
937 
938 /* does not extend to left of? */
939 Datum
range_overright(PG_FUNCTION_ARGS)940 range_overright(PG_FUNCTION_ARGS)
941 {
942 	RangeType  *r1 = PG_GETARG_RANGE_P(0);
943 	RangeType  *r2 = PG_GETARG_RANGE_P(1);
944 	TypeCacheEntry *typcache;
945 
946 	typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
947 
948 	PG_RETURN_BOOL(range_overright_internal(typcache, r1, r2));
949 }
950 
951 
952 /* range, range -> range functions */
953 
954 /* set difference */
955 Datum
range_minus(PG_FUNCTION_ARGS)956 range_minus(PG_FUNCTION_ARGS)
957 {
958 	RangeType  *r1 = PG_GETARG_RANGE_P(0);
959 	RangeType  *r2 = PG_GETARG_RANGE_P(1);
960 	TypeCacheEntry *typcache;
961 	RangeBound	lower1,
962 				lower2;
963 	RangeBound	upper1,
964 				upper2;
965 	bool		empty1,
966 				empty2;
967 	int			cmp_l1l2,
968 				cmp_l1u2,
969 				cmp_u1l2,
970 				cmp_u1u2;
971 
972 	/* Different types should be prevented by ANYRANGE matching rules */
973 	if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
974 		elog(ERROR, "range types do not match");
975 
976 	typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
977 
978 	range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
979 	range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
980 
981 	/* if either is empty, r1 is the correct answer */
982 	if (empty1 || empty2)
983 		PG_RETURN_RANGE_P(r1);
984 
985 	cmp_l1l2 = range_cmp_bounds(typcache, &lower1, &lower2);
986 	cmp_l1u2 = range_cmp_bounds(typcache, &lower1, &upper2);
987 	cmp_u1l2 = range_cmp_bounds(typcache, &upper1, &lower2);
988 	cmp_u1u2 = range_cmp_bounds(typcache, &upper1, &upper2);
989 
990 	if (cmp_l1l2 < 0 && cmp_u1u2 > 0)
991 		ereport(ERROR,
992 				(errcode(ERRCODE_DATA_EXCEPTION),
993 				 errmsg("result of range difference would not be contiguous")));
994 
995 	if (cmp_l1u2 > 0 || cmp_u1l2 < 0)
996 		PG_RETURN_RANGE_P(r1);
997 
998 	if (cmp_l1l2 >= 0 && cmp_u1u2 <= 0)
999 		PG_RETURN_RANGE_P(make_empty_range(typcache));
1000 
1001 	if (cmp_l1l2 <= 0 && cmp_u1l2 >= 0 && cmp_u1u2 <= 0)
1002 	{
1003 		lower2.inclusive = !lower2.inclusive;
1004 		lower2.lower = false;	/* it will become the upper bound */
1005 		PG_RETURN_RANGE_P(make_range(typcache, &lower1, &lower2, false));
1006 	}
1007 
1008 	if (cmp_l1l2 >= 0 && cmp_u1u2 >= 0 && cmp_l1u2 <= 0)
1009 	{
1010 		upper2.inclusive = !upper2.inclusive;
1011 		upper2.lower = true;	/* it will become the lower bound */
1012 		PG_RETURN_RANGE_P(make_range(typcache, &upper2, &upper1, false));
1013 	}
1014 
1015 	elog(ERROR, "unexpected case in range_minus");
1016 	PG_RETURN_NULL();
1017 }
1018 
1019 /*
1020  * Set union.  If strict is true, it is an error that the two input ranges
1021  * are not adjacent or overlapping.
1022  */
1023 static RangeType *
range_union_internal(TypeCacheEntry * typcache,RangeType * r1,RangeType * r2,bool strict)1024 range_union_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2,
1025 					 bool strict)
1026 {
1027 	RangeBound	lower1,
1028 				lower2;
1029 	RangeBound	upper1,
1030 				upper2;
1031 	bool		empty1,
1032 				empty2;
1033 	RangeBound *result_lower;
1034 	RangeBound *result_upper;
1035 
1036 	/* Different types should be prevented by ANYRANGE matching rules */
1037 	if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
1038 		elog(ERROR, "range types do not match");
1039 
1040 	range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
1041 	range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
1042 
1043 	/* if either is empty, the other is the correct answer */
1044 	if (empty1)
1045 		return r2;
1046 	if (empty2)
1047 		return r1;
1048 
1049 	if (strict &&
1050 		!DatumGetBool(range_overlaps_internal(typcache, r1, r2)) &&
1051 		!DatumGetBool(range_adjacent_internal(typcache, r1, r2)))
1052 		ereport(ERROR,
1053 				(errcode(ERRCODE_DATA_EXCEPTION),
1054 				 errmsg("result of range union would not be contiguous")));
1055 
1056 	if (range_cmp_bounds(typcache, &lower1, &lower2) < 0)
1057 		result_lower = &lower1;
1058 	else
1059 		result_lower = &lower2;
1060 
1061 	if (range_cmp_bounds(typcache, &upper1, &upper2) > 0)
1062 		result_upper = &upper1;
1063 	else
1064 		result_upper = &upper2;
1065 
1066 	return make_range(typcache, result_lower, result_upper, false);
1067 }
1068 
1069 Datum
range_union(PG_FUNCTION_ARGS)1070 range_union(PG_FUNCTION_ARGS)
1071 {
1072 	RangeType  *r1 = PG_GETARG_RANGE_P(0);
1073 	RangeType  *r2 = PG_GETARG_RANGE_P(1);
1074 	TypeCacheEntry *typcache;
1075 
1076 	typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
1077 
1078 	PG_RETURN_RANGE_P(range_union_internal(typcache, r1, r2, true));
1079 }
1080 
1081 /*
1082  * range merge: like set union, except also allow and account for non-adjacent
1083  * input ranges.
1084  */
1085 Datum
range_merge(PG_FUNCTION_ARGS)1086 range_merge(PG_FUNCTION_ARGS)
1087 {
1088 	RangeType  *r1 = PG_GETARG_RANGE_P(0);
1089 	RangeType  *r2 = PG_GETARG_RANGE_P(1);
1090 	TypeCacheEntry *typcache;
1091 
1092 	typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
1093 
1094 	PG_RETURN_RANGE_P(range_union_internal(typcache, r1, r2, false));
1095 }
1096 
1097 /* set intersection */
1098 Datum
range_intersect(PG_FUNCTION_ARGS)1099 range_intersect(PG_FUNCTION_ARGS)
1100 {
1101 	RangeType  *r1 = PG_GETARG_RANGE_P(0);
1102 	RangeType  *r2 = PG_GETARG_RANGE_P(1);
1103 	TypeCacheEntry *typcache;
1104 	RangeBound	lower1,
1105 				lower2;
1106 	RangeBound	upper1,
1107 				upper2;
1108 	bool		empty1,
1109 				empty2;
1110 	RangeBound *result_lower;
1111 	RangeBound *result_upper;
1112 
1113 	/* Different types should be prevented by ANYRANGE matching rules */
1114 	if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
1115 		elog(ERROR, "range types do not match");
1116 
1117 	typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
1118 
1119 	range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
1120 	range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
1121 
1122 	if (empty1 || empty2 || !DatumGetBool(range_overlaps(fcinfo)))
1123 		PG_RETURN_RANGE_P(make_empty_range(typcache));
1124 
1125 	if (range_cmp_bounds(typcache, &lower1, &lower2) >= 0)
1126 		result_lower = &lower1;
1127 	else
1128 		result_lower = &lower2;
1129 
1130 	if (range_cmp_bounds(typcache, &upper1, &upper2) <= 0)
1131 		result_upper = &upper1;
1132 	else
1133 		result_upper = &upper2;
1134 
1135 	PG_RETURN_RANGE_P(make_range(typcache, result_lower, result_upper, false));
1136 }
1137 
1138 /* Btree support */
1139 
1140 /* btree comparator */
1141 Datum
range_cmp(PG_FUNCTION_ARGS)1142 range_cmp(PG_FUNCTION_ARGS)
1143 {
1144 	RangeType  *r1 = PG_GETARG_RANGE_P(0);
1145 	RangeType  *r2 = PG_GETARG_RANGE_P(1);
1146 	TypeCacheEntry *typcache;
1147 	RangeBound	lower1,
1148 				lower2;
1149 	RangeBound	upper1,
1150 				upper2;
1151 	bool		empty1,
1152 				empty2;
1153 	int			cmp;
1154 
1155 	check_stack_depth();		/* recurses when subtype is a range type */
1156 
1157 	/* Different types should be prevented by ANYRANGE matching rules */
1158 	if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
1159 		elog(ERROR, "range types do not match");
1160 
1161 	typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
1162 
1163 	range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
1164 	range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
1165 
1166 	/* For b-tree use, empty ranges sort before all else */
1167 	if (empty1 && empty2)
1168 		cmp = 0;
1169 	else if (empty1)
1170 		cmp = -1;
1171 	else if (empty2)
1172 		cmp = 1;
1173 	else
1174 	{
1175 		cmp = range_cmp_bounds(typcache, &lower1, &lower2);
1176 		if (cmp == 0)
1177 			cmp = range_cmp_bounds(typcache, &upper1, &upper2);
1178 	}
1179 
1180 	PG_FREE_IF_COPY(r1, 0);
1181 	PG_FREE_IF_COPY(r2, 1);
1182 
1183 	PG_RETURN_INT32(cmp);
1184 }
1185 
1186 /* inequality operators using the range_cmp function */
1187 Datum
range_lt(PG_FUNCTION_ARGS)1188 range_lt(PG_FUNCTION_ARGS)
1189 {
1190 	int			cmp = range_cmp(fcinfo);
1191 
1192 	PG_RETURN_BOOL(cmp < 0);
1193 }
1194 
1195 Datum
range_le(PG_FUNCTION_ARGS)1196 range_le(PG_FUNCTION_ARGS)
1197 {
1198 	int			cmp = range_cmp(fcinfo);
1199 
1200 	PG_RETURN_BOOL(cmp <= 0);
1201 }
1202 
1203 Datum
range_ge(PG_FUNCTION_ARGS)1204 range_ge(PG_FUNCTION_ARGS)
1205 {
1206 	int			cmp = range_cmp(fcinfo);
1207 
1208 	PG_RETURN_BOOL(cmp >= 0);
1209 }
1210 
1211 Datum
range_gt(PG_FUNCTION_ARGS)1212 range_gt(PG_FUNCTION_ARGS)
1213 {
1214 	int			cmp = range_cmp(fcinfo);
1215 
1216 	PG_RETURN_BOOL(cmp > 0);
1217 }
1218 
1219 /* Hash support */
1220 
1221 /* hash a range value */
1222 Datum
hash_range(PG_FUNCTION_ARGS)1223 hash_range(PG_FUNCTION_ARGS)
1224 {
1225 	RangeType  *r = PG_GETARG_RANGE_P(0);
1226 	uint32		result;
1227 	TypeCacheEntry *typcache;
1228 	TypeCacheEntry *scache;
1229 	RangeBound	lower;
1230 	RangeBound	upper;
1231 	bool		empty;
1232 	char		flags;
1233 	uint32		lower_hash;
1234 	uint32		upper_hash;
1235 
1236 	check_stack_depth();		/* recurses when subtype is a range type */
1237 
1238 	typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1239 
1240 	/* deserialize */
1241 	range_deserialize(typcache, r, &lower, &upper, &empty);
1242 	flags = range_get_flags(r);
1243 
1244 	/*
1245 	 * Look up the element type's hash function, if not done already.
1246 	 */
1247 	scache = typcache->rngelemtype;
1248 	if (!OidIsValid(scache->hash_proc_finfo.fn_oid))
1249 	{
1250 		scache = lookup_type_cache(scache->type_id, TYPECACHE_HASH_PROC_FINFO);
1251 		if (!OidIsValid(scache->hash_proc_finfo.fn_oid))
1252 			ereport(ERROR,
1253 					(errcode(ERRCODE_UNDEFINED_FUNCTION),
1254 					 errmsg("could not identify a hash function for type %s",
1255 							format_type_be(scache->type_id))));
1256 	}
1257 
1258 	/*
1259 	 * Apply the hash function to each bound.
1260 	 */
1261 	if (RANGE_HAS_LBOUND(flags))
1262 		lower_hash = DatumGetUInt32(FunctionCall1Coll(&scache->hash_proc_finfo,
1263 													  typcache->rng_collation,
1264 													  lower.val));
1265 	else
1266 		lower_hash = 0;
1267 
1268 	if (RANGE_HAS_UBOUND(flags))
1269 		upper_hash = DatumGetUInt32(FunctionCall1Coll(&scache->hash_proc_finfo,
1270 													  typcache->rng_collation,
1271 													  upper.val));
1272 	else
1273 		upper_hash = 0;
1274 
1275 	/* Merge hashes of flags and bounds */
1276 	result = hash_uint32((uint32) flags);
1277 	result ^= lower_hash;
1278 	result = (result << 1) | (result >> 31);
1279 	result ^= upper_hash;
1280 
1281 	PG_RETURN_INT32(result);
1282 }
1283 
1284 /*
1285  * Returns 64-bit value by hashing a value to a 64-bit value, with a seed.
1286  * Otherwise, similar to hash_range.
1287  */
1288 Datum
hash_range_extended(PG_FUNCTION_ARGS)1289 hash_range_extended(PG_FUNCTION_ARGS)
1290 {
1291 	RangeType  *r = PG_GETARG_RANGE_P(0);
1292 	Datum		seed = PG_GETARG_DATUM(1);
1293 	uint64		result;
1294 	TypeCacheEntry *typcache;
1295 	TypeCacheEntry *scache;
1296 	RangeBound	lower;
1297 	RangeBound	upper;
1298 	bool		empty;
1299 	char		flags;
1300 	uint64		lower_hash;
1301 	uint64		upper_hash;
1302 
1303 	check_stack_depth();
1304 
1305 	typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1306 
1307 	range_deserialize(typcache, r, &lower, &upper, &empty);
1308 	flags = range_get_flags(r);
1309 
1310 	scache = typcache->rngelemtype;
1311 	if (!OidIsValid(scache->hash_extended_proc_finfo.fn_oid))
1312 	{
1313 		scache = lookup_type_cache(scache->type_id,
1314 								   TYPECACHE_HASH_EXTENDED_PROC_FINFO);
1315 		if (!OidIsValid(scache->hash_extended_proc_finfo.fn_oid))
1316 			ereport(ERROR,
1317 					(errcode(ERRCODE_UNDEFINED_FUNCTION),
1318 					 errmsg("could not identify a hash function for type %s",
1319 							format_type_be(scache->type_id))));
1320 	}
1321 
1322 	if (RANGE_HAS_LBOUND(flags))
1323 		lower_hash = DatumGetUInt64(FunctionCall2Coll(&scache->hash_extended_proc_finfo,
1324 													  typcache->rng_collation,
1325 													  lower.val,
1326 													  seed));
1327 	else
1328 		lower_hash = 0;
1329 
1330 	if (RANGE_HAS_UBOUND(flags))
1331 		upper_hash = DatumGetUInt64(FunctionCall2Coll(&scache->hash_extended_proc_finfo,
1332 													  typcache->rng_collation,
1333 													  upper.val,
1334 													  seed));
1335 	else
1336 		upper_hash = 0;
1337 
1338 	/* Merge hashes of flags and bounds */
1339 	result = DatumGetUInt64(hash_uint32_extended((uint32) flags,
1340 												 DatumGetInt64(seed)));
1341 	result ^= lower_hash;
1342 	result = ROTATE_HIGH_AND_LOW_32BITS(result);
1343 	result ^= upper_hash;
1344 
1345 	PG_RETURN_UINT64(result);
1346 }
1347 
1348 /*
1349  *----------------------------------------------------------
1350  * CANONICAL FUNCTIONS
1351  *
1352  *	 Functions for specific built-in range types.
1353  *----------------------------------------------------------
1354  */
1355 
1356 Datum
int4range_canonical(PG_FUNCTION_ARGS)1357 int4range_canonical(PG_FUNCTION_ARGS)
1358 {
1359 	RangeType  *r = PG_GETARG_RANGE_P(0);
1360 	TypeCacheEntry *typcache;
1361 	RangeBound	lower;
1362 	RangeBound	upper;
1363 	bool		empty;
1364 
1365 	typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1366 
1367 	range_deserialize(typcache, r, &lower, &upper, &empty);
1368 
1369 	if (empty)
1370 		PG_RETURN_RANGE_P(r);
1371 
1372 	if (!lower.infinite && !lower.inclusive)
1373 	{
1374 		lower.val = DirectFunctionCall2(int4pl, lower.val, Int32GetDatum(1));
1375 		lower.inclusive = true;
1376 	}
1377 
1378 	if (!upper.infinite && upper.inclusive)
1379 	{
1380 		upper.val = DirectFunctionCall2(int4pl, upper.val, Int32GetDatum(1));
1381 		upper.inclusive = false;
1382 	}
1383 
1384 	PG_RETURN_RANGE_P(range_serialize(typcache, &lower, &upper, false));
1385 }
1386 
1387 Datum
int8range_canonical(PG_FUNCTION_ARGS)1388 int8range_canonical(PG_FUNCTION_ARGS)
1389 {
1390 	RangeType  *r = PG_GETARG_RANGE_P(0);
1391 	TypeCacheEntry *typcache;
1392 	RangeBound	lower;
1393 	RangeBound	upper;
1394 	bool		empty;
1395 
1396 	typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1397 
1398 	range_deserialize(typcache, r, &lower, &upper, &empty);
1399 
1400 	if (empty)
1401 		PG_RETURN_RANGE_P(r);
1402 
1403 	if (!lower.infinite && !lower.inclusive)
1404 	{
1405 		lower.val = DirectFunctionCall2(int8pl, lower.val, Int64GetDatum(1));
1406 		lower.inclusive = true;
1407 	}
1408 
1409 	if (!upper.infinite && upper.inclusive)
1410 	{
1411 		upper.val = DirectFunctionCall2(int8pl, upper.val, Int64GetDatum(1));
1412 		upper.inclusive = false;
1413 	}
1414 
1415 	PG_RETURN_RANGE_P(range_serialize(typcache, &lower, &upper, false));
1416 }
1417 
1418 Datum
daterange_canonical(PG_FUNCTION_ARGS)1419 daterange_canonical(PG_FUNCTION_ARGS)
1420 {
1421 	RangeType  *r = PG_GETARG_RANGE_P(0);
1422 	TypeCacheEntry *typcache;
1423 	RangeBound	lower;
1424 	RangeBound	upper;
1425 	bool		empty;
1426 
1427 	typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r));
1428 
1429 	range_deserialize(typcache, r, &lower, &upper, &empty);
1430 
1431 	if (empty)
1432 		PG_RETURN_RANGE_P(r);
1433 
1434 	if (!lower.infinite && !DATE_NOT_FINITE(DatumGetDateADT(lower.val)) &&
1435 		!lower.inclusive)
1436 	{
1437 		lower.val = DirectFunctionCall2(date_pli, lower.val, Int32GetDatum(1));
1438 		lower.inclusive = true;
1439 	}
1440 
1441 	if (!upper.infinite && !DATE_NOT_FINITE(DatumGetDateADT(upper.val)) &&
1442 		upper.inclusive)
1443 	{
1444 		upper.val = DirectFunctionCall2(date_pli, upper.val, Int32GetDatum(1));
1445 		upper.inclusive = false;
1446 	}
1447 
1448 	PG_RETURN_RANGE_P(range_serialize(typcache, &lower, &upper, false));
1449 }
1450 
1451 /*
1452  *----------------------------------------------------------
1453  * SUBTYPE_DIFF FUNCTIONS
1454  *
1455  * Functions for specific built-in range types.
1456  *
1457  * Note that subtype_diff does return the difference, not the absolute value
1458  * of the difference, and it must take care to avoid overflow.
1459  * (numrange_subdiff is at some risk there ...)
1460  *----------------------------------------------------------
1461  */
1462 
1463 Datum
int4range_subdiff(PG_FUNCTION_ARGS)1464 int4range_subdiff(PG_FUNCTION_ARGS)
1465 {
1466 	int32		v1 = PG_GETARG_INT32(0);
1467 	int32		v2 = PG_GETARG_INT32(1);
1468 
1469 	PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
1470 }
1471 
1472 Datum
int8range_subdiff(PG_FUNCTION_ARGS)1473 int8range_subdiff(PG_FUNCTION_ARGS)
1474 {
1475 	int64		v1 = PG_GETARG_INT64(0);
1476 	int64		v2 = PG_GETARG_INT64(1);
1477 
1478 	PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
1479 }
1480 
1481 Datum
numrange_subdiff(PG_FUNCTION_ARGS)1482 numrange_subdiff(PG_FUNCTION_ARGS)
1483 {
1484 	Datum		v1 = PG_GETARG_DATUM(0);
1485 	Datum		v2 = PG_GETARG_DATUM(1);
1486 	Datum		numresult;
1487 	float8		floatresult;
1488 
1489 	numresult = DirectFunctionCall2(numeric_sub, v1, v2);
1490 
1491 	floatresult = DatumGetFloat8(DirectFunctionCall1(numeric_float8,
1492 													 numresult));
1493 
1494 	PG_RETURN_FLOAT8(floatresult);
1495 }
1496 
1497 Datum
daterange_subdiff(PG_FUNCTION_ARGS)1498 daterange_subdiff(PG_FUNCTION_ARGS)
1499 {
1500 	int32		v1 = PG_GETARG_INT32(0);
1501 	int32		v2 = PG_GETARG_INT32(1);
1502 
1503 	PG_RETURN_FLOAT8((float8) v1 - (float8) v2);
1504 }
1505 
1506 Datum
tsrange_subdiff(PG_FUNCTION_ARGS)1507 tsrange_subdiff(PG_FUNCTION_ARGS)
1508 {
1509 	Timestamp	v1 = PG_GETARG_TIMESTAMP(0);
1510 	Timestamp	v2 = PG_GETARG_TIMESTAMP(1);
1511 	float8		result;
1512 
1513 	result = ((float8) v1 - (float8) v2) / USECS_PER_SEC;
1514 	PG_RETURN_FLOAT8(result);
1515 }
1516 
1517 Datum
tstzrange_subdiff(PG_FUNCTION_ARGS)1518 tstzrange_subdiff(PG_FUNCTION_ARGS)
1519 {
1520 	Timestamp	v1 = PG_GETARG_TIMESTAMP(0);
1521 	Timestamp	v2 = PG_GETARG_TIMESTAMP(1);
1522 	float8		result;
1523 
1524 	result = ((float8) v1 - (float8) v2) / USECS_PER_SEC;
1525 	PG_RETURN_FLOAT8(result);
1526 }
1527 
1528 /*
1529  *----------------------------------------------------------
1530  * SUPPORT FUNCTIONS
1531  *
1532  *	 These functions aren't in pg_proc, but are useful for
1533  *	 defining new generic range functions in C.
1534  *----------------------------------------------------------
1535  */
1536 
1537 /*
1538  * range_get_typcache: get cached information about a range type
1539  *
1540  * This is for use by range-related functions that follow the convention
1541  * of using the fn_extra field as a pointer to the type cache entry for
1542  * the range type.  Functions that need to cache more information than
1543  * that must fend for themselves.
1544  */
1545 TypeCacheEntry *
range_get_typcache(FunctionCallInfo fcinfo,Oid rngtypid)1546 range_get_typcache(FunctionCallInfo fcinfo, Oid rngtypid)
1547 {
1548 	TypeCacheEntry *typcache = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
1549 
1550 	if (typcache == NULL ||
1551 		typcache->type_id != rngtypid)
1552 	{
1553 		typcache = lookup_type_cache(rngtypid, TYPECACHE_RANGE_INFO);
1554 		if (typcache->rngelemtype == NULL)
1555 			elog(ERROR, "type %u is not a range type", rngtypid);
1556 		fcinfo->flinfo->fn_extra = (void *) typcache;
1557 	}
1558 
1559 	return typcache;
1560 }
1561 
1562 /*
1563  * range_serialize: construct a range value from bounds and empty-flag
1564  *
1565  * This does not force canonicalization of the range value.  In most cases,
1566  * external callers should only be canonicalization functions.  Note that
1567  * we perform some datatype-independent canonicalization checks anyway.
1568  */
1569 RangeType *
range_serialize(TypeCacheEntry * typcache,RangeBound * lower,RangeBound * upper,bool empty)1570 range_serialize(TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper,
1571 				bool empty)
1572 {
1573 	RangeType  *range;
1574 	int			cmp;
1575 	Size		msize;
1576 	Pointer		ptr;
1577 	int16		typlen;
1578 	bool		typbyval;
1579 	char		typalign;
1580 	char		typstorage;
1581 	char		flags = 0;
1582 
1583 	/*
1584 	 * Verify range is not invalid on its face, and construct flags value,
1585 	 * preventing any non-canonical combinations such as infinite+inclusive.
1586 	 */
1587 	Assert(lower->lower);
1588 	Assert(!upper->lower);
1589 
1590 	if (empty)
1591 		flags |= RANGE_EMPTY;
1592 	else
1593 	{
1594 		cmp = range_cmp_bound_values(typcache, lower, upper);
1595 
1596 		/* error check: if lower bound value is above upper, it's wrong */
1597 		if (cmp > 0)
1598 			ereport(ERROR,
1599 					(errcode(ERRCODE_DATA_EXCEPTION),
1600 					 errmsg("range lower bound must be less than or equal to range upper bound")));
1601 
1602 		/* if bounds are equal, and not both inclusive, range is empty */
1603 		if (cmp == 0 && !(lower->inclusive && upper->inclusive))
1604 			flags |= RANGE_EMPTY;
1605 		else
1606 		{
1607 			/* infinite boundaries are never inclusive */
1608 			if (lower->infinite)
1609 				flags |= RANGE_LB_INF;
1610 			else if (lower->inclusive)
1611 				flags |= RANGE_LB_INC;
1612 			if (upper->infinite)
1613 				flags |= RANGE_UB_INF;
1614 			else if (upper->inclusive)
1615 				flags |= RANGE_UB_INC;
1616 		}
1617 	}
1618 
1619 	/* Fetch information about range's element type */
1620 	typlen = typcache->rngelemtype->typlen;
1621 	typbyval = typcache->rngelemtype->typbyval;
1622 	typalign = typcache->rngelemtype->typalign;
1623 	typstorage = typcache->rngelemtype->typstorage;
1624 
1625 	/* Count space for varlena header and range type's OID */
1626 	msize = sizeof(RangeType);
1627 	Assert(msize == MAXALIGN(msize));
1628 
1629 	/* Count space for bounds */
1630 	if (RANGE_HAS_LBOUND(flags))
1631 	{
1632 		/*
1633 		 * Make sure item to be inserted is not toasted.  It is essential that
1634 		 * we not insert an out-of-line toast value pointer into a range
1635 		 * object, for the same reasons that arrays and records can't contain
1636 		 * them.  It would work to store a compressed-in-line value, but we
1637 		 * prefer to decompress and then let compression be applied to the
1638 		 * whole range object if necessary.  But, unlike arrays, we do allow
1639 		 * short-header varlena objects to stay as-is.
1640 		 */
1641 		if (typlen == -1)
1642 			lower->val = PointerGetDatum(PG_DETOAST_DATUM_PACKED(lower->val));
1643 
1644 		msize = datum_compute_size(msize, lower->val, typbyval, typalign,
1645 								   typlen, typstorage);
1646 	}
1647 
1648 	if (RANGE_HAS_UBOUND(flags))
1649 	{
1650 		/* Make sure item to be inserted is not toasted */
1651 		if (typlen == -1)
1652 			upper->val = PointerGetDatum(PG_DETOAST_DATUM_PACKED(upper->val));
1653 
1654 		msize = datum_compute_size(msize, upper->val, typbyval, typalign,
1655 								   typlen, typstorage);
1656 	}
1657 
1658 	/* Add space for flag byte */
1659 	msize += sizeof(char);
1660 
1661 	/* Note: zero-fill is required here, just as in heap tuples */
1662 	range = (RangeType *) palloc0(msize);
1663 	SET_VARSIZE(range, msize);
1664 
1665 	/* Now fill in the datum */
1666 	range->rangetypid = typcache->type_id;
1667 
1668 	ptr = (char *) (range + 1);
1669 
1670 	if (RANGE_HAS_LBOUND(flags))
1671 	{
1672 		Assert(lower->lower);
1673 		ptr = datum_write(ptr, lower->val, typbyval, typalign, typlen,
1674 						  typstorage);
1675 	}
1676 
1677 	if (RANGE_HAS_UBOUND(flags))
1678 	{
1679 		Assert(!upper->lower);
1680 		ptr = datum_write(ptr, upper->val, typbyval, typalign, typlen,
1681 						  typstorage);
1682 	}
1683 
1684 	*((char *) ptr) = flags;
1685 
1686 	return range;
1687 }
1688 
1689 /*
1690  * range_deserialize: deconstruct a range value
1691  *
1692  * NB: the given range object must be fully detoasted; it cannot have a
1693  * short varlena header.
1694  *
1695  * Note that if the element type is pass-by-reference, the datums in the
1696  * RangeBound structs will be pointers into the given range object.
1697  */
1698 void
range_deserialize(TypeCacheEntry * typcache,RangeType * range,RangeBound * lower,RangeBound * upper,bool * empty)1699 range_deserialize(TypeCacheEntry *typcache, RangeType *range,
1700 				  RangeBound *lower, RangeBound *upper, bool *empty)
1701 {
1702 	char		flags;
1703 	int16		typlen;
1704 	bool		typbyval;
1705 	char		typalign;
1706 	Pointer		ptr;
1707 	Datum		lbound;
1708 	Datum		ubound;
1709 
1710 	/* assert caller passed the right typcache entry */
1711 	Assert(RangeTypeGetOid(range) == typcache->type_id);
1712 
1713 	/* fetch the flag byte from datum's last byte */
1714 	flags = *((char *) range + VARSIZE(range) - 1);
1715 
1716 	/* fetch information about range's element type */
1717 	typlen = typcache->rngelemtype->typlen;
1718 	typbyval = typcache->rngelemtype->typbyval;
1719 	typalign = typcache->rngelemtype->typalign;
1720 
1721 	/* initialize data pointer just after the range OID */
1722 	ptr = (Pointer) (range + 1);
1723 
1724 	/* fetch lower bound, if any */
1725 	if (RANGE_HAS_LBOUND(flags))
1726 	{
1727 		/* att_align_pointer cannot be necessary here */
1728 		lbound = fetch_att(ptr, typbyval, typlen);
1729 		ptr = (Pointer) att_addlength_pointer(ptr, typlen, ptr);
1730 	}
1731 	else
1732 		lbound = (Datum) 0;
1733 
1734 	/* fetch upper bound, if any */
1735 	if (RANGE_HAS_UBOUND(flags))
1736 	{
1737 		ptr = (Pointer) att_align_pointer(ptr, typalign, typlen, ptr);
1738 		ubound = fetch_att(ptr, typbyval, typlen);
1739 		/* no need for att_addlength_pointer */
1740 	}
1741 	else
1742 		ubound = (Datum) 0;
1743 
1744 	/* emit results */
1745 
1746 	*empty = (flags & RANGE_EMPTY) != 0;
1747 
1748 	lower->val = lbound;
1749 	lower->infinite = (flags & RANGE_LB_INF) != 0;
1750 	lower->inclusive = (flags & RANGE_LB_INC) != 0;
1751 	lower->lower = true;
1752 
1753 	upper->val = ubound;
1754 	upper->infinite = (flags & RANGE_UB_INF) != 0;
1755 	upper->inclusive = (flags & RANGE_UB_INC) != 0;
1756 	upper->lower = false;
1757 }
1758 
1759 /*
1760  * range_get_flags: just get the flags from a RangeType value.
1761  *
1762  * This is frequently useful in places that only need the flags and not
1763  * the full results of range_deserialize.
1764  */
1765 char
range_get_flags(RangeType * range)1766 range_get_flags(RangeType *range)
1767 {
1768 	/* fetch the flag byte from datum's last byte */
1769 	return *((char *) range + VARSIZE(range) - 1);
1770 }
1771 
1772 /*
1773  * range_set_contain_empty: set the RANGE_CONTAIN_EMPTY bit in the value.
1774  *
1775  * This is only needed in GiST operations, so we don't include a provision
1776  * for setting it in range_serialize; rather, this function must be applied
1777  * afterwards.
1778  */
1779 void
range_set_contain_empty(RangeType * range)1780 range_set_contain_empty(RangeType *range)
1781 {
1782 	char	   *flagsp;
1783 
1784 	/* flag byte is datum's last byte */
1785 	flagsp = (char *) range + VARSIZE(range) - 1;
1786 
1787 	*flagsp |= RANGE_CONTAIN_EMPTY;
1788 }
1789 
1790 /*
1791  * This both serializes and canonicalizes (if applicable) the range.
1792  * This should be used by most callers.
1793  */
1794 RangeType *
make_range(TypeCacheEntry * typcache,RangeBound * lower,RangeBound * upper,bool empty)1795 make_range(TypeCacheEntry *typcache, RangeBound *lower, RangeBound *upper,
1796 		   bool empty)
1797 {
1798 	RangeType  *range;
1799 
1800 	range = range_serialize(typcache, lower, upper, empty);
1801 
1802 	/* no need to call canonical on empty ranges ... */
1803 	if (OidIsValid(typcache->rng_canonical_finfo.fn_oid) &&
1804 		!RangeIsEmpty(range))
1805 		range = DatumGetRangeTypeP(FunctionCall1(&typcache->rng_canonical_finfo,
1806 												 RangeTypePGetDatum(range)));
1807 
1808 	return range;
1809 }
1810 
1811 /*
1812  * Compare two range boundary points, returning <0, 0, or >0 according to
1813  * whether b1 is less than, equal to, or greater than b2.
1814  *
1815  * The boundaries can be any combination of upper and lower; so it's useful
1816  * for a variety of operators.
1817  *
1818  * The simple case is when b1 and b2 are both finite and inclusive, in which
1819  * case the result is just a comparison of the values held in b1 and b2.
1820  *
1821  * If a bound is exclusive, then we need to know whether it's a lower bound,
1822  * in which case we treat the boundary point as "just greater than" the held
1823  * value; or an upper bound, in which case we treat the boundary point as
1824  * "just less than" the held value.
1825  *
1826  * If a bound is infinite, it represents minus infinity (less than every other
1827  * point) if it's a lower bound; or plus infinity (greater than every other
1828  * point) if it's an upper bound.
1829  *
1830  * There is only one case where two boundaries compare equal but are not
1831  * identical: when both bounds are inclusive and hold the same finite value,
1832  * but one is an upper bound and the other a lower bound.
1833  */
1834 int
range_cmp_bounds(TypeCacheEntry * typcache,RangeBound * b1,RangeBound * b2)1835 range_cmp_bounds(TypeCacheEntry *typcache, RangeBound *b1, RangeBound *b2)
1836 {
1837 	int32		result;
1838 
1839 	/*
1840 	 * First, handle cases involving infinity, which don't require invoking
1841 	 * the comparison proc.
1842 	 */
1843 	if (b1->infinite && b2->infinite)
1844 	{
1845 		/*
1846 		 * Both are infinity, so they are equal unless one is lower and the
1847 		 * other not.
1848 		 */
1849 		if (b1->lower == b2->lower)
1850 			return 0;
1851 		else
1852 			return b1->lower ? -1 : 1;
1853 	}
1854 	else if (b1->infinite)
1855 		return b1->lower ? -1 : 1;
1856 	else if (b2->infinite)
1857 		return b2->lower ? 1 : -1;
1858 
1859 	/*
1860 	 * Both boundaries are finite, so compare the held values.
1861 	 */
1862 	result = DatumGetInt32(FunctionCall2Coll(&typcache->rng_cmp_proc_finfo,
1863 											 typcache->rng_collation,
1864 											 b1->val, b2->val));
1865 
1866 	/*
1867 	 * If the comparison is anything other than equal, we're done. If they
1868 	 * compare equal though, we still have to consider whether the boundaries
1869 	 * are inclusive or exclusive.
1870 	 */
1871 	if (result == 0)
1872 	{
1873 		if (!b1->inclusive && !b2->inclusive)
1874 		{
1875 			/* both are exclusive */
1876 			if (b1->lower == b2->lower)
1877 				return 0;
1878 			else
1879 				return b1->lower ? 1 : -1;
1880 		}
1881 		else if (!b1->inclusive)
1882 			return b1->lower ? 1 : -1;
1883 		else if (!b2->inclusive)
1884 			return b2->lower ? -1 : 1;
1885 		else
1886 		{
1887 			/*
1888 			 * Both are inclusive and the values held are equal, so they are
1889 			 * equal regardless of whether they are upper or lower boundaries,
1890 			 * or a mix.
1891 			 */
1892 			return 0;
1893 		}
1894 	}
1895 
1896 	return result;
1897 }
1898 
1899 /*
1900  * Compare two range boundary point values, returning <0, 0, or >0 according
1901  * to whether b1 is less than, equal to, or greater than b2.
1902  *
1903  * This is similar to but simpler than range_cmp_bounds().  We just compare
1904  * the values held in b1 and b2, ignoring inclusive/exclusive flags.  The
1905  * lower/upper flags only matter for infinities, where they tell us if the
1906  * infinity is plus or minus.
1907  */
1908 int
range_cmp_bound_values(TypeCacheEntry * typcache,RangeBound * b1,RangeBound * b2)1909 range_cmp_bound_values(TypeCacheEntry *typcache, RangeBound *b1,
1910 					   RangeBound *b2)
1911 {
1912 	/*
1913 	 * First, handle cases involving infinity, which don't require invoking
1914 	 * the comparison proc.
1915 	 */
1916 	if (b1->infinite && b2->infinite)
1917 	{
1918 		/*
1919 		 * Both are infinity, so they are equal unless one is lower and the
1920 		 * other not.
1921 		 */
1922 		if (b1->lower == b2->lower)
1923 			return 0;
1924 		else
1925 			return b1->lower ? -1 : 1;
1926 	}
1927 	else if (b1->infinite)
1928 		return b1->lower ? -1 : 1;
1929 	else if (b2->infinite)
1930 		return b2->lower ? 1 : -1;
1931 
1932 	/*
1933 	 * Both boundaries are finite, so compare the held values.
1934 	 */
1935 	return DatumGetInt32(FunctionCall2Coll(&typcache->rng_cmp_proc_finfo,
1936 										   typcache->rng_collation,
1937 										   b1->val, b2->val));
1938 }
1939 
1940 /*
1941  * Build an empty range value of the type indicated by the typcache entry.
1942  */
1943 RangeType *
make_empty_range(TypeCacheEntry * typcache)1944 make_empty_range(TypeCacheEntry *typcache)
1945 {
1946 	RangeBound	lower;
1947 	RangeBound	upper;
1948 
1949 	lower.val = (Datum) 0;
1950 	lower.infinite = false;
1951 	lower.inclusive = false;
1952 	lower.lower = true;
1953 
1954 	upper.val = (Datum) 0;
1955 	upper.infinite = false;
1956 	upper.inclusive = false;
1957 	upper.lower = false;
1958 
1959 	return make_range(typcache, &lower, &upper, true);
1960 }
1961 
1962 
1963 /*
1964  *----------------------------------------------------------
1965  * STATIC FUNCTIONS
1966  *----------------------------------------------------------
1967  */
1968 
1969 /*
1970  * Given a string representing the flags for the range type, return the flags
1971  * represented as a char.
1972  */
1973 static char
range_parse_flags(const char * flags_str)1974 range_parse_flags(const char *flags_str)
1975 {
1976 	char		flags = 0;
1977 
1978 	if (flags_str[0] == '\0' ||
1979 		flags_str[1] == '\0' ||
1980 		flags_str[2] != '\0')
1981 		ereport(ERROR,
1982 				(errcode(ERRCODE_SYNTAX_ERROR),
1983 				 errmsg("invalid range bound flags"),
1984 				 errhint("Valid values are \"[]\", \"[)\", \"(]\", and \"()\".")));
1985 
1986 	switch (flags_str[0])
1987 	{
1988 		case '[':
1989 			flags |= RANGE_LB_INC;
1990 			break;
1991 		case '(':
1992 			break;
1993 		default:
1994 			ereport(ERROR,
1995 					(errcode(ERRCODE_SYNTAX_ERROR),
1996 					 errmsg("invalid range bound flags"),
1997 					 errhint("Valid values are \"[]\", \"[)\", \"(]\", and \"()\".")));
1998 	}
1999 
2000 	switch (flags_str[1])
2001 	{
2002 		case ']':
2003 			flags |= RANGE_UB_INC;
2004 			break;
2005 		case ')':
2006 			break;
2007 		default:
2008 			ereport(ERROR,
2009 					(errcode(ERRCODE_SYNTAX_ERROR),
2010 					 errmsg("invalid range bound flags"),
2011 					 errhint("Valid values are \"[]\", \"[)\", \"(]\", and \"()\".")));
2012 	}
2013 
2014 	return flags;
2015 }
2016 
2017 /*
2018  * Parse range input.
2019  *
2020  * Input parameters:
2021  *	string: input string to be parsed
2022  * Output parameters:
2023  *	*flags: receives flags bitmask
2024  *	*lbound_str: receives palloc'd lower bound string, or NULL if none
2025  *	*ubound_str: receives palloc'd upper bound string, or NULL if none
2026  *
2027  * This is modeled somewhat after record_in in rowtypes.c.
2028  * The input syntax is:
2029  *	<range>   := EMPTY
2030  *			   | <lb-inc> <string>, <string> <ub-inc>
2031  *	<lb-inc>  := '[' | '('
2032  *	<ub-inc>  := ']' | ')'
2033  *
2034  * Whitespace before or after <range> is ignored.  Whitespace within a <string>
2035  * is taken literally and becomes part of the input string for that bound.
2036  *
2037  * A <string> of length zero is taken as "infinite" (i.e. no bound), unless it
2038  * is surrounded by double-quotes, in which case it is the literal empty
2039  * string.
2040  *
2041  * Within a <string>, special characters (such as comma, parenthesis, or
2042  * brackets) can be enclosed in double-quotes or escaped with backslash. Within
2043  * double-quotes, a double-quote can be escaped with double-quote or backslash.
2044  */
2045 static void
range_parse(const char * string,char * flags,char ** lbound_str,char ** ubound_str)2046 range_parse(const char *string, char *flags, char **lbound_str,
2047 			char **ubound_str)
2048 {
2049 	const char *ptr = string;
2050 	bool		infinite;
2051 
2052 	*flags = 0;
2053 
2054 	/* consume whitespace */
2055 	while (*ptr != '\0' && isspace((unsigned char) *ptr))
2056 		ptr++;
2057 
2058 	/* check for empty range */
2059 	if (pg_strncasecmp(ptr, RANGE_EMPTY_LITERAL,
2060 					   strlen(RANGE_EMPTY_LITERAL)) == 0)
2061 	{
2062 		*flags = RANGE_EMPTY;
2063 		*lbound_str = NULL;
2064 		*ubound_str = NULL;
2065 
2066 		ptr += strlen(RANGE_EMPTY_LITERAL);
2067 
2068 		/* the rest should be whitespace */
2069 		while (*ptr != '\0' && isspace((unsigned char) *ptr))
2070 			ptr++;
2071 
2072 		/* should have consumed everything */
2073 		if (*ptr != '\0')
2074 			ereport(ERROR,
2075 					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2076 					 errmsg("malformed range literal: \"%s\"",
2077 							string),
2078 					 errdetail("Junk after \"empty\" key word.")));
2079 
2080 		return;
2081 	}
2082 
2083 	if (*ptr == '[')
2084 	{
2085 		*flags |= RANGE_LB_INC;
2086 		ptr++;
2087 	}
2088 	else if (*ptr == '(')
2089 		ptr++;
2090 	else
2091 		ereport(ERROR,
2092 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2093 				 errmsg("malformed range literal: \"%s\"",
2094 						string),
2095 				 errdetail("Missing left parenthesis or bracket.")));
2096 
2097 	ptr = range_parse_bound(string, ptr, lbound_str, &infinite);
2098 	if (infinite)
2099 		*flags |= RANGE_LB_INF;
2100 
2101 	if (*ptr == ',')
2102 		ptr++;
2103 	else
2104 		ereport(ERROR,
2105 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2106 				 errmsg("malformed range literal: \"%s\"",
2107 						string),
2108 				 errdetail("Missing comma after lower bound.")));
2109 
2110 	ptr = range_parse_bound(string, ptr, ubound_str, &infinite);
2111 	if (infinite)
2112 		*flags |= RANGE_UB_INF;
2113 
2114 	if (*ptr == ']')
2115 	{
2116 		*flags |= RANGE_UB_INC;
2117 		ptr++;
2118 	}
2119 	else if (*ptr == ')')
2120 		ptr++;
2121 	else						/* must be a comma */
2122 		ereport(ERROR,
2123 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2124 				 errmsg("malformed range literal: \"%s\"",
2125 						string),
2126 				 errdetail("Too many commas.")));
2127 
2128 	/* consume whitespace */
2129 	while (*ptr != '\0' && isspace((unsigned char) *ptr))
2130 		ptr++;
2131 
2132 	if (*ptr != '\0')
2133 		ereport(ERROR,
2134 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2135 				 errmsg("malformed range literal: \"%s\"",
2136 						string),
2137 				 errdetail("Junk after right parenthesis or bracket.")));
2138 }
2139 
2140 /*
2141  * Helper for range_parse: parse and de-quote one bound string.
2142  *
2143  * We scan until finding comma, right parenthesis, or right bracket.
2144  *
2145  * Input parameters:
2146  *	string: entire input string (used only for error reports)
2147  *	ptr: where to start parsing bound
2148  * Output parameters:
2149  *	*bound_str: receives palloc'd bound string, or NULL if none
2150  *	*infinite: set true if no bound, else false
2151  *
2152  * The return value is the scan ptr, advanced past the bound string.
2153  */
2154 static const char *
range_parse_bound(const char * string,const char * ptr,char ** bound_str,bool * infinite)2155 range_parse_bound(const char *string, const char *ptr,
2156 				  char **bound_str, bool *infinite)
2157 {
2158 	StringInfoData buf;
2159 
2160 	/* Check for null: completely empty input means null */
2161 	if (*ptr == ',' || *ptr == ')' || *ptr == ']')
2162 	{
2163 		*bound_str = NULL;
2164 		*infinite = true;
2165 	}
2166 	else
2167 	{
2168 		/* Extract string for this bound */
2169 		bool		inquote = false;
2170 
2171 		initStringInfo(&buf);
2172 		while (inquote || !(*ptr == ',' || *ptr == ')' || *ptr == ']'))
2173 		{
2174 			char		ch = *ptr++;
2175 
2176 			if (ch == '\0')
2177 				ereport(ERROR,
2178 						(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2179 						 errmsg("malformed range literal: \"%s\"",
2180 								string),
2181 						 errdetail("Unexpected end of input.")));
2182 			if (ch == '\\')
2183 			{
2184 				if (*ptr == '\0')
2185 					ereport(ERROR,
2186 							(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2187 							 errmsg("malformed range literal: \"%s\"",
2188 									string),
2189 							 errdetail("Unexpected end of input.")));
2190 				appendStringInfoChar(&buf, *ptr++);
2191 			}
2192 			else if (ch == '"')
2193 			{
2194 				if (!inquote)
2195 					inquote = true;
2196 				else if (*ptr == '"')
2197 				{
2198 					/* doubled quote within quote sequence */
2199 					appendStringInfoChar(&buf, *ptr++);
2200 				}
2201 				else
2202 					inquote = false;
2203 			}
2204 			else
2205 				appendStringInfoChar(&buf, ch);
2206 		}
2207 
2208 		*bound_str = buf.data;
2209 		*infinite = false;
2210 	}
2211 
2212 	return ptr;
2213 }
2214 
2215 /*
2216  * Convert a deserialized range value to text form
2217  *
2218  * Inputs are the flags byte, and the two bound values already converted to
2219  * text (but not yet quoted).  If no bound value, pass NULL.
2220  *
2221  * Result is a palloc'd string
2222  */
2223 static char *
range_deparse(char flags,const char * lbound_str,const char * ubound_str)2224 range_deparse(char flags, const char *lbound_str, const char *ubound_str)
2225 {
2226 	StringInfoData buf;
2227 
2228 	if (flags & RANGE_EMPTY)
2229 		return pstrdup(RANGE_EMPTY_LITERAL);
2230 
2231 	initStringInfo(&buf);
2232 
2233 	appendStringInfoChar(&buf, (flags & RANGE_LB_INC) ? '[' : '(');
2234 
2235 	if (RANGE_HAS_LBOUND(flags))
2236 		appendStringInfoString(&buf, range_bound_escape(lbound_str));
2237 
2238 	appendStringInfoChar(&buf, ',');
2239 
2240 	if (RANGE_HAS_UBOUND(flags))
2241 		appendStringInfoString(&buf, range_bound_escape(ubound_str));
2242 
2243 	appendStringInfoChar(&buf, (flags & RANGE_UB_INC) ? ']' : ')');
2244 
2245 	return buf.data;
2246 }
2247 
2248 /*
2249  * Helper for range_deparse: quote a bound value as needed
2250  *
2251  * Result is a palloc'd string
2252  */
2253 static char *
range_bound_escape(const char * value)2254 range_bound_escape(const char *value)
2255 {
2256 	bool		nq;
2257 	const char *ptr;
2258 	StringInfoData buf;
2259 
2260 	initStringInfo(&buf);
2261 
2262 	/* Detect whether we need double quotes for this value */
2263 	nq = (value[0] == '\0');	/* force quotes for empty string */
2264 	for (ptr = value; *ptr; ptr++)
2265 	{
2266 		char		ch = *ptr;
2267 
2268 		if (ch == '"' || ch == '\\' ||
2269 			ch == '(' || ch == ')' ||
2270 			ch == '[' || ch == ']' ||
2271 			ch == ',' ||
2272 			isspace((unsigned char) ch))
2273 		{
2274 			nq = true;
2275 			break;
2276 		}
2277 	}
2278 
2279 	/* And emit the string */
2280 	if (nq)
2281 		appendStringInfoChar(&buf, '"');
2282 	for (ptr = value; *ptr; ptr++)
2283 	{
2284 		char		ch = *ptr;
2285 
2286 		if (ch == '"' || ch == '\\')
2287 			appendStringInfoChar(&buf, ch);
2288 		appendStringInfoChar(&buf, ch);
2289 	}
2290 	if (nq)
2291 		appendStringInfoChar(&buf, '"');
2292 
2293 	return buf.data;
2294 }
2295 
2296 /*
2297  * Test whether range r1 contains range r2.
2298  *
2299  * Caller has already checked that they are the same range type, and looked up
2300  * the necessary typcache entry.
2301  */
2302 bool
range_contains_internal(TypeCacheEntry * typcache,RangeType * r1,RangeType * r2)2303 range_contains_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
2304 {
2305 	RangeBound	lower1;
2306 	RangeBound	upper1;
2307 	bool		empty1;
2308 	RangeBound	lower2;
2309 	RangeBound	upper2;
2310 	bool		empty2;
2311 
2312 	/* Different types should be prevented by ANYRANGE matching rules */
2313 	if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
2314 		elog(ERROR, "range types do not match");
2315 
2316 	range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
2317 	range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
2318 
2319 	/* If either range is empty, the answer is easy */
2320 	if (empty2)
2321 		return true;
2322 	else if (empty1)
2323 		return false;
2324 
2325 	/* Else we must have lower1 <= lower2 and upper1 >= upper2 */
2326 	if (range_cmp_bounds(typcache, &lower1, &lower2) > 0)
2327 		return false;
2328 	if (range_cmp_bounds(typcache, &upper1, &upper2) < 0)
2329 		return false;
2330 
2331 	return true;
2332 }
2333 
2334 bool
range_contained_by_internal(TypeCacheEntry * typcache,RangeType * r1,RangeType * r2)2335 range_contained_by_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
2336 {
2337 	return range_contains_internal(typcache, r2, r1);
2338 }
2339 
2340 /*
2341  * Test whether range r contains a specific element value.
2342  */
2343 bool
range_contains_elem_internal(TypeCacheEntry * typcache,RangeType * r,Datum val)2344 range_contains_elem_internal(TypeCacheEntry *typcache, RangeType *r, Datum val)
2345 {
2346 	RangeBound	lower;
2347 	RangeBound	upper;
2348 	bool		empty;
2349 	int32		cmp;
2350 
2351 	range_deserialize(typcache, r, &lower, &upper, &empty);
2352 
2353 	if (empty)
2354 		return false;
2355 
2356 	if (!lower.infinite)
2357 	{
2358 		cmp = DatumGetInt32(FunctionCall2Coll(&typcache->rng_cmp_proc_finfo,
2359 											  typcache->rng_collation,
2360 											  lower.val, val));
2361 		if (cmp > 0)
2362 			return false;
2363 		if (cmp == 0 && !lower.inclusive)
2364 			return false;
2365 	}
2366 
2367 	if (!upper.infinite)
2368 	{
2369 		cmp = DatumGetInt32(FunctionCall2Coll(&typcache->rng_cmp_proc_finfo,
2370 											  typcache->rng_collation,
2371 											  upper.val, val));
2372 		if (cmp < 0)
2373 			return false;
2374 		if (cmp == 0 && !upper.inclusive)
2375 			return false;
2376 	}
2377 
2378 	return true;
2379 }
2380 
2381 
2382 /*
2383  * datum_compute_size() and datum_write() are used to insert the bound
2384  * values into a range object.  They are modeled after heaptuple.c's
2385  * heap_compute_data_size() and heap_fill_tuple(), but we need not handle
2386  * null values here.  TYPE_IS_PACKABLE must test the same conditions as
2387  * heaptuple.c's ATT_IS_PACKABLE macro.
2388  */
2389 
2390 /* Does datatype allow packing into the 1-byte-header varlena format? */
2391 #define TYPE_IS_PACKABLE(typlen, typstorage) \
2392 	((typlen) == -1 && (typstorage) != 'p')
2393 
2394 /*
2395  * Increment data_length by the space needed by the datum, including any
2396  * preceding alignment padding.
2397  */
2398 static Size
datum_compute_size(Size data_length,Datum val,bool typbyval,char typalign,int16 typlen,char typstorage)2399 datum_compute_size(Size data_length, Datum val, bool typbyval, char typalign,
2400 				   int16 typlen, char typstorage)
2401 {
2402 	if (TYPE_IS_PACKABLE(typlen, typstorage) &&
2403 		VARATT_CAN_MAKE_SHORT(DatumGetPointer(val)))
2404 	{
2405 		/*
2406 		 * we're anticipating converting to a short varlena header, so adjust
2407 		 * length and don't count any alignment
2408 		 */
2409 		data_length += VARATT_CONVERTED_SHORT_SIZE(DatumGetPointer(val));
2410 	}
2411 	else
2412 	{
2413 		data_length = att_align_datum(data_length, typalign, typlen, val);
2414 		data_length = att_addlength_datum(data_length, typlen, val);
2415 	}
2416 
2417 	return data_length;
2418 }
2419 
2420 /*
2421  * Write the given datum beginning at ptr (after advancing to correct
2422  * alignment, if needed).  Return the pointer incremented by space used.
2423  */
2424 static Pointer
datum_write(Pointer ptr,Datum datum,bool typbyval,char typalign,int16 typlen,char typstorage)2425 datum_write(Pointer ptr, Datum datum, bool typbyval, char typalign,
2426 			int16 typlen, char typstorage)
2427 {
2428 	Size		data_length;
2429 
2430 	if (typbyval)
2431 	{
2432 		/* pass-by-value */
2433 		ptr = (char *) att_align_nominal(ptr, typalign);
2434 		store_att_byval(ptr, datum, typlen);
2435 		data_length = typlen;
2436 	}
2437 	else if (typlen == -1)
2438 	{
2439 		/* varlena */
2440 		Pointer		val = DatumGetPointer(datum);
2441 
2442 		if (VARATT_IS_EXTERNAL(val))
2443 		{
2444 			/*
2445 			 * Throw error, because we must never put a toast pointer inside a
2446 			 * range object.  Caller should have detoasted it.
2447 			 */
2448 			elog(ERROR, "cannot store a toast pointer inside a range");
2449 			data_length = 0;	/* keep compiler quiet */
2450 		}
2451 		else if (VARATT_IS_SHORT(val))
2452 		{
2453 			/* no alignment for short varlenas */
2454 			data_length = VARSIZE_SHORT(val);
2455 			memcpy(ptr, val, data_length);
2456 		}
2457 		else if (TYPE_IS_PACKABLE(typlen, typstorage) &&
2458 				 VARATT_CAN_MAKE_SHORT(val))
2459 		{
2460 			/* convert to short varlena -- no alignment */
2461 			data_length = VARATT_CONVERTED_SHORT_SIZE(val);
2462 			SET_VARSIZE_SHORT(ptr, data_length);
2463 			memcpy(ptr + 1, VARDATA(val), data_length - 1);
2464 		}
2465 		else
2466 		{
2467 			/* full 4-byte header varlena */
2468 			ptr = (char *) att_align_nominal(ptr, typalign);
2469 			data_length = VARSIZE(val);
2470 			memcpy(ptr, val, data_length);
2471 		}
2472 	}
2473 	else if (typlen == -2)
2474 	{
2475 		/* cstring ... never needs alignment */
2476 		Assert(typalign == 'c');
2477 		data_length = strlen(DatumGetCString(datum)) + 1;
2478 		memcpy(ptr, DatumGetPointer(datum), data_length);
2479 	}
2480 	else
2481 	{
2482 		/* fixed-length pass-by-reference */
2483 		ptr = (char *) att_align_nominal(ptr, typalign);
2484 		Assert(typlen > 0);
2485 		data_length = typlen;
2486 		memcpy(ptr, DatumGetPointer(datum), data_length);
2487 	}
2488 
2489 	ptr += data_length;
2490 
2491 	return ptr;
2492 }
2493