Branch data 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 : 82425 : int8in(PG_FUNCTION_ARGS)
52 : : {
53 : 82425 : char *num = PG_GETARG_CSTRING(0);
54 : :
55 : 82425 : PG_RETURN_INT64(pg_strtoint64_safe(num, fcinfo->context));
56 : : }
57 : :
58 : :
59 : : /*
60 : : * int8out()
61 : : */
62 : : Datum
63 : 174371 : int8out(PG_FUNCTION_ARGS)
64 : : {
65 : 174371 : int64 val = PG_GETARG_INT64(0);
66 : : char buf[MAXINT8LEN + 1];
67 : : char *result;
68 : : int len;
69 : :
70 : 174371 : 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 : 174371 : result = palloc(len);
77 : 174371 : memcpy(result, buf, len);
78 : 174371 : 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 : 2419 : int8send(PG_FUNCTION_ARGS)
97 : : {
98 : 2419 : int64 arg1 = PG_GETARG_INT64(0);
99 : : StringInfoData buf;
100 : :
101 : 2419 : pq_begintypsend(&buf);
102 : 2419 : pq_sendint64(&buf, arg1);
103 : 2419 : 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 : 231232 : int8eq(PG_FUNCTION_ARGS)
117 : : {
118 : 231232 : int64 val1 = PG_GETARG_INT64(0);
119 : 231232 : int64 val2 = PG_GETARG_INT64(1);
120 : :
121 : 231232 : PG_RETURN_BOOL(val1 == val2);
122 : : }
123 : :
124 : : Datum
125 : 40034 : int8ne(PG_FUNCTION_ARGS)
126 : : {
127 : 40034 : int64 val1 = PG_GETARG_INT64(0);
128 : 40034 : int64 val2 = PG_GETARG_INT64(1);
129 : :
130 : 40034 : PG_RETURN_BOOL(val1 != val2);
131 : : }
132 : :
133 : : Datum
134 : 349925 : int8lt(PG_FUNCTION_ARGS)
135 : : {
136 : 349925 : int64 val1 = PG_GETARG_INT64(0);
137 : 349925 : int64 val2 = PG_GETARG_INT64(1);
138 : :
139 : 349925 : 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 : 3498 : int8ge(PG_FUNCTION_ARGS)
162 : : {
163 : 3498 : int64 val1 = PG_GETARG_INT64(0);
164 : 3498 : int64 val2 = PG_GETARG_INT64(1);
165 : :
166 : 3498 : PG_RETURN_BOOL(val1 >= val2);
167 : : }
168 : :
169 : : /*
170 : : * int84relop()
171 : : * Is 64-bit val1 relop 32-bit val2?
172 : : */
173 : : Datum
174 : 117539 : int84eq(PG_FUNCTION_ARGS)
175 : : {
176 : 117539 : int64 val1 = PG_GETARG_INT64(0);
177 : 117539 : int32 val2 = PG_GETARG_INT32(1);
178 : :
179 : 117539 : 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 : 437656 : int84lt(PG_FUNCTION_ARGS)
193 : : {
194 : 437656 : int64 val1 = PG_GETARG_INT64(0);
195 : 437656 : int32 val2 = PG_GETARG_INT32(1);
196 : :
197 : 437656 : PG_RETURN_BOOL(val1 < val2);
198 : : }
199 : :
200 : : Datum
201 : 94198 : int84gt(PG_FUNCTION_ARGS)
202 : : {
203 : 94198 : int64 val1 = PG_GETARG_INT64(0);
204 : 94198 : int32 val2 = PG_GETARG_INT32(1);
205 : :
206 : 94198 : 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 : 6688 : int84ge(PG_FUNCTION_ARGS)
220 : : {
221 : 6688 : int64 val1 = PG_GETARG_INT64(0);
222 : 6688 : int32 val2 = PG_GETARG_INT32(1);
223 : :
224 : 6688 : PG_RETURN_BOOL(val1 >= val2);
225 : : }
226 : :
227 : : /*
228 : : * int48relop()
229 : : * Is 32-bit val1 relop 64-bit val2?
230 : : */
231 : : Datum
232 : 103539 : int48eq(PG_FUNCTION_ARGS)
233 : : {
234 : 103539 : int32 val1 = PG_GETARG_INT32(0);
235 : 103539 : int64 val2 = PG_GETARG_INT64(1);
236 : :
237 : 103539 : 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 : 2253 : int28ne(PG_FUNCTION_ARGS)
358 : : {
359 : 2253 : int16 val1 = PG_GETARG_INT16(0);
360 : 2253 : int64 val2 = PG_GETARG_INT64(1);
361 : :
362 : 2253 : 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 : 641 : int8um(PG_FUNCTION_ARGS)
448 : : {
449 : 641 : int64 arg = PG_GETARG_INT64(0);
450 : : int64 result;
451 : :
452 [ + + ]: 641 : if (pg_neg_s64_overflow(arg, &result))
453 [ + - ]: 4 : ereport(ERROR,
454 : : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
455 : : errmsg("bigint out of range")));
456 : 637 : PG_RETURN_INT64(result);
457 : : }
458 : :
459 : : Datum
460 : 5 : int8up(PG_FUNCTION_ARGS)
461 : : {
462 : 5 : int64 arg = PG_GETARG_INT64(0);
463 : :
464 : 5 : PG_RETURN_INT64(arg);
465 : : }
466 : :
467 : : Datum
468 : 169917 : int8pl(PG_FUNCTION_ARGS)
469 : : {
470 : 169917 : int64 arg1 = PG_GETARG_INT64(0);
471 : 169917 : int64 arg2 = PG_GETARG_INT64(1);
472 : : int64 result;
473 : :
474 [ + + ]: 169917 : if (unlikely(pg_add_s64_overflow(arg1, arg2, &result)))
475 [ + - ]: 8 : ereport(ERROR,
476 : : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
477 : : errmsg("bigint out of range")));
478 : 169909 : PG_RETURN_INT64(result);
479 : : }
480 : :
481 : : Datum
482 : 160 : int8mi(PG_FUNCTION_ARGS)
483 : : {
484 : 160 : int64 arg1 = PG_GETARG_INT64(0);
485 : 160 : int64 arg2 = PG_GETARG_INT64(1);
486 : : int64 result;
487 : :
488 [ + + ]: 160 : if (unlikely(pg_sub_s64_overflow(arg1, arg2, &result)))
489 [ + - ]: 12 : ereport(ERROR,
490 : : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
491 : : errmsg("bigint out of range")));
492 : 148 : PG_RETURN_INT64(result);
493 : : }
494 : :
495 : : Datum
496 : 88 : int8mul(PG_FUNCTION_ARGS)
497 : : {
498 : 88 : int64 arg1 = PG_GETARG_INT64(0);
499 : 88 : int64 arg2 = PG_GETARG_INT64(1);
500 : : int64 result;
501 : :
502 [ + + ]: 88 : if (unlikely(pg_mul_s64_overflow(arg1, arg2, &result)))
503 [ + - ]: 13 : ereport(ERROR,
504 : : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
505 : : errmsg("bigint out of range")));
506 : 75 : PG_RETURN_INT64(result);
507 : : }
508 : :
509 : : Datum
510 : 83 : int8div(PG_FUNCTION_ARGS)
511 : : {
512 : 83 : int64 arg1 = PG_GETARG_INT64(0);
513 : 83 : int64 arg2 = PG_GETARG_INT64(1);
514 : : int64 result;
515 : :
516 [ + + ]: 83 : if (arg2 == 0)
517 : : {
518 [ + - ]: 4 : ereport(ERROR,
519 : : (errcode(ERRCODE_DIVISION_BY_ZERO),
520 : : errmsg("division by zero")));
521 : : /* ensure compiler realizes we mustn't reach the division (gcc bug) */
522 : : PG_RETURN_NULL();
523 : : }
524 : :
525 : : /*
526 : : * INT64_MIN / -1 is problematic, since the result can't be represented on
527 : : * a two's-complement machine. Some machines produce INT64_MIN, some
528 : : * produce zero, some throw an exception. We can dodge the problem by
529 : : * recognizing that division by -1 is the same as negation.
530 : : */
531 [ + + ]: 79 : if (arg2 == -1)
532 : : {
533 [ + - ]: 4 : if (pg_neg_s64_overflow(arg1, &result))
534 [ + - ]: 4 : ereport(ERROR,
535 : : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
536 : : errmsg("bigint out of range")));
537 : 0 : PG_RETURN_INT64(result);
538 : : }
539 : :
540 : : /* No overflow is possible */
541 : :
542 : 75 : result = arg1 / arg2;
543 : :
544 : 75 : PG_RETURN_INT64(result);
545 : : }
546 : :
547 : : /*
548 : : * int8abs()
549 : : * Absolute value
550 : : */
551 : : Datum
552 : 24 : int8abs(PG_FUNCTION_ARGS)
553 : : {
554 : 24 : int64 arg1 = PG_GETARG_INT64(0);
555 : : int64 result;
556 : :
557 [ + + ]: 24 : if (unlikely(arg1 == PG_INT64_MIN))
558 [ + - ]: 4 : ereport(ERROR,
559 : : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
560 : : errmsg("bigint out of range")));
561 : 20 : result = (arg1 < 0) ? -arg1 : arg1;
562 : 20 : PG_RETURN_INT64(result);
563 : : }
564 : :
565 : : /*
566 : : * int8mod()
567 : : * Modulo operation.
568 : : */
569 : : Datum
570 : 131 : int8mod(PG_FUNCTION_ARGS)
571 : : {
572 : 131 : int64 arg1 = PG_GETARG_INT64(0);
573 : 131 : int64 arg2 = PG_GETARG_INT64(1);
574 : :
575 [ + + ]: 131 : if (unlikely(arg2 == 0))
576 : : {
577 [ + - ]: 4 : ereport(ERROR,
578 : : (errcode(ERRCODE_DIVISION_BY_ZERO),
579 : : errmsg("division by zero")));
580 : : /* ensure compiler realizes we mustn't reach the division (gcc bug) */
581 : : PG_RETURN_NULL();
582 : : }
583 : :
584 : : /*
585 : : * Some machines throw a floating-point exception for INT64_MIN % -1,
586 : : * which is a bit silly since the correct answer is perfectly
587 : : * well-defined, namely zero.
588 : : */
589 [ + + ]: 127 : if (arg2 == -1)
590 : 15 : PG_RETURN_INT64(0);
591 : :
592 : : /* No overflow is possible */
593 : :
594 : 112 : PG_RETURN_INT64(arg1 % arg2);
595 : : }
596 : :
597 : : /*
598 : : * Greatest Common Divisor
599 : : *
600 : : * Returns the largest positive integer that exactly divides both inputs.
601 : : * Special cases:
602 : : * - gcd(x, 0) = gcd(0, x) = abs(x)
603 : : * because 0 is divisible by anything
604 : : * - gcd(0, 0) = 0
605 : : * complies with the previous definition and is a common convention
606 : : *
607 : : * Special care must be taken if either input is INT64_MIN ---
608 : : * gcd(0, INT64_MIN), gcd(INT64_MIN, 0) and gcd(INT64_MIN, INT64_MIN) are
609 : : * all equal to abs(INT64_MIN), which cannot be represented as a 64-bit signed
610 : : * integer.
611 : : */
612 : : static int64
613 : 176 : int8gcd_internal(int64 arg1, int64 arg2)
614 : : {
615 : : int64 swap;
616 : : int64 a1,
617 : : a2;
618 : :
619 : : /*
620 : : * Put the greater absolute value in arg1.
621 : : *
622 : : * This would happen automatically in the loop below, but avoids an
623 : : * expensive modulo operation, and simplifies the special-case handling
624 : : * for INT64_MIN below.
625 : : *
626 : : * We do this in negative space in order to handle INT64_MIN.
627 : : */
628 : 176 : a1 = (arg1 < 0) ? arg1 : -arg1;
629 : 176 : a2 = (arg2 < 0) ? arg2 : -arg2;
630 [ + + ]: 176 : if (a1 > a2)
631 : : {
632 : 64 : swap = arg1;
633 : 64 : arg1 = arg2;
634 : 64 : arg2 = swap;
635 : : }
636 : :
637 : : /* Special care needs to be taken with INT64_MIN. See comments above. */
638 [ + + ]: 176 : if (arg1 == PG_INT64_MIN)
639 : : {
640 [ + + + + ]: 60 : if (arg2 == 0 || arg2 == PG_INT64_MIN)
641 [ + - ]: 8 : ereport(ERROR,
642 : : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
643 : : errmsg("bigint out of range")));
644 : :
645 : : /*
646 : : * Some machines throw a floating-point exception for INT64_MIN % -1,
647 : : * which is a bit silly since the correct answer is perfectly
648 : : * well-defined, namely zero. Guard against this and just return the
649 : : * result, gcd(INT64_MIN, -1) = 1.
650 : : */
651 [ + + ]: 52 : if (arg2 == -1)
652 : 8 : return 1;
653 : : }
654 : :
655 : : /* Use the Euclidean algorithm to find the GCD */
656 [ + + ]: 820 : while (arg2 != 0)
657 : : {
658 : 660 : swap = arg2;
659 : 660 : arg2 = arg1 % arg2;
660 : 660 : arg1 = swap;
661 : : }
662 : :
663 : : /*
664 : : * Make sure the result is positive. (We know we don't have INT64_MIN
665 : : * anymore).
666 : : */
667 [ + + ]: 160 : if (arg1 < 0)
668 : 68 : arg1 = -arg1;
669 : :
670 : 160 : return arg1;
671 : : }
672 : :
673 : : Datum
674 : 120 : int8gcd(PG_FUNCTION_ARGS)
675 : : {
676 : 120 : int64 arg1 = PG_GETARG_INT64(0);
677 : 120 : int64 arg2 = PG_GETARG_INT64(1);
678 : : int64 result;
679 : :
680 : 120 : result = int8gcd_internal(arg1, arg2);
681 : :
682 : 112 : PG_RETURN_INT64(result);
683 : : }
684 : :
685 : : /*
686 : : * Least Common Multiple
687 : : */
688 : : Datum
689 : 104 : int8lcm(PG_FUNCTION_ARGS)
690 : : {
691 : 104 : int64 arg1 = PG_GETARG_INT64(0);
692 : 104 : int64 arg2 = PG_GETARG_INT64(1);
693 : : int64 gcd;
694 : : int64 result;
695 : :
696 : : /*
697 : : * Handle lcm(x, 0) = lcm(0, x) = 0 as a special case. This prevents a
698 : : * division-by-zero error below when x is zero, and an overflow error from
699 : : * the GCD computation when x = INT64_MIN.
700 : : */
701 [ + + + + ]: 104 : if (arg1 == 0 || arg2 == 0)
702 : 48 : PG_RETURN_INT64(0);
703 : :
704 : : /* lcm(x, y) = abs(x / gcd(x, y) * y) */
705 : 56 : gcd = int8gcd_internal(arg1, arg2);
706 : 56 : arg1 = arg1 / gcd;
707 : :
708 [ + + ]: 56 : if (unlikely(pg_mul_s64_overflow(arg1, arg2, &result)))
709 [ + - ]: 4 : ereport(ERROR,
710 : : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
711 : : errmsg("bigint out of range")));
712 : :
713 : : /* If the result is INT64_MIN, it cannot be represented. */
714 [ + + ]: 52 : if (unlikely(result == PG_INT64_MIN))
715 [ + - ]: 4 : ereport(ERROR,
716 : : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
717 : : errmsg("bigint out of range")));
718 : :
719 [ + + ]: 48 : if (result < 0)
720 : 24 : result = -result;
721 : :
722 : 48 : PG_RETURN_INT64(result);
723 : : }
724 : :
725 : : Datum
726 : 14629599 : int8inc(PG_FUNCTION_ARGS)
727 : : {
728 : 14629599 : int64 arg = PG_GETARG_INT64(0);
729 : : int64 result;
730 : :
731 [ - + ]: 14629599 : if (unlikely(pg_add_s64_overflow(arg, 1, &result)))
732 [ # # ]: 0 : ereport(ERROR,
733 : : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
734 : : errmsg("bigint out of range")));
735 : :
736 : 14629599 : PG_RETURN_INT64(result);
737 : : }
738 : :
739 : : Datum
740 : 16 : int8dec(PG_FUNCTION_ARGS)
741 : : {
742 : 16 : int64 arg = PG_GETARG_INT64(0);
743 : : int64 result;
744 : :
745 [ - + ]: 16 : if (unlikely(pg_sub_s64_overflow(arg, 1, &result)))
746 [ # # ]: 0 : ereport(ERROR,
747 : : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
748 : : errmsg("bigint out of range")));
749 : :
750 : 16 : PG_RETURN_INT64(result);
751 : : }
752 : :
753 : :
754 : : /*
755 : : * These functions are exactly like int8inc/int8dec but are used for
756 : : * aggregates that count only non-null values. Since the functions are
757 : : * declared strict, the null checks happen before we ever get here, and all we
758 : : * need do is increment the state value. We could actually make these pg_proc
759 : : * entries point right at int8inc/int8dec, but then the opr_sanity regression
760 : : * test would complain about mismatched entries for a built-in function.
761 : : */
762 : :
763 : : Datum
764 : 796825 : int8inc_any(PG_FUNCTION_ARGS)
765 : : {
766 : 796825 : return int8inc(fcinfo);
767 : : }
768 : :
769 : : Datum
770 : 160016 : int8inc_float8_float8(PG_FUNCTION_ARGS)
771 : : {
772 : 160016 : return int8inc(fcinfo);
773 : : }
774 : :
775 : : Datum
776 : 4 : int8dec_any(PG_FUNCTION_ARGS)
777 : : {
778 : 4 : return int8dec(fcinfo);
779 : : }
780 : :
781 : : /*
782 : : * int8inc_support
783 : : * prosupport function for int8inc() and int8inc_any()
784 : : */
785 : : Datum
786 : 15170 : int8inc_support(PG_FUNCTION_ARGS)
787 : : {
788 : 15170 : Node *rawreq = (Node *) PG_GETARG_POINTER(0);
789 : :
790 [ + + ]: 15170 : if (IsA(rawreq, SupportRequestWFuncMonotonic))
791 : : {
792 : 125 : SupportRequestWFuncMonotonic *req = (SupportRequestWFuncMonotonic *) rawreq;
793 : 125 : MonotonicFunction monotonic = MONOTONICFUNC_NONE;
794 : 125 : int frameOptions = req->window_clause->frameOptions;
795 : :
796 : : /*
797 : : * Because an EXCLUDE clauses in the window definition can exclude
798 : : * rows that have previously been included in the aggregate result for
799 : : * prior rows, this can break the monotonic properties that might
800 : : * otherwise be guaranteed. There's a narrow set of circumstances
801 : : * that can be guaranteed, which we check for below.
802 : : */
803 [ + + ]: 125 : if (frameOptions & FRAMEOPTION_EXCLUSION)
804 : : {
805 : 45 : WindowFunc *wfunc = req->window_func;
806 : :
807 : : /*
808 : : * To add handling for all valid monotonic cases with an EXCLUDE
809 : : * clause is complex and likely not worth troubling over. For
810 : : * now, just bail unless we see EXCLUDE CURRENT ROW with COUNT(*)
811 : : * and no FILTER. Excluding the current row is fine when using
812 : : * COUNT(*) as this always reduces the count by 1. The same isn't
813 : : * true for COUNY(ANY) as a NULL won't be counted, and a
814 : : * subsequent non-NULL could make the count decrease.
815 : : */
816 [ + + ]: 45 : if ((frameOptions & FRAMEOPTION_EXCLUDE_CURRENT_ROW) == 0 ||
817 [ + + ]: 25 : wfunc->winfnoid != F_COUNT_ ||
818 [ + + ]: 20 : wfunc->aggfilter != NULL)
819 : : {
820 : 30 : req->monotonic = MONOTONICFUNC_NONE;
821 : 30 : PG_RETURN_POINTER(req);
822 : : }
823 : : }
824 : :
825 : : /* No ORDER BY clause and RANGE mode means all rows are peers. */
826 [ + + ]: 95 : if (req->window_clause->orderClause == NIL &&
827 [ + + ]: 35 : (frameOptions & FRAMEOPTION_RANGE))
828 : 30 : monotonic = MONOTONICFUNC_BOTH;
829 : : else
830 : : {
831 : : /*
832 : : * Otherwise take into account the frame options. When the frame
833 : : * bound is the start of the window then the resulting value can
834 : : * never decrease, therefore is monotonically increasing
835 : : */
836 [ + + ]: 65 : if (frameOptions & FRAMEOPTION_START_UNBOUNDED_PRECEDING)
837 : 50 : monotonic |= MONOTONICFUNC_INCREASING;
838 : :
839 : : /*
840 : : * Likewise, if the frame bound is the end of the window then the
841 : : * resulting value can never decrease.
842 : : */
843 [ + + ]: 65 : if (frameOptions & FRAMEOPTION_END_UNBOUNDED_FOLLOWING)
844 : 10 : monotonic |= MONOTONICFUNC_DECREASING;
845 : : }
846 : :
847 : 95 : req->monotonic = monotonic;
848 : 95 : PG_RETURN_POINTER(req);
849 : : }
850 : :
851 [ + + ]: 15045 : if (IsA(rawreq, SupportRequestSimplifyAggref))
852 : : {
853 : 14450 : SupportRequestSimplifyAggref *req = (SupportRequestSimplifyAggref *) rawreq;
854 : 14450 : Aggref *agg = req->aggref;
855 : :
856 : : /*
857 : : * Check for COUNT(ANY) and try to convert to COUNT(*). The input
858 : : * argument cannot be NULL, we can't have an ORDER BY / DISTINCT in
859 : : * the aggregate, and agglevelsup must be 0.
860 : : *
861 : : * Technically COUNT(ANY) must have 1 arg, but be paranoid and check.
862 : : */
863 [ + + + - ]: 14450 : if (agg->aggfnoid == F_COUNT_ANY && list_length(agg->args) == 1)
864 : : {
865 : 1203 : TargetEntry *tle = (TargetEntry *) linitial(agg->args);
866 : 1203 : Expr *arg = tle->expr;
867 : :
868 : : /* Check for unsupported cases */
869 [ + + + + ]: 1203 : if (agg->aggdistinct != NIL || agg->aggorder != NIL ||
870 [ + + ]: 961 : agg->agglevelsup != 0)
871 : 252 : PG_RETURN_POINTER(NULL);
872 : :
873 : : /* If the arg isn't NULLable, do the conversion */
874 [ + + ]: 951 : if (expr_is_nonnullable(req->root, arg, NOTNULL_SOURCE_HASHTABLE))
875 : : {
876 : : Aggref *newagg;
877 : :
878 : : /* We don't expect these to have been set yet */
879 : : Assert(agg->aggtransno == -1);
880 : : Assert(agg->aggtranstype == InvalidOid);
881 : :
882 : : /* Convert COUNT(ANY) to COUNT(*) by making a new Aggref */
883 : 295 : newagg = makeNode(Aggref);
884 : 295 : memcpy(newagg, agg, sizeof(Aggref));
885 : 295 : newagg->aggfnoid = F_COUNT_;
886 : :
887 : : /* count(*) has no args */
888 : 295 : newagg->aggargtypes = NULL;
889 : 295 : newagg->args = NULL;
890 : 295 : newagg->aggstar = true;
891 : 295 : newagg->location = -1;
892 : :
893 : 295 : PG_RETURN_POINTER(newagg);
894 : : }
895 : : }
896 : : }
897 : :
898 : 14498 : PG_RETURN_POINTER(NULL);
899 : : }
900 : :
901 : :
902 : : Datum
903 : 572 : int8larger(PG_FUNCTION_ARGS)
904 : : {
905 : 572 : int64 arg1 = PG_GETARG_INT64(0);
906 : 572 : int64 arg2 = PG_GETARG_INT64(1);
907 : : int64 result;
908 : :
909 : 572 : result = ((arg1 > arg2) ? arg1 : arg2);
910 : :
911 : 572 : PG_RETURN_INT64(result);
912 : : }
913 : :
914 : : Datum
915 : 4489 : int8smaller(PG_FUNCTION_ARGS)
916 : : {
917 : 4489 : int64 arg1 = PG_GETARG_INT64(0);
918 : 4489 : int64 arg2 = PG_GETARG_INT64(1);
919 : : int64 result;
920 : :
921 : 4489 : result = ((arg1 < arg2) ? arg1 : arg2);
922 : :
923 : 4489 : PG_RETURN_INT64(result);
924 : : }
925 : :
926 : : Datum
927 : 2753 : int84pl(PG_FUNCTION_ARGS)
928 : : {
929 : 2753 : int64 arg1 = PG_GETARG_INT64(0);
930 : 2753 : int32 arg2 = PG_GETARG_INT32(1);
931 : : int64 result;
932 : :
933 [ + + ]: 2753 : if (unlikely(pg_add_s64_overflow(arg1, (int64) arg2, &result)))
934 [ + - ]: 4 : ereport(ERROR,
935 : : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
936 : : errmsg("bigint out of range")));
937 : 2749 : PG_RETURN_INT64(result);
938 : : }
939 : :
940 : : Datum
941 : 89 : int84mi(PG_FUNCTION_ARGS)
942 : : {
943 : 89 : int64 arg1 = PG_GETARG_INT64(0);
944 : 89 : int32 arg2 = PG_GETARG_INT32(1);
945 : : int64 result;
946 : :
947 [ + + ]: 89 : if (unlikely(pg_sub_s64_overflow(arg1, (int64) arg2, &result)))
948 [ + - ]: 4 : ereport(ERROR,
949 : : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
950 : : errmsg("bigint out of range")));
951 : 85 : PG_RETURN_INT64(result);
952 : : }
953 : :
954 : : Datum
955 : 1631 : int84mul(PG_FUNCTION_ARGS)
956 : : {
957 : 1631 : int64 arg1 = PG_GETARG_INT64(0);
958 : 1631 : int32 arg2 = PG_GETARG_INT32(1);
959 : : int64 result;
960 : :
961 [ + + ]: 1631 : if (unlikely(pg_mul_s64_overflow(arg1, (int64) arg2, &result)))
962 [ + - ]: 8 : ereport(ERROR,
963 : : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
964 : : errmsg("bigint out of range")));
965 : 1623 : PG_RETURN_INT64(result);
966 : : }
967 : :
968 : : Datum
969 : 121 : int84div(PG_FUNCTION_ARGS)
970 : : {
971 : 121 : int64 arg1 = PG_GETARG_INT64(0);
972 : 121 : int32 arg2 = PG_GETARG_INT32(1);
973 : : int64 result;
974 : :
975 [ + + ]: 121 : if (arg2 == 0)
976 : : {
977 [ + - ]: 4 : ereport(ERROR,
978 : : (errcode(ERRCODE_DIVISION_BY_ZERO),
979 : : errmsg("division by zero")));
980 : : /* ensure compiler realizes we mustn't reach the division (gcc bug) */
981 : : PG_RETURN_NULL();
982 : : }
983 : :
984 : : /*
985 : : * INT64_MIN / -1 is problematic, since the result can't be represented on
986 : : * a two's-complement machine. Some machines produce INT64_MIN, some
987 : : * produce zero, some throw an exception. We can dodge the problem by
988 : : * recognizing that division by -1 is the same as negation.
989 : : */
990 [ + + ]: 117 : if (arg2 == -1)
991 : : {
992 [ + - ]: 4 : if (pg_neg_s64_overflow(arg1, &result))
993 [ + - ]: 4 : ereport(ERROR,
994 : : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
995 : : errmsg("bigint out of range")));
996 : 0 : PG_RETURN_INT64(result);
997 : : }
998 : :
999 : : /* No overflow is possible */
1000 : :
1001 : 113 : result = arg1 / arg2;
1002 : :
1003 : 113 : PG_RETURN_INT64(result);
1004 : : }
1005 : :
1006 : : Datum
1007 : 1055 : int48pl(PG_FUNCTION_ARGS)
1008 : : {
1009 : 1055 : int32 arg1 = PG_GETARG_INT32(0);
1010 : 1055 : int64 arg2 = PG_GETARG_INT64(1);
1011 : : int64 result;
1012 : :
1013 [ + + ]: 1055 : if (unlikely(pg_add_s64_overflow((int64) arg1, arg2, &result)))
1014 [ + - ]: 4 : ereport(ERROR,
1015 : : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1016 : : errmsg("bigint out of range")));
1017 : 1051 : PG_RETURN_INT64(result);
1018 : : }
1019 : :
1020 : : Datum
1021 : 44 : int48mi(PG_FUNCTION_ARGS)
1022 : : {
1023 : 44 : int32 arg1 = PG_GETARG_INT32(0);
1024 : 44 : int64 arg2 = PG_GETARG_INT64(1);
1025 : : int64 result;
1026 : :
1027 [ + + ]: 44 : if (unlikely(pg_sub_s64_overflow((int64) arg1, arg2, &result)))
1028 [ + - ]: 4 : ereport(ERROR,
1029 : : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1030 : : errmsg("bigint out of range")));
1031 : 40 : PG_RETURN_INT64(result);
1032 : : }
1033 : :
1034 : : Datum
1035 : 156 : int48mul(PG_FUNCTION_ARGS)
1036 : : {
1037 : 156 : int32 arg1 = PG_GETARG_INT32(0);
1038 : 156 : int64 arg2 = PG_GETARG_INT64(1);
1039 : : int64 result;
1040 : :
1041 [ + + ]: 156 : if (unlikely(pg_mul_s64_overflow((int64) arg1, arg2, &result)))
1042 [ + - ]: 4 : ereport(ERROR,
1043 : : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1044 : : errmsg("bigint out of range")));
1045 : 152 : PG_RETURN_INT64(result);
1046 : : }
1047 : :
1048 : : Datum
1049 : 24 : int48div(PG_FUNCTION_ARGS)
1050 : : {
1051 : 24 : int32 arg1 = PG_GETARG_INT32(0);
1052 : 24 : int64 arg2 = PG_GETARG_INT64(1);
1053 : :
1054 [ + + ]: 24 : if (unlikely(arg2 == 0))
1055 : : {
1056 [ + - ]: 4 : ereport(ERROR,
1057 : : (errcode(ERRCODE_DIVISION_BY_ZERO),
1058 : : errmsg("division by zero")));
1059 : : /* ensure compiler realizes we mustn't reach the division (gcc bug) */
1060 : : PG_RETURN_NULL();
1061 : : }
1062 : :
1063 : : /* No overflow is possible */
1064 : 20 : PG_RETURN_INT64((int64) arg1 / arg2);
1065 : : }
1066 : :
1067 : : Datum
1068 : 24 : int82pl(PG_FUNCTION_ARGS)
1069 : : {
1070 : 24 : int64 arg1 = PG_GETARG_INT64(0);
1071 : 24 : int16 arg2 = PG_GETARG_INT16(1);
1072 : : int64 result;
1073 : :
1074 [ + + ]: 24 : if (unlikely(pg_add_s64_overflow(arg1, (int64) arg2, &result)))
1075 [ + - ]: 4 : ereport(ERROR,
1076 : : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1077 : : errmsg("bigint out of range")));
1078 : 20 : PG_RETURN_INT64(result);
1079 : : }
1080 : :
1081 : : Datum
1082 : 24 : int82mi(PG_FUNCTION_ARGS)
1083 : : {
1084 : 24 : int64 arg1 = PG_GETARG_INT64(0);
1085 : 24 : int16 arg2 = PG_GETARG_INT16(1);
1086 : : int64 result;
1087 : :
1088 [ + + ]: 24 : if (unlikely(pg_sub_s64_overflow(arg1, (int64) arg2, &result)))
1089 [ + - ]: 4 : ereport(ERROR,
1090 : : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1091 : : errmsg("bigint out of range")));
1092 : 20 : PG_RETURN_INT64(result);
1093 : : }
1094 : :
1095 : : Datum
1096 : 28 : int82mul(PG_FUNCTION_ARGS)
1097 : : {
1098 : 28 : int64 arg1 = PG_GETARG_INT64(0);
1099 : 28 : int16 arg2 = PG_GETARG_INT16(1);
1100 : : int64 result;
1101 : :
1102 [ + + ]: 28 : if (unlikely(pg_mul_s64_overflow(arg1, (int64) arg2, &result)))
1103 [ + - ]: 8 : ereport(ERROR,
1104 : : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1105 : : errmsg("bigint out of range")));
1106 : 20 : PG_RETURN_INT64(result);
1107 : : }
1108 : :
1109 : : Datum
1110 : 28 : int82div(PG_FUNCTION_ARGS)
1111 : : {
1112 : 28 : int64 arg1 = PG_GETARG_INT64(0);
1113 : 28 : int16 arg2 = PG_GETARG_INT16(1);
1114 : : int64 result;
1115 : :
1116 [ + + ]: 28 : if (unlikely(arg2 == 0))
1117 : : {
1118 [ + - ]: 4 : ereport(ERROR,
1119 : : (errcode(ERRCODE_DIVISION_BY_ZERO),
1120 : : errmsg("division by zero")));
1121 : : /* ensure compiler realizes we mustn't reach the division (gcc bug) */
1122 : : PG_RETURN_NULL();
1123 : : }
1124 : :
1125 : : /*
1126 : : * INT64_MIN / -1 is problematic, since the result can't be represented on
1127 : : * a two's-complement machine. Some machines produce INT64_MIN, some
1128 : : * produce zero, some throw an exception. We can dodge the problem by
1129 : : * recognizing that division by -1 is the same as negation.
1130 : : */
1131 [ + + ]: 24 : if (arg2 == -1)
1132 : : {
1133 [ + - ]: 4 : if (pg_neg_s64_overflow(arg1, &result))
1134 [ + - ]: 4 : ereport(ERROR,
1135 : : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1136 : : errmsg("bigint out of range")));
1137 : 0 : PG_RETURN_INT64(result);
1138 : : }
1139 : :
1140 : : /* No overflow is possible */
1141 : :
1142 : 20 : result = arg1 / arg2;
1143 : :
1144 : 20 : PG_RETURN_INT64(result);
1145 : : }
1146 : :
1147 : : Datum
1148 : 24 : int28pl(PG_FUNCTION_ARGS)
1149 : : {
1150 : 24 : int16 arg1 = PG_GETARG_INT16(0);
1151 : 24 : int64 arg2 = PG_GETARG_INT64(1);
1152 : : int64 result;
1153 : :
1154 [ + + ]: 24 : if (unlikely(pg_add_s64_overflow((int64) arg1, arg2, &result)))
1155 [ + - ]: 4 : ereport(ERROR,
1156 : : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1157 : : errmsg("bigint out of range")));
1158 : 20 : PG_RETURN_INT64(result);
1159 : : }
1160 : :
1161 : : Datum
1162 : 24 : int28mi(PG_FUNCTION_ARGS)
1163 : : {
1164 : 24 : int16 arg1 = PG_GETARG_INT16(0);
1165 : 24 : int64 arg2 = PG_GETARG_INT64(1);
1166 : : int64 result;
1167 : :
1168 [ + + ]: 24 : if (unlikely(pg_sub_s64_overflow((int64) arg1, arg2, &result)))
1169 [ + - ]: 4 : ereport(ERROR,
1170 : : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1171 : : errmsg("bigint out of range")));
1172 : 20 : PG_RETURN_INT64(result);
1173 : : }
1174 : :
1175 : : Datum
1176 : 24 : int28mul(PG_FUNCTION_ARGS)
1177 : : {
1178 : 24 : int16 arg1 = PG_GETARG_INT16(0);
1179 : 24 : int64 arg2 = PG_GETARG_INT64(1);
1180 : : int64 result;
1181 : :
1182 [ + + ]: 24 : if (unlikely(pg_mul_s64_overflow((int64) arg1, arg2, &result)))
1183 [ + - ]: 4 : ereport(ERROR,
1184 : : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1185 : : errmsg("bigint out of range")));
1186 : 20 : PG_RETURN_INT64(result);
1187 : : }
1188 : :
1189 : : Datum
1190 : 24 : int28div(PG_FUNCTION_ARGS)
1191 : : {
1192 : 24 : int16 arg1 = PG_GETARG_INT16(0);
1193 : 24 : int64 arg2 = PG_GETARG_INT64(1);
1194 : :
1195 [ + + ]: 24 : if (unlikely(arg2 == 0))
1196 : : {
1197 [ + - ]: 4 : ereport(ERROR,
1198 : : (errcode(ERRCODE_DIVISION_BY_ZERO),
1199 : : errmsg("division by zero")));
1200 : : /* ensure compiler realizes we mustn't reach the division (gcc bug) */
1201 : : PG_RETURN_NULL();
1202 : : }
1203 : :
1204 : : /* No overflow is possible */
1205 : 20 : PG_RETURN_INT64((int64) arg1 / arg2);
1206 : : }
1207 : :
1208 : : /*
1209 : : * Binary arithmetics
1210 : : *
1211 : : * int8and - returns arg1 & arg2
1212 : : * int8or - returns arg1 | arg2
1213 : : * int8xor - returns arg1 # arg2
1214 : : * int8not - returns ~arg1
1215 : : * int8shl - returns arg1 << arg2
1216 : : * int8shr - returns arg1 >> arg2
1217 : : */
1218 : :
1219 : : Datum
1220 : 28 : int8and(PG_FUNCTION_ARGS)
1221 : : {
1222 : 28 : int64 arg1 = PG_GETARG_INT64(0);
1223 : 28 : int64 arg2 = PG_GETARG_INT64(1);
1224 : :
1225 : 28 : PG_RETURN_INT64(arg1 & arg2);
1226 : : }
1227 : :
1228 : : Datum
1229 : 30 : int8or(PG_FUNCTION_ARGS)
1230 : : {
1231 : 30 : int64 arg1 = PG_GETARG_INT64(0);
1232 : 30 : int64 arg2 = PG_GETARG_INT64(1);
1233 : :
1234 : 30 : PG_RETURN_INT64(arg1 | arg2);
1235 : : }
1236 : :
1237 : : Datum
1238 : 28 : int8xor(PG_FUNCTION_ARGS)
1239 : : {
1240 : 28 : int64 arg1 = PG_GETARG_INT64(0);
1241 : 28 : int64 arg2 = PG_GETARG_INT64(1);
1242 : :
1243 : 28 : PG_RETURN_INT64(arg1 ^ arg2);
1244 : : }
1245 : :
1246 : : Datum
1247 : 20 : int8not(PG_FUNCTION_ARGS)
1248 : : {
1249 : 20 : int64 arg1 = PG_GETARG_INT64(0);
1250 : :
1251 : 20 : PG_RETURN_INT64(~arg1);
1252 : : }
1253 : :
1254 : : Datum
1255 : 32 : int8shl(PG_FUNCTION_ARGS)
1256 : : {
1257 : 32 : int64 arg1 = PG_GETARG_INT64(0);
1258 : 32 : int32 arg2 = PG_GETARG_INT32(1);
1259 : :
1260 : 32 : PG_RETURN_INT64(arg1 << arg2);
1261 : : }
1262 : :
1263 : : Datum
1264 : 20 : int8shr(PG_FUNCTION_ARGS)
1265 : : {
1266 : 20 : int64 arg1 = PG_GETARG_INT64(0);
1267 : 20 : int32 arg2 = PG_GETARG_INT32(1);
1268 : :
1269 : 20 : PG_RETURN_INT64(arg1 >> arg2);
1270 : : }
1271 : :
1272 : : /*----------------------------------------------------------
1273 : : * Conversion operators.
1274 : : *---------------------------------------------------------*/
1275 : :
1276 : : Datum
1277 : 1593855 : int48(PG_FUNCTION_ARGS)
1278 : : {
1279 : 1593855 : int32 arg = PG_GETARG_INT32(0);
1280 : :
1281 : 1593855 : PG_RETURN_INT64((int64) arg);
1282 : : }
1283 : :
1284 : : Datum
1285 : 306159 : int84(PG_FUNCTION_ARGS)
1286 : : {
1287 : 306159 : int64 arg = PG_GETARG_INT64(0);
1288 : :
1289 [ + - + + ]: 306159 : if (unlikely(arg < PG_INT32_MIN) || unlikely(arg > PG_INT32_MAX))
1290 [ + - ]: 5 : ereturn(fcinfo->context, (Datum) 0,
1291 : : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1292 : : errmsg("integer out of range")));
1293 : :
1294 : 306154 : PG_RETURN_INT32((int32) arg);
1295 : : }
1296 : :
1297 : : Datum
1298 : 20 : int28(PG_FUNCTION_ARGS)
1299 : : {
1300 : 20 : int16 arg = PG_GETARG_INT16(0);
1301 : :
1302 : 20 : PG_RETURN_INT64((int64) arg);
1303 : : }
1304 : :
1305 : : Datum
1306 : 24 : int82(PG_FUNCTION_ARGS)
1307 : : {
1308 : 24 : int64 arg = PG_GETARG_INT64(0);
1309 : :
1310 [ + - + + ]: 24 : if (unlikely(arg < PG_INT16_MIN) || unlikely(arg > PG_INT16_MAX))
1311 [ + - ]: 4 : ereturn(fcinfo->context, (Datum) 0,
1312 : : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1313 : : errmsg("smallint out of range")));
1314 : :
1315 : 20 : PG_RETURN_INT16((int16) arg);
1316 : : }
1317 : :
1318 : : Datum
1319 : 8131 : i8tod(PG_FUNCTION_ARGS)
1320 : : {
1321 : 8131 : int64 arg = PG_GETARG_INT64(0);
1322 : : float8 result;
1323 : :
1324 : 8131 : result = arg;
1325 : :
1326 : 8131 : PG_RETURN_FLOAT8(result);
1327 : : }
1328 : :
1329 : : /*
1330 : : * dtoi8()
1331 : : * Convert float8 to 8-byte integer.
1332 : : */
1333 : : Datum
1334 : 101 : dtoi8(PG_FUNCTION_ARGS)
1335 : : {
1336 : 101 : float8 num = PG_GETARG_FLOAT8(0);
1337 : :
1338 : : /*
1339 : : * Get rid of any fractional part in the input. This is so we don't fail
1340 : : * on just-out-of-range values that would round into range. Note
1341 : : * assumption that rint() will pass through a NaN or Inf unchanged.
1342 : : */
1343 : 101 : num = rint(num);
1344 : :
1345 : : /* Range check */
1346 [ + - + + : 101 : if (unlikely(isnan(num) || !FLOAT8_FITS_IN_INT64(num)))
+ + + + +
+ ]
1347 [ + - ]: 12 : ereturn(fcinfo->context, (Datum) 0,
1348 : : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1349 : : errmsg("bigint out of range")));
1350 : :
1351 : 89 : PG_RETURN_INT64((int64) num);
1352 : : }
1353 : :
1354 : : Datum
1355 : 100 : i8tof(PG_FUNCTION_ARGS)
1356 : : {
1357 : 100 : int64 arg = PG_GETARG_INT64(0);
1358 : : float4 result;
1359 : :
1360 : 100 : result = arg;
1361 : :
1362 : 100 : PG_RETURN_FLOAT4(result);
1363 : : }
1364 : :
1365 : : /*
1366 : : * ftoi8()
1367 : : * Convert float4 to 8-byte integer.
1368 : : */
1369 : : Datum
1370 : 23 : ftoi8(PG_FUNCTION_ARGS)
1371 : : {
1372 : 23 : float4 num = PG_GETARG_FLOAT4(0);
1373 : :
1374 : : /*
1375 : : * Get rid of any fractional part in the input. This is so we don't fail
1376 : : * on just-out-of-range values that would round into range. Note
1377 : : * assumption that rint() will pass through a NaN or Inf unchanged.
1378 : : */
1379 : 23 : num = rint(num);
1380 : :
1381 : : /* Range check */
1382 [ + - + + : 23 : if (unlikely(isnan(num) || !FLOAT4_FITS_IN_INT64(num)))
+ + + + +
+ ]
1383 [ + - ]: 8 : ereturn(fcinfo->context, (Datum) 0,
1384 : : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1385 : : errmsg("bigint out of range")));
1386 : :
1387 : 15 : PG_RETURN_INT64((int64) num);
1388 : : }
1389 : :
1390 : : Datum
1391 : 13 : i8tooid(PG_FUNCTION_ARGS)
1392 : : {
1393 : 13 : int64 arg = PG_GETARG_INT64(0);
1394 : :
1395 [ + - + + ]: 13 : if (unlikely(arg < 0) || unlikely(arg > PG_UINT32_MAX))
1396 [ + - ]: 4 : ereturn(fcinfo->context, (Datum) 0,
1397 : : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1398 : : errmsg("OID out of range")));
1399 : :
1400 : 9 : PG_RETURN_OID((Oid) arg);
1401 : : }
1402 : :
1403 : : Datum
1404 : 12 : oidtoi8(PG_FUNCTION_ARGS)
1405 : : {
1406 : 12 : Oid arg = PG_GETARG_OID(0);
1407 : :
1408 : 12 : PG_RETURN_INT64((int64) arg);
1409 : : }
1410 : :
1411 : : Datum
1412 : 5 : oidtooid8(PG_FUNCTION_ARGS)
1413 : : {
1414 : 5 : Oid arg = PG_GETARG_OID(0);
1415 : :
1416 : 5 : PG_RETURN_OID8((Oid8) arg);
1417 : : }
1418 : :
1419 : : /*
1420 : : * non-persistent numeric series generator
1421 : : */
1422 : : Datum
1423 : 152 : generate_series_int8(PG_FUNCTION_ARGS)
1424 : : {
1425 : 152 : return generate_series_step_int8(fcinfo);
1426 : : }
1427 : :
1428 : : Datum
1429 : 233 : generate_series_step_int8(PG_FUNCTION_ARGS)
1430 : : {
1431 : : FuncCallContext *funcctx;
1432 : : generate_series_fctx *fctx;
1433 : : int64 result;
1434 : : MemoryContext oldcontext;
1435 : :
1436 : : /* stuff done only on the first call of the function */
1437 [ + + ]: 233 : if (SRF_IS_FIRSTCALL())
1438 : : {
1439 : 35 : int64 start = PG_GETARG_INT64(0);
1440 : 35 : int64 finish = PG_GETARG_INT64(1);
1441 : 35 : int64 step = 1;
1442 : :
1443 : : /* see if we were given an explicit step size */
1444 [ + + ]: 35 : if (PG_NARGS() == 3)
1445 : 9 : step = PG_GETARG_INT64(2);
1446 [ + + ]: 35 : if (step == 0)
1447 [ + - ]: 4 : ereport(ERROR,
1448 : : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1449 : : errmsg("step size cannot equal zero")));
1450 : :
1451 : : /* create a function context for cross-call persistence */
1452 : 31 : funcctx = SRF_FIRSTCALL_INIT();
1453 : :
1454 : : /*
1455 : : * switch to memory context appropriate for multiple function calls
1456 : : */
1457 : 31 : oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1458 : :
1459 : : /* allocate memory for user context */
1460 : 31 : fctx = palloc_object(generate_series_fctx);
1461 : :
1462 : : /*
1463 : : * Use fctx to keep state from call to call. Seed current with the
1464 : : * original start value
1465 : : */
1466 : 31 : fctx->current = start;
1467 : 31 : fctx->finish = finish;
1468 : 31 : fctx->step = step;
1469 : :
1470 : 31 : funcctx->user_fctx = fctx;
1471 : 31 : MemoryContextSwitchTo(oldcontext);
1472 : : }
1473 : :
1474 : : /* stuff done on every call of the function */
1475 : 229 : funcctx = SRF_PERCALL_SETUP();
1476 : :
1477 : : /*
1478 : : * get the saved state and use current as the result for this iteration
1479 : : */
1480 : 229 : fctx = funcctx->user_fctx;
1481 : 229 : result = fctx->current;
1482 : :
1483 [ + - + + ]: 229 : if ((fctx->step > 0 && fctx->current <= fctx->finish) ||
1484 [ - + - - ]: 31 : (fctx->step < 0 && fctx->current >= fctx->finish))
1485 : : {
1486 : : /*
1487 : : * Increment current in preparation for next iteration. If next-value
1488 : : * computation overflows, this is the final result.
1489 : : */
1490 [ - + ]: 198 : if (pg_add_s64_overflow(fctx->current, fctx->step, &fctx->current))
1491 : 0 : fctx->step = 0;
1492 : :
1493 : : /* do when there is more left to send */
1494 : 198 : SRF_RETURN_NEXT(funcctx, Int64GetDatum(result));
1495 : : }
1496 : : else
1497 : : /* do when there is no more left */
1498 : 31 : SRF_RETURN_DONE(funcctx);
1499 : : }
1500 : :
1501 : : /*
1502 : : * Planner support function for generate_series(int8, int8 [, int8])
1503 : : */
1504 : : Datum
1505 : 153 : generate_series_int8_support(PG_FUNCTION_ARGS)
1506 : : {
1507 : 153 : Node *rawreq = (Node *) PG_GETARG_POINTER(0);
1508 : 153 : Node *ret = NULL;
1509 : :
1510 [ + + ]: 153 : if (IsA(rawreq, SupportRequestRows))
1511 : : {
1512 : : /* Try to estimate the number of rows returned */
1513 : 39 : SupportRequestRows *req = (SupportRequestRows *) rawreq;
1514 : :
1515 [ + - ]: 39 : if (is_funcclause(req->node)) /* be paranoid */
1516 : : {
1517 : 39 : List *args = ((FuncExpr *) req->node)->args;
1518 : : Node *arg1,
1519 : : *arg2,
1520 : : *arg3;
1521 : :
1522 : : /* We can use estimated argument values here */
1523 : 39 : arg1 = estimate_expression_value(req->root, linitial(args));
1524 : 39 : arg2 = estimate_expression_value(req->root, lsecond(args));
1525 [ + + ]: 39 : if (list_length(args) >= 3)
1526 : 11 : arg3 = estimate_expression_value(req->root, lthird(args));
1527 : : else
1528 : 28 : arg3 = NULL;
1529 : :
1530 : : /*
1531 : : * If any argument is constant NULL, we can safely assume that
1532 : : * zero rows are returned. Otherwise, if they're all non-NULL
1533 : : * constants, we can calculate the number of rows that will be
1534 : : * returned. Use double arithmetic to avoid overflow hazards.
1535 : : */
1536 [ + + ]: 39 : if ((IsA(arg1, Const) &&
1537 [ + - ]: 33 : ((Const *) arg1)->constisnull) ||
1538 [ + + ]: 39 : (IsA(arg2, Const) &&
1539 [ + - + + ]: 39 : ((Const *) arg2)->constisnull) ||
1540 [ + - ]: 11 : (arg3 != NULL && IsA(arg3, Const) &&
1541 [ - + ]: 11 : ((Const *) arg3)->constisnull))
1542 : : {
1543 : 0 : req->rows = 0;
1544 : 0 : ret = (Node *) req;
1545 : : }
1546 [ + + ]: 39 : else if (IsA(arg1, Const) &&
1547 [ + + + + ]: 33 : IsA(arg2, Const) &&
1548 [ + - ]: 11 : (arg3 == NULL || IsA(arg3, Const)))
1549 : : {
1550 : : double start,
1551 : : finish,
1552 : : step;
1553 : :
1554 : 26 : start = DatumGetInt64(((Const *) arg1)->constvalue);
1555 : 26 : finish = DatumGetInt64(((Const *) arg2)->constvalue);
1556 [ + + ]: 26 : step = arg3 ? DatumGetInt64(((Const *) arg3)->constvalue) : 1;
1557 : :
1558 : : /* This equation works for either sign of step */
1559 [ + + ]: 26 : if (step != 0)
1560 : : {
1561 : 21 : req->rows = floor((finish - start + step) / step);
1562 : 21 : ret = (Node *) req;
1563 : : }
1564 : : }
1565 : : }
1566 : : }
1567 : :
1568 : 153 : PG_RETURN_POINTER(ret);
1569 : : }
|