1 /*-------------------------------------------------------------------------
2  *
3  * int8.c
4  *	  Internal 64-bit integer operations
5  *
6  * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  * IDENTIFICATION
10  *	  src/backend/utils/adt/int8.c
11  *
12  *-------------------------------------------------------------------------
13  */
14 #include "postgres.h"
15 
16 #include <ctype.h>
17 #include <limits.h>
18 #include <math.h>
19 
20 #include "common/int.h"
21 #include "funcapi.h"
22 #include "libpq/pqformat.h"
23 #include "nodes/nodeFuncs.h"
24 #include "nodes/supportnodes.h"
25 #include "optimizer/optimizer.h"
26 #include "utils/builtins.h"
27 #include "utils/int8.h"
28 
29 
30 typedef struct
31 {
32 	int64		current;
33 	int64		finish;
34 	int64		step;
35 } generate_series_fctx;
36 
37 
38 /***********************************************************************
39  **
40  **		Routines for 64-bit integers.
41  **
42  ***********************************************************************/
43 
44 /*----------------------------------------------------------
45  * Formatting and conversion routines.
46  *---------------------------------------------------------*/
47 
48 /*
49  * scanint8 --- try to parse a string into an int8.
50  *
51  * If errorOK is false, ereport a useful error message if the string is bad.
52  * If errorOK is true, just return "false" for bad input.
53  */
54 bool
scanint8(const char * str,bool errorOK,int64 * result)55 scanint8(const char *str, bool errorOK, int64 *result)
56 {
57 	const char *ptr = str;
58 	int64		tmp = 0;
59 	bool		neg = false;
60 
61 	/*
62 	 * Do our own scan, rather than relying on sscanf which might be broken
63 	 * for long long.
64 	 *
65 	 * As INT64_MIN can't be stored as a positive 64 bit integer, accumulate
66 	 * value as a negative number.
67 	 */
68 
69 	/* skip leading spaces */
70 	while (*ptr && isspace((unsigned char) *ptr))
71 		ptr++;
72 
73 	/* handle sign */
74 	if (*ptr == '-')
75 	{
76 		ptr++;
77 		neg = true;
78 	}
79 	else if (*ptr == '+')
80 		ptr++;
81 
82 	/* require at least one digit */
83 	if (unlikely(!isdigit((unsigned char) *ptr)))
84 		goto invalid_syntax;
85 
86 	/* process digits */
87 	while (*ptr && isdigit((unsigned char) *ptr))
88 	{
89 		int8		digit = (*ptr++ - '0');
90 
91 		if (unlikely(pg_mul_s64_overflow(tmp, 10, &tmp)) ||
92 			unlikely(pg_sub_s64_overflow(tmp, digit, &tmp)))
93 			goto out_of_range;
94 	}
95 
96 	/* allow trailing whitespace, but not other trailing chars */
97 	while (*ptr != '\0' && isspace((unsigned char) *ptr))
98 		ptr++;
99 
100 	if (unlikely(*ptr != '\0'))
101 		goto invalid_syntax;
102 
103 	if (!neg)
104 	{
105 		/* could fail if input is most negative number */
106 		if (unlikely(tmp == PG_INT64_MIN))
107 			goto out_of_range;
108 		tmp = -tmp;
109 	}
110 
111 	*result = tmp;
112 	return true;
113 
114 out_of_range:
115 	if (!errorOK)
116 		ereport(ERROR,
117 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
118 				 errmsg("value \"%s\" is out of range for type %s",
119 						str, "bigint")));
120 	return false;
121 
122 invalid_syntax:
123 	if (!errorOK)
124 		ereport(ERROR,
125 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
126 				 errmsg("invalid input syntax for type %s: \"%s\"",
127 						"bigint", str)));
128 	return false;
129 }
130 
131 /* int8in()
132  */
133 Datum
int8in(PG_FUNCTION_ARGS)134 int8in(PG_FUNCTION_ARGS)
135 {
136 	char	   *str = PG_GETARG_CSTRING(0);
137 	int64		result;
138 
139 	(void) scanint8(str, false, &result);
140 	PG_RETURN_INT64(result);
141 }
142 
143 
144 /* int8out()
145  */
146 Datum
int8out(PG_FUNCTION_ARGS)147 int8out(PG_FUNCTION_ARGS)
148 {
149 	int64		val = PG_GETARG_INT64(0);
150 	char		buf[MAXINT8LEN + 1];
151 	char	   *result;
152 	int			len;
153 
154 	len = pg_lltoa(val, buf) + 1;
155 
156 	/*
157 	 * Since the length is already known, we do a manual palloc() and memcpy()
158 	 * to avoid the strlen() call that would otherwise be done in pstrdup().
159 	 */
160 	result = palloc(len);
161 	memcpy(result, buf, len);
162 	PG_RETURN_CSTRING(result);
163 }
164 
165 /*
166  *		int8recv			- converts external binary format to int8
167  */
168 Datum
int8recv(PG_FUNCTION_ARGS)169 int8recv(PG_FUNCTION_ARGS)
170 {
171 	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);
172 
173 	PG_RETURN_INT64(pq_getmsgint64(buf));
174 }
175 
176 /*
177  *		int8send			- converts int8 to binary format
178  */
179 Datum
int8send(PG_FUNCTION_ARGS)180 int8send(PG_FUNCTION_ARGS)
181 {
182 	int64		arg1 = PG_GETARG_INT64(0);
183 	StringInfoData buf;
184 
185 	pq_begintypsend(&buf);
186 	pq_sendint64(&buf, arg1);
187 	PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
188 }
189 
190 
191 /*----------------------------------------------------------
192  *	Relational operators for int8s, including cross-data-type comparisons.
193  *---------------------------------------------------------*/
194 
195 /* int8relop()
196  * Is val1 relop val2?
197  */
198 Datum
int8eq(PG_FUNCTION_ARGS)199 int8eq(PG_FUNCTION_ARGS)
200 {
201 	int64		val1 = PG_GETARG_INT64(0);
202 	int64		val2 = PG_GETARG_INT64(1);
203 
204 	PG_RETURN_BOOL(val1 == val2);
205 }
206 
207 Datum
int8ne(PG_FUNCTION_ARGS)208 int8ne(PG_FUNCTION_ARGS)
209 {
210 	int64		val1 = PG_GETARG_INT64(0);
211 	int64		val2 = PG_GETARG_INT64(1);
212 
213 	PG_RETURN_BOOL(val1 != val2);
214 }
215 
216 Datum
int8lt(PG_FUNCTION_ARGS)217 int8lt(PG_FUNCTION_ARGS)
218 {
219 	int64		val1 = PG_GETARG_INT64(0);
220 	int64		val2 = PG_GETARG_INT64(1);
221 
222 	PG_RETURN_BOOL(val1 < val2);
223 }
224 
225 Datum
int8gt(PG_FUNCTION_ARGS)226 int8gt(PG_FUNCTION_ARGS)
227 {
228 	int64		val1 = PG_GETARG_INT64(0);
229 	int64		val2 = PG_GETARG_INT64(1);
230 
231 	PG_RETURN_BOOL(val1 > val2);
232 }
233 
234 Datum
int8le(PG_FUNCTION_ARGS)235 int8le(PG_FUNCTION_ARGS)
236 {
237 	int64		val1 = PG_GETARG_INT64(0);
238 	int64		val2 = PG_GETARG_INT64(1);
239 
240 	PG_RETURN_BOOL(val1 <= val2);
241 }
242 
243 Datum
int8ge(PG_FUNCTION_ARGS)244 int8ge(PG_FUNCTION_ARGS)
245 {
246 	int64		val1 = PG_GETARG_INT64(0);
247 	int64		val2 = PG_GETARG_INT64(1);
248 
249 	PG_RETURN_BOOL(val1 >= val2);
250 }
251 
252 /* int84relop()
253  * Is 64-bit val1 relop 32-bit val2?
254  */
255 Datum
int84eq(PG_FUNCTION_ARGS)256 int84eq(PG_FUNCTION_ARGS)
257 {
258 	int64		val1 = PG_GETARG_INT64(0);
259 	int32		val2 = PG_GETARG_INT32(1);
260 
261 	PG_RETURN_BOOL(val1 == val2);
262 }
263 
264 Datum
int84ne(PG_FUNCTION_ARGS)265 int84ne(PG_FUNCTION_ARGS)
266 {
267 	int64		val1 = PG_GETARG_INT64(0);
268 	int32		val2 = PG_GETARG_INT32(1);
269 
270 	PG_RETURN_BOOL(val1 != val2);
271 }
272 
273 Datum
int84lt(PG_FUNCTION_ARGS)274 int84lt(PG_FUNCTION_ARGS)
275 {
276 	int64		val1 = PG_GETARG_INT64(0);
277 	int32		val2 = PG_GETARG_INT32(1);
278 
279 	PG_RETURN_BOOL(val1 < val2);
280 }
281 
282 Datum
int84gt(PG_FUNCTION_ARGS)283 int84gt(PG_FUNCTION_ARGS)
284 {
285 	int64		val1 = PG_GETARG_INT64(0);
286 	int32		val2 = PG_GETARG_INT32(1);
287 
288 	PG_RETURN_BOOL(val1 > val2);
289 }
290 
291 Datum
int84le(PG_FUNCTION_ARGS)292 int84le(PG_FUNCTION_ARGS)
293 {
294 	int64		val1 = PG_GETARG_INT64(0);
295 	int32		val2 = PG_GETARG_INT32(1);
296 
297 	PG_RETURN_BOOL(val1 <= val2);
298 }
299 
300 Datum
int84ge(PG_FUNCTION_ARGS)301 int84ge(PG_FUNCTION_ARGS)
302 {
303 	int64		val1 = PG_GETARG_INT64(0);
304 	int32		val2 = PG_GETARG_INT32(1);
305 
306 	PG_RETURN_BOOL(val1 >= val2);
307 }
308 
309 /* int48relop()
310  * Is 32-bit val1 relop 64-bit val2?
311  */
312 Datum
int48eq(PG_FUNCTION_ARGS)313 int48eq(PG_FUNCTION_ARGS)
314 {
315 	int32		val1 = PG_GETARG_INT32(0);
316 	int64		val2 = PG_GETARG_INT64(1);
317 
318 	PG_RETURN_BOOL(val1 == val2);
319 }
320 
321 Datum
int48ne(PG_FUNCTION_ARGS)322 int48ne(PG_FUNCTION_ARGS)
323 {
324 	int32		val1 = PG_GETARG_INT32(0);
325 	int64		val2 = PG_GETARG_INT64(1);
326 
327 	PG_RETURN_BOOL(val1 != val2);
328 }
329 
330 Datum
int48lt(PG_FUNCTION_ARGS)331 int48lt(PG_FUNCTION_ARGS)
332 {
333 	int32		val1 = PG_GETARG_INT32(0);
334 	int64		val2 = PG_GETARG_INT64(1);
335 
336 	PG_RETURN_BOOL(val1 < val2);
337 }
338 
339 Datum
int48gt(PG_FUNCTION_ARGS)340 int48gt(PG_FUNCTION_ARGS)
341 {
342 	int32		val1 = PG_GETARG_INT32(0);
343 	int64		val2 = PG_GETARG_INT64(1);
344 
345 	PG_RETURN_BOOL(val1 > val2);
346 }
347 
348 Datum
int48le(PG_FUNCTION_ARGS)349 int48le(PG_FUNCTION_ARGS)
350 {
351 	int32		val1 = PG_GETARG_INT32(0);
352 	int64		val2 = PG_GETARG_INT64(1);
353 
354 	PG_RETURN_BOOL(val1 <= val2);
355 }
356 
357 Datum
int48ge(PG_FUNCTION_ARGS)358 int48ge(PG_FUNCTION_ARGS)
359 {
360 	int32		val1 = PG_GETARG_INT32(0);
361 	int64		val2 = PG_GETARG_INT64(1);
362 
363 	PG_RETURN_BOOL(val1 >= val2);
364 }
365 
366 /* int82relop()
367  * Is 64-bit val1 relop 16-bit val2?
368  */
369 Datum
int82eq(PG_FUNCTION_ARGS)370 int82eq(PG_FUNCTION_ARGS)
371 {
372 	int64		val1 = PG_GETARG_INT64(0);
373 	int16		val2 = PG_GETARG_INT16(1);
374 
375 	PG_RETURN_BOOL(val1 == val2);
376 }
377 
378 Datum
int82ne(PG_FUNCTION_ARGS)379 int82ne(PG_FUNCTION_ARGS)
380 {
381 	int64		val1 = PG_GETARG_INT64(0);
382 	int16		val2 = PG_GETARG_INT16(1);
383 
384 	PG_RETURN_BOOL(val1 != val2);
385 }
386 
387 Datum
int82lt(PG_FUNCTION_ARGS)388 int82lt(PG_FUNCTION_ARGS)
389 {
390 	int64		val1 = PG_GETARG_INT64(0);
391 	int16		val2 = PG_GETARG_INT16(1);
392 
393 	PG_RETURN_BOOL(val1 < val2);
394 }
395 
396 Datum
int82gt(PG_FUNCTION_ARGS)397 int82gt(PG_FUNCTION_ARGS)
398 {
399 	int64		val1 = PG_GETARG_INT64(0);
400 	int16		val2 = PG_GETARG_INT16(1);
401 
402 	PG_RETURN_BOOL(val1 > val2);
403 }
404 
405 Datum
int82le(PG_FUNCTION_ARGS)406 int82le(PG_FUNCTION_ARGS)
407 {
408 	int64		val1 = PG_GETARG_INT64(0);
409 	int16		val2 = PG_GETARG_INT16(1);
410 
411 	PG_RETURN_BOOL(val1 <= val2);
412 }
413 
414 Datum
int82ge(PG_FUNCTION_ARGS)415 int82ge(PG_FUNCTION_ARGS)
416 {
417 	int64		val1 = PG_GETARG_INT64(0);
418 	int16		val2 = PG_GETARG_INT16(1);
419 
420 	PG_RETURN_BOOL(val1 >= val2);
421 }
422 
423 /* int28relop()
424  * Is 16-bit val1 relop 64-bit val2?
425  */
426 Datum
int28eq(PG_FUNCTION_ARGS)427 int28eq(PG_FUNCTION_ARGS)
428 {
429 	int16		val1 = PG_GETARG_INT16(0);
430 	int64		val2 = PG_GETARG_INT64(1);
431 
432 	PG_RETURN_BOOL(val1 == val2);
433 }
434 
435 Datum
int28ne(PG_FUNCTION_ARGS)436 int28ne(PG_FUNCTION_ARGS)
437 {
438 	int16		val1 = PG_GETARG_INT16(0);
439 	int64		val2 = PG_GETARG_INT64(1);
440 
441 	PG_RETURN_BOOL(val1 != val2);
442 }
443 
444 Datum
int28lt(PG_FUNCTION_ARGS)445 int28lt(PG_FUNCTION_ARGS)
446 {
447 	int16		val1 = PG_GETARG_INT16(0);
448 	int64		val2 = PG_GETARG_INT64(1);
449 
450 	PG_RETURN_BOOL(val1 < val2);
451 }
452 
453 Datum
int28gt(PG_FUNCTION_ARGS)454 int28gt(PG_FUNCTION_ARGS)
455 {
456 	int16		val1 = PG_GETARG_INT16(0);
457 	int64		val2 = PG_GETARG_INT64(1);
458 
459 	PG_RETURN_BOOL(val1 > val2);
460 }
461 
462 Datum
int28le(PG_FUNCTION_ARGS)463 int28le(PG_FUNCTION_ARGS)
464 {
465 	int16		val1 = PG_GETARG_INT16(0);
466 	int64		val2 = PG_GETARG_INT64(1);
467 
468 	PG_RETURN_BOOL(val1 <= val2);
469 }
470 
471 Datum
int28ge(PG_FUNCTION_ARGS)472 int28ge(PG_FUNCTION_ARGS)
473 {
474 	int16		val1 = PG_GETARG_INT16(0);
475 	int64		val2 = PG_GETARG_INT64(1);
476 
477 	PG_RETURN_BOOL(val1 >= val2);
478 }
479 
480 /*
481  * in_range support function for int8.
482  *
483  * Note: we needn't supply int8_int4 or int8_int2 variants, as implicit
484  * coercion of the offset value takes care of those scenarios just as well.
485  */
486 Datum
in_range_int8_int8(PG_FUNCTION_ARGS)487 in_range_int8_int8(PG_FUNCTION_ARGS)
488 {
489 	int64		val = PG_GETARG_INT64(0);
490 	int64		base = PG_GETARG_INT64(1);
491 	int64		offset = PG_GETARG_INT64(2);
492 	bool		sub = PG_GETARG_BOOL(3);
493 	bool		less = PG_GETARG_BOOL(4);
494 	int64		sum;
495 
496 	if (offset < 0)
497 		ereport(ERROR,
498 				(errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
499 				 errmsg("invalid preceding or following size in window function")));
500 
501 	if (sub)
502 		offset = -offset;		/* cannot overflow */
503 
504 	if (unlikely(pg_add_s64_overflow(base, offset, &sum)))
505 	{
506 		/*
507 		 * If sub is false, the true sum is surely more than val, so correct
508 		 * answer is the same as "less".  If sub is true, the true sum is
509 		 * surely less than val, so the answer is "!less".
510 		 */
511 		PG_RETURN_BOOL(sub ? !less : less);
512 	}
513 
514 	if (less)
515 		PG_RETURN_BOOL(val <= sum);
516 	else
517 		PG_RETURN_BOOL(val >= sum);
518 }
519 
520 
521 /*----------------------------------------------------------
522  *	Arithmetic operators on 64-bit integers.
523  *---------------------------------------------------------*/
524 
525 Datum
int8um(PG_FUNCTION_ARGS)526 int8um(PG_FUNCTION_ARGS)
527 {
528 	int64		arg = PG_GETARG_INT64(0);
529 	int64		result;
530 
531 	if (unlikely(arg == PG_INT64_MIN))
532 		ereport(ERROR,
533 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
534 				 errmsg("bigint out of range")));
535 	result = -arg;
536 	PG_RETURN_INT64(result);
537 }
538 
539 Datum
int8up(PG_FUNCTION_ARGS)540 int8up(PG_FUNCTION_ARGS)
541 {
542 	int64		arg = PG_GETARG_INT64(0);
543 
544 	PG_RETURN_INT64(arg);
545 }
546 
547 Datum
int8pl(PG_FUNCTION_ARGS)548 int8pl(PG_FUNCTION_ARGS)
549 {
550 	int64		arg1 = PG_GETARG_INT64(0);
551 	int64		arg2 = PG_GETARG_INT64(1);
552 	int64		result;
553 
554 	if (unlikely(pg_add_s64_overflow(arg1, arg2, &result)))
555 		ereport(ERROR,
556 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
557 				 errmsg("bigint out of range")));
558 	PG_RETURN_INT64(result);
559 }
560 
561 Datum
int8mi(PG_FUNCTION_ARGS)562 int8mi(PG_FUNCTION_ARGS)
563 {
564 	int64		arg1 = PG_GETARG_INT64(0);
565 	int64		arg2 = PG_GETARG_INT64(1);
566 	int64		result;
567 
568 	if (unlikely(pg_sub_s64_overflow(arg1, arg2, &result)))
569 		ereport(ERROR,
570 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
571 				 errmsg("bigint out of range")));
572 	PG_RETURN_INT64(result);
573 }
574 
575 Datum
int8mul(PG_FUNCTION_ARGS)576 int8mul(PG_FUNCTION_ARGS)
577 {
578 	int64		arg1 = PG_GETARG_INT64(0);
579 	int64		arg2 = PG_GETARG_INT64(1);
580 	int64		result;
581 
582 	if (unlikely(pg_mul_s64_overflow(arg1, arg2, &result)))
583 		ereport(ERROR,
584 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
585 				 errmsg("bigint out of range")));
586 	PG_RETURN_INT64(result);
587 }
588 
589 Datum
int8div(PG_FUNCTION_ARGS)590 int8div(PG_FUNCTION_ARGS)
591 {
592 	int64		arg1 = PG_GETARG_INT64(0);
593 	int64		arg2 = PG_GETARG_INT64(1);
594 	int64		result;
595 
596 	if (arg2 == 0)
597 	{
598 		ereport(ERROR,
599 				(errcode(ERRCODE_DIVISION_BY_ZERO),
600 				 errmsg("division by zero")));
601 		/* ensure compiler realizes we mustn't reach the division (gcc bug) */
602 		PG_RETURN_NULL();
603 	}
604 
605 	/*
606 	 * INT64_MIN / -1 is problematic, since the result can't be represented on
607 	 * a two's-complement machine.  Some machines produce INT64_MIN, some
608 	 * produce zero, some throw an exception.  We can dodge the problem by
609 	 * recognizing that division by -1 is the same as negation.
610 	 */
611 	if (arg2 == -1)
612 	{
613 		if (unlikely(arg1 == PG_INT64_MIN))
614 			ereport(ERROR,
615 					(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
616 					 errmsg("bigint out of range")));
617 		result = -arg1;
618 		PG_RETURN_INT64(result);
619 	}
620 
621 	/* No overflow is possible */
622 
623 	result = arg1 / arg2;
624 
625 	PG_RETURN_INT64(result);
626 }
627 
628 /* int8abs()
629  * Absolute value
630  */
631 Datum
int8abs(PG_FUNCTION_ARGS)632 int8abs(PG_FUNCTION_ARGS)
633 {
634 	int64		arg1 = PG_GETARG_INT64(0);
635 	int64		result;
636 
637 	if (unlikely(arg1 == PG_INT64_MIN))
638 		ereport(ERROR,
639 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
640 				 errmsg("bigint out of range")));
641 	result = (arg1 < 0) ? -arg1 : arg1;
642 	PG_RETURN_INT64(result);
643 }
644 
645 /* int8mod()
646  * Modulo operation.
647  */
648 Datum
int8mod(PG_FUNCTION_ARGS)649 int8mod(PG_FUNCTION_ARGS)
650 {
651 	int64		arg1 = PG_GETARG_INT64(0);
652 	int64		arg2 = PG_GETARG_INT64(1);
653 
654 	if (unlikely(arg2 == 0))
655 	{
656 		ereport(ERROR,
657 				(errcode(ERRCODE_DIVISION_BY_ZERO),
658 				 errmsg("division by zero")));
659 		/* ensure compiler realizes we mustn't reach the division (gcc bug) */
660 		PG_RETURN_NULL();
661 	}
662 
663 	/*
664 	 * Some machines throw a floating-point exception for INT64_MIN % -1,
665 	 * which is a bit silly since the correct answer is perfectly
666 	 * well-defined, namely zero.
667 	 */
668 	if (arg2 == -1)
669 		PG_RETURN_INT64(0);
670 
671 	/* No overflow is possible */
672 
673 	PG_RETURN_INT64(arg1 % arg2);
674 }
675 
676 /*
677  * Greatest Common Divisor
678  *
679  * Returns the largest positive integer that exactly divides both inputs.
680  * Special cases:
681  *   - gcd(x, 0) = gcd(0, x) = abs(x)
682  *   		because 0 is divisible by anything
683  *   - gcd(0, 0) = 0
684  *   		complies with the previous definition and is a common convention
685  *
686  * Special care must be taken if either input is INT64_MIN ---
687  * gcd(0, INT64_MIN), gcd(INT64_MIN, 0) and gcd(INT64_MIN, INT64_MIN) are
688  * all equal to abs(INT64_MIN), which cannot be represented as a 64-bit signed
689  * integer.
690  */
691 static int64
int8gcd_internal(int64 arg1,int64 arg2)692 int8gcd_internal(int64 arg1, int64 arg2)
693 {
694 	int64		swap;
695 	int64		a1,
696 				a2;
697 
698 	/*
699 	 * Put the greater absolute value in arg1.
700 	 *
701 	 * This would happen automatically in the loop below, but avoids an
702 	 * expensive modulo operation, and simplifies the special-case handling
703 	 * for INT64_MIN below.
704 	 *
705 	 * We do this in negative space in order to handle INT64_MIN.
706 	 */
707 	a1 = (arg1 < 0) ? arg1 : -arg1;
708 	a2 = (arg2 < 0) ? arg2 : -arg2;
709 	if (a1 > a2)
710 	{
711 		swap = arg1;
712 		arg1 = arg2;
713 		arg2 = swap;
714 	}
715 
716 	/* Special care needs to be taken with INT64_MIN.  See comments above. */
717 	if (arg1 == PG_INT64_MIN)
718 	{
719 		if (arg2 == 0 || arg2 == PG_INT64_MIN)
720 			ereport(ERROR,
721 					(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
722 					 errmsg("bigint out of range")));
723 
724 		/*
725 		 * Some machines throw a floating-point exception for INT64_MIN % -1,
726 		 * which is a bit silly since the correct answer is perfectly
727 		 * well-defined, namely zero.  Guard against this and just return the
728 		 * result, gcd(INT64_MIN, -1) = 1.
729 		 */
730 		if (arg2 == -1)
731 			return 1;
732 	}
733 
734 	/* Use the Euclidean algorithm to find the GCD */
735 	while (arg2 != 0)
736 	{
737 		swap = arg2;
738 		arg2 = arg1 % arg2;
739 		arg1 = swap;
740 	}
741 
742 	/*
743 	 * Make sure the result is positive. (We know we don't have INT64_MIN
744 	 * anymore).
745 	 */
746 	if (arg1 < 0)
747 		arg1 = -arg1;
748 
749 	return arg1;
750 }
751 
752 Datum
int8gcd(PG_FUNCTION_ARGS)753 int8gcd(PG_FUNCTION_ARGS)
754 {
755 	int64		arg1 = PG_GETARG_INT64(0);
756 	int64		arg2 = PG_GETARG_INT64(1);
757 	int64		result;
758 
759 	result = int8gcd_internal(arg1, arg2);
760 
761 	PG_RETURN_INT64(result);
762 }
763 
764 /*
765  * Least Common Multiple
766  */
767 Datum
int8lcm(PG_FUNCTION_ARGS)768 int8lcm(PG_FUNCTION_ARGS)
769 {
770 	int64		arg1 = PG_GETARG_INT64(0);
771 	int64		arg2 = PG_GETARG_INT64(1);
772 	int64		gcd;
773 	int64		result;
774 
775 	/*
776 	 * Handle lcm(x, 0) = lcm(0, x) = 0 as a special case.  This prevents a
777 	 * division-by-zero error below when x is zero, and an overflow error from
778 	 * the GCD computation when x = INT64_MIN.
779 	 */
780 	if (arg1 == 0 || arg2 == 0)
781 		PG_RETURN_INT64(0);
782 
783 	/* lcm(x, y) = abs(x / gcd(x, y) * y) */
784 	gcd = int8gcd_internal(arg1, arg2);
785 	arg1 = arg1 / gcd;
786 
787 	if (unlikely(pg_mul_s64_overflow(arg1, arg2, &result)))
788 		ereport(ERROR,
789 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
790 				 errmsg("bigint out of range")));
791 
792 	/* If the result is INT64_MIN, it cannot be represented. */
793 	if (unlikely(result == PG_INT64_MIN))
794 		ereport(ERROR,
795 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
796 				 errmsg("bigint out of range")));
797 
798 	if (result < 0)
799 		result = -result;
800 
801 	PG_RETURN_INT64(result);
802 }
803 
804 Datum
int8inc(PG_FUNCTION_ARGS)805 int8inc(PG_FUNCTION_ARGS)
806 {
807 	/*
808 	 * When int8 is pass-by-reference, we provide this special case to avoid
809 	 * palloc overhead for COUNT(): when called as an aggregate, we know that
810 	 * the argument is modifiable local storage, so just update it in-place.
811 	 * (If int8 is pass-by-value, then of course this is useless as well as
812 	 * incorrect, so just ifdef it out.)
813 	 */
814 #ifndef USE_FLOAT8_BYVAL		/* controls int8 too */
815 	if (AggCheckCallContext(fcinfo, NULL))
816 	{
817 		int64	   *arg = (int64 *) PG_GETARG_POINTER(0);
818 
819 		if (unlikely(pg_add_s64_overflow(*arg, 1, arg)))
820 			ereport(ERROR,
821 					(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
822 					 errmsg("bigint out of range")));
823 
824 		PG_RETURN_POINTER(arg);
825 	}
826 	else
827 #endif
828 	{
829 		/* Not called as an aggregate, so just do it the dumb way */
830 		int64		arg = PG_GETARG_INT64(0);
831 		int64		result;
832 
833 		if (unlikely(pg_add_s64_overflow(arg, 1, &result)))
834 			ereport(ERROR,
835 					(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
836 					 errmsg("bigint out of range")));
837 
838 		PG_RETURN_INT64(result);
839 	}
840 }
841 
842 Datum
int8dec(PG_FUNCTION_ARGS)843 int8dec(PG_FUNCTION_ARGS)
844 {
845 	/*
846 	 * When int8 is pass-by-reference, we provide this special case to avoid
847 	 * palloc overhead for COUNT(): when called as an aggregate, we know that
848 	 * the argument is modifiable local storage, so just update it in-place.
849 	 * (If int8 is pass-by-value, then of course this is useless as well as
850 	 * incorrect, so just ifdef it out.)
851 	 */
852 #ifndef USE_FLOAT8_BYVAL		/* controls int8 too */
853 	if (AggCheckCallContext(fcinfo, NULL))
854 	{
855 		int64	   *arg = (int64 *) PG_GETARG_POINTER(0);
856 
857 		if (unlikely(pg_sub_s64_overflow(*arg, 1, arg)))
858 			ereport(ERROR,
859 					(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
860 					 errmsg("bigint out of range")));
861 		PG_RETURN_POINTER(arg);
862 	}
863 	else
864 #endif
865 	{
866 		/* Not called as an aggregate, so just do it the dumb way */
867 		int64		arg = PG_GETARG_INT64(0);
868 		int64		result;
869 
870 		if (unlikely(pg_sub_s64_overflow(arg, 1, &result)))
871 			ereport(ERROR,
872 					(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
873 					 errmsg("bigint out of range")));
874 
875 		PG_RETURN_INT64(result);
876 	}
877 }
878 
879 
880 /*
881  * These functions are exactly like int8inc/int8dec but are used for
882  * aggregates that count only non-null values.  Since the functions are
883  * declared strict, the null checks happen before we ever get here, and all we
884  * need do is increment the state value.  We could actually make these pg_proc
885  * entries point right at int8inc/int8dec, but then the opr_sanity regression
886  * test would complain about mismatched entries for a built-in function.
887  */
888 
889 Datum
int8inc_any(PG_FUNCTION_ARGS)890 int8inc_any(PG_FUNCTION_ARGS)
891 {
892 	return int8inc(fcinfo);
893 }
894 
895 Datum
int8inc_float8_float8(PG_FUNCTION_ARGS)896 int8inc_float8_float8(PG_FUNCTION_ARGS)
897 {
898 	return int8inc(fcinfo);
899 }
900 
901 Datum
int8dec_any(PG_FUNCTION_ARGS)902 int8dec_any(PG_FUNCTION_ARGS)
903 {
904 	return int8dec(fcinfo);
905 }
906 
907 
908 Datum
int8larger(PG_FUNCTION_ARGS)909 int8larger(PG_FUNCTION_ARGS)
910 {
911 	int64		arg1 = PG_GETARG_INT64(0);
912 	int64		arg2 = PG_GETARG_INT64(1);
913 	int64		result;
914 
915 	result = ((arg1 > arg2) ? arg1 : arg2);
916 
917 	PG_RETURN_INT64(result);
918 }
919 
920 Datum
int8smaller(PG_FUNCTION_ARGS)921 int8smaller(PG_FUNCTION_ARGS)
922 {
923 	int64		arg1 = PG_GETARG_INT64(0);
924 	int64		arg2 = PG_GETARG_INT64(1);
925 	int64		result;
926 
927 	result = ((arg1 < arg2) ? arg1 : arg2);
928 
929 	PG_RETURN_INT64(result);
930 }
931 
932 Datum
int84pl(PG_FUNCTION_ARGS)933 int84pl(PG_FUNCTION_ARGS)
934 {
935 	int64		arg1 = PG_GETARG_INT64(0);
936 	int32		arg2 = PG_GETARG_INT32(1);
937 	int64		result;
938 
939 	if (unlikely(pg_add_s64_overflow(arg1, (int64) arg2, &result)))
940 		ereport(ERROR,
941 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
942 				 errmsg("bigint out of range")));
943 	PG_RETURN_INT64(result);
944 }
945 
946 Datum
int84mi(PG_FUNCTION_ARGS)947 int84mi(PG_FUNCTION_ARGS)
948 {
949 	int64		arg1 = PG_GETARG_INT64(0);
950 	int32		arg2 = PG_GETARG_INT32(1);
951 	int64		result;
952 
953 	if (unlikely(pg_sub_s64_overflow(arg1, (int64) arg2, &result)))
954 		ereport(ERROR,
955 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
956 				 errmsg("bigint out of range")));
957 	PG_RETURN_INT64(result);
958 }
959 
960 Datum
int84mul(PG_FUNCTION_ARGS)961 int84mul(PG_FUNCTION_ARGS)
962 {
963 	int64		arg1 = PG_GETARG_INT64(0);
964 	int32		arg2 = PG_GETARG_INT32(1);
965 	int64		result;
966 
967 	if (unlikely(pg_mul_s64_overflow(arg1, (int64) arg2, &result)))
968 		ereport(ERROR,
969 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
970 				 errmsg("bigint out of range")));
971 	PG_RETURN_INT64(result);
972 }
973 
974 Datum
int84div(PG_FUNCTION_ARGS)975 int84div(PG_FUNCTION_ARGS)
976 {
977 	int64		arg1 = PG_GETARG_INT64(0);
978 	int32		arg2 = PG_GETARG_INT32(1);
979 	int64		result;
980 
981 	if (arg2 == 0)
982 	{
983 		ereport(ERROR,
984 				(errcode(ERRCODE_DIVISION_BY_ZERO),
985 				 errmsg("division by zero")));
986 		/* ensure compiler realizes we mustn't reach the division (gcc bug) */
987 		PG_RETURN_NULL();
988 	}
989 
990 	/*
991 	 * INT64_MIN / -1 is problematic, since the result can't be represented on
992 	 * a two's-complement machine.  Some machines produce INT64_MIN, some
993 	 * produce zero, some throw an exception.  We can dodge the problem by
994 	 * recognizing that division by -1 is the same as negation.
995 	 */
996 	if (arg2 == -1)
997 	{
998 		if (unlikely(arg1 == PG_INT64_MIN))
999 			ereport(ERROR,
1000 					(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1001 					 errmsg("bigint out of range")));
1002 		result = -arg1;
1003 		PG_RETURN_INT64(result);
1004 	}
1005 
1006 	/* No overflow is possible */
1007 
1008 	result = arg1 / arg2;
1009 
1010 	PG_RETURN_INT64(result);
1011 }
1012 
1013 Datum
int48pl(PG_FUNCTION_ARGS)1014 int48pl(PG_FUNCTION_ARGS)
1015 {
1016 	int32		arg1 = PG_GETARG_INT32(0);
1017 	int64		arg2 = PG_GETARG_INT64(1);
1018 	int64		result;
1019 
1020 	if (unlikely(pg_add_s64_overflow((int64) arg1, arg2, &result)))
1021 		ereport(ERROR,
1022 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1023 				 errmsg("bigint out of range")));
1024 	PG_RETURN_INT64(result);
1025 }
1026 
1027 Datum
int48mi(PG_FUNCTION_ARGS)1028 int48mi(PG_FUNCTION_ARGS)
1029 {
1030 	int32		arg1 = PG_GETARG_INT32(0);
1031 	int64		arg2 = PG_GETARG_INT64(1);
1032 	int64		result;
1033 
1034 	if (unlikely(pg_sub_s64_overflow((int64) arg1, arg2, &result)))
1035 		ereport(ERROR,
1036 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1037 				 errmsg("bigint out of range")));
1038 	PG_RETURN_INT64(result);
1039 }
1040 
1041 Datum
int48mul(PG_FUNCTION_ARGS)1042 int48mul(PG_FUNCTION_ARGS)
1043 {
1044 	int32		arg1 = PG_GETARG_INT32(0);
1045 	int64		arg2 = PG_GETARG_INT64(1);
1046 	int64		result;
1047 
1048 	if (unlikely(pg_mul_s64_overflow((int64) arg1, arg2, &result)))
1049 		ereport(ERROR,
1050 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1051 				 errmsg("bigint out of range")));
1052 	PG_RETURN_INT64(result);
1053 }
1054 
1055 Datum
int48div(PG_FUNCTION_ARGS)1056 int48div(PG_FUNCTION_ARGS)
1057 {
1058 	int32		arg1 = PG_GETARG_INT32(0);
1059 	int64		arg2 = PG_GETARG_INT64(1);
1060 
1061 	if (unlikely(arg2 == 0))
1062 	{
1063 		ereport(ERROR,
1064 				(errcode(ERRCODE_DIVISION_BY_ZERO),
1065 				 errmsg("division by zero")));
1066 		/* ensure compiler realizes we mustn't reach the division (gcc bug) */
1067 		PG_RETURN_NULL();
1068 	}
1069 
1070 	/* No overflow is possible */
1071 	PG_RETURN_INT64((int64) arg1 / arg2);
1072 }
1073 
1074 Datum
int82pl(PG_FUNCTION_ARGS)1075 int82pl(PG_FUNCTION_ARGS)
1076 {
1077 	int64		arg1 = PG_GETARG_INT64(0);
1078 	int16		arg2 = PG_GETARG_INT16(1);
1079 	int64		result;
1080 
1081 	if (unlikely(pg_add_s64_overflow(arg1, (int64) arg2, &result)))
1082 		ereport(ERROR,
1083 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1084 				 errmsg("bigint out of range")));
1085 	PG_RETURN_INT64(result);
1086 }
1087 
1088 Datum
int82mi(PG_FUNCTION_ARGS)1089 int82mi(PG_FUNCTION_ARGS)
1090 {
1091 	int64		arg1 = PG_GETARG_INT64(0);
1092 	int16		arg2 = PG_GETARG_INT16(1);
1093 	int64		result;
1094 
1095 	if (unlikely(pg_sub_s64_overflow(arg1, (int64) arg2, &result)))
1096 		ereport(ERROR,
1097 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1098 				 errmsg("bigint out of range")));
1099 	PG_RETURN_INT64(result);
1100 }
1101 
1102 Datum
int82mul(PG_FUNCTION_ARGS)1103 int82mul(PG_FUNCTION_ARGS)
1104 {
1105 	int64		arg1 = PG_GETARG_INT64(0);
1106 	int16		arg2 = PG_GETARG_INT16(1);
1107 	int64		result;
1108 
1109 	if (unlikely(pg_mul_s64_overflow(arg1, (int64) arg2, &result)))
1110 		ereport(ERROR,
1111 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1112 				 errmsg("bigint out of range")));
1113 	PG_RETURN_INT64(result);
1114 }
1115 
1116 Datum
int82div(PG_FUNCTION_ARGS)1117 int82div(PG_FUNCTION_ARGS)
1118 {
1119 	int64		arg1 = PG_GETARG_INT64(0);
1120 	int16		arg2 = PG_GETARG_INT16(1);
1121 	int64		result;
1122 
1123 	if (unlikely(arg2 == 0))
1124 	{
1125 		ereport(ERROR,
1126 				(errcode(ERRCODE_DIVISION_BY_ZERO),
1127 				 errmsg("division by zero")));
1128 		/* ensure compiler realizes we mustn't reach the division (gcc bug) */
1129 		PG_RETURN_NULL();
1130 	}
1131 
1132 	/*
1133 	 * INT64_MIN / -1 is problematic, since the result can't be represented on
1134 	 * a two's-complement machine.  Some machines produce INT64_MIN, some
1135 	 * produce zero, some throw an exception.  We can dodge the problem by
1136 	 * recognizing that division by -1 is the same as negation.
1137 	 */
1138 	if (arg2 == -1)
1139 	{
1140 		if (unlikely(arg1 == PG_INT64_MIN))
1141 			ereport(ERROR,
1142 					(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1143 					 errmsg("bigint out of range")));
1144 		result = -arg1;
1145 		PG_RETURN_INT64(result);
1146 	}
1147 
1148 	/* No overflow is possible */
1149 
1150 	result = arg1 / arg2;
1151 
1152 	PG_RETURN_INT64(result);
1153 }
1154 
1155 Datum
int28pl(PG_FUNCTION_ARGS)1156 int28pl(PG_FUNCTION_ARGS)
1157 {
1158 	int16		arg1 = PG_GETARG_INT16(0);
1159 	int64		arg2 = PG_GETARG_INT64(1);
1160 	int64		result;
1161 
1162 	if (unlikely(pg_add_s64_overflow((int64) arg1, arg2, &result)))
1163 		ereport(ERROR,
1164 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1165 				 errmsg("bigint out of range")));
1166 	PG_RETURN_INT64(result);
1167 }
1168 
1169 Datum
int28mi(PG_FUNCTION_ARGS)1170 int28mi(PG_FUNCTION_ARGS)
1171 {
1172 	int16		arg1 = PG_GETARG_INT16(0);
1173 	int64		arg2 = PG_GETARG_INT64(1);
1174 	int64		result;
1175 
1176 	if (unlikely(pg_sub_s64_overflow((int64) arg1, arg2, &result)))
1177 		ereport(ERROR,
1178 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1179 				 errmsg("bigint out of range")));
1180 	PG_RETURN_INT64(result);
1181 }
1182 
1183 Datum
int28mul(PG_FUNCTION_ARGS)1184 int28mul(PG_FUNCTION_ARGS)
1185 {
1186 	int16		arg1 = PG_GETARG_INT16(0);
1187 	int64		arg2 = PG_GETARG_INT64(1);
1188 	int64		result;
1189 
1190 	if (unlikely(pg_mul_s64_overflow((int64) arg1, arg2, &result)))
1191 		ereport(ERROR,
1192 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1193 				 errmsg("bigint out of range")));
1194 	PG_RETURN_INT64(result);
1195 }
1196 
1197 Datum
int28div(PG_FUNCTION_ARGS)1198 int28div(PG_FUNCTION_ARGS)
1199 {
1200 	int16		arg1 = PG_GETARG_INT16(0);
1201 	int64		arg2 = PG_GETARG_INT64(1);
1202 
1203 	if (unlikely(arg2 == 0))
1204 	{
1205 		ereport(ERROR,
1206 				(errcode(ERRCODE_DIVISION_BY_ZERO),
1207 				 errmsg("division by zero")));
1208 		/* ensure compiler realizes we mustn't reach the division (gcc bug) */
1209 		PG_RETURN_NULL();
1210 	}
1211 
1212 	/* No overflow is possible */
1213 	PG_RETURN_INT64((int64) arg1 / arg2);
1214 }
1215 
1216 /* Binary arithmetics
1217  *
1218  *		int8and		- returns arg1 & arg2
1219  *		int8or		- returns arg1 | arg2
1220  *		int8xor		- returns arg1 # arg2
1221  *		int8not		- returns ~arg1
1222  *		int8shl		- returns arg1 << arg2
1223  *		int8shr		- returns arg1 >> arg2
1224  */
1225 
1226 Datum
int8and(PG_FUNCTION_ARGS)1227 int8and(PG_FUNCTION_ARGS)
1228 {
1229 	int64		arg1 = PG_GETARG_INT64(0);
1230 	int64		arg2 = PG_GETARG_INT64(1);
1231 
1232 	PG_RETURN_INT64(arg1 & arg2);
1233 }
1234 
1235 Datum
int8or(PG_FUNCTION_ARGS)1236 int8or(PG_FUNCTION_ARGS)
1237 {
1238 	int64		arg1 = PG_GETARG_INT64(0);
1239 	int64		arg2 = PG_GETARG_INT64(1);
1240 
1241 	PG_RETURN_INT64(arg1 | arg2);
1242 }
1243 
1244 Datum
int8xor(PG_FUNCTION_ARGS)1245 int8xor(PG_FUNCTION_ARGS)
1246 {
1247 	int64		arg1 = PG_GETARG_INT64(0);
1248 	int64		arg2 = PG_GETARG_INT64(1);
1249 
1250 	PG_RETURN_INT64(arg1 ^ arg2);
1251 }
1252 
1253 Datum
int8not(PG_FUNCTION_ARGS)1254 int8not(PG_FUNCTION_ARGS)
1255 {
1256 	int64		arg1 = PG_GETARG_INT64(0);
1257 
1258 	PG_RETURN_INT64(~arg1);
1259 }
1260 
1261 Datum
int8shl(PG_FUNCTION_ARGS)1262 int8shl(PG_FUNCTION_ARGS)
1263 {
1264 	int64		arg1 = PG_GETARG_INT64(0);
1265 	int32		arg2 = PG_GETARG_INT32(1);
1266 
1267 	PG_RETURN_INT64(arg1 << arg2);
1268 }
1269 
1270 Datum
int8shr(PG_FUNCTION_ARGS)1271 int8shr(PG_FUNCTION_ARGS)
1272 {
1273 	int64		arg1 = PG_GETARG_INT64(0);
1274 	int32		arg2 = PG_GETARG_INT32(1);
1275 
1276 	PG_RETURN_INT64(arg1 >> arg2);
1277 }
1278 
1279 /*----------------------------------------------------------
1280  *	Conversion operators.
1281  *---------------------------------------------------------*/
1282 
1283 Datum
int48(PG_FUNCTION_ARGS)1284 int48(PG_FUNCTION_ARGS)
1285 {
1286 	int32		arg = PG_GETARG_INT32(0);
1287 
1288 	PG_RETURN_INT64((int64) arg);
1289 }
1290 
1291 Datum
int84(PG_FUNCTION_ARGS)1292 int84(PG_FUNCTION_ARGS)
1293 {
1294 	int64		arg = PG_GETARG_INT64(0);
1295 
1296 	if (unlikely(arg < PG_INT32_MIN) || unlikely(arg > PG_INT32_MAX))
1297 		ereport(ERROR,
1298 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1299 				 errmsg("integer out of range")));
1300 
1301 	PG_RETURN_INT32((int32) arg);
1302 }
1303 
1304 Datum
int28(PG_FUNCTION_ARGS)1305 int28(PG_FUNCTION_ARGS)
1306 {
1307 	int16		arg = PG_GETARG_INT16(0);
1308 
1309 	PG_RETURN_INT64((int64) arg);
1310 }
1311 
1312 Datum
int82(PG_FUNCTION_ARGS)1313 int82(PG_FUNCTION_ARGS)
1314 {
1315 	int64		arg = PG_GETARG_INT64(0);
1316 
1317 	if (unlikely(arg < PG_INT16_MIN) || unlikely(arg > PG_INT16_MAX))
1318 		ereport(ERROR,
1319 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1320 				 errmsg("smallint out of range")));
1321 
1322 	PG_RETURN_INT16((int16) arg);
1323 }
1324 
1325 Datum
i8tod(PG_FUNCTION_ARGS)1326 i8tod(PG_FUNCTION_ARGS)
1327 {
1328 	int64		arg = PG_GETARG_INT64(0);
1329 	float8		result;
1330 
1331 	result = arg;
1332 
1333 	PG_RETURN_FLOAT8(result);
1334 }
1335 
1336 /* dtoi8()
1337  * Convert float8 to 8-byte integer.
1338  */
1339 Datum
dtoi8(PG_FUNCTION_ARGS)1340 dtoi8(PG_FUNCTION_ARGS)
1341 {
1342 	float8		num = PG_GETARG_FLOAT8(0);
1343 
1344 	/*
1345 	 * Get rid of any fractional part in the input.  This is so we don't fail
1346 	 * on just-out-of-range values that would round into range.  Note
1347 	 * assumption that rint() will pass through a NaN or Inf unchanged.
1348 	 */
1349 	num = rint(num);
1350 
1351 	/* Range check */
1352 	if (unlikely(isnan(num) || !FLOAT8_FITS_IN_INT64(num)))
1353 		ereport(ERROR,
1354 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1355 				 errmsg("bigint out of range")));
1356 
1357 	PG_RETURN_INT64((int64) num);
1358 }
1359 
1360 Datum
i8tof(PG_FUNCTION_ARGS)1361 i8tof(PG_FUNCTION_ARGS)
1362 {
1363 	int64		arg = PG_GETARG_INT64(0);
1364 	float4		result;
1365 
1366 	result = arg;
1367 
1368 	PG_RETURN_FLOAT4(result);
1369 }
1370 
1371 /* ftoi8()
1372  * Convert float4 to 8-byte integer.
1373  */
1374 Datum
ftoi8(PG_FUNCTION_ARGS)1375 ftoi8(PG_FUNCTION_ARGS)
1376 {
1377 	float4		num = PG_GETARG_FLOAT4(0);
1378 
1379 	/*
1380 	 * Get rid of any fractional part in the input.  This is so we don't fail
1381 	 * on just-out-of-range values that would round into range.  Note
1382 	 * assumption that rint() will pass through a NaN or Inf unchanged.
1383 	 */
1384 	num = rint(num);
1385 
1386 	/* Range check */
1387 	if (unlikely(isnan(num) || !FLOAT4_FITS_IN_INT64(num)))
1388 		ereport(ERROR,
1389 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1390 				 errmsg("bigint out of range")));
1391 
1392 	PG_RETURN_INT64((int64) num);
1393 }
1394 
1395 Datum
i8tooid(PG_FUNCTION_ARGS)1396 i8tooid(PG_FUNCTION_ARGS)
1397 {
1398 	int64		arg = PG_GETARG_INT64(0);
1399 
1400 	if (unlikely(arg < 0) || unlikely(arg > PG_UINT32_MAX))
1401 		ereport(ERROR,
1402 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1403 				 errmsg("OID out of range")));
1404 
1405 	PG_RETURN_OID((Oid) arg);
1406 }
1407 
1408 Datum
oidtoi8(PG_FUNCTION_ARGS)1409 oidtoi8(PG_FUNCTION_ARGS)
1410 {
1411 	Oid			arg = PG_GETARG_OID(0);
1412 
1413 	PG_RETURN_INT64((int64) arg);
1414 }
1415 
1416 /*
1417  * non-persistent numeric series generator
1418  */
1419 Datum
generate_series_int8(PG_FUNCTION_ARGS)1420 generate_series_int8(PG_FUNCTION_ARGS)
1421 {
1422 	return generate_series_step_int8(fcinfo);
1423 }
1424 
1425 Datum
generate_series_step_int8(PG_FUNCTION_ARGS)1426 generate_series_step_int8(PG_FUNCTION_ARGS)
1427 {
1428 	FuncCallContext *funcctx;
1429 	generate_series_fctx *fctx;
1430 	int64		result;
1431 	MemoryContext oldcontext;
1432 
1433 	/* stuff done only on the first call of the function */
1434 	if (SRF_IS_FIRSTCALL())
1435 	{
1436 		int64		start = PG_GETARG_INT64(0);
1437 		int64		finish = PG_GETARG_INT64(1);
1438 		int64		step = 1;
1439 
1440 		/* see if we were given an explicit step size */
1441 		if (PG_NARGS() == 3)
1442 			step = PG_GETARG_INT64(2);
1443 		if (step == 0)
1444 			ereport(ERROR,
1445 					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1446 					 errmsg("step size cannot equal zero")));
1447 
1448 		/* create a function context for cross-call persistence */
1449 		funcctx = SRF_FIRSTCALL_INIT();
1450 
1451 		/*
1452 		 * switch to memory context appropriate for multiple function calls
1453 		 */
1454 		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1455 
1456 		/* allocate memory for user context */
1457 		fctx = (generate_series_fctx *) palloc(sizeof(generate_series_fctx));
1458 
1459 		/*
1460 		 * Use fctx to keep state from call to call. Seed current with the
1461 		 * original start value
1462 		 */
1463 		fctx->current = start;
1464 		fctx->finish = finish;
1465 		fctx->step = step;
1466 
1467 		funcctx->user_fctx = fctx;
1468 		MemoryContextSwitchTo(oldcontext);
1469 	}
1470 
1471 	/* stuff done on every call of the function */
1472 	funcctx = SRF_PERCALL_SETUP();
1473 
1474 	/*
1475 	 * get the saved state and use current as the result for this iteration
1476 	 */
1477 	fctx = funcctx->user_fctx;
1478 	result = fctx->current;
1479 
1480 	if ((fctx->step > 0 && fctx->current <= fctx->finish) ||
1481 		(fctx->step < 0 && fctx->current >= fctx->finish))
1482 	{
1483 		/*
1484 		 * Increment current in preparation for next iteration. If next-value
1485 		 * computation overflows, this is the final result.
1486 		 */
1487 		if (pg_add_s64_overflow(fctx->current, fctx->step, &fctx->current))
1488 			fctx->step = 0;
1489 
1490 		/* do when there is more left to send */
1491 		SRF_RETURN_NEXT(funcctx, Int64GetDatum(result));
1492 	}
1493 	else
1494 		/* do when there is no more left */
1495 		SRF_RETURN_DONE(funcctx);
1496 }
1497 
1498 /*
1499  * Planner support function for generate_series(int8, int8 [, int8])
1500  */
1501 Datum
generate_series_int8_support(PG_FUNCTION_ARGS)1502 generate_series_int8_support(PG_FUNCTION_ARGS)
1503 {
1504 	Node	   *rawreq = (Node *) PG_GETARG_POINTER(0);
1505 	Node	   *ret = NULL;
1506 
1507 	if (IsA(rawreq, SupportRequestRows))
1508 	{
1509 		/* Try to estimate the number of rows returned */
1510 		SupportRequestRows *req = (SupportRequestRows *) rawreq;
1511 
1512 		if (is_funcclause(req->node))	/* be paranoid */
1513 		{
1514 			List	   *args = ((FuncExpr *) req->node)->args;
1515 			Node	   *arg1,
1516 					   *arg2,
1517 					   *arg3;
1518 
1519 			/* We can use estimated argument values here */
1520 			arg1 = estimate_expression_value(req->root, linitial(args));
1521 			arg2 = estimate_expression_value(req->root, lsecond(args));
1522 			if (list_length(args) >= 3)
1523 				arg3 = estimate_expression_value(req->root, lthird(args));
1524 			else
1525 				arg3 = NULL;
1526 
1527 			/*
1528 			 * If any argument is constant NULL, we can safely assume that
1529 			 * zero rows are returned.  Otherwise, if they're all non-NULL
1530 			 * constants, we can calculate the number of rows that will be
1531 			 * returned.  Use double arithmetic to avoid overflow hazards.
1532 			 */
1533 			if ((IsA(arg1, Const) &&
1534 				 ((Const *) arg1)->constisnull) ||
1535 				(IsA(arg2, Const) &&
1536 				 ((Const *) arg2)->constisnull) ||
1537 				(arg3 != NULL && IsA(arg3, Const) &&
1538 				 ((Const *) arg3)->constisnull))
1539 			{
1540 				req->rows = 0;
1541 				ret = (Node *) req;
1542 			}
1543 			else if (IsA(arg1, Const) &&
1544 					 IsA(arg2, Const) &&
1545 					 (arg3 == NULL || IsA(arg3, Const)))
1546 			{
1547 				double		start,
1548 							finish,
1549 							step;
1550 
1551 				start = DatumGetInt64(((Const *) arg1)->constvalue);
1552 				finish = DatumGetInt64(((Const *) arg2)->constvalue);
1553 				step = arg3 ? DatumGetInt64(((Const *) arg3)->constvalue) : 1;
1554 
1555 				/* This equation works for either sign of step */
1556 				if (step != 0)
1557 				{
1558 					req->rows = floor((finish - start + step) / step);
1559 					ret = (Node *) req;
1560 				}
1561 			}
1562 		}
1563 	}
1564 
1565 	PG_RETURN_POINTER(ret);
1566 }
1567