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