Branch data 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-2026, 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 : 9799 : int2in(PG_FUNCTION_ARGS)
64 : : {
65 : 9799 : char *num = PG_GETARG_CSTRING(0);
66 : :
67 : 19598 : PG_RETURN_INT16(pg_strtoint16_safe(num, fcinfo->context));
68 : 9799 : }
69 : :
70 : : /*
71 : : * int2out - converts short to "num"
72 : : */
73 : : Datum
74 : 5691 : int2out(PG_FUNCTION_ARGS)
75 : : {
76 : 5691 : int16 arg1 = PG_GETARG_INT16(0);
77 : 5691 : char *result = (char *) palloc(7); /* sign, 5 digits, '\0' */
78 : :
79 : 5691 : pg_itoa(arg1, result);
80 : 11382 : PG_RETURN_CSTRING(result);
81 : 5691 : }
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 : 0 : }
93 : :
94 : : /*
95 : : * int2send - converts int2 to binary format
96 : : */
97 : : Datum
98 : 2 : int2send(PG_FUNCTION_ARGS)
99 : : {
100 : 2 : int16 arg1 = PG_GETARG_INT16(0);
101 : 2 : StringInfoData buf;
102 : :
103 : 2 : pq_begintypsend(&buf);
104 : 2 : pq_sendint16(&buf, arg1);
105 : 4 : PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
106 : 2 : }
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 : 10300 : buildint2vector(const int16 *int2s, int n)
115 : : {
116 : 10300 : int2vector *result;
117 : :
118 : 10300 : result = (int2vector *) palloc0(Int2VectorSize(n));
119 : :
120 [ + + + + ]: 10300 : if (n > 0 && int2s)
121 : 4487 : 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 : 10300 : SET_VARSIZE(result, Int2VectorSize(n));
128 : 10300 : result->ndim = 1;
129 : 10300 : result->dataoffset = 0; /* never any nulls */
130 : 10300 : result->elemtype = INT2OID;
131 : 10300 : result->dim1 = n;
132 : 10300 : result->lbound1 = 0;
133 : :
134 : 20600 : return result;
135 : 10300 : }
136 : :
137 : : /*
138 : : * int2vectorin - converts "num num ..." to internal form
139 : : */
140 : : Datum
141 : 19 : int2vectorin(PG_FUNCTION_ARGS)
142 : : {
143 : 19 : char *intString = PG_GETARG_CSTRING(0);
144 : 19 : Node *escontext = fcinfo->context;
145 : 19 : int2vector *result;
146 : 19 : int nalloc;
147 : 19 : int n;
148 : :
149 : 19 : nalloc = 32; /* arbitrary initial size guess */
150 : 19 : result = (int2vector *) palloc0(Int2VectorSize(nalloc));
151 : :
152 : 64 : for (n = 0;; n++)
153 : : {
154 : 64 : long l;
155 : 64 : char *endp;
156 : :
157 [ + + + + ]: 95 : while (*intString && isspace((unsigned char) *intString))
158 : 31 : intString++;
159 [ + + ]: 64 : if (*intString == '\0')
160 : 17 : break;
161 : :
162 [ + - ]: 47 : if (n >= nalloc)
163 : : {
164 : 0 : nalloc *= 2;
165 : 0 : result = (int2vector *) repalloc(result, Int2VectorSize(nalloc));
166 : 0 : }
167 : :
168 : 47 : errno = 0;
169 : 47 : l = strtol(intString, &endp, 10);
170 : :
171 [ + + ]: 47 : if (intString == endp)
172 [ - + ]: 1 : ereturn(escontext, (Datum) 0,
173 : : (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
174 : : errmsg("invalid input syntax for type %s: \"%s\"",
175 : : "smallint", intString)));
176 : :
177 [ + - + - : 46 : if (errno == ERANGE || l < SHRT_MIN || l > SHRT_MAX)
+ + ]
178 [ - + ]: 1 : 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 [ + + + - ]: 45 : 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 : 45 : result->values[n] = l;
190 : 45 : intString = endp;
191 [ + + + ]: 64 : }
192 : :
193 : 17 : SET_VARSIZE(result, Int2VectorSize(n));
194 : 17 : result->ndim = 1;
195 : 17 : result->dataoffset = 0; /* never any nulls */
196 : 17 : result->elemtype = INT2OID;
197 : 17 : result->dim1 = n;
198 : 17 : result->lbound1 = 0;
199 : :
200 : 17 : PG_RETURN_POINTER(result);
201 : 19 : }
202 : :
203 : : /*
204 : : * int2vectorout - converts internal form to "num num ..."
205 : : */
206 : : Datum
207 : 23 : int2vectorout(PG_FUNCTION_ARGS)
208 : : {
209 : 23 : int2vector *int2Array = (int2vector *) PG_GETARG_POINTER(0);
210 : 23 : int num,
211 : 23 : nnums = int2Array->dim1;
212 : 23 : char *rp;
213 : 23 : char *result;
214 : :
215 : : /* assumes sign, 5 digits, ' ' */
216 : 23 : rp = result = (char *) palloc(nnums * 7 + 1);
217 [ + + ]: 90 : for (num = 0; num < nnums; num++)
218 : : {
219 [ + + ]: 67 : if (num != 0)
220 : 44 : *rp++ = ' ';
221 : 67 : rp += pg_itoa(int2Array->values[num], rp);
222 : 67 : }
223 : 23 : *rp = '\0';
224 : 46 : PG_RETURN_CSTRING(result);
225 : 23 : }
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 : 0 : 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 [ # # ]: 0 : 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 : 0 : }
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 : 339308 : int4in(PG_FUNCTION_ARGS)
288 : : {
289 : 339308 : char *num = PG_GETARG_CSTRING(0);
290 : :
291 : 678616 : PG_RETURN_INT32(pg_strtoint32_safe(num, fcinfo->context));
292 : 339308 : }
293 : :
294 : : /*
295 : : * int4out - converts int4 to "num"
296 : : */
297 : : Datum
298 : 710208 : int4out(PG_FUNCTION_ARGS)
299 : : {
300 : 710208 : int32 arg1 = PG_GETARG_INT32(0);
301 : 710208 : char *result = (char *) palloc(12); /* sign, 10 digits, '\0' */
302 : :
303 : 710208 : pg_ltoa(arg1, result);
304 : 1420416 : PG_RETURN_CSTRING(result);
305 : 710208 : }
306 : :
307 : : /*
308 : : * int4recv - converts external binary format to int4
309 : : */
310 : : Datum
311 : 344 : int4recv(PG_FUNCTION_ARGS)
312 : : {
313 : 344 : StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
314 : :
315 : 688 : PG_RETURN_INT32((int32) pq_getmsgint(buf, sizeof(int32)));
316 : 344 : }
317 : :
318 : : /*
319 : : * int4send - converts int4 to binary format
320 : : */
321 : : Datum
322 : 182 : int4send(PG_FUNCTION_ARGS)
323 : : {
324 : 182 : int32 arg1 = PG_GETARG_INT32(0);
325 : 182 : StringInfoData buf;
326 : :
327 : 182 : pq_begintypsend(&buf);
328 : 182 : pq_sendint32(&buf, arg1);
329 : 364 : PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
330 : 182 : }
331 : :
332 : :
333 : : /*
334 : : * ===================
335 : : * CONVERSION ROUTINES
336 : : * ===================
337 : : */
338 : :
339 : : Datum
340 : 5112 : i2toi4(PG_FUNCTION_ARGS)
341 : : {
342 : 5112 : int16 arg1 = PG_GETARG_INT16(0);
343 : :
344 : 10224 : PG_RETURN_INT32((int32) arg1);
345 : 5112 : }
346 : :
347 : : Datum
348 : 517 : i4toi2(PG_FUNCTION_ARGS)
349 : : {
350 : 517 : int32 arg1 = PG_GETARG_INT32(0);
351 : :
352 [ + + ]: 517 : if (unlikely(arg1 < SHRT_MIN) || unlikely(arg1 > SHRT_MAX))
353 [ + - + - ]: 4 : ereport(ERROR,
354 : : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
355 : : errmsg("smallint out of range")));
356 : :
357 : 1026 : PG_RETURN_INT16((int16) arg1);
358 : 513 : }
359 : :
360 : : /* Cast int4 -> bool */
361 : : Datum
362 : 5 : int4_bool(PG_FUNCTION_ARGS)
363 : : {
364 [ + + ]: 5 : if (PG_GETARG_INT32(0) == 0)
365 : 2 : PG_RETURN_BOOL(false);
366 : : else
367 : 3 : PG_RETURN_BOOL(true);
368 : 5 : }
369 : :
370 : : /* Cast bool -> int4 */
371 : : Datum
372 : 127 : bool_int4(PG_FUNCTION_ARGS)
373 : : {
374 [ + + ]: 127 : if (PG_GETARG_BOOL(0) == false)
375 : 19 : PG_RETURN_INT32(0);
376 : : else
377 : 108 : PG_RETURN_INT32(1);
378 : 127 : }
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 : 12397076 : int4eq(PG_FUNCTION_ARGS)
397 : : {
398 : 12397076 : int32 arg1 = PG_GETARG_INT32(0);
399 : 12397076 : int32 arg2 = PG_GETARG_INT32(1);
400 : :
401 : 24794152 : PG_RETURN_BOOL(arg1 == arg2);
402 : 12397076 : }
403 : :
404 : : Datum
405 : 66781 : int4ne(PG_FUNCTION_ARGS)
406 : : {
407 : 66781 : int32 arg1 = PG_GETARG_INT32(0);
408 : 66781 : int32 arg2 = PG_GETARG_INT32(1);
409 : :
410 : 133562 : PG_RETURN_BOOL(arg1 != arg2);
411 : 66781 : }
412 : :
413 : : Datum
414 : 37331683 : int4lt(PG_FUNCTION_ARGS)
415 : : {
416 : 37331683 : int32 arg1 = PG_GETARG_INT32(0);
417 : 37331683 : int32 arg2 = PG_GETARG_INT32(1);
418 : :
419 : 74663366 : PG_RETURN_BOOL(arg1 < arg2);
420 : 37331683 : }
421 : :
422 : : Datum
423 : 224286 : int4le(PG_FUNCTION_ARGS)
424 : : {
425 : 224286 : int32 arg1 = PG_GETARG_INT32(0);
426 : 224286 : int32 arg2 = PG_GETARG_INT32(1);
427 : :
428 : 448572 : PG_RETURN_BOOL(arg1 <= arg2);
429 : 224286 : }
430 : :
431 : : Datum
432 : 767374 : int4gt(PG_FUNCTION_ARGS)
433 : : {
434 : 767374 : int32 arg1 = PG_GETARG_INT32(0);
435 : 767374 : int32 arg2 = PG_GETARG_INT32(1);
436 : :
437 : 1534748 : PG_RETURN_BOOL(arg1 > arg2);
438 : 767374 : }
439 : :
440 : : Datum
441 : 83320 : int4ge(PG_FUNCTION_ARGS)
442 : : {
443 : 83320 : int32 arg1 = PG_GETARG_INT32(0);
444 : 83320 : int32 arg2 = PG_GETARG_INT32(1);
445 : :
446 : 166640 : PG_RETURN_BOOL(arg1 >= arg2);
447 : 83320 : }
448 : :
449 : : Datum
450 : 107815 : int2eq(PG_FUNCTION_ARGS)
451 : : {
452 : 107815 : int16 arg1 = PG_GETARG_INT16(0);
453 : 107815 : int16 arg2 = PG_GETARG_INT16(1);
454 : :
455 : 215630 : PG_RETURN_BOOL(arg1 == arg2);
456 : 107815 : }
457 : :
458 : : Datum
459 : 5289 : int2ne(PG_FUNCTION_ARGS)
460 : : {
461 : 5289 : int16 arg1 = PG_GETARG_INT16(0);
462 : 5289 : int16 arg2 = PG_GETARG_INT16(1);
463 : :
464 : 10578 : PG_RETURN_BOOL(arg1 != arg2);
465 : 5289 : }
466 : :
467 : : Datum
468 : 100894 : int2lt(PG_FUNCTION_ARGS)
469 : : {
470 : 100894 : int16 arg1 = PG_GETARG_INT16(0);
471 : 100894 : int16 arg2 = PG_GETARG_INT16(1);
472 : :
473 : 201788 : PG_RETURN_BOOL(arg1 < arg2);
474 : 100894 : }
475 : :
476 : : Datum
477 : 731 : int2le(PG_FUNCTION_ARGS)
478 : : {
479 : 731 : int16 arg1 = PG_GETARG_INT16(0);
480 : 731 : int16 arg2 = PG_GETARG_INT16(1);
481 : :
482 : 1462 : PG_RETURN_BOOL(arg1 <= arg2);
483 : 731 : }
484 : :
485 : : Datum
486 : 282448 : int2gt(PG_FUNCTION_ARGS)
487 : : {
488 : 282448 : int16 arg1 = PG_GETARG_INT16(0);
489 : 282448 : int16 arg2 = PG_GETARG_INT16(1);
490 : :
491 : 564896 : PG_RETURN_BOOL(arg1 > arg2);
492 : 282448 : }
493 : :
494 : : Datum
495 : 619 : int2ge(PG_FUNCTION_ARGS)
496 : : {
497 : 619 : int16 arg1 = PG_GETARG_INT16(0);
498 : 619 : int16 arg2 = PG_GETARG_INT16(1);
499 : :
500 : 1238 : PG_RETURN_BOOL(arg1 >= arg2);
501 : 619 : }
502 : :
503 : : Datum
504 : 14914 : int24eq(PG_FUNCTION_ARGS)
505 : : {
506 : 14914 : int16 arg1 = PG_GETARG_INT16(0);
507 : 14914 : int32 arg2 = PG_GETARG_INT32(1);
508 : :
509 : 29828 : PG_RETURN_BOOL(arg1 == arg2);
510 : 14914 : }
511 : :
512 : : Datum
513 : 12521 : int24ne(PG_FUNCTION_ARGS)
514 : : {
515 : 12521 : int16 arg1 = PG_GETARG_INT16(0);
516 : 12521 : int32 arg2 = PG_GETARG_INT32(1);
517 : :
518 : 25042 : PG_RETURN_BOOL(arg1 != arg2);
519 : 12521 : }
520 : :
521 : : Datum
522 : 17708 : int24lt(PG_FUNCTION_ARGS)
523 : : {
524 : 17708 : int16 arg1 = PG_GETARG_INT16(0);
525 : 17708 : int32 arg2 = PG_GETARG_INT32(1);
526 : :
527 : 35416 : PG_RETURN_BOOL(arg1 < arg2);
528 : 17708 : }
529 : :
530 : : Datum
531 : 4835 : int24le(PG_FUNCTION_ARGS)
532 : : {
533 : 4835 : int16 arg1 = PG_GETARG_INT16(0);
534 : 4835 : int32 arg2 = PG_GETARG_INT32(1);
535 : :
536 : 9670 : PG_RETURN_BOOL(arg1 <= arg2);
537 : 4835 : }
538 : :
539 : : Datum
540 : 91987 : int24gt(PG_FUNCTION_ARGS)
541 : : {
542 : 91987 : int16 arg1 = PG_GETARG_INT16(0);
543 : 91987 : int32 arg2 = PG_GETARG_INT32(1);
544 : :
545 : 183974 : PG_RETURN_BOOL(arg1 > arg2);
546 : 91987 : }
547 : :
548 : : Datum
549 : 1406 : int24ge(PG_FUNCTION_ARGS)
550 : : {
551 : 1406 : int16 arg1 = PG_GETARG_INT16(0);
552 : 1406 : int32 arg2 = PG_GETARG_INT32(1);
553 : :
554 : 2812 : PG_RETURN_BOOL(arg1 >= arg2);
555 : 1406 : }
556 : :
557 : : Datum
558 : 3956 : int42eq(PG_FUNCTION_ARGS)
559 : : {
560 : 3956 : int32 arg1 = PG_GETARG_INT32(0);
561 : 3956 : int16 arg2 = PG_GETARG_INT16(1);
562 : :
563 : 7912 : PG_RETURN_BOOL(arg1 == arg2);
564 : 3956 : }
565 : :
566 : : Datum
567 : 5 : int42ne(PG_FUNCTION_ARGS)
568 : : {
569 : 5 : int32 arg1 = PG_GETARG_INT32(0);
570 : 5 : int16 arg2 = PG_GETARG_INT16(1);
571 : :
572 : 10 : PG_RETURN_BOOL(arg1 != arg2);
573 : 5 : }
574 : :
575 : : Datum
576 : 2476 : int42lt(PG_FUNCTION_ARGS)
577 : : {
578 : 2476 : int32 arg1 = PG_GETARG_INT32(0);
579 : 2476 : int16 arg2 = PG_GETARG_INT16(1);
580 : :
581 : 4952 : PG_RETURN_BOOL(arg1 < arg2);
582 : 2476 : }
583 : :
584 : : Datum
585 : 2519 : int42le(PG_FUNCTION_ARGS)
586 : : {
587 : 2519 : int32 arg1 = PG_GETARG_INT32(0);
588 : 2519 : int16 arg2 = PG_GETARG_INT16(1);
589 : :
590 : 5038 : PG_RETURN_BOOL(arg1 <= arg2);
591 : 2519 : }
592 : :
593 : : Datum
594 : 538 : int42gt(PG_FUNCTION_ARGS)
595 : : {
596 : 538 : int32 arg1 = PG_GETARG_INT32(0);
597 : 538 : int16 arg2 = PG_GETARG_INT16(1);
598 : :
599 : 1076 : PG_RETURN_BOOL(arg1 > arg2);
600 : 538 : }
601 : :
602 : : Datum
603 : 576 : int42ge(PG_FUNCTION_ARGS)
604 : : {
605 : 576 : int32 arg1 = PG_GETARG_INT32(0);
606 : 576 : int16 arg2 = PG_GETARG_INT16(1);
607 : :
608 : 1152 : PG_RETURN_BOOL(arg1 >= arg2);
609 : 576 : }
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 : 533 : in_range_int4_int4(PG_FUNCTION_ARGS)
624 : : {
625 : 533 : int32 val = PG_GETARG_INT32(0);
626 : 533 : int32 base = PG_GETARG_INT32(1);
627 : 533 : int32 offset = PG_GETARG_INT32(2);
628 : 533 : bool sub = PG_GETARG_BOOL(3);
629 : 533 : bool less = PG_GETARG_BOOL(4);
630 : 533 : int32 sum;
631 : :
632 [ + + ]: 533 : if (offset < 0)
633 [ + - + - ]: 2 : ereport(ERROR,
634 : : (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
635 : : errmsg("invalid preceding or following size in window function")));
636 : :
637 [ + + ]: 531 : if (sub)
638 : 240 : offset = -offset; /* cannot overflow */
639 : :
640 [ + + ]: 531 : 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 [ + + ]: 6 : PG_RETURN_BOOL(sub ? !less : less);
648 : : }
649 : :
650 [ + + ]: 525 : if (less)
651 : 310 : PG_RETURN_BOOL(val <= sum);
652 : : else
653 : 215 : PG_RETURN_BOOL(val >= sum);
654 : 531 : }
655 : :
656 : : Datum
657 : 151 : in_range_int4_int2(PG_FUNCTION_ARGS)
658 : : {
659 : : /* Doesn't seem worth duplicating code for, so just invoke int4_int4 */
660 : 151 : 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 : 127 : in_range_int4_int8(PG_FUNCTION_ARGS)
670 : : {
671 : : /* We must do all the math in int64 */
672 : 127 : int64 val = (int64) PG_GETARG_INT32(0);
673 : 127 : int64 base = (int64) PG_GETARG_INT32(1);
674 : 127 : int64 offset = PG_GETARG_INT64(2);
675 : 127 : bool sub = PG_GETARG_BOOL(3);
676 : 127 : bool less = PG_GETARG_BOOL(4);
677 : 127 : int64 sum;
678 : :
679 [ + - ]: 127 : 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 [ + + ]: 127 : if (sub)
685 : 115 : offset = -offset; /* cannot overflow */
686 : :
687 [ - + ]: 127 : 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 [ + + ]: 127 : if (less)
698 : 12 : PG_RETURN_BOOL(val <= sum);
699 : : else
700 : 115 : PG_RETURN_BOOL(val >= sum);
701 : 127 : }
702 : :
703 : : Datum
704 : 6 : in_range_int2_int4(PG_FUNCTION_ARGS)
705 : : {
706 : : /* We must do all the math in int32 */
707 : 6 : int32 val = (int32) PG_GETARG_INT16(0);
708 : 6 : int32 base = (int32) PG_GETARG_INT16(1);
709 : 6 : int32 offset = PG_GETARG_INT32(2);
710 : 6 : bool sub = PG_GETARG_BOOL(3);
711 : 6 : bool less = PG_GETARG_BOOL(4);
712 : 6 : int32 sum;
713 : :
714 [ + - ]: 6 : 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 [ + + ]: 6 : if (sub)
720 : 3 : offset = -offset; /* cannot overflow */
721 : :
722 [ + - ]: 6 : 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 [ + + ]: 6 : 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 : 6 : }
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 : 4497 : int4um(PG_FUNCTION_ARGS)
772 : : {
773 : 4497 : int32 arg = PG_GETARG_INT32(0);
774 : :
775 [ + - ]: 4497 : 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 : 8994 : PG_RETURN_INT32(-arg);
780 : 4497 : }
781 : :
782 : : Datum
783 : 1 : int4up(PG_FUNCTION_ARGS)
784 : : {
785 : 1 : int32 arg = PG_GETARG_INT32(0);
786 : :
787 : 2 : PG_RETURN_INT32(arg);
788 : 1 : }
789 : :
790 : : Datum
791 : 1320880 : int4pl(PG_FUNCTION_ARGS)
792 : : {
793 : 1320880 : int32 arg1 = PG_GETARG_INT32(0);
794 : 1320880 : int32 arg2 = PG_GETARG_INT32(1);
795 : 1320880 : int32 result;
796 : :
797 [ + + ]: 1320880 : if (unlikely(pg_add_s32_overflow(arg1, arg2, &result)))
798 [ + - + - ]: 1 : ereport(ERROR,
799 : : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
800 : : errmsg("integer out of range")));
801 : 2641758 : PG_RETURN_INT32(result);
802 : 1320879 : }
803 : :
804 : : Datum
805 : 439307 : int4mi(PG_FUNCTION_ARGS)
806 : : {
807 : 439307 : int32 arg1 = PG_GETARG_INT32(0);
808 : 439307 : int32 arg2 = PG_GETARG_INT32(1);
809 : 439307 : int32 result;
810 : :
811 [ + + ]: 439307 : if (unlikely(pg_sub_s32_overflow(arg1, arg2, &result)))
812 [ + - + - ]: 1 : ereport(ERROR,
813 : : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
814 : : errmsg("integer out of range")));
815 : 878612 : PG_RETURN_INT32(result);
816 : 439306 : }
817 : :
818 : : Datum
819 : 434216 : int4mul(PG_FUNCTION_ARGS)
820 : : {
821 : 434216 : int32 arg1 = PG_GETARG_INT32(0);
822 : 434216 : int32 arg2 = PG_GETARG_INT32(1);
823 : 434216 : int32 result;
824 : :
825 [ + + ]: 434216 : if (unlikely(pg_mul_s32_overflow(arg1, arg2, &result)))
826 [ + - + - ]: 4 : ereport(ERROR,
827 : : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
828 : : errmsg("integer out of range")));
829 : 868424 : PG_RETURN_INT32(result);
830 : 434212 : }
831 : :
832 : : Datum
833 : 213447 : int4div(PG_FUNCTION_ARGS)
834 : : {
835 : 213447 : int32 arg1 = PG_GETARG_INT32(0);
836 : 213447 : int32 arg2 = PG_GETARG_INT32(1);
837 : 213447 : int32 result;
838 : :
839 [ + + ]: 213447 : if (arg2 == 0)
840 : : {
841 [ + - + - ]: 41 : 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 : 0 : PG_RETURN_NULL();
846 : 0 : }
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 [ + + ]: 213406 : if (arg2 == -1)
855 : : {
856 [ - + ]: 1 : if (unlikely(arg1 == PG_INT32_MIN))
857 [ + - + - ]: 1 : ereport(ERROR,
858 : : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
859 : : errmsg("integer out of range")));
860 : 0 : result = -arg1;
861 : 0 : PG_RETURN_INT32(result);
862 : : }
863 : :
864 : : /* No overflow is possible */
865 : :
866 : 213405 : result = arg1 / arg2;
867 : :
868 : 213405 : PG_RETURN_INT32(result);
869 : 213405 : }
870 : :
871 : : Datum
872 : 0 : int4inc(PG_FUNCTION_ARGS)
873 : : {
874 : 0 : int32 arg = PG_GETARG_INT32(0);
875 : 0 : 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 : 0 : }
884 : :
885 : : Datum
886 : 2 : int2um(PG_FUNCTION_ARGS)
887 : : {
888 : 2 : int16 arg = PG_GETARG_INT16(0);
889 : :
890 [ + - ]: 2 : 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 : 4 : PG_RETURN_INT16(-arg);
895 : 2 : }
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 : 0 : }
904 : :
905 : : Datum
906 : 9 : int2pl(PG_FUNCTION_ARGS)
907 : : {
908 : 9 : int16 arg1 = PG_GETARG_INT16(0);
909 : 9 : int16 arg2 = PG_GETARG_INT16(1);
910 : 9 : int16 result;
911 : :
912 [ + + ]: 9 : if (unlikely(pg_add_s16_overflow(arg1, arg2, &result)))
913 [ + - + - ]: 1 : ereport(ERROR,
914 : : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
915 : : errmsg("smallint out of range")));
916 : 16 : PG_RETURN_INT16(result);
917 : 8 : }
918 : :
919 : : Datum
920 : 20 : int2mi(PG_FUNCTION_ARGS)
921 : : {
922 : 20 : int16 arg1 = PG_GETARG_INT16(0);
923 : 20 : int16 arg2 = PG_GETARG_INT16(1);
924 : 20 : int16 result;
925 : :
926 [ + + ]: 20 : if (unlikely(pg_sub_s16_overflow(arg1, arg2, &result)))
927 [ + - + - ]: 1 : ereport(ERROR,
928 : : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
929 : : errmsg("smallint out of range")));
930 : 38 : PG_RETURN_INT16(result);
931 : 19 : }
932 : :
933 : : Datum
934 : 9 : int2mul(PG_FUNCTION_ARGS)
935 : : {
936 : 9 : int16 arg1 = PG_GETARG_INT16(0);
937 : 9 : int16 arg2 = PG_GETARG_INT16(1);
938 : 9 : int16 result;
939 : :
940 [ + + ]: 9 : if (unlikely(pg_mul_s16_overflow(arg1, arg2, &result)))
941 [ + - + - ]: 2 : ereport(ERROR,
942 : : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
943 : : errmsg("smallint out of range")));
944 : :
945 : 14 : PG_RETURN_INT16(result);
946 : 7 : }
947 : :
948 : : Datum
949 : 7 : int2div(PG_FUNCTION_ARGS)
950 : : {
951 : 7 : int16 arg1 = PG_GETARG_INT16(0);
952 : 7 : int16 arg2 = PG_GETARG_INT16(1);
953 : 7 : int16 result;
954 : :
955 [ + - ]: 7 : 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 : 0 : PG_RETURN_NULL();
962 : 0 : }
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 [ + + ]: 7 : if (arg2 == -1)
971 : : {
972 [ - + ]: 1 : if (unlikely(arg1 == PG_INT16_MIN))
973 [ + - + - ]: 1 : 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 : 6 : result = arg1 / arg2;
983 : :
984 : 6 : PG_RETURN_INT16(result);
985 : 6 : }
986 : :
987 : : Datum
988 : 376 : int24pl(PG_FUNCTION_ARGS)
989 : : {
990 : 376 : int16 arg1 = PG_GETARG_INT16(0);
991 : 376 : int32 arg2 = PG_GETARG_INT32(1);
992 : 376 : int32 result;
993 : :
994 [ + - ]: 376 : 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 : 752 : PG_RETURN_INT32(result);
999 : 376 : }
1000 : :
1001 : : Datum
1002 : 4312 : int24mi(PG_FUNCTION_ARGS)
1003 : : {
1004 : 4312 : int16 arg1 = PG_GETARG_INT16(0);
1005 : 4312 : int32 arg2 = PG_GETARG_INT32(1);
1006 : 4312 : int32 result;
1007 : :
1008 [ + - ]: 4312 : 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 : 8624 : PG_RETURN_INT32(result);
1013 : 4312 : }
1014 : :
1015 : : Datum
1016 : 6 : int24mul(PG_FUNCTION_ARGS)
1017 : : {
1018 : 6 : int16 arg1 = PG_GETARG_INT16(0);
1019 : 6 : int32 arg2 = PG_GETARG_INT32(1);
1020 : 6 : int32 result;
1021 : :
1022 [ + - ]: 6 : 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 : 12 : PG_RETURN_INT32(result);
1027 : 6 : }
1028 : :
1029 : : Datum
1030 : 7 : int24div(PG_FUNCTION_ARGS)
1031 : : {
1032 : 7 : int16 arg1 = PG_GETARG_INT16(0);
1033 : 7 : int32 arg2 = PG_GETARG_INT32(1);
1034 : :
1035 [ + + ]: 7 : if (unlikely(arg2 == 0))
1036 : : {
1037 [ + - + - ]: 1 : 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 : 0 : PG_RETURN_NULL();
1042 : 0 : }
1043 : :
1044 : : /* No overflow is possible */
1045 : 6 : PG_RETURN_INT32((int32) arg1 / arg2);
1046 : 6 : }
1047 : :
1048 : : Datum
1049 : 8 : int42pl(PG_FUNCTION_ARGS)
1050 : : {
1051 : 8 : int32 arg1 = PG_GETARG_INT32(0);
1052 : 8 : int16 arg2 = PG_GETARG_INT16(1);
1053 : 8 : int32 result;
1054 : :
1055 [ + + ]: 8 : if (unlikely(pg_add_s32_overflow(arg1, (int32) arg2, &result)))
1056 [ + - + - ]: 1 : ereport(ERROR,
1057 : : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1058 : : errmsg("integer out of range")));
1059 : 14 : PG_RETURN_INT32(result);
1060 : 7 : }
1061 : :
1062 : : Datum
1063 : 9 : int42mi(PG_FUNCTION_ARGS)
1064 : : {
1065 : 9 : int32 arg1 = PG_GETARG_INT32(0);
1066 : 9 : int16 arg2 = PG_GETARG_INT16(1);
1067 : 9 : int32 result;
1068 : :
1069 [ + + ]: 9 : if (unlikely(pg_sub_s32_overflow(arg1, (int32) arg2, &result)))
1070 [ + - + - ]: 1 : ereport(ERROR,
1071 : : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1072 : : errmsg("integer out of range")));
1073 : 16 : PG_RETURN_INT32(result);
1074 : 8 : }
1075 : :
1076 : : Datum
1077 : 9 : int42mul(PG_FUNCTION_ARGS)
1078 : : {
1079 : 9 : int32 arg1 = PG_GETARG_INT32(0);
1080 : 9 : int16 arg2 = PG_GETARG_INT16(1);
1081 : 9 : int32 result;
1082 : :
1083 [ + + ]: 9 : if (unlikely(pg_mul_s32_overflow(arg1, (int32) arg2, &result)))
1084 [ + - + - ]: 2 : ereport(ERROR,
1085 : : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1086 : : errmsg("integer out of range")));
1087 : 14 : PG_RETURN_INT32(result);
1088 : 7 : }
1089 : :
1090 : : Datum
1091 : 8 : int42div(PG_FUNCTION_ARGS)
1092 : : {
1093 : 8 : int32 arg1 = PG_GETARG_INT32(0);
1094 : 8 : int16 arg2 = PG_GETARG_INT16(1);
1095 : 8 : int32 result;
1096 : :
1097 [ + + ]: 8 : if (unlikely(arg2 == 0))
1098 : : {
1099 [ + - + - ]: 1 : 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 : 0 : PG_RETURN_NULL();
1104 : 0 : }
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 [ + + ]: 7 : if (arg2 == -1)
1113 : : {
1114 [ - + ]: 1 : if (unlikely(arg1 == PG_INT32_MIN))
1115 [ + - + - ]: 1 : 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 : 6 : result = arg1 / arg2;
1125 : :
1126 : 6 : PG_RETURN_INT32(result);
1127 : 6 : }
1128 : :
1129 : : Datum
1130 : 1372101 : int4mod(PG_FUNCTION_ARGS)
1131 : : {
1132 : 1372101 : int32 arg1 = PG_GETARG_INT32(0);
1133 : 1372101 : int32 arg2 = PG_GETARG_INT32(1);
1134 : :
1135 [ + - ]: 1372101 : 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 : 0 : PG_RETURN_NULL();
1142 : 0 : }
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 [ + + ]: 1372101 : if (arg2 == -1)
1150 : 2 : PG_RETURN_INT32(0);
1151 : :
1152 : : /* No overflow is possible */
1153 : :
1154 : 1372099 : PG_RETURN_INT32(arg1 % arg2);
1155 : 1372101 : }
1156 : :
1157 : : Datum
1158 : 6 : int2mod(PG_FUNCTION_ARGS)
1159 : : {
1160 : 6 : int16 arg1 = PG_GETARG_INT16(0);
1161 : 6 : int16 arg2 = PG_GETARG_INT16(1);
1162 : :
1163 [ + - ]: 6 : 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 : 0 : PG_RETURN_NULL();
1170 : 0 : }
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 [ + + ]: 6 : if (arg2 == -1)
1179 : 1 : PG_RETURN_INT16(0);
1180 : :
1181 : : /* No overflow is possible */
1182 : :
1183 : 5 : PG_RETURN_INT16(arg1 % arg2);
1184 : 6 : }
1185 : :
1186 : :
1187 : : /* int[24]abs()
1188 : : * Absolute value
1189 : : */
1190 : : Datum
1191 : 20221 : int4abs(PG_FUNCTION_ARGS)
1192 : : {
1193 : 20221 : int32 arg1 = PG_GETARG_INT32(0);
1194 : 20221 : int32 result;
1195 : :
1196 [ + - ]: 20221 : 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 [ + + ]: 20221 : result = (arg1 < 0) ? -arg1 : arg1;
1201 : 40442 : PG_RETURN_INT32(result);
1202 : 20221 : }
1203 : :
1204 : : Datum
1205 : 5 : int2abs(PG_FUNCTION_ARGS)
1206 : : {
1207 : 5 : int16 arg1 = PG_GETARG_INT16(0);
1208 : 5 : int16 result;
1209 : :
1210 [ + - ]: 5 : 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 [ + + ]: 5 : result = (arg1 < 0) ? -arg1 : arg1;
1215 : 10 : PG_RETURN_INT16(result);
1216 : 5 : }
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 : 44 : int4gcd_internal(int32 arg1, int32 arg2)
1234 : : {
1235 : 44 : int32 swap;
1236 : 44 : 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 [ + + ]: 44 : a1 = (arg1 < 0) ? arg1 : -arg1;
1249 [ + + ]: 44 : a2 = (arg2 < 0) ? arg2 : -arg2;
1250 [ + + ]: 44 : if (a1 > a2)
1251 : : {
1252 : 16 : swap = arg1;
1253 : 16 : arg1 = arg2;
1254 : 16 : arg2 = swap;
1255 : 16 : }
1256 : :
1257 : : /* Special care needs to be taken with INT_MIN. See comments above. */
1258 [ + + ]: 44 : if (arg1 == PG_INT32_MIN)
1259 : : {
1260 [ + + ]: 15 : if (arg2 == 0 || arg2 == PG_INT32_MIN)
1261 [ + - + - ]: 2 : 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 [ + + ]: 13 : if (arg2 == -1)
1272 : 2 : return 1;
1273 : 11 : }
1274 : :
1275 : : /* Use the Euclidean algorithm to find the GCD */
1276 [ + + ]: 157 : while (arg2 != 0)
1277 : : {
1278 : 117 : swap = arg2;
1279 : 117 : arg2 = arg1 % arg2;
1280 : 117 : arg1 = swap;
1281 : : }
1282 : :
1283 : : /*
1284 : : * Make sure the result is positive. (We know we don't have INT_MIN
1285 : : * anymore).
1286 : : */
1287 [ + + ]: 40 : if (arg1 < 0)
1288 : 17 : arg1 = -arg1;
1289 : :
1290 : 40 : return arg1;
1291 : 42 : }
1292 : :
1293 : : Datum
1294 : 30 : int4gcd(PG_FUNCTION_ARGS)
1295 : : {
1296 : 30 : int32 arg1 = PG_GETARG_INT32(0);
1297 : 30 : int32 arg2 = PG_GETARG_INT32(1);
1298 : 30 : int32 result;
1299 : :
1300 : 30 : result = int4gcd_internal(arg1, arg2);
1301 : :
1302 : 60 : PG_RETURN_INT32(result);
1303 : 30 : }
1304 : :
1305 : : /*
1306 : : * Least Common Multiple
1307 : : */
1308 : : Datum
1309 : 26 : int4lcm(PG_FUNCTION_ARGS)
1310 : : {
1311 : 26 : int32 arg1 = PG_GETARG_INT32(0);
1312 : 26 : int32 arg2 = PG_GETARG_INT32(1);
1313 : 26 : int32 gcd;
1314 : 26 : 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 [ + + + + ]: 26 : if (arg1 == 0 || arg2 == 0)
1322 : 12 : PG_RETURN_INT32(0);
1323 : :
1324 : : /* lcm(x, y) = abs(x / gcd(x, y) * y) */
1325 : 14 : gcd = int4gcd_internal(arg1, arg2);
1326 : 14 : arg1 = arg1 / gcd;
1327 : :
1328 [ + + ]: 14 : if (unlikely(pg_mul_s32_overflow(arg1, arg2, &result)))
1329 [ + - + - ]: 1 : 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 [ + + ]: 13 : if (unlikely(result == PG_INT32_MIN))
1335 [ + - + - ]: 1 : ereport(ERROR,
1336 : : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1337 : : errmsg("integer out of range")));
1338 : :
1339 [ + + ]: 12 : if (result < 0)
1340 : 6 : result = -result;
1341 : :
1342 : 12 : PG_RETURN_INT32(result);
1343 : 24 : }
1344 : :
1345 : : Datum
1346 : 67 : int2larger(PG_FUNCTION_ARGS)
1347 : : {
1348 : 67 : int16 arg1 = PG_GETARG_INT16(0);
1349 : 67 : int16 arg2 = PG_GETARG_INT16(1);
1350 : :
1351 [ + + ]: 67 : PG_RETURN_INT16((arg1 > arg2) ? arg1 : arg2);
1352 : 67 : }
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 : 0 : }
1362 : :
1363 : : Datum
1364 : 151273 : int4larger(PG_FUNCTION_ARGS)
1365 : : {
1366 : 151273 : int32 arg1 = PG_GETARG_INT32(0);
1367 : 151273 : int32 arg2 = PG_GETARG_INT32(1);
1368 : :
1369 [ + + ]: 151273 : PG_RETURN_INT32((arg1 > arg2) ? arg1 : arg2);
1370 : 151273 : }
1371 : :
1372 : : Datum
1373 : 88610 : int4smaller(PG_FUNCTION_ARGS)
1374 : : {
1375 : 88610 : int32 arg1 = PG_GETARG_INT32(0);
1376 : 88610 : int32 arg2 = PG_GETARG_INT32(1);
1377 : :
1378 [ + + ]: 88610 : PG_RETURN_INT32((arg1 < arg2) ? arg1 : arg2);
1379 : 88610 : }
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 : 822 : int4and(PG_FUNCTION_ARGS)
1394 : : {
1395 : 822 : int32 arg1 = PG_GETARG_INT32(0);
1396 : 822 : int32 arg2 = PG_GETARG_INT32(1);
1397 : :
1398 : 1644 : PG_RETURN_INT32(arg1 & arg2);
1399 : 822 : }
1400 : :
1401 : : Datum
1402 : 3 : int4or(PG_FUNCTION_ARGS)
1403 : : {
1404 : 3 : int32 arg1 = PG_GETARG_INT32(0);
1405 : 3 : int32 arg2 = PG_GETARG_INT32(1);
1406 : :
1407 : 6 : PG_RETURN_INT32(arg1 | arg2);
1408 : 3 : }
1409 : :
1410 : : Datum
1411 : 3 : int4xor(PG_FUNCTION_ARGS)
1412 : : {
1413 : 3 : int32 arg1 = PG_GETARG_INT32(0);
1414 : 3 : int32 arg2 = PG_GETARG_INT32(1);
1415 : :
1416 : 6 : PG_RETURN_INT32(arg1 ^ arg2);
1417 : 3 : }
1418 : :
1419 : : Datum
1420 : 258 : int4shl(PG_FUNCTION_ARGS)
1421 : : {
1422 : 258 : int32 arg1 = PG_GETARG_INT32(0);
1423 : 258 : int32 arg2 = PG_GETARG_INT32(1);
1424 : :
1425 : 516 : PG_RETURN_INT32(arg1 << arg2);
1426 : 258 : }
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 : 0 : }
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 : 0 : }
1444 : :
1445 : : Datum
1446 : 4 : int2and(PG_FUNCTION_ARGS)
1447 : : {
1448 : 4 : int16 arg1 = PG_GETARG_INT16(0);
1449 : 4 : int16 arg2 = PG_GETARG_INT16(1);
1450 : :
1451 : 8 : PG_RETURN_INT16(arg1 & arg2);
1452 : 4 : }
1453 : :
1454 : : Datum
1455 : 4 : int2or(PG_FUNCTION_ARGS)
1456 : : {
1457 : 4 : int16 arg1 = PG_GETARG_INT16(0);
1458 : 4 : int16 arg2 = PG_GETARG_INT16(1);
1459 : :
1460 : 8 : PG_RETURN_INT16(arg1 | arg2);
1461 : 4 : }
1462 : :
1463 : : Datum
1464 : 4 : int2xor(PG_FUNCTION_ARGS)
1465 : : {
1466 : 4 : int16 arg1 = PG_GETARG_INT16(0);
1467 : 4 : int16 arg2 = PG_GETARG_INT16(1);
1468 : :
1469 : 8 : PG_RETURN_INT16(arg1 ^ arg2);
1470 : 4 : }
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 : 0 : }
1479 : :
1480 : :
1481 : : Datum
1482 : 2 : int2shl(PG_FUNCTION_ARGS)
1483 : : {
1484 : 2 : int16 arg1 = PG_GETARG_INT16(0);
1485 : 2 : int32 arg2 = PG_GETARG_INT32(1);
1486 : :
1487 : 4 : PG_RETURN_INT16(arg1 << arg2);
1488 : 2 : }
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 : 0 : }
1498 : :
1499 : : /*
1500 : : * non-persistent numeric series generator
1501 : : */
1502 : : Datum
1503 : 1686198 : generate_series_int4(PG_FUNCTION_ARGS)
1504 : : {
1505 : 1686198 : return generate_series_step_int4(fcinfo);
1506 : : }
1507 : :
1508 : : Datum
1509 : 1713727 : generate_series_step_int4(PG_FUNCTION_ARGS)
1510 : : {
1511 : 1713727 : FuncCallContext *funcctx;
1512 : 1713727 : generate_series_fctx *fctx;
1513 : 1713727 : int32 result;
1514 : 1713727 : MemoryContext oldcontext;
1515 : :
1516 : : /* stuff done only on the first call of the function */
1517 [ + + ]: 1713727 : if (SRF_IS_FIRSTCALL())
1518 : : {
1519 : 11377 : int32 start = PG_GETARG_INT32(0);
1520 : 11377 : int32 finish = PG_GETARG_INT32(1);
1521 : 11377 : int32 step = 1;
1522 : :
1523 : : /* see if we were given an explicit step size */
1524 [ + + ]: 11377 : if (PG_NARGS() == 3)
1525 : 51 : step = PG_GETARG_INT32(2);
1526 [ + - ]: 11377 : 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 : 11377 : funcctx = SRF_FIRSTCALL_INIT();
1533 : :
1534 : : /*
1535 : : * switch to memory context appropriate for multiple function calls
1536 : : */
1537 : 11377 : oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1538 : :
1539 : : /* allocate memory for user context */
1540 : 11377 : fctx = palloc_object(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 : 11377 : fctx->current = start;
1547 : 11377 : fctx->finish = finish;
1548 : 11377 : fctx->step = step;
1549 : :
1550 : 11377 : funcctx->user_fctx = fctx;
1551 : 11377 : MemoryContextSwitchTo(oldcontext);
1552 : 11377 : }
1553 : :
1554 : : /* stuff done on every call of the function */
1555 : 1713727 : funcctx = SRF_PERCALL_SETUP();
1556 : :
1557 : : /*
1558 : : * get the saved state and use current as the result for this iteration
1559 : : */
1560 : 1713727 : fctx = funcctx->user_fctx;
1561 : 1713727 : result = fctx->current;
1562 : :
1563 [ + - + + ]: 1713727 : if ((fctx->step > 0 && fctx->current <= fctx->finish) ||
1564 [ - + ]: 11369 : (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 [ + - ]: 1702358 : 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 : 1702358 : SRF_RETURN_NEXT(funcctx, Int32GetDatum(result));
1575 : 0 : }
1576 : : else
1577 : : /* do when there is no more left */
1578 [ + - ]: 11369 : SRF_RETURN_DONE(funcctx);
1579 [ - + ]: 1713727 : }
1580 : :
1581 : : /*
1582 : : * Planner support function for generate_series(int4, int4 [, int4])
1583 : : */
1584 : : Datum
1585 : 6011 : generate_series_int4_support(PG_FUNCTION_ARGS)
1586 : : {
1587 : 6011 : Node *rawreq = (Node *) PG_GETARG_POINTER(0);
1588 : 6011 : Node *ret = NULL;
1589 : :
1590 [ + + ]: 6011 : if (IsA(rawreq, SupportRequestRows))
1591 : : {
1592 : : /* Try to estimate the number of rows returned */
1593 : 3559 : SupportRequestRows *req = (SupportRequestRows *) rawreq;
1594 : :
1595 [ + + ]: 3559 : if (is_funcclause(req->node)) /* be paranoid */
1596 : : {
1597 : 1545 : List *args = ((FuncExpr *) req->node)->args;
1598 : 1545 : Node *arg1,
1599 : : *arg2,
1600 : : *arg3;
1601 : :
1602 : : /* We can use estimated argument values here */
1603 : 1545 : arg1 = estimate_expression_value(req->root, linitial(args));
1604 : 1545 : arg2 = estimate_expression_value(req->root, lsecond(args));
1605 [ + + ]: 1545 : if (list_length(args) >= 3)
1606 : 55 : arg3 = estimate_expression_value(req->root, lthird(args));
1607 : : else
1608 : 1490 : 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 [ + + ]: 1545 : if ((IsA(arg1, Const) &&
1617 [ + + ]: 1532 : ((Const *) arg1)->constisnull) ||
1618 [ + + ]: 2552 : (IsA(arg2, Const) &&
1619 : 1007 : ((Const *) arg2)->constisnull) ||
1620 [ + + + - ]: 1600 : (arg3 != NULL && IsA(arg3, Const) &&
1621 : 55 : ((Const *) arg3)->constisnull))
1622 : : {
1623 : 2014 : req->rows = 0;
1624 : 2014 : ret = (Node *) req;
1625 : 2014 : }
1626 [ + + ]: 1545 : else if (IsA(arg1, Const) &&
1627 [ + + + - ]: 1587 : IsA(arg2, Const) &&
1628 [ + + ]: 945 : (arg3 == NULL || IsA(arg3, Const)))
1629 : : {
1630 : 945 : double start,
1631 : : finish,
1632 : : step;
1633 : :
1634 : 945 : start = DatumGetInt32(((Const *) arg1)->constvalue);
1635 : 945 : finish = DatumGetInt32(((Const *) arg2)->constvalue);
1636 [ + + ]: 945 : step = arg3 ? DatumGetInt32(((Const *) arg3)->constvalue) : 1;
1637 : :
1638 : : /* This equation works for either sign of step */
1639 [ - + ]: 945 : if (step != 0)
1640 : : {
1641 : 945 : req->rows = floor((finish - start + step) / step);
1642 : 945 : ret = (Node *) req;
1643 : 945 : }
1644 : 945 : }
1645 : 3559 : }
1646 : 5573 : }
1647 : :
1648 : 7994 : PG_RETURN_POINTER(ret);
1649 : 3997 : }
|