1 /*-------------------------------------------------------------------------
4 * Functions for the built-in integer types (except int8).
6 * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * $PostgreSQL: pgsql/src/backend/utils/adt/int.c,v 1.75 2006/10/04 00:29:59 momjian Exp $
13 *-------------------------------------------------------------------------
18 * int2in, int2out, int2recv, int2send
19 * int4in, int4out, int4recv, int4send
20 * int2vectorin, int2vectorout, int2vectorrecv, int2vectorsend
21 * Conversion routines:
22 * itoi, int2_text, int4_text
24 * inteq, intne, intlt, intle, intgt, intge
25 * Arithmetic operators:
26 * intpl, intmi, int4mul, intdiv
28 * Arithmetic operators:
36 #include "catalog/pg_type.h"
38 #include "libpq/pqformat.h"
39 #include "utils/array.h"
40 #include "utils/builtins.h"
43 #define SAMESIGN(a,b) (((a) < 0) == ((b) < 0))
45 #define Int2VectorSize(n) (offsetof(int2vector, values) + (n) * sizeof(int2))
52 } generate_series_fctx;
55 /*****************************************************************************
57 *****************************************************************************/
60 * int2in - converts "num" to short
63 int2in(PG_FUNCTION_ARGS)
65 char *num = PG_GETARG_CSTRING(0);
67 PG_RETURN_INT16(pg_atoi(num, sizeof(int16), '\0'));
71 * int2out - converts short to "num"
74 int2out(PG_FUNCTION_ARGS)
76 int16 arg1 = PG_GETARG_INT16(0);
77 char *result = (char *) palloc(7); /* sign, 5 digits, '\0' */
79 pg_itoa(arg1, result);
80 PG_RETURN_CSTRING(result);
84 * int2recv - converts external binary format to int2
87 int2recv(PG_FUNCTION_ARGS)
89 StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
91 PG_RETURN_INT16((int16) pq_getmsgint(buf, sizeof(int16)));
95 * int2send - converts int2 to binary format
98 int2send(PG_FUNCTION_ARGS)
100 int16 arg1 = PG_GETARG_INT16(0);
103 pq_begintypsend(&buf);
104 pq_sendint(&buf, arg1, sizeof(int16));
105 PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
109 * construct int2vector given a raw array of int2s
111 * If int2s is NULL then caller must fill values[] afterward
114 buildint2vector(const int2 *int2s, int n)
118 result = (int2vector *) palloc0(Int2VectorSize(n));
121 memcpy(result->values, int2s, n * sizeof(int2));
124 * Attach standard array header. For historical reasons, we set the index
125 * lower bound to 0 not 1.
127 result->size = Int2VectorSize(n);
129 result->dataoffset = 0; /* never any nulls */
130 result->elemtype = INT2OID;
138 * int2vectorin - converts "num num ..." to internal form
141 int2vectorin(PG_FUNCTION_ARGS)
143 char *intString = PG_GETARG_CSTRING(0);
147 result = (int2vector *) palloc0(Int2VectorSize(FUNC_MAX_ARGS));
149 for (n = 0; *intString && n < FUNC_MAX_ARGS; n++)
151 if (sscanf(intString, "%hd", &result->values[n]) != 1)
153 while (*intString && isspace((unsigned char) *intString))
155 while (*intString && !isspace((unsigned char) *intString))
158 while (*intString && isspace((unsigned char) *intString))
162 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
163 errmsg("int2vector has too many elements")));
165 result->size = Int2VectorSize(n);
167 result->dataoffset = 0; /* never any nulls */
168 result->elemtype = INT2OID;
172 PG_RETURN_POINTER(result);
176 * int2vectorout - converts internal form to "num num ..."
179 int2vectorout(PG_FUNCTION_ARGS)
181 int2vector *int2Array = (int2vector *) PG_GETARG_POINTER(0);
183 nnums = int2Array->dim1;
187 /* assumes sign, 5 digits, ' ' */
188 rp = result = (char *) palloc(nnums * 7 + 1);
189 for (num = 0; num < nnums; num++)
193 pg_itoa(int2Array->values[num], rp);
194 while (*++rp != '\0')
198 PG_RETURN_CSTRING(result);
202 * int2vectorrecv - converts external binary format to int2vector
205 int2vectorrecv(PG_FUNCTION_ARGS)
207 StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
208 FunctionCallInfoData locfcinfo;
212 * Normally one would call array_recv() using DirectFunctionCall3, but
213 * that does not work since array_recv wants to cache some data using
214 * fcinfo->flinfo->fn_extra. So we need to pass it our own flinfo
217 InitFunctionCallInfoData(locfcinfo, fcinfo->flinfo, 3, NULL, NULL);
219 locfcinfo.arg[0] = PointerGetDatum(buf);
220 locfcinfo.arg[1] = ObjectIdGetDatum(INT2OID);
221 locfcinfo.arg[2] = Int32GetDatum(-1);
222 locfcinfo.argnull[0] = false;
223 locfcinfo.argnull[1] = false;
224 locfcinfo.argnull[2] = false;
226 result = (int2vector *) DatumGetPointer(array_recv(&locfcinfo));
228 Assert(!locfcinfo.isnull);
230 /* sanity checks: int2vector must be 1-D, no nulls */
231 if (ARR_NDIM(result) != 1 ||
232 ARR_HASNULL(result) ||
233 ARR_ELEMTYPE(result) != INT2OID)
235 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
236 errmsg("invalid int2vector data")));
237 PG_RETURN_POINTER(result);
241 * int2vectorsend - converts int2vector to binary format
244 int2vectorsend(PG_FUNCTION_ARGS)
246 return array_send(fcinfo);
250 * We don't have a complete set of int2vector support routines,
251 * but we need int2vectoreq for catcache indexing.
254 int2vectoreq(PG_FUNCTION_ARGS)
256 int2vector *a = (int2vector *) PG_GETARG_POINTER(0);
257 int2vector *b = (int2vector *) PG_GETARG_POINTER(1);
259 if (a->dim1 != b->dim1)
260 PG_RETURN_BOOL(false);
261 PG_RETURN_BOOL(memcmp(a->values, b->values, a->dim1 * sizeof(int2)) == 0);
265 /*****************************************************************************
267 *****************************************************************************/
270 * int4in - converts "num" to int4
273 int4in(PG_FUNCTION_ARGS)
275 char *num = PG_GETARG_CSTRING(0);
277 PG_RETURN_INT32(pg_atoi(num, sizeof(int32), '\0'));
281 * int4out - converts int4 to "num"
284 int4out(PG_FUNCTION_ARGS)
286 int32 arg1 = PG_GETARG_INT32(0);
287 char *result = (char *) palloc(12); /* sign, 10 digits, '\0' */
289 pg_ltoa(arg1, result);
290 PG_RETURN_CSTRING(result);
294 * int4recv - converts external binary format to int4
297 int4recv(PG_FUNCTION_ARGS)
299 StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
301 PG_RETURN_INT32((int32) pq_getmsgint(buf, sizeof(int32)));
305 * int4send - converts int4 to binary format
308 int4send(PG_FUNCTION_ARGS)
310 int32 arg1 = PG_GETARG_INT32(0);
313 pq_begintypsend(&buf);
314 pq_sendint(&buf, arg1, sizeof(int32));
315 PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
320 * ===================
321 * CONVERSION ROUTINES
322 * ===================
326 i2toi4(PG_FUNCTION_ARGS)
328 int16 arg1 = PG_GETARG_INT16(0);
330 PG_RETURN_INT32((int32) arg1);
334 i4toi2(PG_FUNCTION_ARGS)
336 int32 arg1 = PG_GETARG_INT32(0);
338 if (arg1 < SHRT_MIN || arg1 > SHRT_MAX)
340 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
341 errmsg("smallint out of range")));
343 PG_RETURN_INT16((int16) arg1);
347 int2_text(PG_FUNCTION_ARGS)
349 int16 arg1 = PG_GETARG_INT16(0);
350 text *result = (text *) palloc(7 + VARHDRSZ); /* sign,5 digits, '\0' */
352 pg_itoa(arg1, VARDATA(result));
353 VARATT_SIZEP(result) = strlen(VARDATA(result)) + VARHDRSZ;
354 PG_RETURN_TEXT_P(result);
358 text_int2(PG_FUNCTION_ARGS)
360 text *string = PG_GETARG_TEXT_P(0);
365 len = VARSIZE(string) - VARHDRSZ;
367 str = palloc(len + 1);
368 memcpy(str, VARDATA(string), len);
371 result = DirectFunctionCall1(int2in, CStringGetDatum(str));
378 int4_text(PG_FUNCTION_ARGS)
380 int32 arg1 = PG_GETARG_INT32(0);
381 text *result = (text *) palloc(12 + VARHDRSZ); /* sign,10 digits,'\0' */
383 pg_ltoa(arg1, VARDATA(result));
384 VARATT_SIZEP(result) = strlen(VARDATA(result)) + VARHDRSZ;
385 PG_RETURN_TEXT_P(result);
389 text_int4(PG_FUNCTION_ARGS)
391 text *string = PG_GETARG_TEXT_P(0);
396 len = VARSIZE(string) - VARHDRSZ;
398 str = palloc(len + 1);
399 memcpy(str, VARDATA(string), len);
402 result = DirectFunctionCall1(int4in, CStringGetDatum(str));
408 /* Cast int4 -> bool */
410 int4_bool(PG_FUNCTION_ARGS)
412 if (PG_GETARG_INT32(0) == 0)
413 PG_RETURN_BOOL(false);
415 PG_RETURN_BOOL(true);
418 /* Cast bool -> int4 */
420 bool_int4(PG_FUNCTION_ARGS)
422 if (PG_GETARG_BOOL(0) == false)
429 * ============================
430 * COMPARISON OPERATOR ROUTINES
431 * ============================
435 * inteq - returns 1 iff arg1 == arg2
436 * intne - returns 1 iff arg1 != arg2
437 * intlt - returns 1 iff arg1 < arg2
438 * intle - returns 1 iff arg1 <= arg2
439 * intgt - returns 1 iff arg1 > arg2
440 * intge - returns 1 iff arg1 >= arg2
444 int4eq(PG_FUNCTION_ARGS)
446 int32 arg1 = PG_GETARG_INT32(0);
447 int32 arg2 = PG_GETARG_INT32(1);
449 PG_RETURN_BOOL(arg1 == arg2);
453 int4ne(PG_FUNCTION_ARGS)
455 int32 arg1 = PG_GETARG_INT32(0);
456 int32 arg2 = PG_GETARG_INT32(1);
458 PG_RETURN_BOOL(arg1 != arg2);
462 int4lt(PG_FUNCTION_ARGS)
464 int32 arg1 = PG_GETARG_INT32(0);
465 int32 arg2 = PG_GETARG_INT32(1);
467 PG_RETURN_BOOL(arg1 < arg2);
471 int4le(PG_FUNCTION_ARGS)
473 int32 arg1 = PG_GETARG_INT32(0);
474 int32 arg2 = PG_GETARG_INT32(1);
476 PG_RETURN_BOOL(arg1 <= arg2);
480 int4gt(PG_FUNCTION_ARGS)
482 int32 arg1 = PG_GETARG_INT32(0);
483 int32 arg2 = PG_GETARG_INT32(1);
485 PG_RETURN_BOOL(arg1 > arg2);
489 int4ge(PG_FUNCTION_ARGS)
491 int32 arg1 = PG_GETARG_INT32(0);
492 int32 arg2 = PG_GETARG_INT32(1);
494 PG_RETURN_BOOL(arg1 >= arg2);
498 int2eq(PG_FUNCTION_ARGS)
500 int16 arg1 = PG_GETARG_INT16(0);
501 int16 arg2 = PG_GETARG_INT16(1);
503 PG_RETURN_BOOL(arg1 == arg2);
507 int2ne(PG_FUNCTION_ARGS)
509 int16 arg1 = PG_GETARG_INT16(0);
510 int16 arg2 = PG_GETARG_INT16(1);
512 PG_RETURN_BOOL(arg1 != arg2);
516 int2lt(PG_FUNCTION_ARGS)
518 int16 arg1 = PG_GETARG_INT16(0);
519 int16 arg2 = PG_GETARG_INT16(1);
521 PG_RETURN_BOOL(arg1 < arg2);
525 int2le(PG_FUNCTION_ARGS)
527 int16 arg1 = PG_GETARG_INT16(0);
528 int16 arg2 = PG_GETARG_INT16(1);
530 PG_RETURN_BOOL(arg1 <= arg2);
534 int2gt(PG_FUNCTION_ARGS)
536 int16 arg1 = PG_GETARG_INT16(0);
537 int16 arg2 = PG_GETARG_INT16(1);
539 PG_RETURN_BOOL(arg1 > arg2);
543 int2ge(PG_FUNCTION_ARGS)
545 int16 arg1 = PG_GETARG_INT16(0);
546 int16 arg2 = PG_GETARG_INT16(1);
548 PG_RETURN_BOOL(arg1 >= arg2);
552 int24eq(PG_FUNCTION_ARGS)
554 int16 arg1 = PG_GETARG_INT16(0);
555 int32 arg2 = PG_GETARG_INT32(1);
557 PG_RETURN_BOOL(arg1 == arg2);
561 int24ne(PG_FUNCTION_ARGS)
563 int16 arg1 = PG_GETARG_INT16(0);
564 int32 arg2 = PG_GETARG_INT32(1);
566 PG_RETURN_BOOL(arg1 != arg2);
570 int24lt(PG_FUNCTION_ARGS)
572 int16 arg1 = PG_GETARG_INT16(0);
573 int32 arg2 = PG_GETARG_INT32(1);
575 PG_RETURN_BOOL(arg1 < arg2);
579 int24le(PG_FUNCTION_ARGS)
581 int16 arg1 = PG_GETARG_INT16(0);
582 int32 arg2 = PG_GETARG_INT32(1);
584 PG_RETURN_BOOL(arg1 <= arg2);
588 int24gt(PG_FUNCTION_ARGS)
590 int16 arg1 = PG_GETARG_INT16(0);
591 int32 arg2 = PG_GETARG_INT32(1);
593 PG_RETURN_BOOL(arg1 > arg2);
597 int24ge(PG_FUNCTION_ARGS)
599 int16 arg1 = PG_GETARG_INT16(0);
600 int32 arg2 = PG_GETARG_INT32(1);
602 PG_RETURN_BOOL(arg1 >= arg2);
606 int42eq(PG_FUNCTION_ARGS)
608 int32 arg1 = PG_GETARG_INT32(0);
609 int16 arg2 = PG_GETARG_INT16(1);
611 PG_RETURN_BOOL(arg1 == arg2);
615 int42ne(PG_FUNCTION_ARGS)
617 int32 arg1 = PG_GETARG_INT32(0);
618 int16 arg2 = PG_GETARG_INT16(1);
620 PG_RETURN_BOOL(arg1 != arg2);
624 int42lt(PG_FUNCTION_ARGS)
626 int32 arg1 = PG_GETARG_INT32(0);
627 int16 arg2 = PG_GETARG_INT16(1);
629 PG_RETURN_BOOL(arg1 < arg2);
633 int42le(PG_FUNCTION_ARGS)
635 int32 arg1 = PG_GETARG_INT32(0);
636 int16 arg2 = PG_GETARG_INT16(1);
638 PG_RETURN_BOOL(arg1 <= arg2);
642 int42gt(PG_FUNCTION_ARGS)
644 int32 arg1 = PG_GETARG_INT32(0);
645 int16 arg2 = PG_GETARG_INT16(1);
647 PG_RETURN_BOOL(arg1 > arg2);
651 int42ge(PG_FUNCTION_ARGS)
653 int32 arg1 = PG_GETARG_INT32(0);
654 int16 arg2 = PG_GETARG_INT16(1);
656 PG_RETURN_BOOL(arg1 >= arg2);
660 * int[24]pl - returns arg1 + arg2
661 * int[24]mi - returns arg1 - arg2
662 * int[24]mul - returns arg1 * arg2
663 * int[24]div - returns arg1 / arg2
667 int4um(PG_FUNCTION_ARGS)
669 int32 arg = PG_GETARG_INT32(0);
673 /* overflow check (needed for INT_MIN) */
674 if (arg != 0 && SAMESIGN(result, arg))
676 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
677 errmsg("integer out of range")));
678 PG_RETURN_INT32(result);
682 int4up(PG_FUNCTION_ARGS)
684 int32 arg = PG_GETARG_INT32(0);
686 PG_RETURN_INT32(arg);
690 int4pl(PG_FUNCTION_ARGS)
692 int32 arg1 = PG_GETARG_INT32(0);
693 int32 arg2 = PG_GETARG_INT32(1);
696 result = arg1 + arg2;
699 * Overflow check. If the inputs are of different signs then their sum
700 * cannot overflow. If the inputs are of the same sign, their sum had
701 * better be that sign too.
703 if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
705 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
706 errmsg("integer out of range")));
707 PG_RETURN_INT32(result);
711 int4mi(PG_FUNCTION_ARGS)
713 int32 arg1 = PG_GETARG_INT32(0);
714 int32 arg2 = PG_GETARG_INT32(1);
717 result = arg1 - arg2;
720 * Overflow check. If the inputs are of the same sign then their
721 * difference cannot overflow. If they are of different signs then the
722 * result should be of the same sign as the first input.
724 if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
726 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
727 errmsg("integer out of range")));
728 PG_RETURN_INT32(result);
732 int4mul(PG_FUNCTION_ARGS)
734 int32 arg1 = PG_GETARG_INT32(0);
735 int32 arg2 = PG_GETARG_INT32(1);
741 * Win32 doesn't throw a catchable exception for SELECT -2147483648 *
744 if (arg2 == -1 && arg1 == INT_MIN)
746 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
747 errmsg("integer out of range")));
750 result = arg1 * arg2;
753 * Overflow check. We basically check to see if result / arg2 gives arg1
754 * again. There are two cases where this fails: arg2 = 0 (which cannot
755 * overflow) and arg1 = INT_MIN, arg2 = -1 (where the division itself will
756 * overflow and thus incorrectly match).
758 * Since the division is likely much more expensive than the actual
759 * multiplication, we'd like to skip it where possible. The best bang for
760 * the buck seems to be to check whether both inputs are in the int16
761 * range; if so, no overflow is possible.
763 if (!(arg1 >= (int32) SHRT_MIN && arg1 <= (int32) SHRT_MAX &&
764 arg2 >= (int32) SHRT_MIN && arg2 <= (int32) SHRT_MAX) &&
766 (result / arg2 != arg1 || (arg2 == -1 && arg1 < 0 && result < 0)))
768 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
769 errmsg("integer out of range")));
770 PG_RETURN_INT32(result);
774 int4div(PG_FUNCTION_ARGS)
776 int32 arg1 = PG_GETARG_INT32(0);
777 int32 arg2 = PG_GETARG_INT32(1);
782 (errcode(ERRCODE_DIVISION_BY_ZERO),
783 errmsg("division by zero")));
788 * Win32 doesn't throw a catchable exception for SELECT -2147483648 /
791 if (arg2 == -1 && arg1 == INT_MIN)
793 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
794 errmsg("integer out of range")));
797 result = arg1 / arg2;
800 * Overflow check. The only possible overflow case is for arg1 = INT_MIN,
801 * arg2 = -1, where the correct result is -INT_MIN, which can't be
802 * represented on a two's-complement machine.
804 if (arg2 == -1 && arg1 < 0 && result < 0)
806 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
807 errmsg("integer out of range")));
808 PG_RETURN_INT32(result);
812 int4inc(PG_FUNCTION_ARGS)
814 int32 arg = PG_GETARG_INT32(0);
819 if (arg > 0 && result < 0)
821 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
822 errmsg("integer out of range")));
824 PG_RETURN_INT32(result);
828 int2um(PG_FUNCTION_ARGS)
830 int16 arg = PG_GETARG_INT16(0);
834 /* overflow check (needed for SHRT_MIN) */
835 if (arg != 0 && SAMESIGN(result, arg))
837 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
838 errmsg("smallint out of range")));
839 PG_RETURN_INT16(result);
843 int2up(PG_FUNCTION_ARGS)
845 int16 arg = PG_GETARG_INT16(0);
847 PG_RETURN_INT16(arg);
851 int2pl(PG_FUNCTION_ARGS)
853 int16 arg1 = PG_GETARG_INT16(0);
854 int16 arg2 = PG_GETARG_INT16(1);
857 result = arg1 + arg2;
860 * Overflow check. If the inputs are of different signs then their sum
861 * cannot overflow. If the inputs are of the same sign, their sum had
862 * better be that sign too.
864 if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
866 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
867 errmsg("smallint out of range")));
868 PG_RETURN_INT16(result);
872 int2mi(PG_FUNCTION_ARGS)
874 int16 arg1 = PG_GETARG_INT16(0);
875 int16 arg2 = PG_GETARG_INT16(1);
878 result = arg1 - arg2;
881 * Overflow check. If the inputs are of the same sign then their
882 * difference cannot overflow. If they are of different signs then the
883 * result should be of the same sign as the first input.
885 if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
887 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
888 errmsg("smallint out of range")));
889 PG_RETURN_INT16(result);
893 int2mul(PG_FUNCTION_ARGS)
895 int16 arg1 = PG_GETARG_INT16(0);
896 int16 arg2 = PG_GETARG_INT16(1);
900 * The most practical way to detect overflow is to do the arithmetic in
901 * int32 (so that the result can't overflow) and then do a range check.
903 result32 = (int32) arg1 *(int32) arg2;
905 if (result32 < SHRT_MIN || result32 > SHRT_MAX)
907 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
908 errmsg("smallint out of range")));
910 PG_RETURN_INT16((int16) result32);
914 int2div(PG_FUNCTION_ARGS)
916 int16 arg1 = PG_GETARG_INT16(0);
917 int16 arg2 = PG_GETARG_INT16(1);
922 (errcode(ERRCODE_DIVISION_BY_ZERO),
923 errmsg("division by zero")));
925 result = arg1 / arg2;
928 * Overflow check. The only possible overflow case is for arg1 =
929 * SHRT_MIN, arg2 = -1, where the correct result is -SHRT_MIN, which can't
930 * be represented on a two's-complement machine.
932 if (arg2 == -1 && arg1 < 0 && result < 0)
934 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
935 errmsg("smallint out of range")));
936 PG_RETURN_INT16(result);
940 int24pl(PG_FUNCTION_ARGS)
942 int16 arg1 = PG_GETARG_INT16(0);
943 int32 arg2 = PG_GETARG_INT32(1);
946 result = arg1 + arg2;
949 * Overflow check. If the inputs are of different signs then their sum
950 * cannot overflow. If the inputs are of the same sign, their sum had
951 * better be that sign too.
953 if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
955 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
956 errmsg("integer out of range")));
957 PG_RETURN_INT32(result);
961 int24mi(PG_FUNCTION_ARGS)
963 int16 arg1 = PG_GETARG_INT16(0);
964 int32 arg2 = PG_GETARG_INT32(1);
967 result = arg1 - arg2;
970 * Overflow check. If the inputs are of the same sign then their
971 * difference cannot overflow. If they are of different signs then the
972 * result should be of the same sign as the first input.
974 if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
976 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
977 errmsg("integer out of range")));
978 PG_RETURN_INT32(result);
982 int24mul(PG_FUNCTION_ARGS)
984 int16 arg1 = PG_GETARG_INT16(0);
985 int32 arg2 = PG_GETARG_INT32(1);
988 result = arg1 * arg2;
991 * Overflow check. We basically check to see if result / arg2 gives arg1
992 * again. There is one case where this fails: arg2 = 0 (which cannot
995 * Since the division is likely much more expensive than the actual
996 * multiplication, we'd like to skip it where possible. The best bang for
997 * the buck seems to be to check whether both inputs are in the int16
998 * range; if so, no overflow is possible.
1000 if (!(arg2 >= (int32) SHRT_MIN && arg2 <= (int32) SHRT_MAX) &&
1001 result / arg2 != arg1)
1003 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1004 errmsg("integer out of range")));
1005 PG_RETURN_INT32(result);
1009 int24div(PG_FUNCTION_ARGS)
1011 int16 arg1 = PG_GETARG_INT16(0);
1012 int32 arg2 = PG_GETARG_INT32(1);
1016 (errcode(ERRCODE_DIVISION_BY_ZERO),
1017 errmsg("division by zero")));
1018 /* No overflow is possible */
1019 PG_RETURN_INT32((int32) arg1 / arg2);
1023 int42pl(PG_FUNCTION_ARGS)
1025 int32 arg1 = PG_GETARG_INT32(0);
1026 int16 arg2 = PG_GETARG_INT16(1);
1029 result = arg1 + arg2;
1032 * Overflow check. If the inputs are of different signs then their sum
1033 * cannot overflow. If the inputs are of the same sign, their sum had
1034 * better be that sign too.
1036 if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
1038 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1039 errmsg("integer out of range")));
1040 PG_RETURN_INT32(result);
1044 int42mi(PG_FUNCTION_ARGS)
1046 int32 arg1 = PG_GETARG_INT32(0);
1047 int16 arg2 = PG_GETARG_INT16(1);
1050 result = arg1 - arg2;
1053 * Overflow check. If the inputs are of the same sign then their
1054 * difference cannot overflow. If they are of different signs then the
1055 * result should be of the same sign as the first input.
1057 if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
1059 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1060 errmsg("integer out of range")));
1061 PG_RETURN_INT32(result);
1065 int42mul(PG_FUNCTION_ARGS)
1067 int32 arg1 = PG_GETARG_INT32(0);
1068 int16 arg2 = PG_GETARG_INT16(1);
1071 result = arg1 * arg2;
1074 * Overflow check. We basically check to see if result / arg1 gives arg2
1075 * again. There is one case where this fails: arg1 = 0 (which cannot
1078 * Since the division is likely much more expensive than the actual
1079 * multiplication, we'd like to skip it where possible. The best bang for
1080 * the buck seems to be to check whether both inputs are in the int16
1081 * range; if so, no overflow is possible.
1083 if (!(arg1 >= (int32) SHRT_MIN && arg1 <= (int32) SHRT_MAX) &&
1084 result / arg1 != arg2)
1086 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1087 errmsg("integer out of range")));
1088 PG_RETURN_INT32(result);
1092 int42div(PG_FUNCTION_ARGS)
1094 int32 arg1 = PG_GETARG_INT32(0);
1095 int16 arg2 = PG_GETARG_INT16(1);
1100 (errcode(ERRCODE_DIVISION_BY_ZERO),
1101 errmsg("division by zero")));
1103 result = arg1 / arg2;
1106 * Overflow check. The only possible overflow case is for arg1 = INT_MIN,
1107 * arg2 = -1, where the correct result is -INT_MIN, which can't be
1108 * represented on a two's-complement machine.
1110 if (arg2 == -1 && arg1 < 0 && result < 0)
1112 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1113 errmsg("integer out of range")));
1114 PG_RETURN_INT32(result);
1118 int4mod(PG_FUNCTION_ARGS)
1120 int32 arg1 = PG_GETARG_INT32(0);
1121 int32 arg2 = PG_GETARG_INT32(1);
1125 (errcode(ERRCODE_DIVISION_BY_ZERO),
1126 errmsg("division by zero")));
1127 /* No overflow is possible */
1129 PG_RETURN_INT32(arg1 % arg2);
1133 int2mod(PG_FUNCTION_ARGS)
1135 int16 arg1 = PG_GETARG_INT16(0);
1136 int16 arg2 = PG_GETARG_INT16(1);
1140 (errcode(ERRCODE_DIVISION_BY_ZERO),
1141 errmsg("division by zero")));
1142 /* No overflow is possible */
1144 PG_RETURN_INT16(arg1 % arg2);
1148 int24mod(PG_FUNCTION_ARGS)
1150 int16 arg1 = PG_GETARG_INT16(0);
1151 int32 arg2 = PG_GETARG_INT32(1);
1155 (errcode(ERRCODE_DIVISION_BY_ZERO),
1156 errmsg("division by zero")));
1157 /* No overflow is possible */
1159 PG_RETURN_INT32(arg1 % arg2);
1163 int42mod(PG_FUNCTION_ARGS)
1165 int32 arg1 = PG_GETARG_INT32(0);
1166 int16 arg2 = PG_GETARG_INT16(1);
1170 (errcode(ERRCODE_DIVISION_BY_ZERO),
1171 errmsg("division by zero")));
1172 /* No overflow is possible */
1174 PG_RETURN_INT32(arg1 % arg2);
1182 int4abs(PG_FUNCTION_ARGS)
1184 int32 arg1 = PG_GETARG_INT32(0);
1187 result = (arg1 < 0) ? -arg1 : arg1;
1188 /* overflow check (needed for INT_MIN) */
1191 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1192 errmsg("integer out of range")));
1193 PG_RETURN_INT32(result);
1197 int2abs(PG_FUNCTION_ARGS)
1199 int16 arg1 = PG_GETARG_INT16(0);
1202 result = (arg1 < 0) ? -arg1 : arg1;
1203 /* overflow check (needed for SHRT_MIN) */
1206 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1207 errmsg("smallint out of range")));
1208 PG_RETURN_INT16(result);
1212 int2larger(PG_FUNCTION_ARGS)
1214 int16 arg1 = PG_GETARG_INT16(0);
1215 int16 arg2 = PG_GETARG_INT16(1);
1217 PG_RETURN_INT16((arg1 > arg2) ? arg1 : arg2);
1221 int2smaller(PG_FUNCTION_ARGS)
1223 int16 arg1 = PG_GETARG_INT16(0);
1224 int16 arg2 = PG_GETARG_INT16(1);
1226 PG_RETURN_INT16((arg1 < arg2) ? arg1 : arg2);
1230 int4larger(PG_FUNCTION_ARGS)
1232 int32 arg1 = PG_GETARG_INT32(0);
1233 int32 arg2 = PG_GETARG_INT32(1);
1235 PG_RETURN_INT32((arg1 > arg2) ? arg1 : arg2);
1239 int4smaller(PG_FUNCTION_ARGS)
1241 int32 arg1 = PG_GETARG_INT32(0);
1242 int32 arg2 = PG_GETARG_INT32(1);
1244 PG_RETURN_INT32((arg1 < arg2) ? arg1 : arg2);
1248 * Bit-pushing operators
1250 * int[24]and - returns arg1 & arg2
1251 * int[24]or - returns arg1 | arg2
1252 * int[24]xor - returns arg1 # arg2
1253 * int[24]not - returns ~arg1
1254 * int[24]shl - returns arg1 << arg2
1255 * int[24]shr - returns arg1 >> arg2
1259 int4and(PG_FUNCTION_ARGS)
1261 int32 arg1 = PG_GETARG_INT32(0);
1262 int32 arg2 = PG_GETARG_INT32(1);
1264 PG_RETURN_INT32(arg1 & arg2);
1268 int4or(PG_FUNCTION_ARGS)
1270 int32 arg1 = PG_GETARG_INT32(0);
1271 int32 arg2 = PG_GETARG_INT32(1);
1273 PG_RETURN_INT32(arg1 | arg2);
1277 int4xor(PG_FUNCTION_ARGS)
1279 int32 arg1 = PG_GETARG_INT32(0);
1280 int32 arg2 = PG_GETARG_INT32(1);
1282 PG_RETURN_INT32(arg1 ^ arg2);
1286 int4shl(PG_FUNCTION_ARGS)
1288 int32 arg1 = PG_GETARG_INT32(0);
1289 int32 arg2 = PG_GETARG_INT32(1);
1291 PG_RETURN_INT32(arg1 << arg2);
1295 int4shr(PG_FUNCTION_ARGS)
1297 int32 arg1 = PG_GETARG_INT32(0);
1298 int32 arg2 = PG_GETARG_INT32(1);
1300 PG_RETURN_INT32(arg1 >> arg2);
1304 int4not(PG_FUNCTION_ARGS)
1306 int32 arg1 = PG_GETARG_INT32(0);
1308 PG_RETURN_INT32(~arg1);
1312 int2and(PG_FUNCTION_ARGS)
1314 int16 arg1 = PG_GETARG_INT16(0);
1315 int16 arg2 = PG_GETARG_INT16(1);
1317 PG_RETURN_INT16(arg1 & arg2);
1321 int2or(PG_FUNCTION_ARGS)
1323 int16 arg1 = PG_GETARG_INT16(0);
1324 int16 arg2 = PG_GETARG_INT16(1);
1326 PG_RETURN_INT16(arg1 | arg2);
1330 int2xor(PG_FUNCTION_ARGS)
1332 int16 arg1 = PG_GETARG_INT16(0);
1333 int16 arg2 = PG_GETARG_INT16(1);
1335 PG_RETURN_INT16(arg1 ^ arg2);
1339 int2not(PG_FUNCTION_ARGS)
1341 int16 arg1 = PG_GETARG_INT16(0);
1343 PG_RETURN_INT16(~arg1);
1348 int2shl(PG_FUNCTION_ARGS)
1350 int16 arg1 = PG_GETARG_INT16(0);
1351 int32 arg2 = PG_GETARG_INT32(1);
1353 PG_RETURN_INT16(arg1 << arg2);
1357 int2shr(PG_FUNCTION_ARGS)
1359 int16 arg1 = PG_GETARG_INT16(0);
1360 int32 arg2 = PG_GETARG_INT32(1);
1362 PG_RETURN_INT16(arg1 >> arg2);
1366 * non-persistent numeric series generator
1369 generate_series_int4(PG_FUNCTION_ARGS)
1371 return generate_series_step_int4(fcinfo);
1375 generate_series_step_int4(PG_FUNCTION_ARGS)
1377 FuncCallContext *funcctx;
1378 generate_series_fctx *fctx;
1380 MemoryContext oldcontext;
1382 /* stuff done only on the first call of the function */
1383 if (SRF_IS_FIRSTCALL())
1385 int32 start = PG_GETARG_INT32(0);
1386 int32 finish = PG_GETARG_INT32(1);
1389 /* see if we were given an explicit step size */
1390 if (PG_NARGS() == 3)
1391 step = PG_GETARG_INT32(2);
1394 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1395 errmsg("step size may not equal zero")));
1397 /* create a function context for cross-call persistence */
1398 funcctx = SRF_FIRSTCALL_INIT();
1401 * switch to memory context appropriate for multiple function calls
1403 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1405 /* allocate memory for user context */
1406 fctx = (generate_series_fctx *) palloc(sizeof(generate_series_fctx));
1409 * Use fctx to keep state from call to call. Seed current with the
1410 * original start value
1412 fctx->current = start;
1413 fctx->finish = finish;
1416 funcctx->user_fctx = fctx;
1417 MemoryContextSwitchTo(oldcontext);
1420 /* stuff done on every call of the function */
1421 funcctx = SRF_PERCALL_SETUP();
1424 * get the saved state and use current as the result for this iteration
1426 fctx = funcctx->user_fctx;
1427 result = fctx->current;
1429 if ((fctx->step > 0 && fctx->current <= fctx->finish) ||
1430 (fctx->step < 0 && fctx->current >= fctx->finish))
1432 /* increment current in preparation for next iteration */
1433 fctx->current += fctx->step;
1435 /* do when there is more left to send */
1436 SRF_RETURN_NEXT(funcctx, Int32GetDatum(result));
1439 /* do when there is no more left */
1440 SRF_RETURN_DONE(funcctx);