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