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-2017, 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 :
34 : #include "catalog/pg_type.h"
35 : #include "funcapi.h"
36 : #include "libpq/pqformat.h"
37 : #include "utils/array.h"
38 : #include "utils/builtins.h"
39 :
40 :
41 : #define SAMESIGN(a,b) (((a) < 0) == ((b) < 0))
42 :
43 : #define Int2VectorSize(n) (offsetof(int2vector, values) + (n) * sizeof(int16))
44 :
45 : typedef struct
46 : {
47 : int32 current;
48 : int32 finish;
49 : int32 step;
50 : } generate_series_fctx;
51 :
52 :
53 : /*****************************************************************************
54 : * USER I/O ROUTINES *
55 : *****************************************************************************/
56 :
57 : /*
58 : * int2in - converts "num" to short
59 : */
60 : Datum
61 7600 : int2in(PG_FUNCTION_ARGS)
62 : {
63 7600 : char *num = PG_GETARG_CSTRING(0);
64 :
65 7600 : PG_RETURN_INT16(pg_atoi(num, sizeof(int16), '\0'));
66 : }
67 :
68 : /*
69 : * int2out - converts short to "num"
70 : */
71 : Datum
72 1543 : int2out(PG_FUNCTION_ARGS)
73 : {
74 1543 : int16 arg1 = PG_GETARG_INT16(0);
75 1543 : char *result = (char *) palloc(7); /* sign, 5 digits, '\0' */
76 :
77 1543 : pg_itoa(arg1, result);
78 1543 : PG_RETURN_CSTRING(result);
79 : }
80 :
81 : /*
82 : * int2recv - converts external binary format to int2
83 : */
84 : Datum
85 0 : int2recv(PG_FUNCTION_ARGS)
86 : {
87 0 : StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
88 :
89 0 : PG_RETURN_INT16((int16) pq_getmsgint(buf, sizeof(int16)));
90 : }
91 :
92 : /*
93 : * int2send - converts int2 to binary format
94 : */
95 : Datum
96 0 : int2send(PG_FUNCTION_ARGS)
97 : {
98 0 : int16 arg1 = PG_GETARG_INT16(0);
99 : StringInfoData buf;
100 :
101 0 : pq_begintypsend(&buf);
102 0 : pq_sendint(&buf, arg1, sizeof(int16));
103 0 : PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
104 : }
105 :
106 : /*
107 : * construct int2vector given a raw array of int2s
108 : *
109 : * If int2s is NULL then caller must fill values[] afterward
110 : */
111 : int2vector *
112 3383 : buildint2vector(const int16 *int2s, int n)
113 : {
114 : int2vector *result;
115 :
116 3383 : result = (int2vector *) palloc0(Int2VectorSize(n));
117 :
118 3383 : if (n > 0 && int2s)
119 1467 : memcpy(result->values, int2s, n * sizeof(int16));
120 :
121 : /*
122 : * Attach standard array header. For historical reasons, we set the index
123 : * lower bound to 0 not 1.
124 : */
125 3383 : SET_VARSIZE(result, Int2VectorSize(n));
126 3383 : result->ndim = 1;
127 3383 : result->dataoffset = 0; /* never any nulls */
128 3383 : result->elemtype = INT2OID;
129 3383 : result->dim1 = n;
130 3383 : result->lbound1 = 0;
131 :
132 3383 : return result;
133 : }
134 :
135 : /*
136 : * int2vectorin - converts "num num ..." to internal form
137 : */
138 : Datum
139 0 : int2vectorin(PG_FUNCTION_ARGS)
140 : {
141 0 : char *intString = PG_GETARG_CSTRING(0);
142 : int2vector *result;
143 : int n;
144 :
145 0 : result = (int2vector *) palloc0(Int2VectorSize(FUNC_MAX_ARGS));
146 :
147 0 : for (n = 0; *intString && n < FUNC_MAX_ARGS; n++)
148 : {
149 0 : while (*intString && isspace((unsigned char) *intString))
150 0 : intString++;
151 0 : if (*intString == '\0')
152 0 : break;
153 0 : result->values[n] = pg_atoi(intString, sizeof(int16), ' ');
154 0 : while (*intString && !isspace((unsigned char) *intString))
155 0 : intString++;
156 : }
157 0 : while (*intString && isspace((unsigned char) *intString))
158 0 : intString++;
159 0 : if (*intString)
160 0 : ereport(ERROR,
161 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
162 : errmsg("int2vector has too many elements")));
163 :
164 0 : SET_VARSIZE(result, Int2VectorSize(n));
165 0 : result->ndim = 1;
166 0 : result->dataoffset = 0; /* never any nulls */
167 0 : result->elemtype = INT2OID;
168 0 : result->dim1 = n;
169 0 : result->lbound1 = 0;
170 :
171 0 : PG_RETURN_POINTER(result);
172 : }
173 :
174 : /*
175 : * int2vectorout - converts internal form to "num num ..."
176 : */
177 : Datum
178 0 : int2vectorout(PG_FUNCTION_ARGS)
179 : {
180 0 : int2vector *int2Array = (int2vector *) PG_GETARG_POINTER(0);
181 : int num,
182 0 : nnums = int2Array->dim1;
183 : char *rp;
184 : char *result;
185 :
186 : /* assumes sign, 5 digits, ' ' */
187 0 : rp = result = (char *) palloc(nnums * 7 + 1);
188 0 : for (num = 0; num < nnums; num++)
189 : {
190 0 : if (num != 0)
191 0 : *rp++ = ' ';
192 0 : pg_itoa(int2Array->values[num], rp);
193 0 : while (*++rp != '\0')
194 : ;
195 : }
196 0 : *rp = '\0';
197 0 : PG_RETURN_CSTRING(result);
198 : }
199 :
200 : /*
201 : * int2vectorrecv - converts external binary format to int2vector
202 : */
203 : Datum
204 0 : int2vectorrecv(PG_FUNCTION_ARGS)
205 : {
206 0 : StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
207 : FunctionCallInfoData locfcinfo;
208 : int2vector *result;
209 :
210 : /*
211 : * Normally one would call array_recv() using DirectFunctionCall3, but
212 : * that does not work since array_recv wants to cache some data using
213 : * fcinfo->flinfo->fn_extra. So we need to pass it our own flinfo
214 : * parameter.
215 : */
216 0 : InitFunctionCallInfoData(locfcinfo, fcinfo->flinfo, 3,
217 : InvalidOid, NULL, NULL);
218 :
219 0 : locfcinfo.arg[0] = PointerGetDatum(buf);
220 0 : locfcinfo.arg[1] = ObjectIdGetDatum(INT2OID);
221 0 : locfcinfo.arg[2] = Int32GetDatum(-1);
222 0 : locfcinfo.argnull[0] = false;
223 0 : locfcinfo.argnull[1] = false;
224 0 : locfcinfo.argnull[2] = false;
225 :
226 0 : result = (int2vector *) DatumGetPointer(array_recv(&locfcinfo));
227 :
228 0 : Assert(!locfcinfo.isnull);
229 :
230 : /* sanity checks: int2vector must be 1-D, 0-based, no nulls */
231 0 : if (ARR_NDIM(result) != 1 ||
232 0 : ARR_HASNULL(result) ||
233 0 : ARR_ELEMTYPE(result) != INT2OID ||
234 0 : ARR_LBOUND(result)[0] != 0)
235 0 : ereport(ERROR,
236 : (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
237 : errmsg("invalid int2vector data")));
238 :
239 : /* check length for consistency with int2vectorin() */
240 0 : if (ARR_DIMS(result)[0] > FUNC_MAX_ARGS)
241 0 : ereport(ERROR,
242 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
243 : errmsg("oidvector has too many elements")));
244 :
245 0 : PG_RETURN_POINTER(result);
246 : }
247 :
248 : /*
249 : * int2vectorsend - converts int2vector to binary format
250 : */
251 : Datum
252 0 : int2vectorsend(PG_FUNCTION_ARGS)
253 : {
254 0 : return array_send(fcinfo);
255 : }
256 :
257 :
258 : /*****************************************************************************
259 : * PUBLIC ROUTINES *
260 : *****************************************************************************/
261 :
262 : /*
263 : * int4in - converts "num" to int4
264 : */
265 : Datum
266 292038 : int4in(PG_FUNCTION_ARGS)
267 : {
268 292038 : char *num = PG_GETARG_CSTRING(0);
269 :
270 292038 : PG_RETURN_INT32(pg_atoi(num, sizeof(int32), '\0'));
271 : }
272 :
273 : /*
274 : * int4out - converts int4 to "num"
275 : */
276 : Datum
277 149692 : int4out(PG_FUNCTION_ARGS)
278 : {
279 149692 : int32 arg1 = PG_GETARG_INT32(0);
280 149692 : char *result = (char *) palloc(12); /* sign, 10 digits, '\0' */
281 :
282 149692 : pg_ltoa(arg1, result);
283 149692 : PG_RETURN_CSTRING(result);
284 : }
285 :
286 : /*
287 : * int4recv - converts external binary format to int4
288 : */
289 : Datum
290 344 : int4recv(PG_FUNCTION_ARGS)
291 : {
292 344 : StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
293 :
294 344 : PG_RETURN_INT32((int32) pq_getmsgint(buf, sizeof(int32)));
295 : }
296 :
297 : /*
298 : * int4send - converts int4 to binary format
299 : */
300 : Datum
301 179 : int4send(PG_FUNCTION_ARGS)
302 : {
303 179 : int32 arg1 = PG_GETARG_INT32(0);
304 : StringInfoData buf;
305 :
306 179 : pq_begintypsend(&buf);
307 179 : pq_sendint(&buf, arg1, sizeof(int32));
308 179 : PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
309 : }
310 :
311 :
312 : /*
313 : * ===================
314 : * CONVERSION ROUTINES
315 : * ===================
316 : */
317 :
318 : Datum
319 562 : i2toi4(PG_FUNCTION_ARGS)
320 : {
321 562 : int16 arg1 = PG_GETARG_INT16(0);
322 :
323 562 : PG_RETURN_INT32((int32) arg1);
324 : }
325 :
326 : Datum
327 244 : i4toi2(PG_FUNCTION_ARGS)
328 : {
329 244 : int32 arg1 = PG_GETARG_INT32(0);
330 :
331 244 : if (arg1 < SHRT_MIN || arg1 > SHRT_MAX)
332 6 : ereport(ERROR,
333 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
334 : errmsg("smallint out of range")));
335 :
336 238 : PG_RETURN_INT16((int16) arg1);
337 : }
338 :
339 : /* Cast int4 -> bool */
340 : Datum
341 0 : int4_bool(PG_FUNCTION_ARGS)
342 : {
343 0 : if (PG_GETARG_INT32(0) == 0)
344 0 : PG_RETURN_BOOL(false);
345 : else
346 0 : PG_RETURN_BOOL(true);
347 : }
348 :
349 : /* Cast bool -> int4 */
350 : Datum
351 3 : bool_int4(PG_FUNCTION_ARGS)
352 : {
353 3 : if (PG_GETARG_BOOL(0) == false)
354 1 : PG_RETURN_INT32(0);
355 : else
356 2 : PG_RETURN_INT32(1);
357 : }
358 :
359 : /*
360 : * ============================
361 : * COMPARISON OPERATOR ROUTINES
362 : * ============================
363 : */
364 :
365 : /*
366 : * inteq - returns 1 iff arg1 == arg2
367 : * intne - returns 1 iff arg1 != arg2
368 : * intlt - returns 1 iff arg1 < arg2
369 : * intle - returns 1 iff arg1 <= arg2
370 : * intgt - returns 1 iff arg1 > arg2
371 : * intge - returns 1 iff arg1 >= arg2
372 : */
373 :
374 : Datum
375 1103065 : int4eq(PG_FUNCTION_ARGS)
376 : {
377 1103065 : int32 arg1 = PG_GETARG_INT32(0);
378 1103065 : int32 arg2 = PG_GETARG_INT32(1);
379 :
380 1103065 : PG_RETURN_BOOL(arg1 == arg2);
381 : }
382 :
383 : Datum
384 42082 : int4ne(PG_FUNCTION_ARGS)
385 : {
386 42082 : int32 arg1 = PG_GETARG_INT32(0);
387 42082 : int32 arg2 = PG_GETARG_INT32(1);
388 :
389 42082 : PG_RETURN_BOOL(arg1 != arg2);
390 : }
391 :
392 : Datum
393 90653 : int4lt(PG_FUNCTION_ARGS)
394 : {
395 90653 : int32 arg1 = PG_GETARG_INT32(0);
396 90653 : int32 arg2 = PG_GETARG_INT32(1);
397 :
398 90653 : PG_RETURN_BOOL(arg1 < arg2);
399 : }
400 :
401 : Datum
402 13741 : int4le(PG_FUNCTION_ARGS)
403 : {
404 13741 : int32 arg1 = PG_GETARG_INT32(0);
405 13741 : int32 arg2 = PG_GETARG_INT32(1);
406 :
407 13741 : PG_RETURN_BOOL(arg1 <= arg2);
408 : }
409 :
410 : Datum
411 382791 : int4gt(PG_FUNCTION_ARGS)
412 : {
413 382791 : int32 arg1 = PG_GETARG_INT32(0);
414 382791 : int32 arg2 = PG_GETARG_INT32(1);
415 :
416 382791 : PG_RETURN_BOOL(arg1 > arg2);
417 : }
418 :
419 : Datum
420 32096 : int4ge(PG_FUNCTION_ARGS)
421 : {
422 32096 : int32 arg1 = PG_GETARG_INT32(0);
423 32096 : int32 arg2 = PG_GETARG_INT32(1);
424 :
425 32096 : PG_RETURN_BOOL(arg1 >= arg2);
426 : }
427 :
428 : Datum
429 284199 : int2eq(PG_FUNCTION_ARGS)
430 : {
431 284199 : int16 arg1 = PG_GETARG_INT16(0);
432 284199 : int16 arg2 = PG_GETARG_INT16(1);
433 :
434 284199 : PG_RETURN_BOOL(arg1 == arg2);
435 : }
436 :
437 : Datum
438 3643 : int2ne(PG_FUNCTION_ARGS)
439 : {
440 3643 : int16 arg1 = PG_GETARG_INT16(0);
441 3643 : int16 arg2 = PG_GETARG_INT16(1);
442 :
443 3643 : PG_RETURN_BOOL(arg1 != arg2);
444 : }
445 :
446 : Datum
447 1787 : int2lt(PG_FUNCTION_ARGS)
448 : {
449 1787 : int16 arg1 = PG_GETARG_INT16(0);
450 1787 : int16 arg2 = PG_GETARG_INT16(1);
451 :
452 1787 : PG_RETURN_BOOL(arg1 < arg2);
453 : }
454 :
455 : Datum
456 463 : int2le(PG_FUNCTION_ARGS)
457 : {
458 463 : int16 arg1 = PG_GETARG_INT16(0);
459 463 : int16 arg2 = PG_GETARG_INT16(1);
460 :
461 463 : PG_RETURN_BOOL(arg1 <= arg2);
462 : }
463 :
464 : Datum
465 88085 : int2gt(PG_FUNCTION_ARGS)
466 : {
467 88085 : int16 arg1 = PG_GETARG_INT16(0);
468 88085 : int16 arg2 = PG_GETARG_INT16(1);
469 :
470 88085 : PG_RETURN_BOOL(arg1 > arg2);
471 : }
472 :
473 : Datum
474 386 : int2ge(PG_FUNCTION_ARGS)
475 : {
476 386 : int16 arg1 = PG_GETARG_INT16(0);
477 386 : int16 arg2 = PG_GETARG_INT16(1);
478 :
479 386 : PG_RETURN_BOOL(arg1 >= arg2);
480 : }
481 :
482 : Datum
483 6773 : int24eq(PG_FUNCTION_ARGS)
484 : {
485 6773 : int16 arg1 = PG_GETARG_INT16(0);
486 6773 : int32 arg2 = PG_GETARG_INT32(1);
487 :
488 6773 : PG_RETURN_BOOL(arg1 == arg2);
489 : }
490 :
491 : Datum
492 33242 : int24ne(PG_FUNCTION_ARGS)
493 : {
494 33242 : int16 arg1 = PG_GETARG_INT16(0);
495 33242 : int32 arg2 = PG_GETARG_INT32(1);
496 :
497 33242 : PG_RETURN_BOOL(arg1 != arg2);
498 : }
499 :
500 : Datum
501 8588 : int24lt(PG_FUNCTION_ARGS)
502 : {
503 8588 : int16 arg1 = PG_GETARG_INT16(0);
504 8588 : int32 arg2 = PG_GETARG_INT32(1);
505 :
506 8588 : PG_RETURN_BOOL(arg1 < arg2);
507 : }
508 :
509 : Datum
510 1525 : int24le(PG_FUNCTION_ARGS)
511 : {
512 1525 : int16 arg1 = PG_GETARG_INT16(0);
513 1525 : int32 arg2 = PG_GETARG_INT32(1);
514 :
515 1525 : PG_RETURN_BOOL(arg1 <= arg2);
516 : }
517 :
518 : Datum
519 16316 : int24gt(PG_FUNCTION_ARGS)
520 : {
521 16316 : int16 arg1 = PG_GETARG_INT16(0);
522 16316 : int32 arg2 = PG_GETARG_INT32(1);
523 :
524 16316 : PG_RETURN_BOOL(arg1 > arg2);
525 : }
526 :
527 : Datum
528 648 : int24ge(PG_FUNCTION_ARGS)
529 : {
530 648 : int16 arg1 = PG_GETARG_INT16(0);
531 648 : int32 arg2 = PG_GETARG_INT32(1);
532 :
533 648 : PG_RETURN_BOOL(arg1 >= arg2);
534 : }
535 :
536 : Datum
537 902 : int42eq(PG_FUNCTION_ARGS)
538 : {
539 902 : int32 arg1 = PG_GETARG_INT32(0);
540 902 : int16 arg2 = PG_GETARG_INT16(1);
541 :
542 902 : PG_RETURN_BOOL(arg1 == arg2);
543 : }
544 :
545 : Datum
546 5 : int42ne(PG_FUNCTION_ARGS)
547 : {
548 5 : int32 arg1 = PG_GETARG_INT32(0);
549 5 : int16 arg2 = PG_GETARG_INT16(1);
550 :
551 5 : PG_RETURN_BOOL(arg1 != arg2);
552 : }
553 :
554 : Datum
555 419 : int42lt(PG_FUNCTION_ARGS)
556 : {
557 419 : int32 arg1 = PG_GETARG_INT32(0);
558 419 : int16 arg2 = PG_GETARG_INT16(1);
559 :
560 419 : PG_RETURN_BOOL(arg1 < arg2);
561 : }
562 :
563 : Datum
564 501 : int42le(PG_FUNCTION_ARGS)
565 : {
566 501 : int32 arg1 = PG_GETARG_INT32(0);
567 501 : int16 arg2 = PG_GETARG_INT16(1);
568 :
569 501 : PG_RETURN_BOOL(arg1 <= arg2);
570 : }
571 :
572 : Datum
573 305 : int42gt(PG_FUNCTION_ARGS)
574 : {
575 305 : int32 arg1 = PG_GETARG_INT32(0);
576 305 : int16 arg2 = PG_GETARG_INT16(1);
577 :
578 305 : PG_RETURN_BOOL(arg1 > arg2);
579 : }
580 :
581 : Datum
582 343 : int42ge(PG_FUNCTION_ARGS)
583 : {
584 343 : int32 arg1 = PG_GETARG_INT32(0);
585 343 : int16 arg2 = PG_GETARG_INT16(1);
586 :
587 343 : PG_RETURN_BOOL(arg1 >= arg2);
588 : }
589 :
590 : /*
591 : * int[24]pl - returns arg1 + arg2
592 : * int[24]mi - returns arg1 - arg2
593 : * int[24]mul - returns arg1 * arg2
594 : * int[24]div - returns arg1 / arg2
595 : */
596 :
597 : Datum
598 993 : int4um(PG_FUNCTION_ARGS)
599 : {
600 993 : int32 arg = PG_GETARG_INT32(0);
601 : int32 result;
602 :
603 993 : result = -arg;
604 : /* overflow check (needed for INT_MIN) */
605 993 : if (arg != 0 && SAMESIGN(result, arg))
606 0 : ereport(ERROR,
607 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
608 : errmsg("integer out of range")));
609 993 : PG_RETURN_INT32(result);
610 : }
611 :
612 : Datum
613 0 : int4up(PG_FUNCTION_ARGS)
614 : {
615 0 : int32 arg = PG_GETARG_INT32(0);
616 :
617 0 : PG_RETURN_INT32(arg);
618 : }
619 :
620 : Datum
621 135276 : int4pl(PG_FUNCTION_ARGS)
622 : {
623 135276 : int32 arg1 = PG_GETARG_INT32(0);
624 135276 : int32 arg2 = PG_GETARG_INT32(1);
625 : int32 result;
626 :
627 135276 : result = arg1 + arg2;
628 :
629 : /*
630 : * Overflow check. If the inputs are of different signs then their sum
631 : * cannot overflow. If the inputs are of the same sign, their sum had
632 : * better be that sign too.
633 : */
634 135276 : if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
635 1 : ereport(ERROR,
636 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
637 : errmsg("integer out of range")));
638 135275 : PG_RETURN_INT32(result);
639 : }
640 :
641 : Datum
642 12361 : int4mi(PG_FUNCTION_ARGS)
643 : {
644 12361 : int32 arg1 = PG_GETARG_INT32(0);
645 12361 : int32 arg2 = PG_GETARG_INT32(1);
646 : int32 result;
647 :
648 12361 : result = arg1 - arg2;
649 :
650 : /*
651 : * Overflow check. If the inputs are of the same sign then their
652 : * difference cannot overflow. If they are of different signs then the
653 : * result should be of the same sign as the first input.
654 : */
655 12361 : if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
656 1 : ereport(ERROR,
657 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
658 : errmsg("integer out of range")));
659 12360 : PG_RETURN_INT32(result);
660 : }
661 :
662 : Datum
663 122536 : int4mul(PG_FUNCTION_ARGS)
664 : {
665 122536 : int32 arg1 = PG_GETARG_INT32(0);
666 122536 : int32 arg2 = PG_GETARG_INT32(1);
667 : int32 result;
668 :
669 122536 : result = arg1 * arg2;
670 :
671 : /*
672 : * Overflow check. We basically check to see if result / arg2 gives arg1
673 : * again. There are two cases where this fails: arg2 = 0 (which cannot
674 : * overflow) and arg1 = INT_MIN, arg2 = -1 (where the division itself will
675 : * overflow and thus incorrectly match).
676 : *
677 : * Since the division is likely much more expensive than the actual
678 : * multiplication, we'd like to skip it where possible. The best bang for
679 : * the buck seems to be to check whether both inputs are in the int16
680 : * range; if so, no overflow is possible.
681 : */
682 122536 : if (!(arg1 >= (int32) SHRT_MIN && arg1 <= (int32) SHRT_MAX &&
683 117 : arg2 >= (int32) SHRT_MIN && arg2 <= (int32) SHRT_MAX) &&
684 117 : arg2 != 0 &&
685 117 : ((arg2 == -1 && arg1 < 0 && result < 0) ||
686 116 : result / arg2 != arg1))
687 2 : ereport(ERROR,
688 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
689 : errmsg("integer out of range")));
690 122534 : PG_RETURN_INT32(result);
691 : }
692 :
693 : Datum
694 177258 : int4div(PG_FUNCTION_ARGS)
695 : {
696 177258 : int32 arg1 = PG_GETARG_INT32(0);
697 177258 : int32 arg2 = PG_GETARG_INT32(1);
698 : int32 result;
699 :
700 177258 : if (arg2 == 0)
701 : {
702 31 : ereport(ERROR,
703 : (errcode(ERRCODE_DIVISION_BY_ZERO),
704 : errmsg("division by zero")));
705 : /* ensure compiler realizes we mustn't reach the division (gcc bug) */
706 : PG_RETURN_NULL();
707 : }
708 :
709 : /*
710 : * INT_MIN / -1 is problematic, since the result can't be represented on a
711 : * two's-complement machine. Some machines produce INT_MIN, some produce
712 : * zero, some throw an exception. We can dodge the problem by recognizing
713 : * that division by -1 is the same as negation.
714 : */
715 177227 : if (arg2 == -1)
716 : {
717 1 : result = -arg1;
718 : /* overflow check (needed for INT_MIN) */
719 1 : if (arg1 != 0 && SAMESIGN(result, arg1))
720 1 : ereport(ERROR,
721 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
722 : errmsg("integer out of range")));
723 0 : PG_RETURN_INT32(result);
724 : }
725 :
726 : /* No overflow is possible */
727 :
728 177226 : result = arg1 / arg2;
729 :
730 177226 : PG_RETURN_INT32(result);
731 : }
732 :
733 : Datum
734 0 : int4inc(PG_FUNCTION_ARGS)
735 : {
736 0 : int32 arg = PG_GETARG_INT32(0);
737 : int32 result;
738 :
739 0 : result = arg + 1;
740 : /* Overflow check */
741 0 : if (arg > 0 && result < 0)
742 0 : ereport(ERROR,
743 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
744 : errmsg("integer out of range")));
745 :
746 0 : PG_RETURN_INT32(result);
747 : }
748 :
749 : Datum
750 2 : int2um(PG_FUNCTION_ARGS)
751 : {
752 2 : int16 arg = PG_GETARG_INT16(0);
753 : int16 result;
754 :
755 2 : result = -arg;
756 : /* overflow check (needed for SHRT_MIN) */
757 2 : if (arg != 0 && SAMESIGN(result, arg))
758 0 : ereport(ERROR,
759 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
760 : errmsg("smallint out of range")));
761 2 : PG_RETURN_INT16(result);
762 : }
763 :
764 : Datum
765 0 : int2up(PG_FUNCTION_ARGS)
766 : {
767 0 : int16 arg = PG_GETARG_INT16(0);
768 :
769 0 : PG_RETURN_INT16(arg);
770 : }
771 :
772 : Datum
773 9 : int2pl(PG_FUNCTION_ARGS)
774 : {
775 9 : int16 arg1 = PG_GETARG_INT16(0);
776 9 : int16 arg2 = PG_GETARG_INT16(1);
777 : int16 result;
778 :
779 9 : result = arg1 + arg2;
780 :
781 : /*
782 : * Overflow check. If the inputs are of different signs then their sum
783 : * cannot overflow. If the inputs are of the same sign, their sum had
784 : * better be that sign too.
785 : */
786 9 : if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
787 1 : ereport(ERROR,
788 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
789 : errmsg("smallint out of range")));
790 8 : PG_RETURN_INT16(result);
791 : }
792 :
793 : Datum
794 20 : int2mi(PG_FUNCTION_ARGS)
795 : {
796 20 : int16 arg1 = PG_GETARG_INT16(0);
797 20 : int16 arg2 = PG_GETARG_INT16(1);
798 : int16 result;
799 :
800 20 : result = arg1 - arg2;
801 :
802 : /*
803 : * Overflow check. If the inputs are of the same sign then their
804 : * difference cannot overflow. If they are of different signs then the
805 : * result should be of the same sign as the first input.
806 : */
807 20 : if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
808 1 : ereport(ERROR,
809 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
810 : errmsg("smallint out of range")));
811 19 : PG_RETURN_INT16(result);
812 : }
813 :
814 : Datum
815 9 : int2mul(PG_FUNCTION_ARGS)
816 : {
817 9 : int16 arg1 = PG_GETARG_INT16(0);
818 9 : int16 arg2 = PG_GETARG_INT16(1);
819 : int32 result32;
820 :
821 : /*
822 : * The most practical way to detect overflow is to do the arithmetic in
823 : * int32 (so that the result can't overflow) and then do a range check.
824 : */
825 9 : result32 = (int32) arg1 * (int32) arg2;
826 :
827 9 : if (result32 < SHRT_MIN || result32 > SHRT_MAX)
828 2 : ereport(ERROR,
829 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
830 : errmsg("smallint out of range")));
831 :
832 7 : PG_RETURN_INT16((int16) result32);
833 : }
834 :
835 : Datum
836 7 : int2div(PG_FUNCTION_ARGS)
837 : {
838 7 : int16 arg1 = PG_GETARG_INT16(0);
839 7 : int16 arg2 = PG_GETARG_INT16(1);
840 : int16 result;
841 :
842 7 : if (arg2 == 0)
843 : {
844 0 : ereport(ERROR,
845 : (errcode(ERRCODE_DIVISION_BY_ZERO),
846 : errmsg("division by zero")));
847 : /* ensure compiler realizes we mustn't reach the division (gcc bug) */
848 : PG_RETURN_NULL();
849 : }
850 :
851 : /*
852 : * SHRT_MIN / -1 is problematic, since the result can't be represented on
853 : * a two's-complement machine. Some machines produce SHRT_MIN, some
854 : * produce zero, some throw an exception. We can dodge the problem by
855 : * recognizing that division by -1 is the same as negation.
856 : */
857 7 : if (arg2 == -1)
858 : {
859 1 : result = -arg1;
860 : /* overflow check (needed for SHRT_MIN) */
861 1 : if (arg1 != 0 && SAMESIGN(result, arg1))
862 1 : ereport(ERROR,
863 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
864 : errmsg("smallint out of range")));
865 0 : PG_RETURN_INT16(result);
866 : }
867 :
868 : /* No overflow is possible */
869 :
870 6 : result = arg1 / arg2;
871 :
872 6 : PG_RETURN_INT16(result);
873 : }
874 :
875 : Datum
876 468 : int24pl(PG_FUNCTION_ARGS)
877 : {
878 468 : int16 arg1 = PG_GETARG_INT16(0);
879 468 : int32 arg2 = PG_GETARG_INT32(1);
880 : int32 result;
881 :
882 468 : result = arg1 + arg2;
883 :
884 : /*
885 : * Overflow check. If the inputs are of different signs then their sum
886 : * cannot overflow. If the inputs are of the same sign, their sum had
887 : * better be that sign too.
888 : */
889 468 : if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
890 0 : ereport(ERROR,
891 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
892 : errmsg("integer out of range")));
893 468 : PG_RETURN_INT32(result);
894 : }
895 :
896 : Datum
897 3560 : int24mi(PG_FUNCTION_ARGS)
898 : {
899 3560 : int16 arg1 = PG_GETARG_INT16(0);
900 3560 : int32 arg2 = PG_GETARG_INT32(1);
901 : int32 result;
902 :
903 3560 : result = arg1 - arg2;
904 :
905 : /*
906 : * Overflow check. If the inputs are of the same sign then their
907 : * difference cannot overflow. If they are of different signs then the
908 : * result should be of the same sign as the first input.
909 : */
910 3560 : if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
911 0 : ereport(ERROR,
912 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
913 : errmsg("integer out of range")));
914 3560 : PG_RETURN_INT32(result);
915 : }
916 :
917 : Datum
918 6 : int24mul(PG_FUNCTION_ARGS)
919 : {
920 6 : int16 arg1 = PG_GETARG_INT16(0);
921 6 : int32 arg2 = PG_GETARG_INT32(1);
922 : int32 result;
923 :
924 6 : result = arg1 * arg2;
925 :
926 : /*
927 : * Overflow check. We basically check to see if result / arg2 gives arg1
928 : * again. There is one case where this fails: arg2 = 0 (which cannot
929 : * overflow).
930 : *
931 : * Since the division is likely much more expensive than the actual
932 : * multiplication, we'd like to skip it where possible. The best bang for
933 : * the buck seems to be to check whether both inputs are in the int16
934 : * range; if so, no overflow is possible.
935 : */
936 6 : if (!(arg2 >= (int32) SHRT_MIN && arg2 <= (int32) SHRT_MAX) &&
937 0 : result / arg2 != arg1)
938 0 : ereport(ERROR,
939 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
940 : errmsg("integer out of range")));
941 6 : PG_RETURN_INT32(result);
942 : }
943 :
944 : Datum
945 7 : int24div(PG_FUNCTION_ARGS)
946 : {
947 7 : int16 arg1 = PG_GETARG_INT16(0);
948 7 : int32 arg2 = PG_GETARG_INT32(1);
949 :
950 7 : if (arg2 == 0)
951 : {
952 1 : ereport(ERROR,
953 : (errcode(ERRCODE_DIVISION_BY_ZERO),
954 : errmsg("division by zero")));
955 : /* ensure compiler realizes we mustn't reach the division (gcc bug) */
956 : PG_RETURN_NULL();
957 : }
958 :
959 : /* No overflow is possible */
960 6 : PG_RETURN_INT32((int32) arg1 / arg2);
961 : }
962 :
963 : Datum
964 8 : int42pl(PG_FUNCTION_ARGS)
965 : {
966 8 : int32 arg1 = PG_GETARG_INT32(0);
967 8 : int16 arg2 = PG_GETARG_INT16(1);
968 : int32 result;
969 :
970 8 : result = arg1 + arg2;
971 :
972 : /*
973 : * Overflow check. If the inputs are of different signs then their sum
974 : * cannot overflow. If the inputs are of the same sign, their sum had
975 : * better be that sign too.
976 : */
977 8 : if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
978 1 : ereport(ERROR,
979 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
980 : errmsg("integer out of range")));
981 7 : PG_RETURN_INT32(result);
982 : }
983 :
984 : Datum
985 9 : int42mi(PG_FUNCTION_ARGS)
986 : {
987 9 : int32 arg1 = PG_GETARG_INT32(0);
988 9 : int16 arg2 = PG_GETARG_INT16(1);
989 : int32 result;
990 :
991 9 : result = arg1 - arg2;
992 :
993 : /*
994 : * Overflow check. If the inputs are of the same sign then their
995 : * difference cannot overflow. If they are of different signs then the
996 : * result should be of the same sign as the first input.
997 : */
998 9 : if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
999 1 : ereport(ERROR,
1000 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1001 : errmsg("integer out of range")));
1002 8 : PG_RETURN_INT32(result);
1003 : }
1004 :
1005 : Datum
1006 9 : int42mul(PG_FUNCTION_ARGS)
1007 : {
1008 9 : int32 arg1 = PG_GETARG_INT32(0);
1009 9 : int16 arg2 = PG_GETARG_INT16(1);
1010 : int32 result;
1011 :
1012 9 : result = arg1 * arg2;
1013 :
1014 : /*
1015 : * Overflow check. We basically check to see if result / arg1 gives arg2
1016 : * again. There is one case where this fails: arg1 = 0 (which cannot
1017 : * overflow).
1018 : *
1019 : * Since the division is likely much more expensive than the actual
1020 : * multiplication, we'd like to skip it where possible. The best bang for
1021 : * the buck seems to be to check whether both inputs are in the int16
1022 : * range; if so, no overflow is possible.
1023 : */
1024 15 : if (!(arg1 >= (int32) SHRT_MIN && arg1 <= (int32) SHRT_MAX) &&
1025 6 : result / arg1 != arg2)
1026 2 : ereport(ERROR,
1027 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1028 : errmsg("integer out of range")));
1029 7 : PG_RETURN_INT32(result);
1030 : }
1031 :
1032 : Datum
1033 8 : int42div(PG_FUNCTION_ARGS)
1034 : {
1035 8 : int32 arg1 = PG_GETARG_INT32(0);
1036 8 : int16 arg2 = PG_GETARG_INT16(1);
1037 : int32 result;
1038 :
1039 8 : if (arg2 == 0)
1040 : {
1041 1 : ereport(ERROR,
1042 : (errcode(ERRCODE_DIVISION_BY_ZERO),
1043 : errmsg("division by zero")));
1044 : /* ensure compiler realizes we mustn't reach the division (gcc bug) */
1045 : PG_RETURN_NULL();
1046 : }
1047 :
1048 : /*
1049 : * INT_MIN / -1 is problematic, since the result can't be represented on a
1050 : * two's-complement machine. Some machines produce INT_MIN, some produce
1051 : * zero, some throw an exception. We can dodge the problem by recognizing
1052 : * that division by -1 is the same as negation.
1053 : */
1054 7 : if (arg2 == -1)
1055 : {
1056 1 : result = -arg1;
1057 : /* overflow check (needed for INT_MIN) */
1058 1 : if (arg1 != 0 && SAMESIGN(result, arg1))
1059 1 : ereport(ERROR,
1060 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1061 : errmsg("integer out of range")));
1062 0 : PG_RETURN_INT32(result);
1063 : }
1064 :
1065 : /* No overflow is possible */
1066 :
1067 6 : result = arg1 / arg2;
1068 :
1069 6 : PG_RETURN_INT32(result);
1070 : }
1071 :
1072 : Datum
1073 283884 : int4mod(PG_FUNCTION_ARGS)
1074 : {
1075 283884 : int32 arg1 = PG_GETARG_INT32(0);
1076 283884 : int32 arg2 = PG_GETARG_INT32(1);
1077 :
1078 283884 : if (arg2 == 0)
1079 : {
1080 0 : ereport(ERROR,
1081 : (errcode(ERRCODE_DIVISION_BY_ZERO),
1082 : errmsg("division by zero")));
1083 : /* ensure compiler realizes we mustn't reach the division (gcc bug) */
1084 : PG_RETURN_NULL();
1085 : }
1086 :
1087 : /*
1088 : * Some machines throw a floating-point exception for INT_MIN % -1, which
1089 : * is a bit silly since the correct answer is perfectly well-defined,
1090 : * namely zero.
1091 : */
1092 283884 : if (arg2 == -1)
1093 2 : PG_RETURN_INT32(0);
1094 :
1095 : /* No overflow is possible */
1096 :
1097 283882 : PG_RETURN_INT32(arg1 % arg2);
1098 : }
1099 :
1100 : Datum
1101 6 : int2mod(PG_FUNCTION_ARGS)
1102 : {
1103 6 : int16 arg1 = PG_GETARG_INT16(0);
1104 6 : int16 arg2 = PG_GETARG_INT16(1);
1105 :
1106 6 : if (arg2 == 0)
1107 : {
1108 0 : ereport(ERROR,
1109 : (errcode(ERRCODE_DIVISION_BY_ZERO),
1110 : errmsg("division by zero")));
1111 : /* ensure compiler realizes we mustn't reach the division (gcc bug) */
1112 : PG_RETURN_NULL();
1113 : }
1114 :
1115 : /*
1116 : * Some machines throw a floating-point exception for INT_MIN % -1, which
1117 : * is a bit silly since the correct answer is perfectly well-defined,
1118 : * namely zero. (It's not clear this ever happens when dealing with
1119 : * int16, but we might as well have the test for safety.)
1120 : */
1121 6 : if (arg2 == -1)
1122 1 : PG_RETURN_INT16(0);
1123 :
1124 : /* No overflow is possible */
1125 :
1126 5 : PG_RETURN_INT16(arg1 % arg2);
1127 : }
1128 :
1129 :
1130 : /* int[24]abs()
1131 : * Absolute value
1132 : */
1133 : Datum
1134 20042 : int4abs(PG_FUNCTION_ARGS)
1135 : {
1136 20042 : int32 arg1 = PG_GETARG_INT32(0);
1137 : int32 result;
1138 :
1139 20042 : result = (arg1 < 0) ? -arg1 : arg1;
1140 : /* overflow check (needed for INT_MIN) */
1141 20042 : if (result < 0)
1142 0 : ereport(ERROR,
1143 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1144 : errmsg("integer out of range")));
1145 20042 : PG_RETURN_INT32(result);
1146 : }
1147 :
1148 : Datum
1149 5 : int2abs(PG_FUNCTION_ARGS)
1150 : {
1151 5 : int16 arg1 = PG_GETARG_INT16(0);
1152 : int16 result;
1153 :
1154 5 : result = (arg1 < 0) ? -arg1 : arg1;
1155 : /* overflow check (needed for SHRT_MIN) */
1156 5 : if (result < 0)
1157 0 : ereport(ERROR,
1158 : (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1159 : errmsg("smallint out of range")));
1160 5 : PG_RETURN_INT16(result);
1161 : }
1162 :
1163 : Datum
1164 67 : int2larger(PG_FUNCTION_ARGS)
1165 : {
1166 67 : int16 arg1 = PG_GETARG_INT16(0);
1167 67 : int16 arg2 = PG_GETARG_INT16(1);
1168 :
1169 67 : PG_RETURN_INT16((arg1 > arg2) ? arg1 : arg2);
1170 : }
1171 :
1172 : Datum
1173 0 : int2smaller(PG_FUNCTION_ARGS)
1174 : {
1175 0 : int16 arg1 = PG_GETARG_INT16(0);
1176 0 : int16 arg2 = PG_GETARG_INT16(1);
1177 :
1178 0 : PG_RETURN_INT16((arg1 < arg2) ? arg1 : arg2);
1179 : }
1180 :
1181 : Datum
1182 12564 : int4larger(PG_FUNCTION_ARGS)
1183 : {
1184 12564 : int32 arg1 = PG_GETARG_INT32(0);
1185 12564 : int32 arg2 = PG_GETARG_INT32(1);
1186 :
1187 12564 : PG_RETURN_INT32((arg1 > arg2) ? arg1 : arg2);
1188 : }
1189 :
1190 : Datum
1191 10106 : int4smaller(PG_FUNCTION_ARGS)
1192 : {
1193 10106 : int32 arg1 = PG_GETARG_INT32(0);
1194 10106 : int32 arg2 = PG_GETARG_INT32(1);
1195 :
1196 10106 : PG_RETURN_INT32((arg1 < arg2) ? arg1 : arg2);
1197 : }
1198 :
1199 : /*
1200 : * Bit-pushing operators
1201 : *
1202 : * int[24]and - returns arg1 & arg2
1203 : * int[24]or - returns arg1 | arg2
1204 : * int[24]xor - returns arg1 # arg2
1205 : * int[24]not - returns ~arg1
1206 : * int[24]shl - returns arg1 << arg2
1207 : * int[24]shr - returns arg1 >> arg2
1208 : */
1209 :
1210 : Datum
1211 168 : int4and(PG_FUNCTION_ARGS)
1212 : {
1213 168 : int32 arg1 = PG_GETARG_INT32(0);
1214 168 : int32 arg2 = PG_GETARG_INT32(1);
1215 :
1216 168 : PG_RETURN_INT32(arg1 & arg2);
1217 : }
1218 :
1219 : Datum
1220 3 : int4or(PG_FUNCTION_ARGS)
1221 : {
1222 3 : int32 arg1 = PG_GETARG_INT32(0);
1223 3 : int32 arg2 = PG_GETARG_INT32(1);
1224 :
1225 3 : PG_RETURN_INT32(arg1 | arg2);
1226 : }
1227 :
1228 : Datum
1229 0 : int4xor(PG_FUNCTION_ARGS)
1230 : {
1231 0 : int32 arg1 = PG_GETARG_INT32(0);
1232 0 : int32 arg2 = PG_GETARG_INT32(1);
1233 :
1234 0 : PG_RETURN_INT32(arg1 ^ arg2);
1235 : }
1236 :
1237 : Datum
1238 2 : int4shl(PG_FUNCTION_ARGS)
1239 : {
1240 2 : int32 arg1 = PG_GETARG_INT32(0);
1241 2 : int32 arg2 = PG_GETARG_INT32(1);
1242 :
1243 2 : PG_RETURN_INT32(arg1 << arg2);
1244 : }
1245 :
1246 : Datum
1247 0 : int4shr(PG_FUNCTION_ARGS)
1248 : {
1249 0 : int32 arg1 = PG_GETARG_INT32(0);
1250 0 : int32 arg2 = PG_GETARG_INT32(1);
1251 :
1252 0 : PG_RETURN_INT32(arg1 >> arg2);
1253 : }
1254 :
1255 : Datum
1256 0 : int4not(PG_FUNCTION_ARGS)
1257 : {
1258 0 : int32 arg1 = PG_GETARG_INT32(0);
1259 :
1260 0 : PG_RETURN_INT32(~arg1);
1261 : }
1262 :
1263 : Datum
1264 4 : int2and(PG_FUNCTION_ARGS)
1265 : {
1266 4 : int16 arg1 = PG_GETARG_INT16(0);
1267 4 : int16 arg2 = PG_GETARG_INT16(1);
1268 :
1269 4 : PG_RETURN_INT16(arg1 & arg2);
1270 : }
1271 :
1272 : Datum
1273 4 : int2or(PG_FUNCTION_ARGS)
1274 : {
1275 4 : int16 arg1 = PG_GETARG_INT16(0);
1276 4 : int16 arg2 = PG_GETARG_INT16(1);
1277 :
1278 4 : PG_RETURN_INT16(arg1 | arg2);
1279 : }
1280 :
1281 : Datum
1282 0 : int2xor(PG_FUNCTION_ARGS)
1283 : {
1284 0 : int16 arg1 = PG_GETARG_INT16(0);
1285 0 : int16 arg2 = PG_GETARG_INT16(1);
1286 :
1287 0 : PG_RETURN_INT16(arg1 ^ arg2);
1288 : }
1289 :
1290 : Datum
1291 0 : int2not(PG_FUNCTION_ARGS)
1292 : {
1293 0 : int16 arg1 = PG_GETARG_INT16(0);
1294 :
1295 0 : PG_RETURN_INT16(~arg1);
1296 : }
1297 :
1298 :
1299 : Datum
1300 2 : int2shl(PG_FUNCTION_ARGS)
1301 : {
1302 2 : int16 arg1 = PG_GETARG_INT16(0);
1303 2 : int32 arg2 = PG_GETARG_INT32(1);
1304 :
1305 2 : PG_RETURN_INT16(arg1 << arg2);
1306 : }
1307 :
1308 : Datum
1309 0 : int2shr(PG_FUNCTION_ARGS)
1310 : {
1311 0 : int16 arg1 = PG_GETARG_INT16(0);
1312 0 : int32 arg2 = PG_GETARG_INT32(1);
1313 :
1314 0 : PG_RETURN_INT16(arg1 >> arg2);
1315 : }
1316 :
1317 : /*
1318 : * non-persistent numeric series generator
1319 : */
1320 : Datum
1321 667913 : generate_series_int4(PG_FUNCTION_ARGS)
1322 : {
1323 667913 : return generate_series_step_int4(fcinfo);
1324 : }
1325 :
1326 : Datum
1327 668034 : generate_series_step_int4(PG_FUNCTION_ARGS)
1328 : {
1329 : FuncCallContext *funcctx;
1330 : generate_series_fctx *fctx;
1331 : int32 result;
1332 : MemoryContext oldcontext;
1333 :
1334 : /* stuff done only on the first call of the function */
1335 668034 : if (SRF_IS_FIRSTCALL())
1336 : {
1337 10654 : int32 start = PG_GETARG_INT32(0);
1338 10654 : int32 finish = PG_GETARG_INT32(1);
1339 10654 : int32 step = 1;
1340 :
1341 : /* see if we were given an explicit step size */
1342 10654 : if (PG_NARGS() == 3)
1343 26 : step = PG_GETARG_INT32(2);
1344 10654 : if (step == 0)
1345 0 : ereport(ERROR,
1346 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1347 : errmsg("step size cannot equal zero")));
1348 :
1349 : /* create a function context for cross-call persistence */
1350 10654 : funcctx = SRF_FIRSTCALL_INIT();
1351 :
1352 : /*
1353 : * switch to memory context appropriate for multiple function calls
1354 : */
1355 10654 : oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1356 :
1357 : /* allocate memory for user context */
1358 10654 : fctx = (generate_series_fctx *) palloc(sizeof(generate_series_fctx));
1359 :
1360 : /*
1361 : * Use fctx to keep state from call to call. Seed current with the
1362 : * original start value
1363 : */
1364 10654 : fctx->current = start;
1365 10654 : fctx->finish = finish;
1366 10654 : fctx->step = step;
1367 :
1368 10654 : funcctx->user_fctx = fctx;
1369 10654 : MemoryContextSwitchTo(oldcontext);
1370 : }
1371 :
1372 : /* stuff done on every call of the function */
1373 668034 : funcctx = SRF_PERCALL_SETUP();
1374 :
1375 : /*
1376 : * get the saved state and use current as the result for this iteration
1377 : */
1378 668034 : fctx = funcctx->user_fctx;
1379 668034 : result = fctx->current;
1380 :
1381 678680 : if ((fctx->step > 0 && fctx->current <= fctx->finish) ||
1382 10646 : (fctx->step < 0 && fctx->current >= fctx->finish))
1383 : {
1384 : /* increment current in preparation for next iteration */
1385 657388 : fctx->current += fctx->step;
1386 :
1387 : /* if next-value computation overflows, this is the final result */
1388 657388 : if (SAMESIGN(result, fctx->step) && !SAMESIGN(result, fctx->current))
1389 0 : fctx->step = 0;
1390 :
1391 : /* do when there is more left to send */
1392 657388 : SRF_RETURN_NEXT(funcctx, Int32GetDatum(result));
1393 : }
1394 : else
1395 : /* do when there is no more left */
1396 10646 : SRF_RETURN_DONE(funcctx);
1397 : }
|