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