Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

expression: fix wrong result of greatest/least(mixed unsigned/signed int) #30121

Merged
merged 12 commits into from
Dec 2, 2021
15 changes: 15 additions & 0 deletions expression/builtin_compare.go
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,13 @@ func (c *greatestFunctionClass) getFunction(ctx sessionctx.Context, args []Expre
}
switch tp {
case types.ETInt:
//default signed, if one field is unsigned, return unsigned result
for _, arg := range args {
if mysql.HasUnsignedFlag(arg.GetType().Flag) {
bf.tp.Flag |= mysql.UnsignedFlag
break
}
}
sig = &builtinGreatestIntSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_GreatestInt)
case types.ETReal:
Expand Down Expand Up @@ -745,6 +752,14 @@ func (c *leastFunctionClass) getFunction(ctx sessionctx.Context, args []Expressi
}
switch tp {
case types.ETInt:
// default unsigned, if one field is signed, return signed result
sylzd marked this conversation as resolved.
Show resolved Hide resolved
bf.tp.Flag |= mysql.UnsignedFlag
for _, arg := range args {
if !mysql.HasUnsignedFlag(arg.GetType().Flag) {
bf.tp.Flag &= ^mysql.UnsignedFlag
break
}
}
sig = &builtinLeastIntSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_LeastInt)
case types.ETReal:
Expand Down
10 changes: 10 additions & 0 deletions expression/builtin_compare_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,8 @@ func TestGreatestLeastFunc(t *testing.T) {
sc := ctx.GetSessionVars().StmtCtx
originIgnoreTruncate := sc.IgnoreTruncate
sc.IgnoreTruncate = true
decG := &types.MyDecimal{}
decL := &types.MyDecimal{}
defer func() {
sc.IgnoreTruncate = originIgnoreTruncate
}()
Expand All @@ -290,6 +292,14 @@ func TestGreatestLeastFunc(t *testing.T) {
isNil bool
getErr bool
}{
{
[]interface{}{int64(-9223372036854775808), uint64(9223372036854775809)},
decG.FromUint(9223372036854775809), decL.FromInt(-9223372036854775808), false, false,
},
{
[]interface{}{uint64(9223372036854775808), uint64(9223372036854775809)},
uint64(9223372036854775809), uint64(9223372036854775808), false, false,
},
{
[]interface{}{1, 2, 3, 4},
int64(4), int64(1), false, false,
Expand Down
9 changes: 9 additions & 0 deletions expression/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10644,3 +10644,12 @@ func (s *testIntegrationSuite) TestIssue29513(c *C) {
tk.MustQuery("select '123' union select cast(a as char) from t;").Sort().Check(testkit.Rows("123", "45678"))
tk.MustQuery("select '123' union select cast(a as char(2)) from t;").Sort().Check(testkit.Rows("123", "45"))
}

func (s *testIntegrationSuite) TestIssue30101(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t1;")
tk.MustExec("create table t1(c1 bigint unsigned, c2 bigint unsigned);")
tk.MustExec("insert into t1 values(9223372036854775808, 9223372036854775809);")
tk.MustQuery("select greatest(c1, c2) from t1;").Sort().Check(testkit.Rows("9223372036854775809"))
}