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