|
7 | 7 | * Portions Copyright (c) 1994, Regents of the University of California
|
8 | 8 | *
|
9 | 9 | * IDENTIFICATION
|
10 |
| - * $PostgreSQL: pgsql/src/backend/utils/adt/int8.c,v 1.69 2008/04/21 00:26:45 tgl Exp $ |
| 10 | + * $PostgreSQL: pgsql/src/backend/utils/adt/int8.c,v 1.70 2008/06/17 19:10:56 tgl Exp $ |
11 | 11 | *
|
12 | 12 | *-------------------------------------------------------------------------
|
13 | 13 | */
|
@@ -922,6 +922,184 @@ int48div(PG_FUNCTION_ARGS)
|
922 | 922 | PG_RETURN_INT64((int64) arg1 / arg2);
|
923 | 923 | }
|
924 | 924 |
|
| 925 | +Datum |
| 926 | +int82pl(PG_FUNCTION_ARGS) |
| 927 | +{ |
| 928 | + int64 arg1 = PG_GETARG_INT64(0); |
| 929 | + int16 arg2 = PG_GETARG_INT16(1); |
| 930 | + int64 result; |
| 931 | + |
| 932 | + result = arg1 + arg2; |
| 933 | + |
| 934 | + /* |
| 935 | + * Overflow check. If the inputs are of different signs then their sum |
| 936 | + * cannot overflow. If the inputs are of the same sign, their sum had |
| 937 | + * better be that sign too. |
| 938 | + */ |
| 939 | + if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1)) |
| 940 | + ereport(ERROR, |
| 941 | + (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
| 942 | + errmsg("bigint out of range"))); |
| 943 | + PG_RETURN_INT64(result); |
| 944 | +} |
| 945 | + |
| 946 | +Datum |
| 947 | +int82mi(PG_FUNCTION_ARGS) |
| 948 | +{ |
| 949 | + int64 arg1 = PG_GETARG_INT64(0); |
| 950 | + int16 arg2 = PG_GETARG_INT16(1); |
| 951 | + int64 result; |
| 952 | + |
| 953 | + result = arg1 - arg2; |
| 954 | + |
| 955 | + /* |
| 956 | + * Overflow check. If the inputs are of the same sign then their |
| 957 | + * difference cannot overflow. If they are of different signs then the |
| 958 | + * result should be of the same sign as the first input. |
| 959 | + */ |
| 960 | + if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1)) |
| 961 | + ereport(ERROR, |
| 962 | + (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
| 963 | + errmsg("bigint out of range"))); |
| 964 | + PG_RETURN_INT64(result); |
| 965 | +} |
| 966 | + |
| 967 | +Datum |
| 968 | +int82mul(PG_FUNCTION_ARGS) |
| 969 | +{ |
| 970 | + int64 arg1 = PG_GETARG_INT64(0); |
| 971 | + int16 arg2 = PG_GETARG_INT16(1); |
| 972 | + int64 result; |
| 973 | + |
| 974 | + result = arg1 * arg2; |
| 975 | + |
| 976 | + /* |
| 977 | + * Overflow check. We basically check to see if result / arg1 gives arg2 |
| 978 | + * again. There is one case where this fails: arg1 = 0 (which cannot |
| 979 | + * overflow). |
| 980 | + * |
| 981 | + * Since the division is likely much more expensive than the actual |
| 982 | + * multiplication, we'd like to skip it where possible. The best bang for |
| 983 | + * the buck seems to be to check whether both inputs are in the int32 |
| 984 | + * range; if so, no overflow is possible. |
| 985 | + */ |
| 986 | + if (arg1 != (int64) ((int32) arg1) && |
| 987 | + result / arg1 != arg2) |
| 988 | + ereport(ERROR, |
| 989 | + (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
| 990 | + errmsg("bigint out of range"))); |
| 991 | + PG_RETURN_INT64(result); |
| 992 | +} |
| 993 | + |
| 994 | +Datum |
| 995 | +int82div(PG_FUNCTION_ARGS) |
| 996 | +{ |
| 997 | + int64 arg1 = PG_GETARG_INT64(0); |
| 998 | + int16 arg2 = PG_GETARG_INT16(1); |
| 999 | + int64 result; |
| 1000 | + |
| 1001 | + if (arg2 == 0) |
| 1002 | + ereport(ERROR, |
| 1003 | + (errcode(ERRCODE_DIVISION_BY_ZERO), |
| 1004 | + errmsg("division by zero"))); |
| 1005 | + |
| 1006 | + result = arg1 / arg2; |
| 1007 | + |
| 1008 | + /* |
| 1009 | + * Overflow check. The only possible overflow case is for arg1 = |
| 1010 | + * INT64_MIN, arg2 = -1, where the correct result is -INT64_MIN, which |
| 1011 | + * can't be represented on a two's-complement machine. |
| 1012 | + */ |
| 1013 | + if (arg2 == -1 && arg1 < 0 && result < 0) |
| 1014 | + ereport(ERROR, |
| 1015 | + (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
| 1016 | + errmsg("bigint out of range"))); |
| 1017 | + PG_RETURN_INT64(result); |
| 1018 | +} |
| 1019 | + |
| 1020 | +Datum |
| 1021 | +int28pl(PG_FUNCTION_ARGS) |
| 1022 | +{ |
| 1023 | + int16 arg1 = PG_GETARG_INT16(0); |
| 1024 | + int64 arg2 = PG_GETARG_INT64(1); |
| 1025 | + int64 result; |
| 1026 | + |
| 1027 | + result = arg1 + arg2; |
| 1028 | + |
| 1029 | + /* |
| 1030 | + * Overflow check. If the inputs are of different signs then their sum |
| 1031 | + * cannot overflow. If the inputs are of the same sign, their sum had |
| 1032 | + * better be that sign too. |
| 1033 | + */ |
| 1034 | + if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1)) |
| 1035 | + ereport(ERROR, |
| 1036 | + (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
| 1037 | + errmsg("bigint out of range"))); |
| 1038 | + PG_RETURN_INT64(result); |
| 1039 | +} |
| 1040 | + |
| 1041 | +Datum |
| 1042 | +int28mi(PG_FUNCTION_ARGS) |
| 1043 | +{ |
| 1044 | + int16 arg1 = PG_GETARG_INT16(0); |
| 1045 | + int64 arg2 = PG_GETARG_INT64(1); |
| 1046 | + int64 result; |
| 1047 | + |
| 1048 | + result = arg1 - arg2; |
| 1049 | + |
| 1050 | + /* |
| 1051 | + * Overflow check. If the inputs are of the same sign then their |
| 1052 | + * difference cannot overflow. If they are of different signs then the |
| 1053 | + * result should be of the same sign as the first input. |
| 1054 | + */ |
| 1055 | + if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1)) |
| 1056 | + ereport(ERROR, |
| 1057 | + (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
| 1058 | + errmsg("bigint out of range"))); |
| 1059 | + PG_RETURN_INT64(result); |
| 1060 | +} |
| 1061 | + |
| 1062 | +Datum |
| 1063 | +int28mul(PG_FUNCTION_ARGS) |
| 1064 | +{ |
| 1065 | + int16 arg1 = PG_GETARG_INT16(0); |
| 1066 | + int64 arg2 = PG_GETARG_INT64(1); |
| 1067 | + int64 result; |
| 1068 | + |
| 1069 | + result = arg1 * arg2; |
| 1070 | + |
| 1071 | + /* |
| 1072 | + * Overflow check. We basically check to see if result / arg2 gives arg1 |
| 1073 | + * again. There is one case where this fails: arg2 = 0 (which cannot |
| 1074 | + * overflow). |
| 1075 | + * |
| 1076 | + * Since the division is likely much more expensive than the actual |
| 1077 | + * multiplication, we'd like to skip it where possible. The best bang for |
| 1078 | + * the buck seems to be to check whether both inputs are in the int32 |
| 1079 | + * range; if so, no overflow is possible. |
| 1080 | + */ |
| 1081 | + if (arg2 != (int64) ((int32) arg2) && |
| 1082 | + result / arg2 != arg1) |
| 1083 | + ereport(ERROR, |
| 1084 | + (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
| 1085 | + errmsg("bigint out of range"))); |
| 1086 | + PG_RETURN_INT64(result); |
| 1087 | +} |
| 1088 | + |
| 1089 | +Datum |
| 1090 | +int28div(PG_FUNCTION_ARGS) |
| 1091 | +{ |
| 1092 | + int16 arg1 = PG_GETARG_INT16(0); |
| 1093 | + int64 arg2 = PG_GETARG_INT64(1); |
| 1094 | + |
| 1095 | + if (arg2 == 0) |
| 1096 | + ereport(ERROR, |
| 1097 | + (errcode(ERRCODE_DIVISION_BY_ZERO), |
| 1098 | + errmsg("division by zero"))); |
| 1099 | + /* No overflow is possible */ |
| 1100 | + PG_RETURN_INT64((int64) arg1 / arg2); |
| 1101 | +} |
| 1102 | + |
925 | 1103 | /* Binary arithmetics
|
926 | 1104 | *
|
927 | 1105 | * int8and - returns arg1 & arg2
|
|
0 commit comments