From 1ec575a0962739daefd4a9c1a32e98a6230637ec Mon Sep 17 00:00:00 2001 From: tiancaiamao Date: Tue, 29 Jan 2019 09:59:16 +0800 Subject: [PATCH] expression: fix precision when casting float to string (#9137) --- expression/builtin_cast.go | 15 +++++++++++++-- expression/integration_test.go | 6 ++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/expression/builtin_cast.go b/expression/builtin_cast.go index f623899032f41..5731e2abee065 100644 --- a/expression/builtin_cast.go +++ b/expression/builtin_cast.go @@ -796,9 +796,20 @@ func (b *builtinCastRealAsStringSig) Clone() builtinFunc { func (b *builtinCastRealAsStringSig) evalString(row chunk.Row) (res string, isNull bool, err error) { val, isNull, err := b.args[0].EvalReal(b.ctx, row) if isNull || err != nil { - return res, isNull, errors.Trace(err) + return res, isNull, err + } + + bits := 64 + if b.args[0].GetType().Tp == mysql.TypeFloat { + // b.args[0].EvalReal() casts the value from float32 to float64, for example: + // float32(208.867) is cast to float64(208.86700439) + // If we strconv.FormatFloat the value with 64bits, the result is incorrect! + bits = 32 + } + res, err = types.ProduceStrWithSpecifiedTp(strconv.FormatFloat(val, 'f', -1, bits), b.tp, b.ctx.GetSessionVars().StmtCtx) + if err != nil { + return res, false, err } - res, err = types.ProduceStrWithSpecifiedTp(strconv.FormatFloat(val, 'f', -1, 64), b.tp, b.ctx.GetSessionVars().StmtCtx) return res, isNull, errors.Trace(err) } diff --git a/expression/integration_test.go b/expression/integration_test.go index 8c7922ae36a38..c01f8364a24ec 100644 --- a/expression/integration_test.go +++ b/expression/integration_test.go @@ -572,6 +572,12 @@ func (s *testIntegrationSuite) TestStringBuiltin(c *C) { result.Check(testkit.Rows("")) result = tk.MustQuery("select concat(null, a, b) from t") result.Check(testkit.Rows("")) + tk.MustExec("drop table if exists t") + // Fix issue 9123 + tk.MustExec("create table t(a char(32) not null, b float default '0') engine=innodb default charset=utf8mb4") + tk.MustExec("insert into t value('0a6f9d012f98467f8e671e9870044528', 208.867)") + result = tk.MustQuery("select concat_ws( ',', b) from t where a = '0a6f9d012f98467f8e671e9870044528';") + result.Check(testkit.Rows("208.867")) // for concat_ws tk.MustExec("drop table if exists t")