Skip to content

Commit

Permalink
expression: fix the corner case of CAST int as unsigned real/decimal (p…
Browse files Browse the repository at this point in the history
  • Loading branch information
Deardrops committed Nov 26, 2019
1 parent ac4767a commit 54392d5
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 4 deletions.
17 changes: 13 additions & 4 deletions expression/builtin_cast.go
Original file line number Diff line number Diff line change
Expand Up @@ -461,9 +461,13 @@ func (b *builtinCastIntAsRealSig) evalReal(row chunk.Row) (res float64, isNull b
if isNull || err != nil {
return res, isNull, err
}
if !mysql.HasUnsignedFlag(b.tp.Flag) {
if unsignedArgs0 := mysql.HasUnsignedFlag(b.args[0].GetType().Flag); !mysql.HasUnsignedFlag(b.tp.Flag) && !unsignedArgs0 {
res = float64(val)
} else if b.inUnion && val < 0 {
} else if b.inUnion && !unsignedArgs0 && val < 0 {
// Round up to 0 if the value is negative but the expression eval type is unsigned in `UNION` statement
// NOTE: the following expressions are equal (so choose the more efficient one):
// `b.inUnion && mysql.HasUnsignedFlag(b.tp.Flag) && !unsignedArgs0 && val < 0`
// `b.inUnion && !unsignedArgs0 && val < 0`
res = 0
} else {
// recall that, int to float is different from uint to float
Expand All @@ -487,9 +491,14 @@ func (b *builtinCastIntAsDecimalSig) evalDecimal(row chunk.Row) (res *types.MyDe
if isNull || err != nil {
return res, isNull, err
}
if !mysql.HasUnsignedFlag(b.tp.Flag) && !mysql.HasUnsignedFlag(b.args[0].GetType().Flag) {

if unsignedArgs0 := mysql.HasUnsignedFlag(b.args[0].GetType().Flag); !mysql.HasUnsignedFlag(b.tp.Flag) && !unsignedArgs0 {
res = types.NewDecFromInt(val)
} else if b.inUnion && val < 0 {
// Round up to 0 if the value is negative but the expression eval type is unsigned in `UNION` statement
// NOTE: the following expressions are equal (so choose the more efficient one):
// `b.inUnion && mysql.HasUnsignedFlag(b.tp.Flag) && !unsignedArgs0 && val < 0`
// `b.inUnion && !unsignedArgs0 && val < 0`
} else if b.inUnion && !unsignedArgs0 && val < 0 {
res = &types.MyDecimal{}
} else {
res = types.NewDecFromUint(uint64(val))
Expand Down
16 changes: 16 additions & 0 deletions expression/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2236,6 +2236,22 @@ func (s *testIntegrationSuite) TestBuiltin(c *C) {
result.Check(testkit.Rows("9223372036854775808 9223372036854775808", "9223372036854775808 9223372036854775808"))
tk.MustExec(`drop table tb5;`)

// test builtinCastIntAsDecimalSig
tk.MustExec(`drop table if exists tb5`)
tk.MustExec(`create table tb5 (a decimal(65), b bigint(64) unsigned);`)
tk.MustExec(`insert into tb5 (a, b) values (9223372036854775808, 9223372036854775808);`)
result = tk.MustQuery(`select cast(b as decimal(64)) from tb5 union all select b from tb5;`)
result.Check(testkit.Rows("9223372036854775808", "9223372036854775808"))
tk.MustExec(`drop table tb5`)

// test builtinCastIntAsRealSig
tk.MustExec(`drop table if exists tb5`)
tk.MustExec(`create table tb5 (a bigint(64) unsigned, b double(64, 10));`)
tk.MustExec(`insert into tb5 (a, b) values (9223372036854775808, 9223372036854775808);`)
result = tk.MustQuery(`select a from tb5 where a = b union all select b from tb5;`)
result.Check(testkit.Rows("9223372036854776000", "9223372036854776000"))
tk.MustExec(`drop table tb5`)

// Test corner cases of cast string as datetime
result = tk.MustQuery(`select cast("170102034" as datetime);`)
result.Check(testkit.Rows("2017-01-02 03:04:00"))
Expand Down

0 comments on commit 54392d5

Please sign in to comment.