@@ -681,18 +681,6 @@ int4mul(PG_FUNCTION_ARGS)
681681int32 arg2 = PG_GETARG_INT32 (1 );
682682int32 result ;
683683
684- #ifdef WIN32
685-
686- /*
687- * Win32 doesn't throw a catchable exception for SELECT -2147483648 *
688- * (-1); -- INT_MIN
689- */
690- if (arg2 == -1 && arg1 == INT_MIN )
691- ereport (ERROR ,
692- (errcode (ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ),
693- errmsg ("integer out of range" )));
694- #endif
695-
696684result = arg1 * arg2 ;
697685
698686/*
@@ -709,7 +697,8 @@ int4mul(PG_FUNCTION_ARGS)
709697if (!(arg1 >= (int32 )SHRT_MIN && arg1 <= (int32 )SHRT_MAX &&
710698arg2 >= (int32 )SHRT_MIN && arg2 <= (int32 )SHRT_MAX )&&
711699arg2 != 0 &&
712- (result /arg2 != arg1 || (arg2 == -1 && arg1 < 0 && result < 0 )))
700+ ((arg2 == -1 && arg1 < 0 && result < 0 )||
701+ result /arg2 != arg1 ))
713702ereport (ERROR ,
714703(errcode (ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ),
715704errmsg ("integer out of range" )));
@@ -732,30 +721,27 @@ int4div(PG_FUNCTION_ARGS)
732721PG_RETURN_NULL ();
733722}
734723
735- #ifdef WIN32
736-
737724/*
738- * Win32 doesn't throw a catchable exception for SELECT -2147483648 /
739- * (-1); -- INT_MIN
725+ * INT_MIN / -1 is problematic, since the result can't be represented on a
726+ * two's-complement machine. Some machines produce INT_MIN, some produce
727+ * zero, some throw an exception. We can dodge the problem by recognizing
728+ * that division by -1 is the same as negation.
740729 */
741- if (arg2 == -1 && arg1 == INT_MIN )
742- ereport (ERROR ,
743- (errcode (ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ),
744- errmsg ("integer out of range" )));
745- #endif
730+ if (arg2 == -1 )
731+ {
732+ result = - arg1 ;
733+ /* overflow check (needed for INT_MIN) */
734+ if (arg1 != 0 && SAMESIGN (result ,arg1 ))
735+ ereport (ERROR ,
736+ (errcode (ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ),
737+ errmsg ("integer out of range" )));
738+ PG_RETURN_INT32 (result );
739+ }
740+
741+ /* No overflow is possible */
746742
747743result = arg1 /arg2 ;
748744
749- /*
750- * Overflow check.The only possible overflow case is for arg1 = INT_MIN,
751- * arg2 = -1, where the correct result is -INT_MIN, which can't be
752- * represented on a two's-complement machine. Most machines produce
753- * INT_MIN but it seems some produce zero.
754- */
755- if (arg2 == -1 && arg1 < 0 && result <=0 )
756- ereport (ERROR ,
757- (errcode (ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ),
758- errmsg ("integer out of range" )));
759745PG_RETURN_INT32 (result );
760746}
761747
@@ -877,18 +863,27 @@ int2div(PG_FUNCTION_ARGS)
877863PG_RETURN_NULL ();
878864}
879865
880- result = arg1 /arg2 ;
881-
882866/*
883- *Overflow check.The only possible overflow case is for arg1 =
884- *SHRT_MIN, arg2 = -1, where the correct result is - SHRT_MIN,which can't
885- *be represented on a two's-complement machine .Most machines produce
886- *SHRT_MIN but it seems some produce zero .
867+ *SHRT_MIN / -1 is problematic, since the result can't be represented on
868+ *a two's-complement machine. Some machines produce SHRT_MIN,some
869+ *produce zero, some throw an exception .We can dodge the problem by
870+ *recognizing that division by -1 is the same as negation .
887871 */
888- if (arg2 == -1 && arg1 < 0 && result <=0 )
889- ereport (ERROR ,
890- (errcode (ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ),
891- errmsg ("smallint out of range" )));
872+ if (arg2 == -1 )
873+ {
874+ result = - arg1 ;
875+ /* overflow check (needed for SHRT_MIN) */
876+ if (arg1 != 0 && SAMESIGN (result ,arg1 ))
877+ ereport (ERROR ,
878+ (errcode (ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ),
879+ errmsg ("smallint out of range" )));
880+ PG_RETURN_INT16 (result );
881+ }
882+
883+ /* No overflow is possible */
884+
885+ result = arg1 /arg2 ;
886+
892887PG_RETURN_INT16 (result );
893888}
894889
@@ -1065,18 +1060,27 @@ int42div(PG_FUNCTION_ARGS)
10651060PG_RETURN_NULL ();
10661061}
10671062
1068- result = arg1 /arg2 ;
1069-
10701063/*
1071- *Overflow check.The only possible overflow case is for arg1 = INT_MIN,
1072- *arg2 = -1, where the correct result is - INT_MIN,which can't be
1073- *represented on a two's-complement machine .Most machines produce
1074- *INT_MIN but it seems some produce zero .
1064+ *INT_MIN / -1 is problematic, since the result can't be represented on a
1065+ *two's-complement machine. Some machines produce INT_MIN,some produce
1066+ *zero, some throw an exception .We can dodge the problem by recognizing
1067+ *that division by -1 is the same as negation .
10751068 */
1076- if (arg2 == -1 && arg1 < 0 && result <=0 )
1077- ereport (ERROR ,
1078- (errcode (ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ),
1079- errmsg ("integer out of range" )));
1069+ if (arg2 == -1 )
1070+ {
1071+ result = - arg1 ;
1072+ /* overflow check (needed for INT_MIN) */
1073+ if (arg1 != 0 && SAMESIGN (result ,arg1 ))
1074+ ereport (ERROR ,
1075+ (errcode (ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ),
1076+ errmsg ("integer out of range" )));
1077+ PG_RETURN_INT32 (result );
1078+ }
1079+
1080+ /* No overflow is possible */
1081+
1082+ result = arg1 /arg2 ;
1083+
10801084PG_RETURN_INT32 (result );
10811085}
10821086