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