Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * int.c
4 : * Functions for the built-in integer types (except int8).
5 : *
6 : * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
7 : * Portions Copyright (c) 1994, Regents of the University of California
8 : *
9 : *
10 : * IDENTIFICATION
11 : * src/backend/utils/adt/int.c
12 : *
13 : *-------------------------------------------------------------------------
14 : */
15 : /*
16 : * OLD COMMENTS
17 : * I/O routines:
18 : * int2in, int2out, int2recv, int2send
19 : * int4in, int4out, int4recv, int4send
20 : * int2vectorin, int2vectorout, int2vectorrecv, int2vectorsend
21 : * Boolean operators:
22 : * inteq, intne, intlt, intle, intgt, intge
23 : * Arithmetic operators:
24 : * intpl, intmi, int4mul, intdiv
25 : *
26 : * Arithmetic operators:
27 : * intmod
28 : */
29 : #include "postgres.h"
30 :
31 : #include <ctype.h>
32 : #include <limits.h>
33 : #include <math.h>
34 :
35 : #include "catalog/pg_type.h"
36 : #include "common/int.h"
37 : #include "funcapi.h"
38 : #include "libpq/pqformat.h"
39 : #include "nodes/nodeFuncs.h"
40 : #include "nodes/supportnodes.h"
41 : #include "optimizer/optimizer.h"
42 : #include "utils/array.h"
43 : #include "utils/builtins.h"
44 :
45 : #define Int2VectorSize(n) (offsetof(int2vector, values) + (n) * sizeof(int16))
46 :
47 : typedef struct
48 : {
49 : int32 current;
50 : int32 finish;
51 : int32 step;
52 : } generate_series_fctx;
53 :
54 :
55 : /*****************************************************************************
56 : * USER I/O ROUTINES *
57 : *****************************************************************************/
58 :
59 : /*
60 : * int2in - converts "num" to short
61 : */
62 : Datum
63 841056 : int2in(PG_FUNCTION_ARGS)
64 : {
65 841056 : char *num = PG_GETARG_CSTRING(0);
66 :
67 841056 : PG_RETURN_INT16(pg_strtoint16_safe(num, fcinfo->context));
68 : }
69 :
70 : /*
71 : * int2out - converts short to "num"
72 : */
73 : Datum
74 617822 : int2out(PG_FUNCTION_ARGS)
75 : {
76 617822 : int16 arg1 = PG_GETARG_INT16(0);
77 617822 : char *result = (char *) palloc(7); /* sign, 5 digits, '\0' */
78 :
79 617822 : pg_itoa(arg1, result);
80 617822 : PG_RETURN_CSTRING(result);
81 : }
82 :
83 : /*
84 : * int2recv - converts external binary format to int2
85 : */
86 : Datum
87 0 : int2recv(PG_FUNCTION_ARGS)
88 : {
89 0 : StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
90 :
91 0 : PG_RETURN_INT16((int16) pq_getmsgint(buf, sizeof(int16)));
92 : }
93 :
94 : /*
95 : * int2send - converts int2 to binary format
96 : */
97 : Datum
98 6 : int2send(PG_FUNCTION_ARGS)
99 : {
100 6 : int16 arg1 = PG_GETARG_INT16(0);
101 : StringInfoData buf;
102 :
103 6 : pq_begintypsend(&buf);
104 6 : pq_sendint16(&buf, arg1);
105 6 : PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
106 : }
107 :
108 : /*
109 : * construct int2vector given a raw array of int2s
110 : *
111 : * If int2s is NULL then caller must fill values[] afterward
112 : */
113 : int2vector *
114 113748 : buildint2vector(const int16 *int2s, int n)
115 : {
116 : int2vector *result;
117 :
118 113748 : result = (int2vector *) palloc0(Int2VectorSize(n));
119 :
120 113748 : if (n > 0 && int2s)
121 53396 : memcpy(result->values, int2s, n * sizeof(int16));
122 :
123 : /*
124 : * Attach standard array header. For historical reasons, we set the index
125 : * lower bound to 0 not 1.
126 : */
127 113748 : SET_VARSIZE(result, Int2VectorSize(n));
128 113748 : result->ndim = 1;
129 113748 : result->dataoffset = 0; /* never any nulls */
130 113748 : result->elemtype = INT2OID;
131 113748 : result->dim1 = n;
132 113748 : result->lbound1 = 0;
133 :
134 113748 : return result;
135 : }
136 :
137 : /*
138 : * int2vectorin - converts "num num ..." to internal form
139 : */
140 : Datum
141 584 : int2vectorin(PG_FUNCTION_ARGS)
142 : {
143 584 : char *intString = PG_GETARG_CSTRING(0);
144 584 : Node *escontext = fcinfo->context;
145 : int2vector *result;
146 : int nalloc;
147 : int n;
148 :
149 584 : nalloc = 32; /* arbitrary initial size guess */
150 584 : result = (int2vector *) palloc0(Int2VectorSize(nalloc));
151 :
152 584 : for (n = 0;; n++)
153 982 : {
154 : long l;
155 : char *endp;
156 :
157 1994 : while (*intString && isspace((unsigned char) *intString))
158 428 : intString++;
159 1566 : if (*intString == '\0')
160 572 : break;
161 :
162 994 : if (n >= nalloc)
163 : {
164 0 : nalloc *= 2;
165 0 : result = (int2vector *) repalloc(result, Int2VectorSize(nalloc));
166 : }
167 :
168 994 : errno = 0;
169 994 : l = strtol(intString, &endp, 10);
170 :
171 994 : if (intString == endp)
172 12 : ereturn(escontext, (Datum) 0,
173 : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
174 : errmsg("invalid input syntax for type %s: \"%s\"",
175 : "smallint", intString)));
176 :
177 988 : if (errno == ERANGE || l < SHRT_MIN || l > SHRT_MAX)
178 6 : ereturn(escontext, (Datum) 0,
179 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
180 : errmsg("value \"%s\" is out of range for type %s", intString,
181 : "smallint")));
182 :
183 982 : if (*endp && *endp != ' ')
184 0 : ereturn(escontext, (Datum) 0,
185 : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
186 : errmsg("invalid input syntax for type %s: \"%s\"",
187 : "smallint", intString)));
188 :
189 982 : result->values[n] = l;
190 982 : intString = endp;
191 : }
192 :
193 572 : SET_VARSIZE(result, Int2VectorSize(n));
194 572 : result->ndim = 1;
195 572 : result->dataoffset = 0; /* never any nulls */
196 572 : result->elemtype = INT2OID;
197 572 : result->dim1 = n;
198 572 : result->lbound1 = 0;
199 :
200 572 : PG_RETURN_POINTER(result);
201 : }
202 :
203 : /*
204 : * int2vectorout - converts internal form to "num num ..."
205 : */
206 : Datum
207 13062 : int2vectorout(PG_FUNCTION_ARGS)
208 : {
209 13062 : int2vector *int2Array = (int2vector *) PG_GETARG_POINTER(0);
210 : int num,
211 13062 : nnums = int2Array->dim1;
212 : char *rp;
213 : char *result;
214 :
215 : /* assumes sign, 5 digits, ' ' */
216 13062 : rp = result = (char *) palloc(nnums * 7 + 1);
217 33552 : for (num = 0; num < nnums; num++)
218 : {
219 20490 : if (num != 0)
220 8370 : *rp++ = ' ';
221 20490 : rp += pg_itoa(int2Array->values[num], rp);
222 : }
223 13062 : *rp = '\0';
224 13062 : PG_RETURN_CSTRING(result);
225 : }
226 :
227 : /*
228 : * int2vectorrecv - converts external binary format to int2vector
229 : */
230 : Datum
231 0 : int2vectorrecv(PG_FUNCTION_ARGS)
232 : {
233 0 : LOCAL_FCINFO(locfcinfo, 3);
234 0 : StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
235 : int2vector *result;
236 :
237 : /*
238 : * Normally one would call array_recv() using DirectFunctionCall3, but
239 : * that does not work since array_recv wants to cache some data using
240 : * fcinfo->flinfo->fn_extra. So we need to pass it our own flinfo
241 : * parameter.
242 : */
243 0 : InitFunctionCallInfoData(*locfcinfo, fcinfo->flinfo, 3,
244 : InvalidOid, NULL, NULL);
245 :
246 0 : locfcinfo->args[0].value = PointerGetDatum(buf);
247 0 : locfcinfo->args[0].isnull = false;
248 0 : locfcinfo->args[1].value = ObjectIdGetDatum(INT2OID);
249 0 : locfcinfo->args[1].isnull = false;
250 0 : locfcinfo->args[2].value = Int32GetDatum(-1);
251 0 : locfcinfo->args[2].isnull = false;
252 :
253 0 : result = (int2vector *) DatumGetPointer(array_recv(locfcinfo));
254 :
255 : Assert(!locfcinfo->isnull);
256 :
257 : /* sanity checks: int2vector must be 1-D, 0-based, no nulls */
258 0 : if (ARR_NDIM(result) != 1 ||
259 0 : ARR_HASNULL(result) ||
260 0 : ARR_ELEMTYPE(result) != INT2OID ||
261 0 : ARR_LBOUND(result)[0] != 0)
262 0 : ereport(ERROR,
263 : (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
264 : errmsg("invalid int2vector data")));
265 :
266 0 : PG_RETURN_POINTER(result);
267 : }
268 :
269 : /*
270 : * int2vectorsend - converts int2vector to binary format
271 : */
272 : Datum
273 0 : int2vectorsend(PG_FUNCTION_ARGS)
274 : {
275 0 : return array_send(fcinfo);
276 : }
277 :
278 :
279 : /*****************************************************************************
280 : * PUBLIC ROUTINES *
281 : *****************************************************************************/
282 :
283 : /*
284 : * int4in - converts "num" to int4
285 : */
286 : Datum
287 4328402 : int4in(PG_FUNCTION_ARGS)
288 : {
289 4328402 : char *num = PG_GETARG_CSTRING(0);
290 :
291 4328402 : PG_RETURN_INT32(pg_strtoint32_safe(num, fcinfo->context));
292 : }
293 :
294 : /*
295 : * int4out - converts int4 to "num"
296 : */
297 : Datum
298 16342192 : int4out(PG_FUNCTION_ARGS)
299 : {
300 16342192 : int32 arg1 = PG_GETARG_INT32(0);
301 16342192 : char *result = (char *) palloc(12); /* sign, 10 digits, '\0' */
302 :
303 16342192 : pg_ltoa(arg1, result);
304 16342192 : PG_RETURN_CSTRING(result);
305 : }
306 :
307 : /*
308 : * int4recv - converts external binary format to int4
309 : */
310 : Datum
311 203870 : int4recv(PG_FUNCTION_ARGS)
312 : {
313 203870 : StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
314 :
315 203870 : PG_RETURN_INT32((int32) pq_getmsgint(buf, sizeof(int32)));
316 : }
317 :
318 : /*
319 : * int4send - converts int4 to binary format
320 : */
321 : Datum
322 168120 : int4send(PG_FUNCTION_ARGS)
323 : {
324 168120 : int32 arg1 = PG_GETARG_INT32(0);
325 : StringInfoData buf;
326 :
327 168120 : pq_begintypsend(&buf);
328 168120 : pq_sendint32(&buf, arg1);
329 168120 : PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
330 : }
331 :
332 :
333 : /*
334 : * ===================
335 : * CONVERSION ROUTINES
336 : * ===================
337 : */
338 :
339 : Datum
340 34806 : i2toi4(PG_FUNCTION_ARGS)
341 : {
342 34806 : int16 arg1 = PG_GETARG_INT16(0);
343 :
344 34806 : PG_RETURN_INT32((int32) arg1);
345 : }
346 :
347 : Datum
348 22570 : i4toi2(PG_FUNCTION_ARGS)
349 : {
350 22570 : int32 arg1 = PG_GETARG_INT32(0);
351 :
352 22570 : if (unlikely(arg1 < SHRT_MIN) || unlikely(arg1 > SHRT_MAX))
353 28 : ereport(ERROR,
354 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
355 : errmsg("smallint out of range")));
356 :
357 22542 : PG_RETURN_INT16((int16) arg1);
358 : }
359 :
360 : /* Cast int4 -> bool */
361 : Datum
362 30 : int4_bool(PG_FUNCTION_ARGS)
363 : {
364 30 : if (PG_GETARG_INT32(0) == 0)
365 12 : PG_RETURN_BOOL(false);
366 : else
367 18 : PG_RETURN_BOOL(true);
368 : }
369 :
370 : /* Cast bool -> int4 */
371 : Datum
372 1632 : bool_int4(PG_FUNCTION_ARGS)
373 : {
374 1632 : if (PG_GETARG_BOOL(0) == false)
375 892 : PG_RETURN_INT32(0);
376 : else
377 740 : PG_RETURN_INT32(1);
378 : }
379 :
380 : /*
381 : * ============================
382 : * COMPARISON OPERATOR ROUTINES
383 : * ============================
384 : */
385 :
386 : /*
387 : * inteq - returns 1 iff arg1 == arg2
388 : * intne - returns 1 iff arg1 != arg2
389 : * intlt - returns 1 iff arg1 < arg2
390 : * intle - returns 1 iff arg1 <= arg2
391 : * intgt - returns 1 iff arg1 > arg2
392 : * intge - returns 1 iff arg1 >= arg2
393 : */
394 :
395 : Datum
396 30167802 : int4eq(PG_FUNCTION_ARGS)
397 : {
398 30167802 : int32 arg1 = PG_GETARG_INT32(0);
399 30167802 : int32 arg2 = PG_GETARG_INT32(1);
400 :
401 30167802 : PG_RETURN_BOOL(arg1 == arg2);
402 : }
403 :
404 : Datum
405 431288 : int4ne(PG_FUNCTION_ARGS)
406 : {
407 431288 : int32 arg1 = PG_GETARG_INT32(0);
408 431288 : int32 arg2 = PG_GETARG_INT32(1);
409 :
410 431288 : PG_RETURN_BOOL(arg1 != arg2);
411 : }
412 :
413 : Datum
414 6525656 : int4lt(PG_FUNCTION_ARGS)
415 : {
416 6525656 : int32 arg1 = PG_GETARG_INT32(0);
417 6525656 : int32 arg2 = PG_GETARG_INT32(1);
418 :
419 6525656 : PG_RETURN_BOOL(arg1 < arg2);
420 : }
421 :
422 : Datum
423 1181860 : int4le(PG_FUNCTION_ARGS)
424 : {
425 1181860 : int32 arg1 = PG_GETARG_INT32(0);
426 1181860 : int32 arg2 = PG_GETARG_INT32(1);
427 :
428 1181860 : PG_RETURN_BOOL(arg1 <= arg2);
429 : }
430 :
431 : Datum
432 2247930 : int4gt(PG_FUNCTION_ARGS)
433 : {
434 2247930 : int32 arg1 = PG_GETARG_INT32(0);
435 2247930 : int32 arg2 = PG_GETARG_INT32(1);
436 :
437 2247930 : PG_RETURN_BOOL(arg1 > arg2);
438 : }
439 :
440 : Datum
441 419262 : int4ge(PG_FUNCTION_ARGS)
442 : {
443 419262 : int32 arg1 = PG_GETARG_INT32(0);
444 419262 : int32 arg2 = PG_GETARG_INT32(1);
445 :
446 419262 : PG_RETURN_BOOL(arg1 >= arg2);
447 : }
448 :
449 : Datum
450 2178308 : int2eq(PG_FUNCTION_ARGS)
451 : {
452 2178308 : int16 arg1 = PG_GETARG_INT16(0);
453 2178308 : int16 arg2 = PG_GETARG_INT16(1);
454 :
455 2178308 : PG_RETURN_BOOL(arg1 == arg2);
456 : }
457 :
458 : Datum
459 30388 : int2ne(PG_FUNCTION_ARGS)
460 : {
461 30388 : int16 arg1 = PG_GETARG_INT16(0);
462 30388 : int16 arg2 = PG_GETARG_INT16(1);
463 :
464 30388 : PG_RETURN_BOOL(arg1 != arg2);
465 : }
466 :
467 : Datum
468 572466 : int2lt(PG_FUNCTION_ARGS)
469 : {
470 572466 : int16 arg1 = PG_GETARG_INT16(0);
471 572466 : int16 arg2 = PG_GETARG_INT16(1);
472 :
473 572466 : PG_RETURN_BOOL(arg1 < arg2);
474 : }
475 :
476 : Datum
477 4278 : int2le(PG_FUNCTION_ARGS)
478 : {
479 4278 : int16 arg1 = PG_GETARG_INT16(0);
480 4278 : int16 arg2 = PG_GETARG_INT16(1);
481 :
482 4278 : PG_RETURN_BOOL(arg1 <= arg2);
483 : }
484 :
485 : Datum
486 2164698 : int2gt(PG_FUNCTION_ARGS)
487 : {
488 2164698 : int16 arg1 = PG_GETARG_INT16(0);
489 2164698 : int16 arg2 = PG_GETARG_INT16(1);
490 :
491 2164698 : PG_RETURN_BOOL(arg1 > arg2);
492 : }
493 :
494 : Datum
495 3714 : int2ge(PG_FUNCTION_ARGS)
496 : {
497 3714 : int16 arg1 = PG_GETARG_INT16(0);
498 3714 : int16 arg2 = PG_GETARG_INT16(1);
499 :
500 3714 : PG_RETURN_BOOL(arg1 >= arg2);
501 : }
502 :
503 : Datum
504 139658 : int24eq(PG_FUNCTION_ARGS)
505 : {
506 139658 : int16 arg1 = PG_GETARG_INT16(0);
507 139658 : int32 arg2 = PG_GETARG_INT32(1);
508 :
509 139658 : PG_RETURN_BOOL(arg1 == arg2);
510 : }
511 :
512 : Datum
513 72758 : int24ne(PG_FUNCTION_ARGS)
514 : {
515 72758 : int16 arg1 = PG_GETARG_INT16(0);
516 72758 : int32 arg2 = PG_GETARG_INT32(1);
517 :
518 72758 : PG_RETURN_BOOL(arg1 != arg2);
519 : }
520 :
521 : Datum
522 132578 : int24lt(PG_FUNCTION_ARGS)
523 : {
524 132578 : int16 arg1 = PG_GETARG_INT16(0);
525 132578 : int32 arg2 = PG_GETARG_INT32(1);
526 :
527 132578 : PG_RETURN_BOOL(arg1 < arg2);
528 : }
529 :
530 : Datum
531 57260 : int24le(PG_FUNCTION_ARGS)
532 : {
533 57260 : int16 arg1 = PG_GETARG_INT16(0);
534 57260 : int32 arg2 = PG_GETARG_INT32(1);
535 :
536 57260 : PG_RETURN_BOOL(arg1 <= arg2);
537 : }
538 :
539 : Datum
540 502876 : int24gt(PG_FUNCTION_ARGS)
541 : {
542 502876 : int16 arg1 = PG_GETARG_INT16(0);
543 502876 : int32 arg2 = PG_GETARG_INT32(1);
544 :
545 502876 : PG_RETURN_BOOL(arg1 > arg2);
546 : }
547 :
548 : Datum
549 9762 : int24ge(PG_FUNCTION_ARGS)
550 : {
551 9762 : int16 arg1 = PG_GETARG_INT16(0);
552 9762 : int32 arg2 = PG_GETARG_INT32(1);
553 :
554 9762 : PG_RETURN_BOOL(arg1 >= arg2);
555 : }
556 :
557 : Datum
558 123702 : int42eq(PG_FUNCTION_ARGS)
559 : {
560 123702 : int32 arg1 = PG_GETARG_INT32(0);
561 123702 : int16 arg2 = PG_GETARG_INT16(1);
562 :
563 123702 : PG_RETURN_BOOL(arg1 == arg2);
564 : }
565 :
566 : Datum
567 30 : int42ne(PG_FUNCTION_ARGS)
568 : {
569 30 : int32 arg1 = PG_GETARG_INT32(0);
570 30 : int16 arg2 = PG_GETARG_INT16(1);
571 :
572 30 : PG_RETURN_BOOL(arg1 != arg2);
573 : }
574 :
575 : Datum
576 15828 : int42lt(PG_FUNCTION_ARGS)
577 : {
578 15828 : int32 arg1 = PG_GETARG_INT32(0);
579 15828 : int16 arg2 = PG_GETARG_INT16(1);
580 :
581 15828 : PG_RETURN_BOOL(arg1 < arg2);
582 : }
583 :
584 : Datum
585 15600 : int42le(PG_FUNCTION_ARGS)
586 : {
587 15600 : int32 arg1 = PG_GETARG_INT32(0);
588 15600 : int16 arg2 = PG_GETARG_INT16(1);
589 :
590 15600 : PG_RETURN_BOOL(arg1 <= arg2);
591 : }
592 :
593 : Datum
594 3228 : int42gt(PG_FUNCTION_ARGS)
595 : {
596 3228 : int32 arg1 = PG_GETARG_INT32(0);
597 3228 : int16 arg2 = PG_GETARG_INT16(1);
598 :
599 3228 : PG_RETURN_BOOL(arg1 > arg2);
600 : }
601 :
602 : Datum
603 3456 : int42ge(PG_FUNCTION_ARGS)
604 : {
605 3456 : int32 arg1 = PG_GETARG_INT32(0);
606 3456 : int16 arg2 = PG_GETARG_INT16(1);
607 :
608 3456 : PG_RETURN_BOOL(arg1 >= arg2);
609 : }
610 :
611 :
612 : /*----------------------------------------------------------
613 : * in_range functions for int4 and int2,
614 : * including cross-data-type comparisons.
615 : *
616 : * Note: we provide separate intN_int8 functions for performance
617 : * reasons. This forces also providing intN_int2, else cases with a
618 : * smallint offset value would fail to resolve which function to use.
619 : * But that's an unlikely situation, so don't duplicate code for it.
620 : *---------------------------------------------------------*/
621 :
622 : Datum
623 3198 : in_range_int4_int4(PG_FUNCTION_ARGS)
624 : {
625 3198 : int32 val = PG_GETARG_INT32(0);
626 3198 : int32 base = PG_GETARG_INT32(1);
627 3198 : int32 offset = PG_GETARG_INT32(2);
628 3198 : bool sub = PG_GETARG_BOOL(3);
629 3198 : bool less = PG_GETARG_BOOL(4);
630 : int32 sum;
631 :
632 3198 : if (offset < 0)
633 12 : ereport(ERROR,
634 : (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
635 : errmsg("invalid preceding or following size in window function")));
636 :
637 3186 : if (sub)
638 1440 : offset = -offset; /* cannot overflow */
639 :
640 3186 : if (unlikely(pg_add_s32_overflow(base, offset, &sum)))
641 : {
642 : /*
643 : * If sub is false, the true sum is surely more than val, so correct
644 : * answer is the same as "less". If sub is true, the true sum is
645 : * surely less than val, so the answer is "!less".
646 : */
647 36 : PG_RETURN_BOOL(sub ? !less : less);
648 : }
649 :
650 3150 : if (less)
651 1860 : PG_RETURN_BOOL(val <= sum);
652 : else
653 1290 : PG_RETURN_BOOL(val >= sum);
654 : }
655 :
656 : Datum
657 906 : in_range_int4_int2(PG_FUNCTION_ARGS)
658 : {
659 : /* Doesn't seem worth duplicating code for, so just invoke int4_int4 */
660 906 : return DirectFunctionCall5(in_range_int4_int4,
661 : PG_GETARG_DATUM(0),
662 : PG_GETARG_DATUM(1),
663 : Int32GetDatum((int32) PG_GETARG_INT16(2)),
664 : PG_GETARG_DATUM(3),
665 : PG_GETARG_DATUM(4));
666 : }
667 :
668 : Datum
669 762 : in_range_int4_int8(PG_FUNCTION_ARGS)
670 : {
671 : /* We must do all the math in int64 */
672 762 : int64 val = (int64) PG_GETARG_INT32(0);
673 762 : int64 base = (int64) PG_GETARG_INT32(1);
674 762 : int64 offset = PG_GETARG_INT64(2);
675 762 : bool sub = PG_GETARG_BOOL(3);
676 762 : bool less = PG_GETARG_BOOL(4);
677 : int64 sum;
678 :
679 762 : if (offset < 0)
680 0 : ereport(ERROR,
681 : (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
682 : errmsg("invalid preceding or following size in window function")));
683 :
684 762 : if (sub)
685 690 : offset = -offset; /* cannot overflow */
686 :
687 762 : if (unlikely(pg_add_s64_overflow(base, offset, &sum)))
688 : {
689 : /*
690 : * If sub is false, the true sum is surely more than val, so correct
691 : * answer is the same as "less". If sub is true, the true sum is
692 : * surely less than val, so the answer is "!less".
693 : */
694 0 : PG_RETURN_BOOL(sub ? !less : less);
695 : }
696 :
697 762 : if (less)
698 72 : PG_RETURN_BOOL(val <= sum);
699 : else
700 690 : PG_RETURN_BOOL(val >= sum);
701 : }
702 :
703 : Datum
704 36 : in_range_int2_int4(PG_FUNCTION_ARGS)
705 : {
706 : /* We must do all the math in int32 */
707 36 : int32 val = (int32) PG_GETARG_INT16(0);
708 36 : int32 base = (int32) PG_GETARG_INT16(1);
709 36 : int32 offset = PG_GETARG_INT32(2);
710 36 : bool sub = PG_GETARG_BOOL(3);
711 36 : bool less = PG_GETARG_BOOL(4);
712 : int32 sum;
713 :
714 36 : if (offset < 0)
715 0 : ereport(ERROR,
716 : (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
717 : errmsg("invalid preceding or following size in window function")));
718 :
719 36 : if (sub)
720 18 : offset = -offset; /* cannot overflow */
721 :
722 36 : if (unlikely(pg_add_s32_overflow(base, offset, &sum)))
723 : {
724 : /*
725 : * If sub is false, the true sum is surely more than val, so correct
726 : * answer is the same as "less". If sub is true, the true sum is
727 : * surely less than val, so the answer is "!less".
728 : */
729 36 : PG_RETURN_BOOL(sub ? !less : less);
730 : }
731 :
732 0 : if (less)
733 0 : PG_RETURN_BOOL(val <= sum);
734 : else
735 0 : PG_RETURN_BOOL(val >= sum);
736 : }
737 :
738 : Datum
739 0 : in_range_int2_int2(PG_FUNCTION_ARGS)
740 : {
741 : /* Doesn't seem worth duplicating code for, so just invoke int2_int4 */
742 0 : return DirectFunctionCall5(in_range_int2_int4,
743 : PG_GETARG_DATUM(0),
744 : PG_GETARG_DATUM(1),
745 : Int32GetDatum((int32) PG_GETARG_INT16(2)),
746 : PG_GETARG_DATUM(3),
747 : PG_GETARG_DATUM(4));
748 : }
749 :
750 : Datum
751 0 : in_range_int2_int8(PG_FUNCTION_ARGS)
752 : {
753 : /* Doesn't seem worth duplicating code for, so just invoke int4_int8 */
754 0 : return DirectFunctionCall5(in_range_int4_int8,
755 : Int32GetDatum((int32) PG_GETARG_INT16(0)),
756 : Int32GetDatum((int32) PG_GETARG_INT16(1)),
757 : PG_GETARG_DATUM(2),
758 : PG_GETARG_DATUM(3),
759 : PG_GETARG_DATUM(4));
760 : }
761 :
762 :
763 : /*
764 : * int[24]pl - returns arg1 + arg2
765 : * int[24]mi - returns arg1 - arg2
766 : * int[24]mul - returns arg1 * arg2
767 : * int[24]div - returns arg1 / arg2
768 : */
769 :
770 : Datum
771 53204 : int4um(PG_FUNCTION_ARGS)
772 : {
773 53204 : int32 arg = PG_GETARG_INT32(0);
774 :
775 53204 : if (unlikely(arg == PG_INT32_MIN))
776 0 : ereport(ERROR,
777 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
778 : errmsg("integer out of range")));
779 53204 : PG_RETURN_INT32(-arg);
780 : }
781 :
782 : Datum
783 6 : int4up(PG_FUNCTION_ARGS)
784 : {
785 6 : int32 arg = PG_GETARG_INT32(0);
786 :
787 6 : PG_RETURN_INT32(arg);
788 : }
789 :
790 : Datum
791 3664680 : int4pl(PG_FUNCTION_ARGS)
792 : {
793 3664680 : int32 arg1 = PG_GETARG_INT32(0);
794 3664680 : int32 arg2 = PG_GETARG_INT32(1);
795 : int32 result;
796 :
797 3664680 : if (unlikely(pg_add_s32_overflow(arg1, arg2, &result)))
798 6 : ereport(ERROR,
799 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
800 : errmsg("integer out of range")));
801 3664674 : PG_RETURN_INT32(result);
802 : }
803 :
804 : Datum
805 1410636 : int4mi(PG_FUNCTION_ARGS)
806 : {
807 1410636 : int32 arg1 = PG_GETARG_INT32(0);
808 1410636 : int32 arg2 = PG_GETARG_INT32(1);
809 : int32 result;
810 :
811 1410636 : if (unlikely(pg_sub_s32_overflow(arg1, arg2, &result)))
812 6 : ereport(ERROR,
813 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
814 : errmsg("integer out of range")));
815 1410630 : PG_RETURN_INT32(result);
816 : }
817 :
818 : Datum
819 2848096 : int4mul(PG_FUNCTION_ARGS)
820 : {
821 2848096 : int32 arg1 = PG_GETARG_INT32(0);
822 2848096 : int32 arg2 = PG_GETARG_INT32(1);
823 : int32 result;
824 :
825 2848096 : if (unlikely(pg_mul_s32_overflow(arg1, arg2, &result)))
826 18 : ereport(ERROR,
827 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
828 : errmsg("integer out of range")));
829 2848078 : PG_RETURN_INT32(result);
830 : }
831 :
832 : Datum
833 1505234 : int4div(PG_FUNCTION_ARGS)
834 : {
835 1505234 : int32 arg1 = PG_GETARG_INT32(0);
836 1505234 : int32 arg2 = PG_GETARG_INT32(1);
837 : int32 result;
838 :
839 1505234 : if (arg2 == 0)
840 : {
841 284 : ereport(ERROR,
842 : (errcode(ERRCODE_DIVISION_BY_ZERO),
843 : errmsg("division by zero")));
844 : /* ensure compiler realizes we mustn't reach the division (gcc bug) */
845 : PG_RETURN_NULL();
846 : }
847 :
848 : /*
849 : * INT_MIN / -1 is problematic, since the result can't be represented on a
850 : * two's-complement machine. Some machines produce INT_MIN, some produce
851 : * zero, some throw an exception. We can dodge the problem by recognizing
852 : * that division by -1 is the same as negation.
853 : */
854 1504950 : if (arg2 == -1)
855 : {
856 16 : if (unlikely(arg1 == PG_INT32_MIN))
857 6 : ereport(ERROR,
858 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
859 : errmsg("integer out of range")));
860 10 : result = -arg1;
861 10 : PG_RETURN_INT32(result);
862 : }
863 :
864 : /* No overflow is possible */
865 :
866 1504934 : result = arg1 / arg2;
867 :
868 1504934 : PG_RETURN_INT32(result);
869 : }
870 :
871 : Datum
872 0 : int4inc(PG_FUNCTION_ARGS)
873 : {
874 0 : int32 arg = PG_GETARG_INT32(0);
875 : int32 result;
876 :
877 0 : if (unlikely(pg_add_s32_overflow(arg, 1, &result)))
878 0 : ereport(ERROR,
879 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
880 : errmsg("integer out of range")));
881 :
882 0 : PG_RETURN_INT32(result);
883 : }
884 :
885 : Datum
886 18 : int2um(PG_FUNCTION_ARGS)
887 : {
888 18 : int16 arg = PG_GETARG_INT16(0);
889 :
890 18 : if (unlikely(arg == PG_INT16_MIN))
891 0 : ereport(ERROR,
892 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
893 : errmsg("smallint out of range")));
894 18 : PG_RETURN_INT16(-arg);
895 : }
896 :
897 : Datum
898 0 : int2up(PG_FUNCTION_ARGS)
899 : {
900 0 : int16 arg = PG_GETARG_INT16(0);
901 :
902 0 : PG_RETURN_INT16(arg);
903 : }
904 :
905 : Datum
906 54 : int2pl(PG_FUNCTION_ARGS)
907 : {
908 54 : int16 arg1 = PG_GETARG_INT16(0);
909 54 : int16 arg2 = PG_GETARG_INT16(1);
910 : int16 result;
911 :
912 54 : if (unlikely(pg_add_s16_overflow(arg1, arg2, &result)))
913 6 : ereport(ERROR,
914 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
915 : errmsg("smallint out of range")));
916 48 : PG_RETURN_INT16(result);
917 : }
918 :
919 : Datum
920 120 : int2mi(PG_FUNCTION_ARGS)
921 : {
922 120 : int16 arg1 = PG_GETARG_INT16(0);
923 120 : int16 arg2 = PG_GETARG_INT16(1);
924 : int16 result;
925 :
926 120 : if (unlikely(pg_sub_s16_overflow(arg1, arg2, &result)))
927 6 : ereport(ERROR,
928 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
929 : errmsg("smallint out of range")));
930 114 : PG_RETURN_INT16(result);
931 : }
932 :
933 : Datum
934 54 : int2mul(PG_FUNCTION_ARGS)
935 : {
936 54 : int16 arg1 = PG_GETARG_INT16(0);
937 54 : int16 arg2 = PG_GETARG_INT16(1);
938 : int16 result;
939 :
940 54 : if (unlikely(pg_mul_s16_overflow(arg1, arg2, &result)))
941 12 : ereport(ERROR,
942 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
943 : errmsg("smallint out of range")));
944 :
945 42 : PG_RETURN_INT16(result);
946 : }
947 :
948 : Datum
949 42 : int2div(PG_FUNCTION_ARGS)
950 : {
951 42 : int16 arg1 = PG_GETARG_INT16(0);
952 42 : int16 arg2 = PG_GETARG_INT16(1);
953 : int16 result;
954 :
955 42 : if (arg2 == 0)
956 : {
957 0 : ereport(ERROR,
958 : (errcode(ERRCODE_DIVISION_BY_ZERO),
959 : errmsg("division by zero")));
960 : /* ensure compiler realizes we mustn't reach the division (gcc bug) */
961 : PG_RETURN_NULL();
962 : }
963 :
964 : /*
965 : * SHRT_MIN / -1 is problematic, since the result can't be represented on
966 : * a two's-complement machine. Some machines produce SHRT_MIN, some
967 : * produce zero, some throw an exception. We can dodge the problem by
968 : * recognizing that division by -1 is the same as negation.
969 : */
970 42 : if (arg2 == -1)
971 : {
972 6 : if (unlikely(arg1 == PG_INT16_MIN))
973 6 : ereport(ERROR,
974 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
975 : errmsg("smallint out of range")));
976 0 : result = -arg1;
977 0 : PG_RETURN_INT16(result);
978 : }
979 :
980 : /* No overflow is possible */
981 :
982 36 : result = arg1 / arg2;
983 :
984 36 : PG_RETURN_INT16(result);
985 : }
986 :
987 : Datum
988 2244 : int24pl(PG_FUNCTION_ARGS)
989 : {
990 2244 : int16 arg1 = PG_GETARG_INT16(0);
991 2244 : int32 arg2 = PG_GETARG_INT32(1);
992 : int32 result;
993 :
994 2244 : if (unlikely(pg_add_s32_overflow((int32) arg1, arg2, &result)))
995 0 : ereport(ERROR,
996 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
997 : errmsg("integer out of range")));
998 2244 : PG_RETURN_INT32(result);
999 : }
1000 :
1001 : Datum
1002 25508 : int24mi(PG_FUNCTION_ARGS)
1003 : {
1004 25508 : int16 arg1 = PG_GETARG_INT16(0);
1005 25508 : int32 arg2 = PG_GETARG_INT32(1);
1006 : int32 result;
1007 :
1008 25508 : if (unlikely(pg_sub_s32_overflow((int32) arg1, arg2, &result)))
1009 0 : ereport(ERROR,
1010 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1011 : errmsg("integer out of range")));
1012 25508 : PG_RETURN_INT32(result);
1013 : }
1014 :
1015 : Datum
1016 36 : int24mul(PG_FUNCTION_ARGS)
1017 : {
1018 36 : int16 arg1 = PG_GETARG_INT16(0);
1019 36 : int32 arg2 = PG_GETARG_INT32(1);
1020 : int32 result;
1021 :
1022 36 : if (unlikely(pg_mul_s32_overflow((int32) arg1, arg2, &result)))
1023 0 : ereport(ERROR,
1024 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1025 : errmsg("integer out of range")));
1026 36 : PG_RETURN_INT32(result);
1027 : }
1028 :
1029 : Datum
1030 42 : int24div(PG_FUNCTION_ARGS)
1031 : {
1032 42 : int16 arg1 = PG_GETARG_INT16(0);
1033 42 : int32 arg2 = PG_GETARG_INT32(1);
1034 :
1035 42 : if (unlikely(arg2 == 0))
1036 : {
1037 6 : ereport(ERROR,
1038 : (errcode(ERRCODE_DIVISION_BY_ZERO),
1039 : errmsg("division by zero")));
1040 : /* ensure compiler realizes we mustn't reach the division (gcc bug) */
1041 : PG_RETURN_NULL();
1042 : }
1043 :
1044 : /* No overflow is possible */
1045 36 : PG_RETURN_INT32((int32) arg1 / arg2);
1046 : }
1047 :
1048 : Datum
1049 48 : int42pl(PG_FUNCTION_ARGS)
1050 : {
1051 48 : int32 arg1 = PG_GETARG_INT32(0);
1052 48 : int16 arg2 = PG_GETARG_INT16(1);
1053 : int32 result;
1054 :
1055 48 : if (unlikely(pg_add_s32_overflow(arg1, (int32) arg2, &result)))
1056 6 : ereport(ERROR,
1057 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1058 : errmsg("integer out of range")));
1059 42 : PG_RETURN_INT32(result);
1060 : }
1061 :
1062 : Datum
1063 54 : int42mi(PG_FUNCTION_ARGS)
1064 : {
1065 54 : int32 arg1 = PG_GETARG_INT32(0);
1066 54 : int16 arg2 = PG_GETARG_INT16(1);
1067 : int32 result;
1068 :
1069 54 : if (unlikely(pg_sub_s32_overflow(arg1, (int32) arg2, &result)))
1070 6 : ereport(ERROR,
1071 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1072 : errmsg("integer out of range")));
1073 48 : PG_RETURN_INT32(result);
1074 : }
1075 :
1076 : Datum
1077 54 : int42mul(PG_FUNCTION_ARGS)
1078 : {
1079 54 : int32 arg1 = PG_GETARG_INT32(0);
1080 54 : int16 arg2 = PG_GETARG_INT16(1);
1081 : int32 result;
1082 :
1083 54 : if (unlikely(pg_mul_s32_overflow(arg1, (int32) arg2, &result)))
1084 12 : ereport(ERROR,
1085 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1086 : errmsg("integer out of range")));
1087 42 : PG_RETURN_INT32(result);
1088 : }
1089 :
1090 : Datum
1091 48 : int42div(PG_FUNCTION_ARGS)
1092 : {
1093 48 : int32 arg1 = PG_GETARG_INT32(0);
1094 48 : int16 arg2 = PG_GETARG_INT16(1);
1095 : int32 result;
1096 :
1097 48 : if (unlikely(arg2 == 0))
1098 : {
1099 6 : ereport(ERROR,
1100 : (errcode(ERRCODE_DIVISION_BY_ZERO),
1101 : errmsg("division by zero")));
1102 : /* ensure compiler realizes we mustn't reach the division (gcc bug) */
1103 : PG_RETURN_NULL();
1104 : }
1105 :
1106 : /*
1107 : * INT_MIN / -1 is problematic, since the result can't be represented on a
1108 : * two's-complement machine. Some machines produce INT_MIN, some produce
1109 : * zero, some throw an exception. We can dodge the problem by recognizing
1110 : * that division by -1 is the same as negation.
1111 : */
1112 42 : if (arg2 == -1)
1113 : {
1114 6 : if (unlikely(arg1 == PG_INT32_MIN))
1115 6 : ereport(ERROR,
1116 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1117 : errmsg("integer out of range")));
1118 0 : result = -arg1;
1119 0 : PG_RETURN_INT32(result);
1120 : }
1121 :
1122 : /* No overflow is possible */
1123 :
1124 36 : result = arg1 / arg2;
1125 :
1126 36 : PG_RETURN_INT32(result);
1127 : }
1128 :
1129 : Datum
1130 7210600 : int4mod(PG_FUNCTION_ARGS)
1131 : {
1132 7210600 : int32 arg1 = PG_GETARG_INT32(0);
1133 7210600 : int32 arg2 = PG_GETARG_INT32(1);
1134 :
1135 7210600 : if (unlikely(arg2 == 0))
1136 : {
1137 0 : ereport(ERROR,
1138 : (errcode(ERRCODE_DIVISION_BY_ZERO),
1139 : errmsg("division by zero")));
1140 : /* ensure compiler realizes we mustn't reach the division (gcc bug) */
1141 : PG_RETURN_NULL();
1142 : }
1143 :
1144 : /*
1145 : * Some machines throw a floating-point exception for INT_MIN % -1, which
1146 : * is a bit silly since the correct answer is perfectly well-defined,
1147 : * namely zero.
1148 : */
1149 7210600 : if (arg2 == -1)
1150 12 : PG_RETURN_INT32(0);
1151 :
1152 : /* No overflow is possible */
1153 :
1154 7210588 : PG_RETURN_INT32(arg1 % arg2);
1155 : }
1156 :
1157 : Datum
1158 36 : int2mod(PG_FUNCTION_ARGS)
1159 : {
1160 36 : int16 arg1 = PG_GETARG_INT16(0);
1161 36 : int16 arg2 = PG_GETARG_INT16(1);
1162 :
1163 36 : if (unlikely(arg2 == 0))
1164 : {
1165 0 : ereport(ERROR,
1166 : (errcode(ERRCODE_DIVISION_BY_ZERO),
1167 : errmsg("division by zero")));
1168 : /* ensure compiler realizes we mustn't reach the division (gcc bug) */
1169 : PG_RETURN_NULL();
1170 : }
1171 :
1172 : /*
1173 : * Some machines throw a floating-point exception for INT_MIN % -1, which
1174 : * is a bit silly since the correct answer is perfectly well-defined,
1175 : * namely zero. (It's not clear this ever happens when dealing with
1176 : * int16, but we might as well have the test for safety.)
1177 : */
1178 36 : if (arg2 == -1)
1179 6 : PG_RETURN_INT16(0);
1180 :
1181 : /* No overflow is possible */
1182 :
1183 30 : PG_RETURN_INT16(arg1 % arg2);
1184 : }
1185 :
1186 :
1187 : /* int[24]abs()
1188 : * Absolute value
1189 : */
1190 : Datum
1191 128810 : int4abs(PG_FUNCTION_ARGS)
1192 : {
1193 128810 : int32 arg1 = PG_GETARG_INT32(0);
1194 : int32 result;
1195 :
1196 128810 : if (unlikely(arg1 == PG_INT32_MIN))
1197 0 : ereport(ERROR,
1198 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1199 : errmsg("integer out of range")));
1200 128810 : result = (arg1 < 0) ? -arg1 : arg1;
1201 128810 : PG_RETURN_INT32(result);
1202 : }
1203 :
1204 : Datum
1205 30 : int2abs(PG_FUNCTION_ARGS)
1206 : {
1207 30 : int16 arg1 = PG_GETARG_INT16(0);
1208 : int16 result;
1209 :
1210 30 : if (unlikely(arg1 == PG_INT16_MIN))
1211 0 : ereport(ERROR,
1212 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1213 : errmsg("smallint out of range")));
1214 30 : result = (arg1 < 0) ? -arg1 : arg1;
1215 30 : PG_RETURN_INT16(result);
1216 : }
1217 :
1218 : /*
1219 : * Greatest Common Divisor
1220 : *
1221 : * Returns the largest positive integer that exactly divides both inputs.
1222 : * Special cases:
1223 : * - gcd(x, 0) = gcd(0, x) = abs(x)
1224 : * because 0 is divisible by anything
1225 : * - gcd(0, 0) = 0
1226 : * complies with the previous definition and is a common convention
1227 : *
1228 : * Special care must be taken if either input is INT_MIN --- gcd(0, INT_MIN),
1229 : * gcd(INT_MIN, 0) and gcd(INT_MIN, INT_MIN) are all equal to abs(INT_MIN),
1230 : * which cannot be represented as a 32-bit signed integer.
1231 : */
1232 : static int32
1233 264 : int4gcd_internal(int32 arg1, int32 arg2)
1234 : {
1235 : int32 swap;
1236 : int32 a1,
1237 : a2;
1238 :
1239 : /*
1240 : * Put the greater absolute value in arg1.
1241 : *
1242 : * This would happen automatically in the loop below, but avoids an
1243 : * expensive modulo operation, and simplifies the special-case handling
1244 : * for INT_MIN below.
1245 : *
1246 : * We do this in negative space in order to handle INT_MIN.
1247 : */
1248 264 : a1 = (arg1 < 0) ? arg1 : -arg1;
1249 264 : a2 = (arg2 < 0) ? arg2 : -arg2;
1250 264 : if (a1 > a2)
1251 : {
1252 96 : swap = arg1;
1253 96 : arg1 = arg2;
1254 96 : arg2 = swap;
1255 : }
1256 :
1257 : /* Special care needs to be taken with INT_MIN. See comments above. */
1258 264 : if (arg1 == PG_INT32_MIN)
1259 : {
1260 90 : if (arg2 == 0 || arg2 == PG_INT32_MIN)
1261 12 : ereport(ERROR,
1262 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1263 : errmsg("integer out of range")));
1264 :
1265 : /*
1266 : * Some machines throw a floating-point exception for INT_MIN % -1,
1267 : * which is a bit silly since the correct answer is perfectly
1268 : * well-defined, namely zero. Guard against this and just return the
1269 : * result, gcd(INT_MIN, -1) = 1.
1270 : */
1271 78 : if (arg2 == -1)
1272 12 : return 1;
1273 : }
1274 :
1275 : /* Use the Euclidean algorithm to find the GCD */
1276 942 : while (arg2 != 0)
1277 : {
1278 702 : swap = arg2;
1279 702 : arg2 = arg1 % arg2;
1280 702 : arg1 = swap;
1281 : }
1282 :
1283 : /*
1284 : * Make sure the result is positive. (We know we don't have INT_MIN
1285 : * anymore).
1286 : */
1287 240 : if (arg1 < 0)
1288 102 : arg1 = -arg1;
1289 :
1290 240 : return arg1;
1291 : }
1292 :
1293 : Datum
1294 180 : int4gcd(PG_FUNCTION_ARGS)
1295 : {
1296 180 : int32 arg1 = PG_GETARG_INT32(0);
1297 180 : int32 arg2 = PG_GETARG_INT32(1);
1298 : int32 result;
1299 :
1300 180 : result = int4gcd_internal(arg1, arg2);
1301 :
1302 168 : PG_RETURN_INT32(result);
1303 : }
1304 :
1305 : /*
1306 : * Least Common Multiple
1307 : */
1308 : Datum
1309 156 : int4lcm(PG_FUNCTION_ARGS)
1310 : {
1311 156 : int32 arg1 = PG_GETARG_INT32(0);
1312 156 : int32 arg2 = PG_GETARG_INT32(1);
1313 : int32 gcd;
1314 : int32 result;
1315 :
1316 : /*
1317 : * Handle lcm(x, 0) = lcm(0, x) = 0 as a special case. This prevents a
1318 : * division-by-zero error below when x is zero, and an overflow error from
1319 : * the GCD computation when x = INT_MIN.
1320 : */
1321 156 : if (arg1 == 0 || arg2 == 0)
1322 72 : PG_RETURN_INT32(0);
1323 :
1324 : /* lcm(x, y) = abs(x / gcd(x, y) * y) */
1325 84 : gcd = int4gcd_internal(arg1, arg2);
1326 84 : arg1 = arg1 / gcd;
1327 :
1328 84 : if (unlikely(pg_mul_s32_overflow(arg1, arg2, &result)))
1329 6 : ereport(ERROR,
1330 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1331 : errmsg("integer out of range")));
1332 :
1333 : /* If the result is INT_MIN, it cannot be represented. */
1334 78 : if (unlikely(result == PG_INT32_MIN))
1335 6 : ereport(ERROR,
1336 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1337 : errmsg("integer out of range")));
1338 :
1339 72 : if (result < 0)
1340 36 : result = -result;
1341 :
1342 72 : PG_RETURN_INT32(result);
1343 : }
1344 :
1345 : Datum
1346 402 : int2larger(PG_FUNCTION_ARGS)
1347 : {
1348 402 : int16 arg1 = PG_GETARG_INT16(0);
1349 402 : int16 arg2 = PG_GETARG_INT16(1);
1350 :
1351 402 : PG_RETURN_INT16((arg1 > arg2) ? arg1 : arg2);
1352 : }
1353 :
1354 : Datum
1355 0 : int2smaller(PG_FUNCTION_ARGS)
1356 : {
1357 0 : int16 arg1 = PG_GETARG_INT16(0);
1358 0 : int16 arg2 = PG_GETARG_INT16(1);
1359 :
1360 0 : PG_RETURN_INT16((arg1 < arg2) ? arg1 : arg2);
1361 : }
1362 :
1363 : Datum
1364 322016 : int4larger(PG_FUNCTION_ARGS)
1365 : {
1366 322016 : int32 arg1 = PG_GETARG_INT32(0);
1367 322016 : int32 arg2 = PG_GETARG_INT32(1);
1368 :
1369 322016 : PG_RETURN_INT32((arg1 > arg2) ? arg1 : arg2);
1370 : }
1371 :
1372 : Datum
1373 251958 : int4smaller(PG_FUNCTION_ARGS)
1374 : {
1375 251958 : int32 arg1 = PG_GETARG_INT32(0);
1376 251958 : int32 arg2 = PG_GETARG_INT32(1);
1377 :
1378 251958 : PG_RETURN_INT32((arg1 < arg2) ? arg1 : arg2);
1379 : }
1380 :
1381 : /*
1382 : * Bit-pushing operators
1383 : *
1384 : * int[24]and - returns arg1 & arg2
1385 : * int[24]or - returns arg1 | arg2
1386 : * int[24]xor - returns arg1 # arg2
1387 : * int[24]not - returns ~arg1
1388 : * int[24]shl - returns arg1 << arg2
1389 : * int[24]shr - returns arg1 >> arg2
1390 : */
1391 :
1392 : Datum
1393 5550 : int4and(PG_FUNCTION_ARGS)
1394 : {
1395 5550 : int32 arg1 = PG_GETARG_INT32(0);
1396 5550 : int32 arg2 = PG_GETARG_INT32(1);
1397 :
1398 5550 : PG_RETURN_INT32(arg1 & arg2);
1399 : }
1400 :
1401 : Datum
1402 18 : int4or(PG_FUNCTION_ARGS)
1403 : {
1404 18 : int32 arg1 = PG_GETARG_INT32(0);
1405 18 : int32 arg2 = PG_GETARG_INT32(1);
1406 :
1407 18 : PG_RETURN_INT32(arg1 | arg2);
1408 : }
1409 :
1410 : Datum
1411 18 : int4xor(PG_FUNCTION_ARGS)
1412 : {
1413 18 : int32 arg1 = PG_GETARG_INT32(0);
1414 18 : int32 arg2 = PG_GETARG_INT32(1);
1415 :
1416 18 : PG_RETURN_INT32(arg1 ^ arg2);
1417 : }
1418 :
1419 : Datum
1420 1548 : int4shl(PG_FUNCTION_ARGS)
1421 : {
1422 1548 : int32 arg1 = PG_GETARG_INT32(0);
1423 1548 : int32 arg2 = PG_GETARG_INT32(1);
1424 :
1425 1548 : PG_RETURN_INT32(arg1 << arg2);
1426 : }
1427 :
1428 : Datum
1429 0 : int4shr(PG_FUNCTION_ARGS)
1430 : {
1431 0 : int32 arg1 = PG_GETARG_INT32(0);
1432 0 : int32 arg2 = PG_GETARG_INT32(1);
1433 :
1434 0 : PG_RETURN_INT32(arg1 >> arg2);
1435 : }
1436 :
1437 : Datum
1438 0 : int4not(PG_FUNCTION_ARGS)
1439 : {
1440 0 : int32 arg1 = PG_GETARG_INT32(0);
1441 :
1442 0 : PG_RETURN_INT32(~arg1);
1443 : }
1444 :
1445 : Datum
1446 24 : int2and(PG_FUNCTION_ARGS)
1447 : {
1448 24 : int16 arg1 = PG_GETARG_INT16(0);
1449 24 : int16 arg2 = PG_GETARG_INT16(1);
1450 :
1451 24 : PG_RETURN_INT16(arg1 & arg2);
1452 : }
1453 :
1454 : Datum
1455 24 : int2or(PG_FUNCTION_ARGS)
1456 : {
1457 24 : int16 arg1 = PG_GETARG_INT16(0);
1458 24 : int16 arg2 = PG_GETARG_INT16(1);
1459 :
1460 24 : PG_RETURN_INT16(arg1 | arg2);
1461 : }
1462 :
1463 : Datum
1464 24 : int2xor(PG_FUNCTION_ARGS)
1465 : {
1466 24 : int16 arg1 = PG_GETARG_INT16(0);
1467 24 : int16 arg2 = PG_GETARG_INT16(1);
1468 :
1469 24 : PG_RETURN_INT16(arg1 ^ arg2);
1470 : }
1471 :
1472 : Datum
1473 0 : int2not(PG_FUNCTION_ARGS)
1474 : {
1475 0 : int16 arg1 = PG_GETARG_INT16(0);
1476 :
1477 0 : PG_RETURN_INT16(~arg1);
1478 : }
1479 :
1480 :
1481 : Datum
1482 12 : int2shl(PG_FUNCTION_ARGS)
1483 : {
1484 12 : int16 arg1 = PG_GETARG_INT16(0);
1485 12 : int32 arg2 = PG_GETARG_INT32(1);
1486 :
1487 12 : PG_RETURN_INT16(arg1 << arg2);
1488 : }
1489 :
1490 : Datum
1491 0 : int2shr(PG_FUNCTION_ARGS)
1492 : {
1493 0 : int16 arg1 = PG_GETARG_INT16(0);
1494 0 : int32 arg2 = PG_GETARG_INT32(1);
1495 :
1496 0 : PG_RETURN_INT16(arg1 >> arg2);
1497 : }
1498 :
1499 : /*
1500 : * non-persistent numeric series generator
1501 : */
1502 : Datum
1503 14609218 : generate_series_int4(PG_FUNCTION_ARGS)
1504 : {
1505 14609218 : return generate_series_step_int4(fcinfo);
1506 : }
1507 :
1508 : Datum
1509 14974476 : generate_series_step_int4(PG_FUNCTION_ARGS)
1510 : {
1511 : FuncCallContext *funcctx;
1512 : generate_series_fctx *fctx;
1513 : int32 result;
1514 : MemoryContext oldcontext;
1515 :
1516 : /* stuff done only on the first call of the function */
1517 14974476 : if (SRF_IS_FIRSTCALL())
1518 : {
1519 15602 : int32 start = PG_GETARG_INT32(0);
1520 15602 : int32 finish = PG_GETARG_INT32(1);
1521 15602 : int32 step = 1;
1522 :
1523 : /* see if we were given an explicit step size */
1524 15602 : if (PG_NARGS() == 3)
1525 392 : step = PG_GETARG_INT32(2);
1526 15602 : if (step == 0)
1527 0 : ereport(ERROR,
1528 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1529 : errmsg("step size cannot equal zero")));
1530 :
1531 : /* create a function context for cross-call persistence */
1532 15602 : funcctx = SRF_FIRSTCALL_INIT();
1533 :
1534 : /*
1535 : * switch to memory context appropriate for multiple function calls
1536 : */
1537 15602 : oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1538 :
1539 : /* allocate memory for user context */
1540 15602 : fctx = (generate_series_fctx *) palloc(sizeof(generate_series_fctx));
1541 :
1542 : /*
1543 : * Use fctx to keep state from call to call. Seed current with the
1544 : * original start value
1545 : */
1546 15602 : fctx->current = start;
1547 15602 : fctx->finish = finish;
1548 15602 : fctx->step = step;
1549 :
1550 15602 : funcctx->user_fctx = fctx;
1551 15602 : MemoryContextSwitchTo(oldcontext);
1552 : }
1553 :
1554 : /* stuff done on every call of the function */
1555 14974476 : funcctx = SRF_PERCALL_SETUP();
1556 :
1557 : /*
1558 : * get the saved state and use current as the result for this iteration
1559 : */
1560 14974476 : fctx = funcctx->user_fctx;
1561 14974476 : result = fctx->current;
1562 :
1563 14974476 : if ((fctx->step > 0 && fctx->current <= fctx->finish) ||
1564 215564 : (fctx->step < 0 && fctx->current >= fctx->finish))
1565 : {
1566 : /*
1567 : * Increment current in preparation for next iteration. If next-value
1568 : * computation overflows, this is the final result.
1569 : */
1570 14958922 : if (pg_add_s32_overflow(fctx->current, fctx->step, &fctx->current))
1571 0 : fctx->step = 0;
1572 :
1573 : /* do when there is more left to send */
1574 14958922 : SRF_RETURN_NEXT(funcctx, Int32GetDatum(result));
1575 : }
1576 : else
1577 : /* do when there is no more left */
1578 15554 : SRF_RETURN_DONE(funcctx);
1579 : }
1580 :
1581 : /*
1582 : * Planner support function for generate_series(int4, int4 [, int4])
1583 : */
1584 : Datum
1585 40296 : generate_series_int4_support(PG_FUNCTION_ARGS)
1586 : {
1587 40296 : Node *rawreq = (Node *) PG_GETARG_POINTER(0);
1588 40296 : Node *ret = NULL;
1589 :
1590 40296 : if (IsA(rawreq, SupportRequestRows))
1591 : {
1592 : /* Try to estimate the number of rows returned */
1593 13286 : SupportRequestRows *req = (SupportRequestRows *) rawreq;
1594 :
1595 13286 : if (is_funcclause(req->node)) /* be paranoid */
1596 : {
1597 13286 : List *args = ((FuncExpr *) req->node)->args;
1598 : Node *arg1,
1599 : *arg2,
1600 : *arg3;
1601 :
1602 : /* We can use estimated argument values here */
1603 13286 : arg1 = estimate_expression_value(req->root, linitial(args));
1604 13286 : arg2 = estimate_expression_value(req->root, lsecond(args));
1605 13286 : if (list_length(args) >= 3)
1606 416 : arg3 = estimate_expression_value(req->root, lthird(args));
1607 : else
1608 12870 : arg3 = NULL;
1609 :
1610 : /*
1611 : * If any argument is constant NULL, we can safely assume that
1612 : * zero rows are returned. Otherwise, if they're all non-NULL
1613 : * constants, we can calculate the number of rows that will be
1614 : * returned. Use double arithmetic to avoid overflow hazards.
1615 : */
1616 13286 : if ((IsA(arg1, Const) &&
1617 11284 : ((Const *) arg1)->constisnull) ||
1618 13286 : (IsA(arg2, Const) &&
1619 13286 : ((Const *) arg2)->constisnull) ||
1620 416 : (arg3 != NULL && IsA(arg3, Const) &&
1621 416 : ((Const *) arg3)->constisnull))
1622 : {
1623 0 : req->rows = 0;
1624 0 : ret = (Node *) req;
1625 : }
1626 13286 : else if (IsA(arg1, Const) &&
1627 11284 : IsA(arg2, Const) &&
1628 416 : (arg3 == NULL || IsA(arg3, Const)))
1629 : {
1630 : double start,
1631 : finish,
1632 : step;
1633 :
1634 7770 : start = DatumGetInt32(((Const *) arg1)->constvalue);
1635 7770 : finish = DatumGetInt32(((Const *) arg2)->constvalue);
1636 7770 : step = arg3 ? DatumGetInt32(((Const *) arg3)->constvalue) : 1;
1637 :
1638 : /* This equation works for either sign of step */
1639 7770 : if (step != 0)
1640 : {
1641 7770 : req->rows = floor((finish - start + step) / step);
1642 7770 : ret = (Node *) req;
1643 : }
1644 : }
1645 : }
1646 : }
1647 :
1648 40296 : PG_RETURN_POINTER(ret);
1649 : }
|