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