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