1 /*-------------------------------------------------------------------------
2 *
3 * int8.c
4 * Internal 64-bit integer operations
5 *
6 * Portions Copyright (c) 1996-2018, 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 <float.h> /* for _isnan */
18 #include <limits.h>
19 #include <math.h>
20
21 #include "common/int.h"
22 #include "funcapi.h"
23 #include "libpq/pqformat.h"
24 #include "utils/int8.h"
25 #include "utils/builtins.h"
26
27
28 #define MAXINT8LEN 25
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 if (unlikely(tmp == PG_INT64_MIN))
106 goto out_of_range;
107 tmp = -tmp;
108 }
109
110 *result = tmp;
111 return true;
112
113 out_of_range:
114 if (!errorOK)
115 ereport(ERROR,
116 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
117 errmsg("value \"%s\" is out of range for type %s",
118 str, "bigint")));
119 return false;
120
121 invalid_syntax:
122 if (!errorOK)
123 ereport(ERROR,
124 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
125 errmsg("invalid input syntax for integer: \"%s\"",
126 str)));
127 return false;
128 }
129
130 /* int8in()
131 */
132 Datum
int8in(PG_FUNCTION_ARGS)133 int8in(PG_FUNCTION_ARGS)
134 {
135 char *str = PG_GETARG_CSTRING(0);
136 int64 result;
137
138 (void) scanint8(str, false, &result);
139 PG_RETURN_INT64(result);
140 }
141
142
143 /* int8out()
144 */
145 Datum
int8out(PG_FUNCTION_ARGS)146 int8out(PG_FUNCTION_ARGS)
147 {
148 int64 val = PG_GETARG_INT64(0);
149 char buf[MAXINT8LEN + 1];
150 char *result;
151
152 pg_lltoa(val, buf);
153 result = pstrdup(buf);
154 PG_RETURN_CSTRING(result);
155 }
156
157 /*
158 * int8recv - converts external binary format to int8
159 */
160 Datum
int8recv(PG_FUNCTION_ARGS)161 int8recv(PG_FUNCTION_ARGS)
162 {
163 StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
164
165 PG_RETURN_INT64(pq_getmsgint64(buf));
166 }
167
168 /*
169 * int8send - converts int8 to binary format
170 */
171 Datum
int8send(PG_FUNCTION_ARGS)172 int8send(PG_FUNCTION_ARGS)
173 {
174 int64 arg1 = PG_GETARG_INT64(0);
175 StringInfoData buf;
176
177 pq_begintypsend(&buf);
178 pq_sendint64(&buf, arg1);
179 PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
180 }
181
182
183 /*----------------------------------------------------------
184 * Relational operators for int8s, including cross-data-type comparisons.
185 *---------------------------------------------------------*/
186
187 /* int8relop()
188 * Is val1 relop val2?
189 */
190 Datum
int8eq(PG_FUNCTION_ARGS)191 int8eq(PG_FUNCTION_ARGS)
192 {
193 int64 val1 = PG_GETARG_INT64(0);
194 int64 val2 = PG_GETARG_INT64(1);
195
196 PG_RETURN_BOOL(val1 == val2);
197 }
198
199 Datum
int8ne(PG_FUNCTION_ARGS)200 int8ne(PG_FUNCTION_ARGS)
201 {
202 int64 val1 = PG_GETARG_INT64(0);
203 int64 val2 = PG_GETARG_INT64(1);
204
205 PG_RETURN_BOOL(val1 != val2);
206 }
207
208 Datum
int8lt(PG_FUNCTION_ARGS)209 int8lt(PG_FUNCTION_ARGS)
210 {
211 int64 val1 = PG_GETARG_INT64(0);
212 int64 val2 = PG_GETARG_INT64(1);
213
214 PG_RETURN_BOOL(val1 < val2);
215 }
216
217 Datum
int8gt(PG_FUNCTION_ARGS)218 int8gt(PG_FUNCTION_ARGS)
219 {
220 int64 val1 = PG_GETARG_INT64(0);
221 int64 val2 = PG_GETARG_INT64(1);
222
223 PG_RETURN_BOOL(val1 > val2);
224 }
225
226 Datum
int8le(PG_FUNCTION_ARGS)227 int8le(PG_FUNCTION_ARGS)
228 {
229 int64 val1 = PG_GETARG_INT64(0);
230 int64 val2 = PG_GETARG_INT64(1);
231
232 PG_RETURN_BOOL(val1 <= val2);
233 }
234
235 Datum
int8ge(PG_FUNCTION_ARGS)236 int8ge(PG_FUNCTION_ARGS)
237 {
238 int64 val1 = PG_GETARG_INT64(0);
239 int64 val2 = PG_GETARG_INT64(1);
240
241 PG_RETURN_BOOL(val1 >= val2);
242 }
243
244 /* int84relop()
245 * Is 64-bit val1 relop 32-bit val2?
246 */
247 Datum
int84eq(PG_FUNCTION_ARGS)248 int84eq(PG_FUNCTION_ARGS)
249 {
250 int64 val1 = PG_GETARG_INT64(0);
251 int32 val2 = PG_GETARG_INT32(1);
252
253 PG_RETURN_BOOL(val1 == val2);
254 }
255
256 Datum
int84ne(PG_FUNCTION_ARGS)257 int84ne(PG_FUNCTION_ARGS)
258 {
259 int64 val1 = PG_GETARG_INT64(0);
260 int32 val2 = PG_GETARG_INT32(1);
261
262 PG_RETURN_BOOL(val1 != val2);
263 }
264
265 Datum
int84lt(PG_FUNCTION_ARGS)266 int84lt(PG_FUNCTION_ARGS)
267 {
268 int64 val1 = PG_GETARG_INT64(0);
269 int32 val2 = PG_GETARG_INT32(1);
270
271 PG_RETURN_BOOL(val1 < val2);
272 }
273
274 Datum
int84gt(PG_FUNCTION_ARGS)275 int84gt(PG_FUNCTION_ARGS)
276 {
277 int64 val1 = PG_GETARG_INT64(0);
278 int32 val2 = PG_GETARG_INT32(1);
279
280 PG_RETURN_BOOL(val1 > val2);
281 }
282
283 Datum
int84le(PG_FUNCTION_ARGS)284 int84le(PG_FUNCTION_ARGS)
285 {
286 int64 val1 = PG_GETARG_INT64(0);
287 int32 val2 = PG_GETARG_INT32(1);
288
289 PG_RETURN_BOOL(val1 <= val2);
290 }
291
292 Datum
int84ge(PG_FUNCTION_ARGS)293 int84ge(PG_FUNCTION_ARGS)
294 {
295 int64 val1 = PG_GETARG_INT64(0);
296 int32 val2 = PG_GETARG_INT32(1);
297
298 PG_RETURN_BOOL(val1 >= val2);
299 }
300
301 /* int48relop()
302 * Is 32-bit val1 relop 64-bit val2?
303 */
304 Datum
int48eq(PG_FUNCTION_ARGS)305 int48eq(PG_FUNCTION_ARGS)
306 {
307 int32 val1 = PG_GETARG_INT32(0);
308 int64 val2 = PG_GETARG_INT64(1);
309
310 PG_RETURN_BOOL(val1 == val2);
311 }
312
313 Datum
int48ne(PG_FUNCTION_ARGS)314 int48ne(PG_FUNCTION_ARGS)
315 {
316 int32 val1 = PG_GETARG_INT32(0);
317 int64 val2 = PG_GETARG_INT64(1);
318
319 PG_RETURN_BOOL(val1 != val2);
320 }
321
322 Datum
int48lt(PG_FUNCTION_ARGS)323 int48lt(PG_FUNCTION_ARGS)
324 {
325 int32 val1 = PG_GETARG_INT32(0);
326 int64 val2 = PG_GETARG_INT64(1);
327
328 PG_RETURN_BOOL(val1 < val2);
329 }
330
331 Datum
int48gt(PG_FUNCTION_ARGS)332 int48gt(PG_FUNCTION_ARGS)
333 {
334 int32 val1 = PG_GETARG_INT32(0);
335 int64 val2 = PG_GETARG_INT64(1);
336
337 PG_RETURN_BOOL(val1 > val2);
338 }
339
340 Datum
int48le(PG_FUNCTION_ARGS)341 int48le(PG_FUNCTION_ARGS)
342 {
343 int32 val1 = PG_GETARG_INT32(0);
344 int64 val2 = PG_GETARG_INT64(1);
345
346 PG_RETURN_BOOL(val1 <= val2);
347 }
348
349 Datum
int48ge(PG_FUNCTION_ARGS)350 int48ge(PG_FUNCTION_ARGS)
351 {
352 int32 val1 = PG_GETARG_INT32(0);
353 int64 val2 = PG_GETARG_INT64(1);
354
355 PG_RETURN_BOOL(val1 >= val2);
356 }
357
358 /* int82relop()
359 * Is 64-bit val1 relop 16-bit val2?
360 */
361 Datum
int82eq(PG_FUNCTION_ARGS)362 int82eq(PG_FUNCTION_ARGS)
363 {
364 int64 val1 = PG_GETARG_INT64(0);
365 int16 val2 = PG_GETARG_INT16(1);
366
367 PG_RETURN_BOOL(val1 == val2);
368 }
369
370 Datum
int82ne(PG_FUNCTION_ARGS)371 int82ne(PG_FUNCTION_ARGS)
372 {
373 int64 val1 = PG_GETARG_INT64(0);
374 int16 val2 = PG_GETARG_INT16(1);
375
376 PG_RETURN_BOOL(val1 != val2);
377 }
378
379 Datum
int82lt(PG_FUNCTION_ARGS)380 int82lt(PG_FUNCTION_ARGS)
381 {
382 int64 val1 = PG_GETARG_INT64(0);
383 int16 val2 = PG_GETARG_INT16(1);
384
385 PG_RETURN_BOOL(val1 < val2);
386 }
387
388 Datum
int82gt(PG_FUNCTION_ARGS)389 int82gt(PG_FUNCTION_ARGS)
390 {
391 int64 val1 = PG_GETARG_INT64(0);
392 int16 val2 = PG_GETARG_INT16(1);
393
394 PG_RETURN_BOOL(val1 > val2);
395 }
396
397 Datum
int82le(PG_FUNCTION_ARGS)398 int82le(PG_FUNCTION_ARGS)
399 {
400 int64 val1 = PG_GETARG_INT64(0);
401 int16 val2 = PG_GETARG_INT16(1);
402
403 PG_RETURN_BOOL(val1 <= val2);
404 }
405
406 Datum
int82ge(PG_FUNCTION_ARGS)407 int82ge(PG_FUNCTION_ARGS)
408 {
409 int64 val1 = PG_GETARG_INT64(0);
410 int16 val2 = PG_GETARG_INT16(1);
411
412 PG_RETURN_BOOL(val1 >= val2);
413 }
414
415 /* int28relop()
416 * Is 16-bit val1 relop 64-bit val2?
417 */
418 Datum
int28eq(PG_FUNCTION_ARGS)419 int28eq(PG_FUNCTION_ARGS)
420 {
421 int16 val1 = PG_GETARG_INT16(0);
422 int64 val2 = PG_GETARG_INT64(1);
423
424 PG_RETURN_BOOL(val1 == val2);
425 }
426
427 Datum
int28ne(PG_FUNCTION_ARGS)428 int28ne(PG_FUNCTION_ARGS)
429 {
430 int16 val1 = PG_GETARG_INT16(0);
431 int64 val2 = PG_GETARG_INT64(1);
432
433 PG_RETURN_BOOL(val1 != val2);
434 }
435
436 Datum
int28lt(PG_FUNCTION_ARGS)437 int28lt(PG_FUNCTION_ARGS)
438 {
439 int16 val1 = PG_GETARG_INT16(0);
440 int64 val2 = PG_GETARG_INT64(1);
441
442 PG_RETURN_BOOL(val1 < val2);
443 }
444
445 Datum
int28gt(PG_FUNCTION_ARGS)446 int28gt(PG_FUNCTION_ARGS)
447 {
448 int16 val1 = PG_GETARG_INT16(0);
449 int64 val2 = PG_GETARG_INT64(1);
450
451 PG_RETURN_BOOL(val1 > val2);
452 }
453
454 Datum
int28le(PG_FUNCTION_ARGS)455 int28le(PG_FUNCTION_ARGS)
456 {
457 int16 val1 = PG_GETARG_INT16(0);
458 int64 val2 = PG_GETARG_INT64(1);
459
460 PG_RETURN_BOOL(val1 <= val2);
461 }
462
463 Datum
int28ge(PG_FUNCTION_ARGS)464 int28ge(PG_FUNCTION_ARGS)
465 {
466 int16 val1 = PG_GETARG_INT16(0);
467 int64 val2 = PG_GETARG_INT64(1);
468
469 PG_RETURN_BOOL(val1 >= val2);
470 }
471
472 /*
473 * in_range support function for int8.
474 *
475 * Note: we needn't supply int8_int4 or int8_int2 variants, as implicit
476 * coercion of the offset value takes care of those scenarios just as well.
477 */
478 Datum
in_range_int8_int8(PG_FUNCTION_ARGS)479 in_range_int8_int8(PG_FUNCTION_ARGS)
480 {
481 int64 val = PG_GETARG_INT64(0);
482 int64 base = PG_GETARG_INT64(1);
483 int64 offset = PG_GETARG_INT64(2);
484 bool sub = PG_GETARG_BOOL(3);
485 bool less = PG_GETARG_BOOL(4);
486 int64 sum;
487
488 if (offset < 0)
489 ereport(ERROR,
490 (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
491 errmsg("invalid preceding or following size in window function")));
492
493 if (sub)
494 offset = -offset; /* cannot overflow */
495
496 if (unlikely(pg_add_s64_overflow(base, offset, &sum)))
497 {
498 /*
499 * If sub is false, the true sum is surely more than val, so correct
500 * answer is the same as "less". If sub is true, the true sum is
501 * surely less than val, so the answer is "!less".
502 */
503 PG_RETURN_BOOL(sub ? !less : less);
504 }
505
506 if (less)
507 PG_RETURN_BOOL(val <= sum);
508 else
509 PG_RETURN_BOOL(val >= sum);
510 }
511
512
513 /*----------------------------------------------------------
514 * Arithmetic operators on 64-bit integers.
515 *---------------------------------------------------------*/
516
517 Datum
int8um(PG_FUNCTION_ARGS)518 int8um(PG_FUNCTION_ARGS)
519 {
520 int64 arg = PG_GETARG_INT64(0);
521 int64 result;
522
523 if (unlikely(arg == PG_INT64_MIN))
524 ereport(ERROR,
525 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
526 errmsg("bigint out of range")));
527 result = -arg;
528 PG_RETURN_INT64(result);
529 }
530
531 Datum
int8up(PG_FUNCTION_ARGS)532 int8up(PG_FUNCTION_ARGS)
533 {
534 int64 arg = PG_GETARG_INT64(0);
535
536 PG_RETURN_INT64(arg);
537 }
538
539 Datum
int8pl(PG_FUNCTION_ARGS)540 int8pl(PG_FUNCTION_ARGS)
541 {
542 int64 arg1 = PG_GETARG_INT64(0);
543 int64 arg2 = PG_GETARG_INT64(1);
544 int64 result;
545
546 if (unlikely(pg_add_s64_overflow(arg1, arg2, &result)))
547 ereport(ERROR,
548 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
549 errmsg("bigint out of range")));
550 PG_RETURN_INT64(result);
551 }
552
553 Datum
int8mi(PG_FUNCTION_ARGS)554 int8mi(PG_FUNCTION_ARGS)
555 {
556 int64 arg1 = PG_GETARG_INT64(0);
557 int64 arg2 = PG_GETARG_INT64(1);
558 int64 result;
559
560 if (unlikely(pg_sub_s64_overflow(arg1, arg2, &result)))
561 ereport(ERROR,
562 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
563 errmsg("bigint out of range")));
564 PG_RETURN_INT64(result);
565 }
566
567 Datum
int8mul(PG_FUNCTION_ARGS)568 int8mul(PG_FUNCTION_ARGS)
569 {
570 int64 arg1 = PG_GETARG_INT64(0);
571 int64 arg2 = PG_GETARG_INT64(1);
572 int64 result;
573
574 if (unlikely(pg_mul_s64_overflow(arg1, arg2, &result)))
575 ereport(ERROR,
576 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
577 errmsg("bigint out of range")));
578 PG_RETURN_INT64(result);
579 }
580
581 Datum
int8div(PG_FUNCTION_ARGS)582 int8div(PG_FUNCTION_ARGS)
583 {
584 int64 arg1 = PG_GETARG_INT64(0);
585 int64 arg2 = PG_GETARG_INT64(1);
586 int64 result;
587
588 if (arg2 == 0)
589 {
590 ereport(ERROR,
591 (errcode(ERRCODE_DIVISION_BY_ZERO),
592 errmsg("division by zero")));
593 /* ensure compiler realizes we mustn't reach the division (gcc bug) */
594 PG_RETURN_NULL();
595 }
596
597 /*
598 * INT64_MIN / -1 is problematic, since the result can't be represented on
599 * a two's-complement machine. Some machines produce INT64_MIN, some
600 * produce zero, some throw an exception. We can dodge the problem by
601 * recognizing that division by -1 is the same as negation.
602 */
603 if (arg2 == -1)
604 {
605 if (unlikely(arg1 == PG_INT64_MIN))
606 ereport(ERROR,
607 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
608 errmsg("bigint out of range")));
609 result = -arg1;
610 PG_RETURN_INT64(result);
611 }
612
613 /* No overflow is possible */
614
615 result = arg1 / arg2;
616
617 PG_RETURN_INT64(result);
618 }
619
620 /* int8abs()
621 * Absolute value
622 */
623 Datum
int8abs(PG_FUNCTION_ARGS)624 int8abs(PG_FUNCTION_ARGS)
625 {
626 int64 arg1 = PG_GETARG_INT64(0);
627 int64 result;
628
629 if (unlikely(arg1 == PG_INT64_MIN))
630 ereport(ERROR,
631 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
632 errmsg("bigint out of range")));
633 result = (arg1 < 0) ? -arg1 : arg1;
634 PG_RETURN_INT64(result);
635 }
636
637 /* int8mod()
638 * Modulo operation.
639 */
640 Datum
int8mod(PG_FUNCTION_ARGS)641 int8mod(PG_FUNCTION_ARGS)
642 {
643 int64 arg1 = PG_GETARG_INT64(0);
644 int64 arg2 = PG_GETARG_INT64(1);
645
646 if (unlikely(arg2 == 0))
647 {
648 ereport(ERROR,
649 (errcode(ERRCODE_DIVISION_BY_ZERO),
650 errmsg("division by zero")));
651 /* ensure compiler realizes we mustn't reach the division (gcc bug) */
652 PG_RETURN_NULL();
653 }
654
655 /*
656 * Some machines throw a floating-point exception for INT64_MIN % -1,
657 * which is a bit silly since the correct answer is perfectly
658 * well-defined, namely zero.
659 */
660 if (arg2 == -1)
661 PG_RETURN_INT64(0);
662
663 /* No overflow is possible */
664
665 PG_RETURN_INT64(arg1 % arg2);
666 }
667
668
669 Datum
int8inc(PG_FUNCTION_ARGS)670 int8inc(PG_FUNCTION_ARGS)
671 {
672 /*
673 * When int8 is pass-by-reference, we provide this special case to avoid
674 * palloc overhead for COUNT(): when called as an aggregate, we know that
675 * the argument is modifiable local storage, so just update it in-place.
676 * (If int8 is pass-by-value, then of course this is useless as well as
677 * incorrect, so just ifdef it out.)
678 */
679 #ifndef USE_FLOAT8_BYVAL /* controls int8 too */
680 if (AggCheckCallContext(fcinfo, NULL))
681 {
682 int64 *arg = (int64 *) PG_GETARG_POINTER(0);
683
684 if (unlikely(pg_add_s64_overflow(*arg, 1, arg)))
685 ereport(ERROR,
686 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
687 errmsg("bigint out of range")));
688
689 PG_RETURN_POINTER(arg);
690 }
691 else
692 #endif
693 {
694 /* Not called as an aggregate, so just do it the dumb way */
695 int64 arg = PG_GETARG_INT64(0);
696 int64 result;
697
698 if (unlikely(pg_add_s64_overflow(arg, 1, &result)))
699 ereport(ERROR,
700 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
701 errmsg("bigint out of range")));
702
703 PG_RETURN_INT64(result);
704 }
705 }
706
707 Datum
int8dec(PG_FUNCTION_ARGS)708 int8dec(PG_FUNCTION_ARGS)
709 {
710 /*
711 * When int8 is pass-by-reference, we provide this special case to avoid
712 * palloc overhead for COUNT(): when called as an aggregate, we know that
713 * the argument is modifiable local storage, so just update it in-place.
714 * (If int8 is pass-by-value, then of course this is useless as well as
715 * incorrect, so just ifdef it out.)
716 */
717 #ifndef USE_FLOAT8_BYVAL /* controls int8 too */
718 if (AggCheckCallContext(fcinfo, NULL))
719 {
720 int64 *arg = (int64 *) PG_GETARG_POINTER(0);
721
722 if (unlikely(pg_sub_s64_overflow(*arg, 1, arg)))
723 ereport(ERROR,
724 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
725 errmsg("bigint out of range")));
726 PG_RETURN_POINTER(arg);
727 }
728 else
729 #endif
730 {
731 /* Not called as an aggregate, so just do it the dumb way */
732 int64 arg = PG_GETARG_INT64(0);
733 int64 result;
734
735 if (unlikely(pg_sub_s64_overflow(arg, 1, &result)))
736 ereport(ERROR,
737 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
738 errmsg("bigint out of range")));
739
740 PG_RETURN_INT64(result);
741 }
742 }
743
744
745 /*
746 * These functions are exactly like int8inc/int8dec but are used for
747 * aggregates that count only non-null values. Since the functions are
748 * declared strict, the null checks happen before we ever get here, and all we
749 * need do is increment the state value. We could actually make these pg_proc
750 * entries point right at int8inc/int8dec, but then the opr_sanity regression
751 * test would complain about mismatched entries for a built-in function.
752 */
753
754 Datum
int8inc_any(PG_FUNCTION_ARGS)755 int8inc_any(PG_FUNCTION_ARGS)
756 {
757 return int8inc(fcinfo);
758 }
759
760 Datum
int8inc_float8_float8(PG_FUNCTION_ARGS)761 int8inc_float8_float8(PG_FUNCTION_ARGS)
762 {
763 return int8inc(fcinfo);
764 }
765
766 Datum
int8dec_any(PG_FUNCTION_ARGS)767 int8dec_any(PG_FUNCTION_ARGS)
768 {
769 return int8dec(fcinfo);
770 }
771
772
773 Datum
int8larger(PG_FUNCTION_ARGS)774 int8larger(PG_FUNCTION_ARGS)
775 {
776 int64 arg1 = PG_GETARG_INT64(0);
777 int64 arg2 = PG_GETARG_INT64(1);
778 int64 result;
779
780 result = ((arg1 > arg2) ? arg1 : arg2);
781
782 PG_RETURN_INT64(result);
783 }
784
785 Datum
int8smaller(PG_FUNCTION_ARGS)786 int8smaller(PG_FUNCTION_ARGS)
787 {
788 int64 arg1 = PG_GETARG_INT64(0);
789 int64 arg2 = PG_GETARG_INT64(1);
790 int64 result;
791
792 result = ((arg1 < arg2) ? arg1 : arg2);
793
794 PG_RETURN_INT64(result);
795 }
796
797 Datum
int84pl(PG_FUNCTION_ARGS)798 int84pl(PG_FUNCTION_ARGS)
799 {
800 int64 arg1 = PG_GETARG_INT64(0);
801 int32 arg2 = PG_GETARG_INT32(1);
802 int64 result;
803
804 if (unlikely(pg_add_s64_overflow(arg1, (int64) arg2, &result)))
805 ereport(ERROR,
806 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
807 errmsg("bigint out of range")));
808 PG_RETURN_INT64(result);
809 }
810
811 Datum
int84mi(PG_FUNCTION_ARGS)812 int84mi(PG_FUNCTION_ARGS)
813 {
814 int64 arg1 = PG_GETARG_INT64(0);
815 int32 arg2 = PG_GETARG_INT32(1);
816 int64 result;
817
818 if (unlikely(pg_sub_s64_overflow(arg1, (int64) arg2, &result)))
819 ereport(ERROR,
820 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
821 errmsg("bigint out of range")));
822 PG_RETURN_INT64(result);
823 }
824
825 Datum
int84mul(PG_FUNCTION_ARGS)826 int84mul(PG_FUNCTION_ARGS)
827 {
828 int64 arg1 = PG_GETARG_INT64(0);
829 int32 arg2 = PG_GETARG_INT32(1);
830 int64 result;
831
832 if (unlikely(pg_mul_s64_overflow(arg1, (int64) arg2, &result)))
833 ereport(ERROR,
834 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
835 errmsg("bigint out of range")));
836 PG_RETURN_INT64(result);
837 }
838
839 Datum
int84div(PG_FUNCTION_ARGS)840 int84div(PG_FUNCTION_ARGS)
841 {
842 int64 arg1 = PG_GETARG_INT64(0);
843 int32 arg2 = PG_GETARG_INT32(1);
844 int64 result;
845
846 if (arg2 == 0)
847 {
848 ereport(ERROR,
849 (errcode(ERRCODE_DIVISION_BY_ZERO),
850 errmsg("division by zero")));
851 /* ensure compiler realizes we mustn't reach the division (gcc bug) */
852 PG_RETURN_NULL();
853 }
854
855 /*
856 * INT64_MIN / -1 is problematic, since the result can't be represented on
857 * a two's-complement machine. Some machines produce INT64_MIN, some
858 * produce zero, some throw an exception. We can dodge the problem by
859 * recognizing that division by -1 is the same as negation.
860 */
861 if (arg2 == -1)
862 {
863 if (unlikely(arg1 == PG_INT64_MIN))
864 ereport(ERROR,
865 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
866 errmsg("bigint out of range")));
867 result = -arg1;
868 PG_RETURN_INT64(result);
869 }
870
871 /* No overflow is possible */
872
873 result = arg1 / arg2;
874
875 PG_RETURN_INT64(result);
876 }
877
878 Datum
int48pl(PG_FUNCTION_ARGS)879 int48pl(PG_FUNCTION_ARGS)
880 {
881 int32 arg1 = PG_GETARG_INT32(0);
882 int64 arg2 = PG_GETARG_INT64(1);
883 int64 result;
884
885 if (unlikely(pg_add_s64_overflow((int64) arg1, arg2, &result)))
886 ereport(ERROR,
887 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
888 errmsg("bigint out of range")));
889 PG_RETURN_INT64(result);
890 }
891
892 Datum
int48mi(PG_FUNCTION_ARGS)893 int48mi(PG_FUNCTION_ARGS)
894 {
895 int32 arg1 = PG_GETARG_INT32(0);
896 int64 arg2 = PG_GETARG_INT64(1);
897 int64 result;
898
899 if (unlikely(pg_sub_s64_overflow((int64) arg1, arg2, &result)))
900 ereport(ERROR,
901 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
902 errmsg("bigint out of range")));
903 PG_RETURN_INT64(result);
904 }
905
906 Datum
int48mul(PG_FUNCTION_ARGS)907 int48mul(PG_FUNCTION_ARGS)
908 {
909 int32 arg1 = PG_GETARG_INT32(0);
910 int64 arg2 = PG_GETARG_INT64(1);
911 int64 result;
912
913 if (unlikely(pg_mul_s64_overflow((int64) arg1, arg2, &result)))
914 ereport(ERROR,
915 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
916 errmsg("bigint out of range")));
917 PG_RETURN_INT64(result);
918 }
919
920 Datum
int48div(PG_FUNCTION_ARGS)921 int48div(PG_FUNCTION_ARGS)
922 {
923 int32 arg1 = PG_GETARG_INT32(0);
924 int64 arg2 = PG_GETARG_INT64(1);
925
926 if (unlikely(arg2 == 0))
927 {
928 ereport(ERROR,
929 (errcode(ERRCODE_DIVISION_BY_ZERO),
930 errmsg("division by zero")));
931 /* ensure compiler realizes we mustn't reach the division (gcc bug) */
932 PG_RETURN_NULL();
933 }
934
935 /* No overflow is possible */
936 PG_RETURN_INT64((int64) arg1 / arg2);
937 }
938
939 Datum
int82pl(PG_FUNCTION_ARGS)940 int82pl(PG_FUNCTION_ARGS)
941 {
942 int64 arg1 = PG_GETARG_INT64(0);
943 int16 arg2 = PG_GETARG_INT16(1);
944 int64 result;
945
946 if (unlikely(pg_add_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
int82mi(PG_FUNCTION_ARGS)954 int82mi(PG_FUNCTION_ARGS)
955 {
956 int64 arg1 = PG_GETARG_INT64(0);
957 int16 arg2 = PG_GETARG_INT16(1);
958 int64 result;
959
960 if (unlikely(pg_sub_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
int82mul(PG_FUNCTION_ARGS)968 int82mul(PG_FUNCTION_ARGS)
969 {
970 int64 arg1 = PG_GETARG_INT64(0);
971 int16 arg2 = PG_GETARG_INT16(1);
972 int64 result;
973
974 if (unlikely(pg_mul_s64_overflow(arg1, (int64) arg2, &result)))
975 ereport(ERROR,
976 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
977 errmsg("bigint out of range")));
978 PG_RETURN_INT64(result);
979 }
980
981 Datum
int82div(PG_FUNCTION_ARGS)982 int82div(PG_FUNCTION_ARGS)
983 {
984 int64 arg1 = PG_GETARG_INT64(0);
985 int16 arg2 = PG_GETARG_INT16(1);
986 int64 result;
987
988 if (unlikely(arg2 == 0))
989 {
990 ereport(ERROR,
991 (errcode(ERRCODE_DIVISION_BY_ZERO),
992 errmsg("division by zero")));
993 /* ensure compiler realizes we mustn't reach the division (gcc bug) */
994 PG_RETURN_NULL();
995 }
996
997 /*
998 * INT64_MIN / -1 is problematic, since the result can't be represented on
999 * a two's-complement machine. Some machines produce INT64_MIN, some
1000 * produce zero, some throw an exception. We can dodge the problem by
1001 * recognizing that division by -1 is the same as negation.
1002 */
1003 if (arg2 == -1)
1004 {
1005 if (unlikely(arg1 == PG_INT64_MIN))
1006 ereport(ERROR,
1007 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1008 errmsg("bigint out of range")));
1009 result = -arg1;
1010 PG_RETURN_INT64(result);
1011 }
1012
1013 /* No overflow is possible */
1014
1015 result = arg1 / arg2;
1016
1017 PG_RETURN_INT64(result);
1018 }
1019
1020 Datum
int28pl(PG_FUNCTION_ARGS)1021 int28pl(PG_FUNCTION_ARGS)
1022 {
1023 int16 arg1 = PG_GETARG_INT16(0);
1024 int64 arg2 = PG_GETARG_INT64(1);
1025 int64 result;
1026
1027 if (unlikely(pg_add_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
int28mi(PG_FUNCTION_ARGS)1035 int28mi(PG_FUNCTION_ARGS)
1036 {
1037 int16 arg1 = PG_GETARG_INT16(0);
1038 int64 arg2 = PG_GETARG_INT64(1);
1039 int64 result;
1040
1041 if (unlikely(pg_sub_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
int28mul(PG_FUNCTION_ARGS)1049 int28mul(PG_FUNCTION_ARGS)
1050 {
1051 int16 arg1 = PG_GETARG_INT16(0);
1052 int64 arg2 = PG_GETARG_INT64(1);
1053 int64 result;
1054
1055 if (unlikely(pg_mul_s64_overflow((int64) arg1, arg2, &result)))
1056 ereport(ERROR,
1057 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1058 errmsg("bigint out of range")));
1059 PG_RETURN_INT64(result);
1060 }
1061
1062 Datum
int28div(PG_FUNCTION_ARGS)1063 int28div(PG_FUNCTION_ARGS)
1064 {
1065 int16 arg1 = PG_GETARG_INT16(0);
1066 int64 arg2 = PG_GETARG_INT64(1);
1067
1068 if (unlikely(arg2 == 0))
1069 {
1070 ereport(ERROR,
1071 (errcode(ERRCODE_DIVISION_BY_ZERO),
1072 errmsg("division by zero")));
1073 /* ensure compiler realizes we mustn't reach the division (gcc bug) */
1074 PG_RETURN_NULL();
1075 }
1076
1077 /* No overflow is possible */
1078 PG_RETURN_INT64((int64) arg1 / arg2);
1079 }
1080
1081 /* Binary arithmetics
1082 *
1083 * int8and - returns arg1 & arg2
1084 * int8or - returns arg1 | arg2
1085 * int8xor - returns arg1 # arg2
1086 * int8not - returns ~arg1
1087 * int8shl - returns arg1 << arg2
1088 * int8shr - returns arg1 >> arg2
1089 */
1090
1091 Datum
int8and(PG_FUNCTION_ARGS)1092 int8and(PG_FUNCTION_ARGS)
1093 {
1094 int64 arg1 = PG_GETARG_INT64(0);
1095 int64 arg2 = PG_GETARG_INT64(1);
1096
1097 PG_RETURN_INT64(arg1 & arg2);
1098 }
1099
1100 Datum
int8or(PG_FUNCTION_ARGS)1101 int8or(PG_FUNCTION_ARGS)
1102 {
1103 int64 arg1 = PG_GETARG_INT64(0);
1104 int64 arg2 = PG_GETARG_INT64(1);
1105
1106 PG_RETURN_INT64(arg1 | arg2);
1107 }
1108
1109 Datum
int8xor(PG_FUNCTION_ARGS)1110 int8xor(PG_FUNCTION_ARGS)
1111 {
1112 int64 arg1 = PG_GETARG_INT64(0);
1113 int64 arg2 = PG_GETARG_INT64(1);
1114
1115 PG_RETURN_INT64(arg1 ^ arg2);
1116 }
1117
1118 Datum
int8not(PG_FUNCTION_ARGS)1119 int8not(PG_FUNCTION_ARGS)
1120 {
1121 int64 arg1 = PG_GETARG_INT64(0);
1122
1123 PG_RETURN_INT64(~arg1);
1124 }
1125
1126 Datum
int8shl(PG_FUNCTION_ARGS)1127 int8shl(PG_FUNCTION_ARGS)
1128 {
1129 int64 arg1 = PG_GETARG_INT64(0);
1130 int32 arg2 = PG_GETARG_INT32(1);
1131
1132 PG_RETURN_INT64(arg1 << arg2);
1133 }
1134
1135 Datum
int8shr(PG_FUNCTION_ARGS)1136 int8shr(PG_FUNCTION_ARGS)
1137 {
1138 int64 arg1 = PG_GETARG_INT64(0);
1139 int32 arg2 = PG_GETARG_INT32(1);
1140
1141 PG_RETURN_INT64(arg1 >> arg2);
1142 }
1143
1144 /*----------------------------------------------------------
1145 * Conversion operators.
1146 *---------------------------------------------------------*/
1147
1148 Datum
int48(PG_FUNCTION_ARGS)1149 int48(PG_FUNCTION_ARGS)
1150 {
1151 int32 arg = PG_GETARG_INT32(0);
1152
1153 PG_RETURN_INT64((int64) arg);
1154 }
1155
1156 Datum
int84(PG_FUNCTION_ARGS)1157 int84(PG_FUNCTION_ARGS)
1158 {
1159 int64 arg = PG_GETARG_INT64(0);
1160
1161 if (unlikely(arg < PG_INT32_MIN) || unlikely(arg > PG_INT32_MAX))
1162 ereport(ERROR,
1163 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1164 errmsg("integer out of range")));
1165
1166 PG_RETURN_INT32((int32) arg);
1167 }
1168
1169 Datum
int28(PG_FUNCTION_ARGS)1170 int28(PG_FUNCTION_ARGS)
1171 {
1172 int16 arg = PG_GETARG_INT16(0);
1173
1174 PG_RETURN_INT64((int64) arg);
1175 }
1176
1177 Datum
int82(PG_FUNCTION_ARGS)1178 int82(PG_FUNCTION_ARGS)
1179 {
1180 int64 arg = PG_GETARG_INT64(0);
1181
1182 if (unlikely(arg < PG_INT16_MIN) || unlikely(arg > PG_INT16_MAX))
1183 ereport(ERROR,
1184 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1185 errmsg("smallint out of range")));
1186
1187 PG_RETURN_INT16((int16) arg);
1188 }
1189
1190 Datum
i8tod(PG_FUNCTION_ARGS)1191 i8tod(PG_FUNCTION_ARGS)
1192 {
1193 int64 arg = PG_GETARG_INT64(0);
1194 float8 result;
1195
1196 result = arg;
1197
1198 PG_RETURN_FLOAT8(result);
1199 }
1200
1201 /* dtoi8()
1202 * Convert float8 to 8-byte integer.
1203 */
1204 Datum
dtoi8(PG_FUNCTION_ARGS)1205 dtoi8(PG_FUNCTION_ARGS)
1206 {
1207 float8 num = PG_GETARG_FLOAT8(0);
1208
1209 /*
1210 * Get rid of any fractional part in the input. This is so we don't fail
1211 * on just-out-of-range values that would round into range. Note
1212 * assumption that rint() will pass through a NaN or Inf unchanged.
1213 */
1214 num = rint(num);
1215
1216 /* Range check */
1217 if (unlikely(isnan(num) || !FLOAT8_FITS_IN_INT64(num)))
1218 ereport(ERROR,
1219 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1220 errmsg("bigint out of range")));
1221
1222 PG_RETURN_INT64((int64) num);
1223 }
1224
1225 Datum
i8tof(PG_FUNCTION_ARGS)1226 i8tof(PG_FUNCTION_ARGS)
1227 {
1228 int64 arg = PG_GETARG_INT64(0);
1229 float4 result;
1230
1231 result = arg;
1232
1233 PG_RETURN_FLOAT4(result);
1234 }
1235
1236 /* ftoi8()
1237 * Convert float4 to 8-byte integer.
1238 */
1239 Datum
ftoi8(PG_FUNCTION_ARGS)1240 ftoi8(PG_FUNCTION_ARGS)
1241 {
1242 float4 num = PG_GETARG_FLOAT4(0);
1243
1244 /*
1245 * Get rid of any fractional part in the input. This is so we don't fail
1246 * on just-out-of-range values that would round into range. Note
1247 * assumption that rint() will pass through a NaN or Inf unchanged.
1248 */
1249 num = rint(num);
1250
1251 /* Range check */
1252 if (unlikely(isnan(num) || !FLOAT4_FITS_IN_INT64(num)))
1253 ereport(ERROR,
1254 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1255 errmsg("bigint out of range")));
1256
1257 PG_RETURN_INT64((int64) num);
1258 }
1259
1260 Datum
i8tooid(PG_FUNCTION_ARGS)1261 i8tooid(PG_FUNCTION_ARGS)
1262 {
1263 int64 arg = PG_GETARG_INT64(0);
1264
1265 if (unlikely(arg < 0) || unlikely(arg > PG_UINT32_MAX))
1266 ereport(ERROR,
1267 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1268 errmsg("OID out of range")));
1269
1270 PG_RETURN_OID((Oid) arg);
1271 }
1272
1273 Datum
oidtoi8(PG_FUNCTION_ARGS)1274 oidtoi8(PG_FUNCTION_ARGS)
1275 {
1276 Oid arg = PG_GETARG_OID(0);
1277
1278 PG_RETURN_INT64((int64) arg);
1279 }
1280
1281 /*
1282 * non-persistent numeric series generator
1283 */
1284 Datum
generate_series_int8(PG_FUNCTION_ARGS)1285 generate_series_int8(PG_FUNCTION_ARGS)
1286 {
1287 return generate_series_step_int8(fcinfo);
1288 }
1289
1290 Datum
generate_series_step_int8(PG_FUNCTION_ARGS)1291 generate_series_step_int8(PG_FUNCTION_ARGS)
1292 {
1293 FuncCallContext *funcctx;
1294 generate_series_fctx *fctx;
1295 int64 result;
1296 MemoryContext oldcontext;
1297
1298 /* stuff done only on the first call of the function */
1299 if (SRF_IS_FIRSTCALL())
1300 {
1301 int64 start = PG_GETARG_INT64(0);
1302 int64 finish = PG_GETARG_INT64(1);
1303 int64 step = 1;
1304
1305 /* see if we were given an explicit step size */
1306 if (PG_NARGS() == 3)
1307 step = PG_GETARG_INT64(2);
1308 if (step == 0)
1309 ereport(ERROR,
1310 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1311 errmsg("step size cannot equal zero")));
1312
1313 /* create a function context for cross-call persistence */
1314 funcctx = SRF_FIRSTCALL_INIT();
1315
1316 /*
1317 * switch to memory context appropriate for multiple function calls
1318 */
1319 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1320
1321 /* allocate memory for user context */
1322 fctx = (generate_series_fctx *) palloc(sizeof(generate_series_fctx));
1323
1324 /*
1325 * Use fctx to keep state from call to call. Seed current with the
1326 * original start value
1327 */
1328 fctx->current = start;
1329 fctx->finish = finish;
1330 fctx->step = step;
1331
1332 funcctx->user_fctx = fctx;
1333 MemoryContextSwitchTo(oldcontext);
1334 }
1335
1336 /* stuff done on every call of the function */
1337 funcctx = SRF_PERCALL_SETUP();
1338
1339 /*
1340 * get the saved state and use current as the result for this iteration
1341 */
1342 fctx = funcctx->user_fctx;
1343 result = fctx->current;
1344
1345 if ((fctx->step > 0 && fctx->current <= fctx->finish) ||
1346 (fctx->step < 0 && fctx->current >= fctx->finish))
1347 {
1348 /*
1349 * Increment current in preparation for next iteration. If next-value
1350 * computation overflows, this is the final result.
1351 */
1352 if (pg_add_s64_overflow(fctx->current, fctx->step, &fctx->current))
1353 fctx->step = 0;
1354
1355 /* do when there is more left to send */
1356 SRF_RETURN_NEXT(funcctx, Int64GetDatum(result));
1357 }
1358 else
1359 /* do when there is no more left */
1360 SRF_RETURN_DONE(funcctx);
1361 }
1362