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