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