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