From 84750e85502f863626df02cfe2f5cb5637a6ce49 Mon Sep 17 00:00:00 2001 From: Zhang Jian Date: Tue, 12 Feb 2019 11:48:55 +0800 Subject: [PATCH] expression: handle ENUM in builtin function Values() (#9225) --- expression/builtin_other.go | 21 +++++++++++++++------ expression/column.go | 10 +++------- expression/integration_test.go | 11 +++++++++++ 3 files changed, 29 insertions(+), 13 deletions(-) diff --git a/expression/builtin_other.go b/expression/builtin_other.go index ce9b0bbb88136..4b8ff8d79c343 100644 --- a/expression/builtin_other.go +++ b/expression/builtin_other.go @@ -615,13 +615,22 @@ func (b *builtinValuesStringSig) evalString(_ chunk.Row) (string, bool, error) { if row.IsEmpty() { return "", true, errors.New("Session current insert values is nil") } - if b.offset < row.Len() { - if row.IsNull(b.offset) { - return "", true, nil - } - return row.GetString(b.offset), false, nil + if b.offset >= row.Len() { + return "", true, errors.Errorf("Session current insert values len %d and column's offset %v don't match", row.Len(), b.offset) } - return "", true, errors.Errorf("Session current insert values len %d and column's offset %v don't match", row.Len(), b.offset) + + if row.IsNull(b.offset) { + return "", true, nil + } + + // Specially handle the ENUM/SET/BIT input value. + if retType := b.getRetTp(); retType.Hybrid() { + val := row.GetDatum(b.offset, retType) + res, err := val.ToString() + return res, err != nil, err + } + + return row.GetString(b.offset), false, nil } type builtinValuesTimeSig struct { diff --git a/expression/column.go b/expression/column.go index 72fde92c19d00..d049017417fe6 100644 --- a/expression/column.go +++ b/expression/column.go @@ -231,18 +231,14 @@ func (col *Column) EvalString(ctx sessionctx.Context, row chunk.Row) (string, bo if row.IsNull(col.Index) { return "", true, nil } + + // Specially handle the ENUM/SET/BIT input value. if col.GetType().Hybrid() { val := row.GetDatum(col.Index, col.RetType) - if val.IsNull() { - return "", true, nil - } res, err := val.ToString() - resLen := len([]rune(res)) - if ctx.GetSessionVars().StmtCtx.PadCharToFullLength && col.GetType().Tp == mysql.TypeString && resLen < col.RetType.Flen { - res = res + strings.Repeat(" ", col.RetType.Flen-resLen) - } return res, err != nil, err } + val := row.GetString(col.Index) if ctx.GetSessionVars().StmtCtx.PadCharToFullLength && col.GetType().Tp == mysql.TypeString { valLen := len([]rune(val)) diff --git a/expression/integration_test.go b/expression/integration_test.go index bbf019e567a38..31e9e778b8b8d 100644 --- a/expression/integration_test.go +++ b/expression/integration_test.go @@ -3898,3 +3898,14 @@ func (s *testIntegrationSuite) TestValuesFloat32(c *C) { tk.MustExec(`insert into t values (1, 0.02) on duplicate key update j = values (j);`) tk.MustQuery(`select * from t;`).Check(testkit.Rows(`1 0.02`)) } + +func (s *testIntegrationSuite) TestValuesEnum(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec(`drop table if exists t;`) + tk.MustExec(`create table t (a bigint primary key, b enum('a','b','c'));`) + tk.MustExec(`insert into t values (1, "a");`) + tk.MustQuery(`select * from t;`).Check(testkit.Rows(`1 a`)) + tk.MustExec(`insert into t values (1, "b") on duplicate key update b = values(b);`) + tk.MustQuery(`select * from t;`).Check(testkit.Rows(`1 b`)) +}