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