diff --git a/expression/builtin_arithmetic.go b/expression/builtin_arithmetic.go index 85b1d757767d8..9fbe66ca142f4 100644 --- a/expression/builtin_arithmetic.go +++ b/expression/builtin_arithmetic.go @@ -762,11 +762,30 @@ func (s *builtinArithmeticIntDivideDecimalSig) evalInt(row chunk.Row) (ret int64 return 0, true, err } - ret, err = c.ToInt() - // err returned by ToInt may be ErrTruncated or ErrOverflow, only handle ErrOverflow, ignore ErrTruncated. - if err == types.ErrOverflow { - return 0, true, types.ErrOverflow.GenWithStackByArgs("BIGINT", fmt.Sprintf("(%s DIV %s)", s.args[0].String(), s.args[1].String())) + isLHSUnsigned := mysql.HasUnsignedFlag(s.args[0].GetType().Flag) + isRHSUnsigned := mysql.HasUnsignedFlag(s.args[1].GetType().Flag) + + if isLHSUnsigned || isRHSUnsigned { + val, err := c.ToUint() + // err returned by ToUint may be ErrTruncated or ErrOverflow, only handle ErrOverflow, ignore ErrTruncated. + if err == types.ErrOverflow { + v, err := c.ToInt() + // when the final result is at (-1, 0], it should be return 0 instead of the error + if v == 0 && err == types.ErrTruncated { + ret = int64(0) + return ret, false, nil + } + return 0, true, types.ErrOverflow.GenWithStackByArgs("BIGINT UNSIGNED", fmt.Sprintf("(%s DIV %s)", s.args[0].String(), s.args[1].String())) + } + ret = int64(val) + } else { + ret, err = c.ToInt() + // err returned by ToInt may be ErrTruncated or ErrOverflow, only handle ErrOverflow, ignore ErrTruncated. + if err == types.ErrOverflow { + return 0, true, types.ErrOverflow.GenWithStackByArgs("BIGINT", fmt.Sprintf("(%s DIV %s)", s.args[0].String(), s.args[1].String())) + } } + return ret, false, nil } diff --git a/expression/builtin_arithmetic_test.go b/expression/builtin_arithmetic_test.go index 61a47bbc5d334..c53c5dcb85c1f 100644 --- a/expression/builtin_arithmetic_test.go +++ b/expression/builtin_arithmetic_test.go @@ -441,6 +441,14 @@ func (s *testEvaluatorSuite) TestArithmeticIntDivide(c *C) { args: []interface{}{int64(-9223372036854775808), float64(-1)}, expect: []interface{}{nil, "*BIGINT value is out of range in '\\(-9223372036854775808 DIV -1\\)'"}, }, + { + args: []interface{}{uint64(1), float64(-2)}, + expect: []interface{}{0, nil}, + }, + { + args: []interface{}{uint64(1), float64(-1)}, + expect: []interface{}{nil, "*BIGINT UNSIGNED value is out of range in '\\(1 DIV -1\\)'"}, + }, } for _, tc := range testCases {