From c2b7982cfb45c6bc96dae9e993bd27271d1425ca Mon Sep 17 00:00:00 2001 From: baishen Date: Wed, 9 Oct 2019 16:48:13 +0800 Subject: [PATCH] expression: implement vectorized evaluation for `builtinFromBase64Sig` (#12556) --- expression/builtin_string_vec.go | 43 +++++++++++++++++++++++++-- expression/builtin_string_vec_test.go | 6 ++-- 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/expression/builtin_string_vec.go b/expression/builtin_string_vec.go index 222821b3fc..8146f9485d 100644 --- a/expression/builtin_string_vec.go +++ b/expression/builtin_string_vec.go @@ -983,11 +983,50 @@ func (b *builtinFieldIntSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column } func (b *builtinFromBase64Sig) vectorized() bool { - return false + return true } +// vecEvalString evals FROM_BASE64(str). +// See https://dev.mysql.com/doc/refman/5.7/en/string-functions.html#function_from-base64 func (b *builtinFromBase64Sig) vecEvalString(input *chunk.Chunk, result *chunk.Column) error { - return errors.Errorf("not implemented") + n := input.NumRows() + buf, err := b.bufAllocator.get(types.ETString, n) + if err != nil { + return err + } + defer b.bufAllocator.put(buf) + if err := b.args[0].VecEvalString(b.ctx, input, buf); err != nil { + return err + } + + result.ReserveString(n) + for i := 0; i < n; i++ { + if buf.IsNull(i) { + result.AppendNull() + continue + } + str := buf.GetString(i) + needDecodeLen := base64NeededDecodedLength(len(str)) + if needDecodeLen == -1 { + result.AppendNull() + continue + } else if needDecodeLen > int(b.maxAllowedPacket) { + b.ctx.GetSessionVars().StmtCtx.AppendWarning(errWarnAllowedPacketOverflowed.GenWithStackByArgs("from_base64", b.maxAllowedPacket)) + result.AppendNull() + continue + } + + str = strings.Replace(str, "\t", "", -1) + str = strings.Replace(str, " ", "", -1) + newStr, err := base64.StdEncoding.DecodeString(str) + if err != nil { + // When error happens, take `from_base64("asc")` as an example, we should return NULL. + result.AppendNull() + continue + } + result.AppendString(string(newStr)) + } + return nil } func (b *builtinCharLengthSig) vectorized() bool { diff --git a/expression/builtin_string_vec_test.go b/expression/builtin_string_vec_test.go index 9fb78df27f..73d1b0c123 100644 --- a/expression/builtin_string_vec_test.go +++ b/expression/builtin_string_vec_test.go @@ -54,8 +54,10 @@ var vecBuiltinStringCases = map[string][]vecExprBenchCase{ ast.ToBase64: { {retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString}, geners: []dataGenerator{&randLenStrGener{0, 10}}}, }, - ast.FromBase64: {}, - ast.ExportSet: {}, + ast.FromBase64: { + {retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString}, geners: []dataGenerator{&randLenStrGener{10, 100}}}, + }, + ast.ExportSet: {}, ast.Repeat: { {retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETInt}, geners: []dataGenerator{&randLenStrGener{10, 20}, &rangeInt64Gener{-10, 10}}}, },