From 0fcf1df77276081b6ae27bda4a6a841ff5d6c655 Mon Sep 17 00:00:00 2001 From: CWang Date: Wed, 27 Nov 2019 13:10:43 +0800 Subject: [PATCH] expression:implement vectorized evaluation for builtinConvertSig (#13537) --- expression/builtin_string_vec.go | 36 +++++++++++++++++++++++++-- expression/builtin_string_vec_test.go | 23 ++++++++++++++++- 2 files changed, 56 insertions(+), 3 deletions(-) diff --git a/expression/builtin_string_vec.go b/expression/builtin_string_vec.go index f4fe2ac6a30be..3f48e01fee73f 100644 --- a/expression/builtin_string_vec.go +++ b/expression/builtin_string_vec.go @@ -24,9 +24,11 @@ import ( "github.com/pingcap/errors" "github.com/pingcap/parser/ast" + "github.com/pingcap/parser/charset" "github.com/pingcap/parser/mysql" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/chunk" + "golang.org/x/text/transform" ) func (b *builtinLowerSig) vecEvalString(input *chunk.Chunk, result *chunk.Column) error { @@ -599,11 +601,41 @@ func (b *builtinConcatWSSig) vecEvalString(input *chunk.Chunk, result *chunk.Col } func (b *builtinConvertSig) vectorized() bool { - return false + return true } func (b *builtinConvertSig) vecEvalString(input *chunk.Chunk, result *chunk.Column) error { - return errors.Errorf("not implemented") + n := input.NumRows() + expr, err := b.bufAllocator.get(types.ETString, n) + if err != nil { + return err + } + defer b.bufAllocator.put(expr) + if err := b.args[0].VecEvalString(b.ctx, input, expr); err != nil { + return err + } + // Since charset is already validated and set from getFunction(), there's no + // need to get charset from args again. + encoding, _ := charset.Lookup(b.tp.Charset) + // However, if `b.tp.Charset` is abnormally set to a wrong charset, we still + // return with error. + if encoding == nil { + return errUnknownCharacterSet.GenWithStackByArgs(b.tp.Charset) + } + result.ReserveString(n) + for i := 0; i < n; i++ { + if expr.IsNull(i) { + result.AppendNull() + continue + } + exprI := expr.GetString(i) + target, _, err := transform.String(encoding.NewDecoder(), exprI) + if err != nil { + return err + } + result.AppendString(target) + } + return nil } func (b *builtinSubstringIndexSig) vectorized() bool { diff --git a/expression/builtin_string_vec_test.go b/expression/builtin_string_vec_test.go index 6aaa34af8651a..75a1faaece68e 100644 --- a/expression/builtin_string_vec_test.go +++ b/expression/builtin_string_vec_test.go @@ -58,7 +58,28 @@ var vecBuiltinStringCases = map[string][]vecExprBenchCase{ {retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString, types.ETString}}, }, ast.ConcatWS: {}, - ast.Convert: {}, + ast.Convert: { + { + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString}, + constants: []*Constant{nil, {Value: types.NewDatum("utf8"), RetType: types.NewFieldType(mysql.TypeString)}}, + }, + { + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString}, + constants: []*Constant{nil, {Value: types.NewDatum("binary"), RetType: types.NewFieldType(mysql.TypeString)}}, + }, + { + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString}, + constants: []*Constant{nil, {Value: types.NewDatum("utf8mb4"), RetType: types.NewFieldType(mysql.TypeString)}}, + }, + { + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString}, + constants: []*Constant{nil, {Value: types.NewDatum("ascii"), RetType: types.NewFieldType(mysql.TypeString)}}, + }, + { + retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETString}, + constants: []*Constant{nil, {Value: types.NewDatum("latin1"), RetType: types.NewFieldType(mysql.TypeString)}}, + }, + }, ast.Substring: { { retEvalType: types.ETString,