@@ -671,18 +671,6 @@ int4mul(PG_FUNCTION_ARGS)
671
671
int32 arg2 = PG_GETARG_INT32 (1 );
672
672
int32 result ;
673
673
674
- #ifdef WIN32
675
-
676
- /*
677
- * Win32 doesn't throw a catchable exception for SELECT -2147483648 *
678
- * (-1); -- INT_MIN
679
- */
680
- if (arg2 == -1 && arg1 == INT_MIN )
681
- ereport (ERROR ,
682
- (errcode (ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ),
683
- errmsg ("integer out of range" )));
684
- #endif
685
-
686
674
result = arg1 * arg2 ;
687
675
688
676
/*
@@ -699,7 +687,8 @@ int4mul(PG_FUNCTION_ARGS)
699
687
if (!(arg1 >= (int32 ) SHRT_MIN && arg1 <= (int32 ) SHRT_MAX &&
700
688
arg2 >= (int32 ) SHRT_MIN && arg2 <= (int32 ) SHRT_MAX ) &&
701
689
arg2 != 0 &&
702
- (result / arg2 != arg1 || (arg2 == -1 && arg1 < 0 && result < 0 )))
690
+ ((arg2 == -1 && arg1 < 0 && result < 0 ) ||
691
+ result / arg2 != arg1 ))
703
692
ereport (ERROR ,
704
693
(errcode (ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ),
705
694
errmsg ("integer out of range" )));
@@ -722,29 +711,27 @@ int4div(PG_FUNCTION_ARGS)
722
711
PG_RETURN_NULL ();
723
712
}
724
713
725
- #ifdef WIN32
726
-
727
714
/*
728
- * Win32 doesn't throw a catchable exception for SELECT -2147483648 /
729
- * (-1); -- INT_MIN
715
+ * INT_MIN / -1 is problematic, since the result can't be represented on a
716
+ * two's-complement machine. Some machines produce INT_MIN, some produce
717
+ * zero, some throw an exception. We can dodge the problem by recognizing
718
+ * that division by -1 is the same as negation.
730
719
*/
731
- if (arg2 == -1 && arg1 == INT_MIN )
732
- ereport (ERROR ,
733
- (errcode (ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ),
734
- errmsg ("integer out of range" )));
735
- #endif
720
+ if (arg2 == -1 )
721
+ {
722
+ result = - arg1 ;
723
+ /* overflow check (needed for INT_MIN) */
724
+ if (arg1 != 0 && SAMESIGN (result , arg1 ))
725
+ ereport (ERROR ,
726
+ (errcode (ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ),
727
+ errmsg ("integer out of range" )));
728
+ PG_RETURN_INT32 (result );
729
+ }
730
+
731
+ /* No overflow is possible */
736
732
737
733
result = arg1 / arg2 ;
738
734
739
- /*
740
- * Overflow check. The only possible overflow case is for arg1 = INT_MIN,
741
- * arg2 = -1, where the correct result is -INT_MIN, which can't be
742
- * represented on a two's-complement machine.
743
- */
744
- if (arg2 == -1 && arg1 < 0 && result < 0 )
745
- ereport (ERROR ,
746
- (errcode (ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ),
747
- errmsg ("integer out of range" )));
748
735
PG_RETURN_INT32 (result );
749
736
}
750
737
@@ -866,17 +853,27 @@ int2div(PG_FUNCTION_ARGS)
866
853
PG_RETURN_NULL ();
867
854
}
868
855
869
- result = arg1 / arg2 ;
870
-
871
856
/*
872
- * Overflow check. The only possible overflow case is for arg1 =
873
- * SHRT_MIN, arg2 = -1, where the correct result is -SHRT_MIN, which can't
874
- * be represented on a two's-complement machine.
857
+ * SHRT_MIN / -1 is problematic, since the result can't be represented on
858
+ * a two's-complement machine. Some machines produce SHRT_MIN, some
859
+ * produce zero, some throw an exception. We can dodge the problem by
860
+ * recognizing that division by -1 is the same as negation.
875
861
*/
876
- if (arg2 == -1 && arg1 < 0 && result < 0 )
877
- ereport (ERROR ,
878
- (errcode (ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ),
879
- errmsg ("smallint out of range" )));
862
+ if (arg2 == -1 )
863
+ {
864
+ result = - arg1 ;
865
+ /* overflow check (needed for SHRT_MIN) */
866
+ if (arg1 != 0 && SAMESIGN (result , arg1 ))
867
+ ereport (ERROR ,
868
+ (errcode (ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ),
869
+ errmsg ("smallint out of range" )));
870
+ PG_RETURN_INT16 (result );
871
+ }
872
+
873
+ /* No overflow is possible */
874
+
875
+ result = arg1 / arg2 ;
876
+
880
877
PG_RETURN_INT16 (result );
881
878
}
882
879
@@ -1054,17 +1051,27 @@ int42div(PG_FUNCTION_ARGS)
1054
1051
PG_RETURN_NULL ();
1055
1052
}
1056
1053
1057
- result = arg1 / arg2 ;
1058
-
1059
1054
/*
1060
- * Overflow check. The only possible overflow case is for arg1 = INT_MIN,
1061
- * arg2 = -1, where the correct result is -INT_MIN, which can't be
1062
- * represented on a two's-complement machine.
1055
+ * INT_MIN / -1 is problematic, since the result can't be represented on a
1056
+ * two's-complement machine. Some machines produce INT_MIN, some produce
1057
+ * zero, some throw an exception. We can dodge the problem by recognizing
1058
+ * that division by -1 is the same as negation.
1063
1059
*/
1064
- if (arg2 == -1 && arg1 < 0 && result < 0 )
1065
- ereport (ERROR ,
1066
- (errcode (ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ),
1067
- errmsg ("integer out of range" )));
1060
+ if (arg2 == -1 )
1061
+ {
1062
+ result = - arg1 ;
1063
+ /* overflow check (needed for INT_MIN) */
1064
+ if (arg1 != 0 && SAMESIGN (result , arg1 ))
1065
+ ereport (ERROR ,
1066
+ (errcode (ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ),
1067
+ errmsg ("integer out of range" )));
1068
+ PG_RETURN_INT32 (result );
1069
+ }
1070
+
1071
+ /* No overflow is possible */
1072
+
1073
+ result = arg1 / arg2 ;
1074
+
1068
1075
PG_RETURN_INT32 (result );
1069
1076
}
1070
1077
@@ -1160,6 +1167,14 @@ int42mod(PG_FUNCTION_ARGS)
1160
1167
PG_RETURN_NULL ();
1161
1168
}
1162
1169
1170
+ /*
1171
+ * Some machines throw a floating-point exception for INT_MIN % -1, which
1172
+ * is a bit silly since the correct answer is perfectly well-defined,
1173
+ * namely zero.
1174
+ */
1175
+ if (arg2 == -1 )
1176
+ PG_RETURN_INT32 (0 );
1177
+
1163
1178
/* No overflow is possible */
1164
1179
1165
1180
PG_RETURN_INT32 (arg1 % arg2 );
0 commit comments