diff --git a/enginetest/queries/script_queries.go b/enginetest/queries/script_queries.go index 2237701910..cd77a1af72 100644 --- a/enginetest/queries/script_queries.go +++ b/enginetest/queries/script_queries.go @@ -7833,6 +7833,27 @@ where }, }, }, + { + Name: "negative int limits", + Dialect: "mysql", + SetUpScript: []string{ + "CREATE TABLE t(i8 tinyint, i16 smallint, i24 mediumint, i32 int, i64 bigint);", + "INSERT INTO t VALUES(-128, -32768, -8388608, -2147483648, -9223372036854775808);", + }, + Assertions: []ScriptTestAssertion{ + { + SkipResultCheckOnServerEngine: true, + Query: "SELECT -i8, -i16, -i24, -i32 from t;", + Expected: []sql.Row{ + {128, 32768, 8388608, 2147483648}, + }, + }, + { + Query: "SELECT -i64 from t;", + ExpectedErrStr: "BIGINT out of range for -9223372036854775808", + }, + }, + }, } var SpatialScriptTests = []ScriptTest{ diff --git a/sql/expression/arithmetic.go b/sql/expression/arithmetic.go index 4fa8e45330..559459a0f2 100644 --- a/sql/expression/arithmetic.go +++ b/sql/expression/arithmetic.go @@ -16,6 +16,7 @@ package expression import ( "fmt" + "math" "reflect" "regexp" "strconv" @@ -704,12 +705,24 @@ func (e *UnaryMinus) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) { case int: return -n, nil case int8: + if n == math.MinInt8 { + return -int16(n), nil + } return -n, nil case int16: + if n == math.MinInt16 { + return -int32(n), nil + } return -n, nil case int32: + if n == math.MinInt32 { + return -int64(n), nil + } return -n, nil case int64: + if n == math.MinInt64 { + return nil, sql.ErrValueOutOfRange.New("BIGINT", fmt.Sprintf("%d", n)) + } return -n, nil case uint: return -int(n), nil