Age Owner TLA 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
7508 tgl 51 CBC 63944 : int8in(PG_FUNCTION_ARGS)
52 : {
419 peter 53 63944 : char *num = PG_GETARG_CSTRING(0);
54 :
121 tgl 55 GNC 63944 : PG_RETURN_INT64(pg_strtoint64_safe(num, fcinfo->context));
56 : }
57 :
58 :
59 : /* int8out()
60 : */
61 : Datum
8335 tgl 62 CBC 150046 : int8out(PG_FUNCTION_ARGS)
63 : {
64 150046 : int64 val = PG_GETARG_INT64(0);
65 : char buf[MAXINT8LEN + 1];
66 : char *result;
67 : int len;
68 :
1030 drowley 69 150046 : 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 150046 : result = palloc(len);
76 150046 : memcpy(result, buf, len);
8335 tgl 77 150046 : PG_RETURN_CSTRING(result);
78 : }
79 :
80 : /*
81 : * int8recv - converts external binary format to int8
82 : */
83 : Datum
7275 84 12 : int8recv(PG_FUNCTION_ARGS)
85 : {
86 12 : StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
87 :
88 12 : PG_RETURN_INT64(pq_getmsgint64(buf));
89 : }
90 :
91 : /*
92 : * int8send - converts int8 to binary format
93 : */
94 : Datum
95 2437 : int8send(PG_FUNCTION_ARGS)
96 : {
97 2437 : int64 arg1 = PG_GETARG_INT64(0);
98 : StringInfoData buf;
99 :
100 2437 : pq_begintypsend(&buf);
101 2437 : pq_sendint64(&buf, arg1);
102 2437 : 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
8335 114 130580 : int8eq(PG_FUNCTION_ARGS)
115 : {
116 130580 : int64 val1 = PG_GETARG_INT64(0);
117 130580 : int64 val2 = PG_GETARG_INT64(1);
118 :
119 130580 : PG_RETURN_BOOL(val1 == val2);
120 : }
121 :
122 : Datum
123 30025 : int8ne(PG_FUNCTION_ARGS)
124 : {
125 30025 : int64 val1 = PG_GETARG_INT64(0);
126 30025 : int64 val2 = PG_GETARG_INT64(1);
127 :
128 30025 : PG_RETURN_BOOL(val1 != val2);
129 : }
130 :
131 : Datum
132 149306 : int8lt(PG_FUNCTION_ARGS)
133 : {
134 149306 : int64 val1 = PG_GETARG_INT64(0);
135 149306 : int64 val2 = PG_GETARG_INT64(1);
136 :
137 149306 : PG_RETURN_BOOL(val1 < val2);
138 : }
139 :
140 : Datum
141 104910 : int8gt(PG_FUNCTION_ARGS)
142 : {
143 104910 : int64 val1 = PG_GETARG_INT64(0);
144 104910 : int64 val2 = PG_GETARG_INT64(1);
145 :
146 104910 : PG_RETURN_BOOL(val1 > val2);
147 : }
148 :
149 : Datum
150 2708 : int8le(PG_FUNCTION_ARGS)
151 : {
152 2708 : int64 val1 = PG_GETARG_INT64(0);
153 2708 : int64 val2 = PG_GETARG_INT64(1);
154 :
155 2708 : PG_RETURN_BOOL(val1 <= val2);
156 : }
157 :
158 : Datum
159 2823 : int8ge(PG_FUNCTION_ARGS)
160 : {
161 2823 : int64 val1 = PG_GETARG_INT64(0);
162 2823 : int64 val2 = PG_GETARG_INT64(1);
163 :
164 2823 : PG_RETURN_BOOL(val1 >= val2);
165 : }
166 :
167 : /* int84relop()
168 : * Is 64-bit val1 relop 32-bit val2?
169 : */
170 : Datum
171 89343 : int84eq(PG_FUNCTION_ARGS)
172 : {
173 89343 : int64 val1 = PG_GETARG_INT64(0);
174 89343 : int32 val2 = PG_GETARG_INT32(1);
175 :
176 89343 : PG_RETURN_BOOL(val1 == val2);
177 : }
178 :
179 : Datum
180 36 : int84ne(PG_FUNCTION_ARGS)
181 : {
182 36 : int64 val1 = PG_GETARG_INT64(0);
183 36 : int32 val2 = PG_GETARG_INT32(1);
184 :
185 36 : PG_RETURN_BOOL(val1 != val2);
186 : }
187 :
188 : Datum
189 335444 : int84lt(PG_FUNCTION_ARGS)
190 : {
191 335444 : int64 val1 = PG_GETARG_INT64(0);
192 335444 : int32 val2 = PG_GETARG_INT32(1);
193 :
194 335444 : PG_RETURN_BOOL(val1 < val2);
195 : }
196 :
197 : Datum
198 16909 : int84gt(PG_FUNCTION_ARGS)
199 : {
200 16909 : int64 val1 = PG_GETARG_INT64(0);
201 16909 : int32 val2 = PG_GETARG_INT32(1);
202 :
203 16909 : PG_RETURN_BOOL(val1 > val2);
204 : }
205 :
206 : Datum
207 139 : int84le(PG_FUNCTION_ARGS)
208 : {
209 139 : int64 val1 = PG_GETARG_INT64(0);
210 139 : int32 val2 = PG_GETARG_INT32(1);
211 :
212 139 : PG_RETURN_BOOL(val1 <= val2);
213 : }
214 :
215 : Datum
216 1676 : int84ge(PG_FUNCTION_ARGS)
217 : {
218 1676 : int64 val1 = PG_GETARG_INT64(0);
219 1676 : int32 val2 = PG_GETARG_INT32(1);
220 :
221 1676 : PG_RETURN_BOOL(val1 >= val2);
222 : }
223 :
224 : /* int48relop()
225 : * Is 32-bit val1 relop 64-bit val2?
226 : */
227 : Datum
228 45989 : int48eq(PG_FUNCTION_ARGS)
229 : {
230 45989 : int32 val1 = PG_GETARG_INT32(0);
231 45989 : int64 val2 = PG_GETARG_INT64(1);
232 :
233 45989 : PG_RETURN_BOOL(val1 == val2);
234 : }
235 :
236 : Datum
237 18 : int48ne(PG_FUNCTION_ARGS)
238 : {
239 18 : int32 val1 = PG_GETARG_INT32(0);
240 18 : int64 val2 = PG_GETARG_INT64(1);
241 :
242 18 : PG_RETURN_BOOL(val1 != val2);
243 : }
244 :
245 : Datum
246 3222 : int48lt(PG_FUNCTION_ARGS)
247 : {
248 3222 : int32 val1 = PG_GETARG_INT32(0);
249 3222 : int64 val2 = PG_GETARG_INT64(1);
250 :
251 3222 : PG_RETURN_BOOL(val1 < val2);
252 : }
253 :
254 : Datum
255 1635 : int48gt(PG_FUNCTION_ARGS)
256 : {
257 1635 : int32 val1 = PG_GETARG_INT32(0);
258 1635 : int64 val2 = PG_GETARG_INT64(1);
259 :
260 1635 : PG_RETURN_BOOL(val1 > val2);
261 : }
262 :
263 : Datum
264 1914 : int48le(PG_FUNCTION_ARGS)
265 : {
266 1914 : int32 val1 = PG_GETARG_INT32(0);
267 1914 : int64 val2 = PG_GETARG_INT64(1);
268 :
269 1914 : PG_RETURN_BOOL(val1 <= val2);
270 : }
271 :
272 : Datum
273 1737 : int48ge(PG_FUNCTION_ARGS)
274 : {
275 1737 : int32 val1 = PG_GETARG_INT32(0);
276 1737 : int64 val2 = PG_GETARG_INT64(1);
277 :
8290 278 1737 : PG_RETURN_BOOL(val1 >= val2);
279 : }
280 :
281 : /* int82relop()
282 : * Is 64-bit val1 relop 16-bit val2?
283 : */
284 : Datum
285 15 : int82eq(PG_FUNCTION_ARGS)
286 : {
287 15 : int64 val1 = PG_GETARG_INT64(0);
288 15 : int16 val2 = PG_GETARG_INT16(1);
289 :
290 15 : PG_RETURN_BOOL(val1 == val2);
291 : }
292 :
293 : Datum
294 15 : int82ne(PG_FUNCTION_ARGS)
295 : {
296 15 : int64 val1 = PG_GETARG_INT64(0);
297 15 : int16 val2 = PG_GETARG_INT16(1);
298 :
299 15 : PG_RETURN_BOOL(val1 != val2);
300 : }
301 :
302 : Datum
303 15 : int82lt(PG_FUNCTION_ARGS)
304 : {
305 15 : int64 val1 = PG_GETARG_INT64(0);
306 15 : int16 val2 = PG_GETARG_INT16(1);
307 :
308 15 : PG_RETURN_BOOL(val1 < val2);
309 : }
310 :
311 : Datum
312 1614 : int82gt(PG_FUNCTION_ARGS)
313 : {
314 1614 : int64 val1 = PG_GETARG_INT64(0);
315 1614 : int16 val2 = PG_GETARG_INT16(1);
316 :
317 1614 : PG_RETURN_BOOL(val1 > val2);
318 : }
319 :
320 : Datum
321 15 : int82le(PG_FUNCTION_ARGS)
322 : {
323 15 : int64 val1 = PG_GETARG_INT64(0);
324 15 : int16 val2 = PG_GETARG_INT16(1);
325 :
326 15 : PG_RETURN_BOOL(val1 <= val2);
327 : }
328 :
329 : Datum
330 1614 : int82ge(PG_FUNCTION_ARGS)
331 : {
332 1614 : int64 val1 = PG_GETARG_INT64(0);
333 1614 : int16 val2 = PG_GETARG_INT16(1);
334 :
335 1614 : PG_RETURN_BOOL(val1 >= val2);
336 : }
337 :
338 : /* int28relop()
339 : * Is 16-bit val1 relop 64-bit val2?
340 : */
341 : Datum
342 924 : int28eq(PG_FUNCTION_ARGS)
343 : {
344 924 : int16 val1 = PG_GETARG_INT16(0);
345 924 : int64 val2 = PG_GETARG_INT64(1);
346 :
347 924 : PG_RETURN_BOOL(val1 == val2);
348 : }
349 :
350 : Datum
351 1601 : int28ne(PG_FUNCTION_ARGS)
352 : {
353 1601 : int16 val1 = PG_GETARG_INT16(0);
354 1601 : int64 val2 = PG_GETARG_INT64(1);
355 :
356 1601 : PG_RETURN_BOOL(val1 != val2);
357 : }
358 :
359 : Datum
360 1614 : int28lt(PG_FUNCTION_ARGS)
361 : {
362 1614 : int16 val1 = PG_GETARG_INT16(0);
363 1614 : int64 val2 = PG_GETARG_INT64(1);
364 :
365 1614 : PG_RETURN_BOOL(val1 < val2);
366 : }
367 :
368 : Datum
369 1614 : int28gt(PG_FUNCTION_ARGS)
370 : {
371 1614 : int16 val1 = PG_GETARG_INT16(0);
372 1614 : int64 val2 = PG_GETARG_INT64(1);
373 :
374 1614 : PG_RETURN_BOOL(val1 > val2);
375 : }
376 :
377 : Datum
378 1914 : int28le(PG_FUNCTION_ARGS)
379 : {
380 1914 : int16 val1 = PG_GETARG_INT16(0);
381 1914 : int64 val2 = PG_GETARG_INT64(1);
382 :
383 1914 : PG_RETURN_BOOL(val1 <= val2);
384 : }
385 :
386 : Datum
387 1857 : int28ge(PG_FUNCTION_ARGS)
388 : {
389 1857 : int16 val1 = PG_GETARG_INT16(0);
390 1857 : int64 val2 = PG_GETARG_INT64(1);
391 :
8335 392 1857 : 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
1887 402 54 : in_range_int8_int8(PG_FUNCTION_ARGS)
403 : {
404 54 : int64 val = PG_GETARG_INT64(0);
405 54 : int64 base = PG_GETARG_INT64(1);
406 54 : int64 offset = PG_GETARG_INT64(2);
407 54 : bool sub = PG_GETARG_BOOL(3);
408 54 : bool less = PG_GETARG_BOOL(4);
409 : int64 sum;
410 :
411 54 : if (offset < 0)
1887 tgl 412 UBC 0 : ereport(ERROR,
413 : (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
414 : errmsg("invalid preceding or following size in window function")));
415 :
1887 tgl 416 CBC 54 : if (sub)
417 27 : offset = -offset; /* cannot overflow */
418 :
419 54 : 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 18 : PG_RETURN_BOOL(sub ? !less : less);
427 : }
428 :
429 36 : if (less)
430 18 : PG_RETURN_BOOL(val <= sum);
431 : else
432 18 : PG_RETURN_BOOL(val >= sum);
433 : }
434 :
435 :
436 : /*----------------------------------------------------------
437 : * Arithmetic operators on 64-bit integers.
438 : *---------------------------------------------------------*/
439 :
440 : Datum
8335 441 441 : int8um(PG_FUNCTION_ARGS)
442 : {
6761 443 441 : int64 arg = PG_GETARG_INT64(0);
444 : int64 result;
445 :
1944 andres 446 441 : if (unlikely(arg == PG_INT64_MIN))
6761 tgl 447 3 : ereport(ERROR,
448 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
449 : errmsg("bigint out of range")));
1944 andres 450 438 : result = -arg;
6761 tgl 451 438 : PG_RETURN_INT64(result);
452 : }
453 :
454 : Datum
7976 bruce 455 3 : int8up(PG_FUNCTION_ARGS)
456 : {
6761 tgl 457 3 : int64 arg = PG_GETARG_INT64(0);
458 :
459 3 : PG_RETURN_INT64(arg);
460 : }
461 :
462 : Datum
8335 463 65152 : int8pl(PG_FUNCTION_ARGS)
464 : {
6761 465 65152 : int64 arg1 = PG_GETARG_INT64(0);
466 65152 : int64 arg2 = PG_GETARG_INT64(1);
467 : int64 result;
468 :
1944 andres 469 65152 : if (unlikely(pg_add_s64_overflow(arg1, arg2, &result)))
6761 tgl 470 6 : ereport(ERROR,
471 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
472 : errmsg("bigint out of range")));
473 65146 : PG_RETURN_INT64(result);
474 : }
475 :
476 : Datum
8335 477 45 : int8mi(PG_FUNCTION_ARGS)
478 : {
6761 479 45 : int64 arg1 = PG_GETARG_INT64(0);
480 45 : int64 arg2 = PG_GETARG_INT64(1);
481 : int64 result;
482 :
1944 andres 483 45 : if (unlikely(pg_sub_s64_overflow(arg1, arg2, &result)))
6761 tgl 484 6 : ereport(ERROR,
485 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
486 : errmsg("bigint out of range")));
487 39 : PG_RETURN_INT64(result);
488 : }
489 :
490 : Datum
8335 491 6120 : int8mul(PG_FUNCTION_ARGS)
492 : {
6761 493 6120 : int64 arg1 = PG_GETARG_INT64(0);
494 6120 : int64 arg2 = PG_GETARG_INT64(1);
495 : int64 result;
496 :
1944 andres 497 6120 : if (unlikely(pg_mul_s64_overflow(arg1, arg2, &result)))
498 9 : ereport(ERROR,
499 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
500 : errmsg("bigint out of range")));
6761 tgl 501 6111 : PG_RETURN_INT64(result);
502 : }
503 :
504 : Datum
8335 505 61 : int8div(PG_FUNCTION_ARGS)
506 : {
6761 507 61 : int64 arg1 = PG_GETARG_INT64(0);
508 61 : int64 arg2 = PG_GETARG_INT64(1);
509 : int64 result;
510 :
511 61 : if (arg2 == 0)
512 : {
7196 513 3 : 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 : */
3793 526 58 : if (arg2 == -1)
527 : {
1944 andres 528 3 : if (unlikely(arg1 == PG_INT64_MIN))
3793 tgl 529 3 : ereport(ERROR,
530 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
531 : errmsg("bigint out of range")));
1944 andres 532 UBC 0 : result = -arg1;
3793 tgl 533 0 : PG_RETURN_INT64(result);
534 : }
535 :
536 : /* No overflow is possible */
537 :
3793 tgl 538 CBC 55 : result = arg1 / arg2;
539 :
6761 540 55 : PG_RETURN_INT64(result);
541 : }
542 :
543 : /* int8abs()
544 : * Absolute value
545 : */
546 : Datum
8335 547 18 : int8abs(PG_FUNCTION_ARGS)
548 : {
549 18 : int64 arg1 = PG_GETARG_INT64(0);
550 : int64 result;
551 :
1944 andres 552 18 : if (unlikely(arg1 == PG_INT64_MIN))
6761 tgl 553 3 : ereport(ERROR,
554 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
555 : errmsg("bigint out of range")));
1944 andres 556 15 : result = (arg1 < 0) ? -arg1 : arg1;
6761 tgl 557 15 : PG_RETURN_INT64(result);
558 : }
559 :
560 : /* int8mod()
561 : * Modulo operation.
562 : */
563 : Datum
8335 564 27 : int8mod(PG_FUNCTION_ARGS)
565 : {
6761 566 27 : int64 arg1 = PG_GETARG_INT64(0);
567 27 : int64 arg2 = PG_GETARG_INT64(1);
568 :
1944 andres 569 27 : if (unlikely(arg2 == 0))
570 : {
7196 tgl 571 3 : 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 : */
3798 583 24 : if (arg2 == -1)
584 9 : PG_RETURN_INT64(0);
585 :
586 : /* No overflow is possible */
587 :
6761 588 15 : 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
1170 dean.a.rasheed 607 132 : 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 132 : a1 = (arg1 < 0) ? arg1 : -arg1;
623 132 : a2 = (arg2 < 0) ? arg2 : -arg2;
624 132 : if (a1 > a2)
625 : {
626 48 : swap = arg1;
627 48 : arg1 = arg2;
628 48 : arg2 = swap;
629 : }
630 :
631 : /* Special care needs to be taken with INT64_MIN. See comments above. */
632 132 : if (arg1 == PG_INT64_MIN)
633 : {
634 45 : if (arg2 == 0 || arg2 == PG_INT64_MIN)
635 6 : 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 39 : if (arg2 == -1)
646 6 : return 1;
647 : }
648 :
649 : /* Use the Euclidean algorithm to find the GCD */
650 615 : while (arg2 != 0)
651 : {
652 495 : swap = arg2;
653 495 : arg2 = arg1 % arg2;
654 495 : arg1 = swap;
655 : }
656 :
657 : /*
658 : * Make sure the result is positive. (We know we don't have INT64_MIN
659 : * anymore).
660 : */
661 120 : if (arg1 < 0)
662 51 : arg1 = -arg1;
663 :
664 120 : return arg1;
665 : }
666 :
667 : Datum
668 90 : int8gcd(PG_FUNCTION_ARGS)
669 : {
1060 tgl 670 90 : int64 arg1 = PG_GETARG_INT64(0);
671 90 : int64 arg2 = PG_GETARG_INT64(1);
672 : int64 result;
673 :
1170 dean.a.rasheed 674 90 : result = int8gcd_internal(arg1, arg2);
675 :
676 84 : PG_RETURN_INT64(result);
677 : }
678 :
679 : /*
680 : * Least Common Multiple
681 : */
682 : Datum
683 78 : int8lcm(PG_FUNCTION_ARGS)
684 : {
1060 tgl 685 78 : int64 arg1 = PG_GETARG_INT64(0);
686 78 : 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 : */
1170 dean.a.rasheed 695 78 : if (arg1 == 0 || arg2 == 0)
696 36 : PG_RETURN_INT64(0);
697 :
698 : /* lcm(x, y) = abs(x / gcd(x, y) * y) */
699 42 : gcd = int8gcd_internal(arg1, arg2);
700 42 : arg1 = arg1 / gcd;
701 :
702 42 : if (unlikely(pg_mul_s64_overflow(arg1, arg2, &result)))
703 3 : 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 39 : if (unlikely(result == PG_INT64_MIN))
709 3 : ereport(ERROR,
710 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
711 : errmsg("bigint out of range")));
712 :
713 36 : if (result < 0)
714 18 : result = -result;
715 :
716 36 : PG_RETURN_INT64(result);
717 : }
718 :
719 : Datum
7908 tgl 720 9015050 : 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 */
6602 745 9015050 : int64 arg = PG_GETARG_INT64(0);
746 : int64 result;
747 :
1944 andres 748 9015050 : if (unlikely(pg_add_s64_overflow(arg, 1, &result)))
6602 tgl 749 UBC 0 : ereport(ERROR,
750 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
751 : errmsg("bigint out of range")));
752 :
6602 tgl 753 CBC 9015050 : PG_RETURN_INT64(result);
754 : }
755 : }
756 :
757 : Datum
3284 758 12 : 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 12 : int64 arg = PG_GETARG_INT64(0);
783 : int64 result;
784 :
1944 andres 785 12 : if (unlikely(pg_sub_s64_overflow(arg, 1, &result)))
3284 tgl 786 UBC 0 : ereport(ERROR,
787 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
788 : errmsg("bigint out of range")));
789 :
3284 tgl 790 CBC 12 : 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
6099 805 592172 : int8inc_any(PG_FUNCTION_ARGS)
806 : {
807 592172 : return int8inc(fcinfo);
808 : }
809 :
810 : Datum
811 120012 : int8inc_float8_float8(PG_FUNCTION_ARGS)
812 : {
813 120012 : return int8inc(fcinfo);
814 : }
815 :
816 : Datum
3284 817 3 : int8dec_any(PG_FUNCTION_ARGS)
818 : {
819 3 : return int8dec(fcinfo);
820 : }
821 :
822 : /*
823 : * int8inc_support
824 : * prosupport function for int8inc() and int8inc_any()
825 : */
826 : Datum
366 drowley 827 241 : int8inc_support(PG_FUNCTION_ARGS)
828 : {
829 241 : Node *rawreq = (Node *) PG_GETARG_POINTER(0);
830 :
831 241 : if (IsA(rawreq, SupportRequestWFuncMonotonic))
832 : {
833 39 : SupportRequestWFuncMonotonic *req = (SupportRequestWFuncMonotonic *) rawreq;
834 39 : MonotonicFunction monotonic = MONOTONICFUNC_NONE;
835 39 : int frameOptions = req->window_clause->frameOptions;
836 :
837 : /* No ORDER BY clause then all rows are peers */
838 39 : if (req->window_clause->orderClause == NIL)
839 12 : 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 27 : if (frameOptions & FRAMEOPTION_START_UNBOUNDED_PRECEDING)
848 21 : 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 27 : if (frameOptions & FRAMEOPTION_END_UNBOUNDED_FOLLOWING)
855 6 : monotonic |= MONOTONICFUNC_DECREASING;
856 : }
857 :
858 39 : req->monotonic = monotonic;
859 39 : PG_RETURN_POINTER(req);
860 : }
861 :
862 202 : PG_RETURN_POINTER(NULL);
863 : }
864 :
865 :
866 : Datum
8335 tgl 867 24 : int8larger(PG_FUNCTION_ARGS)
868 : {
6761 869 24 : int64 arg1 = PG_GETARG_INT64(0);
870 24 : int64 arg2 = PG_GETARG_INT64(1);
871 : int64 result;
872 :
873 24 : result = ((arg1 > arg2) ? arg1 : arg2);
874 :
8335 875 24 : PG_RETURN_INT64(result);
876 : }
877 :
878 : Datum
879 4068 : int8smaller(PG_FUNCTION_ARGS)
880 : {
6761 881 4068 : int64 arg1 = PG_GETARG_INT64(0);
882 4068 : int64 arg2 = PG_GETARG_INT64(1);
883 : int64 result;
884 :
885 4068 : result = ((arg1 < arg2) ? arg1 : arg2);
886 :
8335 887 4068 : PG_RETURN_INT64(result);
888 : }
889 :
890 : Datum
891 2420 : int84pl(PG_FUNCTION_ARGS)
892 : {
6761 893 2420 : int64 arg1 = PG_GETARG_INT64(0);
894 2420 : int32 arg2 = PG_GETARG_INT32(1);
895 : int64 result;
896 :
1944 andres 897 2420 : if (unlikely(pg_add_s64_overflow(arg1, (int64) arg2, &result)))
6761 tgl 898 3 : ereport(ERROR,
899 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
900 : errmsg("bigint out of range")));
901 2417 : PG_RETURN_INT64(result);
902 : }
903 :
904 : Datum
8335 905 51 : int84mi(PG_FUNCTION_ARGS)
906 : {
6761 907 51 : int64 arg1 = PG_GETARG_INT64(0);
908 51 : int32 arg2 = PG_GETARG_INT32(1);
909 : int64 result;
910 :
1944 andres 911 51 : if (unlikely(pg_sub_s64_overflow(arg1, (int64) arg2, &result)))
6761 tgl 912 3 : ereport(ERROR,
913 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
914 : errmsg("bigint out of range")));
915 48 : PG_RETURN_INT64(result);
916 : }
917 :
918 : Datum
8335 919 1075 : int84mul(PG_FUNCTION_ARGS)
920 : {
6761 921 1075 : int64 arg1 = PG_GETARG_INT64(0);
922 1075 : int32 arg2 = PG_GETARG_INT32(1);
923 : int64 result;
924 :
1944 andres 925 1075 : if (unlikely(pg_mul_s64_overflow(arg1, (int64) arg2, &result)))
6761 tgl 926 6 : ereport(ERROR,
927 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
928 : errmsg("bigint out of range")));
929 1069 : PG_RETURN_INT64(result);
930 : }
931 :
932 : Datum
8335 933 89 : int84div(PG_FUNCTION_ARGS)
934 : {
6761 935 89 : int64 arg1 = PG_GETARG_INT64(0);
936 89 : int32 arg2 = PG_GETARG_INT32(1);
937 : int64 result;
938 :
939 89 : if (arg2 == 0)
940 : {
7196 941 3 : 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 : */
3793 954 86 : if (arg2 == -1)
955 : {
1944 andres 956 3 : if (unlikely(arg1 == PG_INT64_MIN))
3793 tgl 957 3 : ereport(ERROR,
958 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
959 : errmsg("bigint out of range")));
1944 andres 960 UBC 0 : result = -arg1;
3793 tgl 961 0 : PG_RETURN_INT64(result);
962 : }
963 :
964 : /* No overflow is possible */
965 :
3793 tgl 966 CBC 83 : result = arg1 / arg2;
967 :
6761 968 83 : PG_RETURN_INT64(result);
969 : }
970 :
971 : Datum
8335 972 247 : int48pl(PG_FUNCTION_ARGS)
973 : {
6761 974 247 : int32 arg1 = PG_GETARG_INT32(0);
975 247 : int64 arg2 = PG_GETARG_INT64(1);
976 : int64 result;
977 :
1944 andres 978 247 : if (unlikely(pg_add_s64_overflow((int64) arg1, arg2, &result)))
6761 tgl 979 3 : ereport(ERROR,
980 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
981 : errmsg("bigint out of range")));
982 244 : PG_RETURN_INT64(result);
983 : }
984 :
985 : Datum
8335 986 33 : int48mi(PG_FUNCTION_ARGS)
987 : {
6761 988 33 : int32 arg1 = PG_GETARG_INT32(0);
989 33 : int64 arg2 = PG_GETARG_INT64(1);
990 : int64 result;
991 :
1944 andres 992 33 : if (unlikely(pg_sub_s64_overflow((int64) arg1, arg2, &result)))
6761 tgl 993 3 : ereport(ERROR,
994 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
995 : errmsg("bigint out of range")));
996 30 : PG_RETURN_INT64(result);
997 : }
998 :
999 : Datum
8335 1000 111 : int48mul(PG_FUNCTION_ARGS)
1001 : {
6761 1002 111 : int32 arg1 = PG_GETARG_INT32(0);
1003 111 : int64 arg2 = PG_GETARG_INT64(1);
1004 : int64 result;
1005 :
1944 andres 1006 111 : if (unlikely(pg_mul_s64_overflow((int64) arg1, arg2, &result)))
6761 tgl 1007 3 : ereport(ERROR,
1008 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1009 : errmsg("bigint out of range")));
1010 108 : PG_RETURN_INT64(result);
1011 : }
1012 :
1013 : Datum
8335 1014 18 : int48div(PG_FUNCTION_ARGS)
1015 : {
6761 1016 18 : int32 arg1 = PG_GETARG_INT32(0);
1017 18 : int64 arg2 = PG_GETARG_INT64(1);
1018 :
1944 andres 1019 18 : if (unlikely(arg2 == 0))
1020 : {
7196 tgl 1021 3 : 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 */
6761 1029 15 : PG_RETURN_INT64((int64) arg1 / arg2);
1030 : }
1031 :
1032 : Datum
5409 1033 18 : int82pl(PG_FUNCTION_ARGS)
1034 : {
1035 18 : int64 arg1 = PG_GETARG_INT64(0);
1036 18 : int16 arg2 = PG_GETARG_INT16(1);
1037 : int64 result;
1038 :
1944 andres 1039 18 : if (unlikely(pg_add_s64_overflow(arg1, (int64) arg2, &result)))
5409 tgl 1040 3 : ereport(ERROR,
1041 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1042 : errmsg("bigint out of range")));
1043 15 : PG_RETURN_INT64(result);
1044 : }
1045 :
1046 : Datum
1047 18 : int82mi(PG_FUNCTION_ARGS)
1048 : {
1049 18 : int64 arg1 = PG_GETARG_INT64(0);
1050 18 : int16 arg2 = PG_GETARG_INT16(1);
1051 : int64 result;
1052 :
1944 andres 1053 18 : if (unlikely(pg_sub_s64_overflow(arg1, (int64) arg2, &result)))
5409 tgl 1054 3 : ereport(ERROR,
1055 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1056 : errmsg("bigint out of range")));
1057 15 : PG_RETURN_INT64(result);
1058 : }
1059 :
1060 : Datum
1061 21 : int82mul(PG_FUNCTION_ARGS)
1062 : {
1063 21 : int64 arg1 = PG_GETARG_INT64(0);
1064 21 : int16 arg2 = PG_GETARG_INT16(1);
1065 : int64 result;
1066 :
1944 andres 1067 21 : if (unlikely(pg_mul_s64_overflow(arg1, (int64) arg2, &result)))
5409 tgl 1068 6 : ereport(ERROR,
1069 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1070 : errmsg("bigint out of range")));
1071 15 : PG_RETURN_INT64(result);
1072 : }
1073 :
1074 : Datum
1075 21 : int82div(PG_FUNCTION_ARGS)
1076 : {
1077 21 : int64 arg1 = PG_GETARG_INT64(0);
1078 21 : int16 arg2 = PG_GETARG_INT16(1);
1079 : int64 result;
1080 :
1944 andres 1081 21 : if (unlikely(arg2 == 0))
1082 : {
5409 tgl 1083 3 : 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 : */
3793 1096 18 : if (arg2 == -1)
1097 : {
1944 andres 1098 3 : if (unlikely(arg1 == PG_INT64_MIN))
3793 tgl 1099 3 : ereport(ERROR,
1100 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1101 : errmsg("bigint out of range")));
1944 andres 1102 UBC 0 : result = -arg1;
3793 tgl 1103 0 : PG_RETURN_INT64(result);
1104 : }
1105 :
1106 : /* No overflow is possible */
1107 :
3793 tgl 1108 CBC 15 : result = arg1 / arg2;
1109 :
5409 1110 15 : PG_RETURN_INT64(result);
1111 : }
1112 :
1113 : Datum
1114 18 : int28pl(PG_FUNCTION_ARGS)
1115 : {
1116 18 : int16 arg1 = PG_GETARG_INT16(0);
1117 18 : int64 arg2 = PG_GETARG_INT64(1);
1118 : int64 result;
1119 :
1944 andres 1120 18 : if (unlikely(pg_add_s64_overflow((int64) arg1, arg2, &result)))
5409 tgl 1121 3 : ereport(ERROR,
1122 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1123 : errmsg("bigint out of range")));
1124 15 : PG_RETURN_INT64(result);
1125 : }
1126 :
1127 : Datum
1128 18 : int28mi(PG_FUNCTION_ARGS)
1129 : {
1130 18 : int16 arg1 = PG_GETARG_INT16(0);
1131 18 : int64 arg2 = PG_GETARG_INT64(1);
1132 : int64 result;
1133 :
1944 andres 1134 18 : if (unlikely(pg_sub_s64_overflow((int64) arg1, arg2, &result)))
5409 tgl 1135 3 : ereport(ERROR,
1136 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1137 : errmsg("bigint out of range")));
1138 15 : PG_RETURN_INT64(result);
1139 : }
1140 :
1141 : Datum
1142 18 : int28mul(PG_FUNCTION_ARGS)
1143 : {
1144 18 : int16 arg1 = PG_GETARG_INT16(0);
1145 18 : int64 arg2 = PG_GETARG_INT64(1);
1146 : int64 result;
1147 :
1944 andres 1148 18 : if (unlikely(pg_mul_s64_overflow((int64) arg1, arg2, &result)))
5409 tgl 1149 3 : ereport(ERROR,
1150 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1151 : errmsg("bigint out of range")));
1152 15 : PG_RETURN_INT64(result);
1153 : }
1154 :
1155 : Datum
1156 18 : int28div(PG_FUNCTION_ARGS)
1157 : {
1158 18 : int16 arg1 = PG_GETARG_INT16(0);
1159 18 : int64 arg2 = PG_GETARG_INT64(1);
1160 :
1944 andres 1161 18 : if (unlikely(arg2 == 0))
1162 : {
5409 tgl 1163 3 : 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 15 : 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
8202 peter_e 1185 21 : int8and(PG_FUNCTION_ARGS)
1186 : {
1187 21 : int64 arg1 = PG_GETARG_INT64(0);
1188 21 : int64 arg2 = PG_GETARG_INT64(1);
1189 :
1190 21 : PG_RETURN_INT64(arg1 & arg2);
1191 : }
1192 :
1193 : Datum
1194 23 : int8or(PG_FUNCTION_ARGS)
1195 : {
1196 23 : int64 arg1 = PG_GETARG_INT64(0);
1197 23 : int64 arg2 = PG_GETARG_INT64(1);
1198 :
1199 23 : PG_RETURN_INT64(arg1 | arg2);
1200 : }
1201 :
1202 : Datum
1203 21 : int8xor(PG_FUNCTION_ARGS)
1204 : {
1205 21 : int64 arg1 = PG_GETARG_INT64(0);
1206 21 : int64 arg2 = PG_GETARG_INT64(1);
1207 :
1208 21 : PG_RETURN_INT64(arg1 ^ arg2);
1209 : }
1210 :
1211 : Datum
1212 15 : int8not(PG_FUNCTION_ARGS)
1213 : {
1214 15 : int64 arg1 = PG_GETARG_INT64(0);
1215 :
1216 15 : PG_RETURN_INT64(~arg1);
1217 : }
1218 :
1219 : Datum
1220 23 : int8shl(PG_FUNCTION_ARGS)
1221 : {
1222 23 : int64 arg1 = PG_GETARG_INT64(0);
1223 23 : int32 arg2 = PG_GETARG_INT32(1);
1224 :
1225 23 : PG_RETURN_INT64(arg1 << arg2);
1226 : }
1227 :
1228 : Datum
1229 15 : int8shr(PG_FUNCTION_ARGS)
1230 : {
1231 15 : int64 arg1 = PG_GETARG_INT64(0);
1232 15 : int32 arg2 = PG_GETARG_INT32(1);
1233 :
1234 15 : PG_RETURN_INT64(arg1 >> arg2);
1235 : }
1236 :
1237 : /*----------------------------------------------------------
1238 : * Conversion operators.
1239 : *---------------------------------------------------------*/
1240 :
1241 : Datum
8335 tgl 1242 1269101 : int48(PG_FUNCTION_ARGS)
1243 : {
6761 1244 1269101 : int32 arg = PG_GETARG_INT32(0);
1245 :
1246 1269101 : PG_RETURN_INT64((int64) arg);
1247 : }
1248 :
1249 : Datum
8335 1250 102044 : int84(PG_FUNCTION_ARGS)
1251 : {
6761 1252 102044 : int64 arg = PG_GETARG_INT64(0);
1253 :
1944 andres 1254 102044 : if (unlikely(arg < PG_INT32_MIN) || unlikely(arg > PG_INT32_MAX))
7196 tgl 1255 3 : ereport(ERROR,
1256 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1257 : errmsg("integer out of range")));
1258 :
1944 andres 1259 102041 : PG_RETURN_INT32((int32) arg);
1260 : }
1261 :
1262 : Datum
7836 tgl 1263 9 : int28(PG_FUNCTION_ARGS)
1264 : {
6761 1265 9 : int16 arg = PG_GETARG_INT16(0);
1266 :
1267 9 : PG_RETURN_INT64((int64) arg);
1268 : }
1269 :
1270 : Datum
7836 1271 18 : int82(PG_FUNCTION_ARGS)
1272 : {
6761 1273 18 : int64 arg = PG_GETARG_INT64(0);
1274 :
1944 andres 1275 18 : if (unlikely(arg < PG_INT16_MIN) || unlikely(arg > PG_INT16_MAX))
7196 tgl 1276 3 : ereport(ERROR,
1277 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1278 : errmsg("smallint out of range")));
1279 :
1944 andres 1280 15 : PG_RETURN_INT16((int16) arg);
1281 : }
1282 :
1283 : Datum
8335 tgl 1284 93 : i8tod(PG_FUNCTION_ARGS)
1285 : {
6761 1286 93 : int64 arg = PG_GETARG_INT64(0);
1287 : float8 result;
1288 :
1289 93 : result = arg;
1290 :
8335 1291 93 : PG_RETURN_FLOAT8(result);
1292 : }
1293 :
1294 : /* dtoi8()
1295 : * Convert float8 to 8-byte integer.
1296 : */
1297 : Datum
1298 69 : dtoi8(PG_FUNCTION_ARGS)
1299 : {
1598 1300 69 : 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 69 : num = rint(num);
1308 :
1309 : /* Range check */
1249 1310 69 : if (unlikely(isnan(num) || !FLOAT8_FITS_IN_INT64(num)))
7196 1311 9 : ereport(ERROR,
1312 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1313 : errmsg("bigint out of range")));
1314 :
1598 1315 60 : PG_RETURN_INT64((int64) num);
1316 : }
1317 :
1318 : Datum
7508 1319 75 : i8tof(PG_FUNCTION_ARGS)
1320 : {
6761 1321 75 : int64 arg = PG_GETARG_INT64(0);
1322 : float4 result;
1323 :
1324 75 : result = arg;
1325 :
7508 1326 75 : PG_RETURN_FLOAT4(result);
1327 : }
1328 :
1329 : /* ftoi8()
1330 : * Convert float4 to 8-byte integer.
1331 : */
1332 : Datum
1333 15 : ftoi8(PG_FUNCTION_ARGS)
1334 : {
1598 1335 15 : 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 15 : num = rint(num);
1343 :
1344 : /* Range check */
1249 1345 15 : if (unlikely(isnan(num) || !FLOAT4_FITS_IN_INT64(num)))
7196 1346 6 : ereport(ERROR,
1347 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1348 : errmsg("bigint out of range")));
1349 :
1598 1350 9 : PG_RETURN_INT64((int64) num);
1351 : }
1352 :
1353 : Datum
7508 1354 10 : i8tooid(PG_FUNCTION_ARGS)
1355 : {
6761 1356 10 : int64 arg = PG_GETARG_INT64(0);
1357 :
1944 andres 1358 10 : if (unlikely(arg < 0) || unlikely(arg > PG_UINT32_MAX))
7196 tgl 1359 3 : ereport(ERROR,
1360 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1361 : errmsg("OID out of range")));
1362 :
1944 andres 1363 7 : PG_RETURN_OID((Oid) arg);
1364 : }
1365 :
1366 : Datum
7508 tgl 1367 11 : oidtoi8(PG_FUNCTION_ARGS)
1368 : {
6761 1369 11 : Oid arg = PG_GETARG_OID(0);
1370 :
1371 11 : PG_RETURN_INT64((int64) arg);
1372 : }
1373 :
1374 : /*
1375 : * non-persistent numeric series generator
1376 : */
1377 : Datum
7005 mail 1378 198768 : generate_series_int8(PG_FUNCTION_ARGS)
1379 : {
1380 198768 : return generate_series_step_int8(fcinfo);
1381 : }
1382 :
1383 : Datum
1384 198792 : 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 198792 : if (SRF_IS_FIRSTCALL())
1393 : {
6797 bruce 1394 28 : int64 start = PG_GETARG_INT64(0);
1395 28 : int64 finish = PG_GETARG_INT64(1);
1396 28 : int64 step = 1;
1397 :
1398 : /* see if we were given an explicit step size */
7005 mail 1399 28 : if (PG_NARGS() == 3)
1400 6 : step = PG_GETARG_INT64(2);
1401 28 : if (step == 0)
1402 3 : 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 25 : funcctx = SRF_FIRSTCALL_INIT();
1408 :
1409 : /*
1410 : * switch to memory context appropriate for multiple function calls
1411 : */
1412 25 : oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1413 :
1414 : /* allocate memory for user context */
1415 25 : 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 25 : fctx->current = start;
1422 25 : fctx->finish = finish;
1423 25 : fctx->step = step;
1424 :
1425 25 : funcctx->user_fctx = fctx;
1426 25 : MemoryContextSwitchTo(oldcontext);
1427 : }
1428 :
1429 : /* stuff done on every call of the function */
1430 198789 : funcctx = SRF_PERCALL_SETUP();
1431 :
1432 : /*
1433 : * get the saved state and use current as the result for this iteration
1434 : */
1435 198789 : fctx = funcctx->user_fctx;
1436 198789 : result = fctx->current;
1437 :
1438 198789 : if ((fctx->step > 0 && fctx->current <= fctx->finish) ||
1439 24 : (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 : */
1944 andres 1445 198765 : if (pg_add_s64_overflow(fctx->current, fctx->step, &fctx->current))
4314 rhaas 1446 UBC 0 : fctx->step = 0;
1447 :
1448 : /* do when there is more left to send */
7005 mail 1449 CBC 198765 : SRF_RETURN_NEXT(funcctx, Int64GetDatum(result));
1450 : }
1451 : else
1452 : /* do when there is no more left */
1453 24 : SRF_RETURN_DONE(funcctx);
1454 : }
1455 :
1456 : /*
1457 : * Planner support function for generate_series(int8, int8 [, int8])
1458 : */
1459 : Datum
1520 tgl 1460 57 : generate_series_int8_support(PG_FUNCTION_ARGS)
1461 : {
1462 57 : Node *rawreq = (Node *) PG_GETARG_POINTER(0);
1463 57 : Node *ret = NULL;
1464 :
1465 57 : if (IsA(rawreq, SupportRequestRows))
1466 : {
1467 : /* Try to estimate the number of rows returned */
1468 19 : SupportRequestRows *req = (SupportRequestRows *) rawreq;
1469 :
1470 19 : if (is_funcclause(req->node)) /* be paranoid */
1471 : {
1472 19 : List *args = ((FuncExpr *) req->node)->args;
1473 : Node *arg1,
1474 : *arg2,
1475 : *arg3;
1476 :
1477 : /* We can use estimated argument values here */
1478 19 : arg1 = estimate_expression_value(req->root, linitial(args));
1479 19 : arg2 = estimate_expression_value(req->root, lsecond(args));
1480 19 : if (list_length(args) >= 3)
1481 6 : arg3 = estimate_expression_value(req->root, lthird(args));
1482 : else
1483 13 : 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 19 : if ((IsA(arg1, Const) &&
1492 19 : ((Const *) arg1)->constisnull) ||
1493 19 : (IsA(arg2, Const) &&
1494 19 : ((Const *) arg2)->constisnull) ||
1495 6 : (arg3 != NULL && IsA(arg3, Const) &&
1496 6 : ((Const *) arg3)->constisnull))
1497 : {
1520 tgl 1498 UBC 0 : req->rows = 0;
1499 0 : ret = (Node *) req;
1500 : }
1520 tgl 1501 CBC 19 : else if (IsA(arg1, Const) &&
1502 19 : IsA(arg2, Const) &&
1503 6 : (arg3 == NULL || IsA(arg3, Const)))
1504 : {
1505 : double start,
1506 : finish,
1507 : step;
1508 :
1509 16 : start = DatumGetInt64(((Const *) arg1)->constvalue);
1510 16 : finish = DatumGetInt64(((Const *) arg2)->constvalue);
1511 16 : step = arg3 ? DatumGetInt64(((Const *) arg3)->constvalue) : 1;
1512 :
1513 : /* This equation works for either sign of step */
1514 16 : if (step != 0)
1515 : {
1516 13 : req->rows = floor((finish - start + step) / step);
1517 13 : ret = (Node *) req;
1518 : }
1519 : }
1520 : }
1521 : }
1522 :
1523 57 : PG_RETURN_POINTER(ret);
1524 : }
|