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