From e3e9944e99605dc5bb0d7af938babb0d20649046 Mon Sep 17 00:00:00 2001 From: CodeRushing Date: Thu, 27 Sep 2018 15:41:05 +0800 Subject: [PATCH] expression:fix cast unsigned to decimal bug when overflows the signed integer range --- expression/builtin_cast.go | 2 +- expression/builtin_cast_test.go | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/expression/builtin_cast.go b/expression/builtin_cast.go index 2021a37650552..719ca5a2e9614 100644 --- a/expression/builtin_cast.go +++ b/expression/builtin_cast.go @@ -485,7 +485,7 @@ func (b *builtinCastIntAsDecimalSig) evalDecimal(row chunk.Row) (res *types.MyDe if isNull || err != nil { return res, isNull, errors.Trace(err) } - if !mysql.HasUnsignedFlag(b.tp.Flag) { + if !mysql.HasUnsignedFlag(b.tp.Flag) && !mysql.HasUnsignedFlag(b.args[0].GetType().Flag) { res = types.NewDecFromInt(val) } else if b.inUnion && val < 0 { res = &types.MyDecimal{} diff --git a/expression/builtin_cast_test.go b/expression/builtin_cast_test.go index 4de94a8be3798..ab92b03021295 100644 --- a/expression/builtin_cast_test.go +++ b/expression/builtin_cast_test.go @@ -212,6 +212,26 @@ func (s *testEvaluatorSuite) TestCast(c *C) { c.Assert(terror.ErrorEqual(types.ErrOverflow, lastWarn.Err), IsTrue, Commentf("err %v", lastWarn.Err)) sc = origSc + // create table tt(a bigint unsigned); + // insert into tt values(18446744073709551615); + // select cast(a as decimal(65, 0)) from tt; + ft = &types.FieldType{ + Tp: mysql.TypeNewDecimal, + Flag: mysql.BinaryFlag, + Charset: charset.CharsetBin, + Collate: charset.CollationBin, + Flen: 65, + Decimal: 0, + } + rt := types.NewFieldType(mysql.TypeLonglong) + rt.Flag = mysql.BinaryFlag | mysql.UnsignedFlag + f = BuildCastFunction(ctx, &Constant{Value: types.NewUintDatum(18446744073709551615), RetType: rt}, ft) + res, err = f.Eval(chunk.Row{}) + c.Assert(err, IsNil) + u, err := res.GetMysqlDecimal().ToUint() + c.Assert(err, IsNil) + c.Assert(u == 18446744073709551615, IsTrue) + // cast(bad_string as decimal) for _, s := range []string{"hello", ""} { f = BuildCastFunction(ctx, &Constant{Value: types.NewDatum(s), RetType: types.NewFieldType(mysql.TypeDecimal)}, tp)