diff --git a/expression/builtin_math.go b/expression/builtin_math.go index abef8821eff00..0fc139409c51e 100644 --- a/expression/builtin_math.go +++ b/expression/builtin_math.go @@ -26,6 +26,7 @@ import ( "sync" "github.com/cznic/mathutil" + "github.com/pingcap/parser/ast" "github.com/pingcap/parser/mysql" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/types" @@ -1163,11 +1164,25 @@ func (b *builtinConvSig) Clone() builtinFunc { // evalString evals CONV(N,from_base,to_base). // See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_conv. func (b *builtinConvSig) evalString(row chunk.Row) (res string, isNull bool, err error) { - str, isNull, err := b.args[0].EvalString(b.ctx, row) - if isNull || err != nil { - return res, isNull, err + var str string + switch x := b.args[0].(type) { + case *Constant: + if x.Value.Kind() == types.KindBinaryLiteral { + str = x.Value.GetBinaryLiteral().ToBitLiteralString(true) + } + case *ScalarFunction: + if x.FuncName.L == ast.Cast { + arg0 := x.GetArgs()[0] + if arg0.GetType().Hybrid() || IsBinaryLiteral(arg0) { + str, isNull, err = arg0.EvalString(b.ctx, row) + if isNull || err != nil { + return str, isNull, err + } + d := types.NewStringDatum(str) + str = d.GetBinaryLiteral().ToBitLiteralString(true) + } + } } - fromBase, isNull, err := b.args[1].EvalInt(b.ctx, row) if isNull || err != nil { return res, isNull, err @@ -1177,6 +1192,17 @@ func (b *builtinConvSig) evalString(row chunk.Row) (res string, isNull bool, err if isNull || err != nil { return res, isNull, err } + if len(str) == 0 { + str, isNull, err = b.args[0].EvalString(b.ctx, row) + if isNull || err != nil { + return res, isNull, err + } + } else { + str, isNull, err = b.conv(str[2:], 2, fromBase) + if err != nil { + return str, isNull, err + } + } return b.conv(str, fromBase, toBase) } func (b *builtinConvSig) conv(str string, fromBase, toBase int64) (res string, isNull bool, err error) { diff --git a/expression/builtin_math_vec.go b/expression/builtin_math_vec.go index b233c9c9acf09..b28b1a655ba79 100644 --- a/expression/builtin_math_vec.go +++ b/expression/builtin_math_vec.go @@ -1070,7 +1070,8 @@ func (b *builtinSignSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) er } func (b *builtinConvSig) vectorized() bool { - return true + // TODO: change the vecEval match hybrid type fixing. Then open the vectorized evaluation. + return false } func (b *builtinConvSig) vecEvalString(input *chunk.Chunk, result *chunk.Column) error { diff --git a/expression/builtin_math_vec_test.go b/expression/builtin_math_vec_test.go index fe240d053017f..66d79a0534e01 100644 --- a/expression/builtin_math_vec_test.go +++ b/expression/builtin_math_vec_test.go @@ -23,12 +23,14 @@ import ( ) var vecBuiltinMathCases = map[string][]vecExprBenchCase{ + /* TODO: Because of https://github.com/pingcap/tidb/issues/5817, we don't enable it now. ast.Conv: { { retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETInt, types.ETInt}, }, }, + */ ast.Sign: { {retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETReal}}, }, diff --git a/expression/integration_test.go b/expression/integration_test.go index fdf5aef94f1bd..7efd9dd633aca 100644 --- a/expression/integration_test.go +++ b/expression/integration_test.go @@ -531,6 +531,42 @@ func (s *testIntegrationSuite2) TestMathBuiltin(c *C) { result.Check(testkit.Rows("")) result = tk.MustQuery("SELECT CONV('a', 37, 10);") result.Check(testkit.Rows("")) + result = tk.MustQuery("SELECT CONV(0x0020, 2, 2);") + result.Check(testkit.Rows("100000")) + result = tk.MustQuery("SELECT CONV(0b10, 16, 2)") + result.Check(testkit.Rows("10")) + result = tk.MustQuery("SELECT CONV(0b10, 16, 8)") + result.Check(testkit.Rows("2")) + tk.MustExec("drop table if exists bit") + tk.MustExec("create table bit(b bit(10))") + tk.MustExec(`INSERT INTO bit (b) VALUES + (0b0000010101), + (0b0000010101), + (NULL), + (0b0000000001), + (0b0000000000), + (0b1111111111), + (0b1111111111), + (0b1111111111), + (0b0000000000), + (0b0000000000), + (0b0000000000), + (0b0000000000), + (0b0000100000);`) + tk.MustQuery("select conv(b, 2, 2) from `bit`").Check(testkit.Rows( + "10101", + "10101", + "", + "1", + "0", + "1111111111", + "1111111111", + "1111111111", + "0", + "0", + "0", + "0", + "100000")) // for abs result = tk.MustQuery("SELECT ABS(-1);")