Skip to content

Commit

Permalink
expression: fix tikv crash when bool like cast(bit as char)
Browse files Browse the repository at this point in the history
  • Loading branch information
lcwangchao committed Nov 19, 2024
1 parent a22b842 commit 4ed280e
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 6 deletions.
18 changes: 14 additions & 4 deletions pkg/expression/builtin_cast.go
Original file line number Diff line number Diff line change
Expand Up @@ -300,10 +300,20 @@ func (c *castAsStringFunctionClass) getFunction(ctx BuildContext, args []Express
if err != nil {
return nil, err
}
if args[0].GetType(ctx.GetEvalCtx()).Hybrid() {
sig = &builtinCastStringAsStringSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_CastStringAsString)
return sig, nil
if ft := args[0].GetType(ctx.GetEvalCtx()); ft.Hybrid() {
castBitAsUnBinary := ft.GetType() == mysql.TypeBit && c.tp.GetCharset() != charset.CharsetBin
if !castBitAsUnBinary {
sig = &builtinCastStringAsStringSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_CastStringAsString)
return sig, nil
}
// for type BIT, it maybe an invalid value for the specified charset, we need to convert it to binary first,
// and then convert it to the specified charset with `HandleBinaryLiteral` in the following code.
tp := types.NewFieldType(mysql.TypeString)
tp.SetCharset(charset.CharsetBin)
tp.SetCollate(charset.CollationBin)
tp.AddFlag(mysql.BinaryFlag)
args[0] = BuildCastFunction(ctx, args[0], tp)
}
argTp := args[0].GetType(ctx.GetEvalCtx()).EvalType()
switch argTp {
Expand Down
1 change: 1 addition & 0 deletions pkg/expression/builtin_convert_charset.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ type builtinInternalFromBinarySig struct {
func (b *builtinInternalFromBinarySig) Clone() builtinFunc {
newSig := &builtinInternalFromBinarySig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
newSig.cannotConvertStringAsWarning = b.cannotConvertStringAsWarning
return newSig
}

Expand Down
9 changes: 7 additions & 2 deletions pkg/expression/expr_to_pb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1581,7 +1581,8 @@ func TestExprPushDownToTiKV(t *testing.T) {
require.Len(t, pushed, 0)
require.Len(t, remained, len(exprs))

// Test Conv function
// Test Conv function, `conv` function for a BIT column should not be pushed down for its special behavior which
// is only handled in TiDB currently.
exprs = exprs[:0]
function, err = NewFunction(mock.NewContext(), ast.Conv, types.NewFieldType(mysql.TypeString), stringColumn, intColumn, intColumn)
require.NoError(t, err)
Expand All @@ -1590,7 +1591,11 @@ func TestExprPushDownToTiKV(t *testing.T) {
require.Len(t, pushed, len(exprs))
require.Len(t, remained, 0)
exprs = exprs[:0]
castByteAsStringFunc, err := NewFunction(mock.NewContext(), ast.Cast, types.NewFieldType(mysql.TypeString), byteColumn)
// when conv a column with type BIT, a cast function will be used to cast bit to a binary string
castTp := types.NewFieldType(mysql.TypeString)
castTp.SetCharset(charset.CharsetBin)
castTp.SetCollate(charset.CollationBin)
castByteAsStringFunc, err := NewFunction(mock.NewContext(), ast.Cast, castTp, byteColumn)
require.NoError(t, err)
function, err = NewFunction(mock.NewContext(), ast.Conv, types.NewFieldType(mysql.TypeString), castByteAsStringFunc, intColumn, intColumn)
require.NoError(t, err)
Expand Down
15 changes: 15 additions & 0 deletions tests/integrationtest/r/expression/cast.result
Original file line number Diff line number Diff line change
Expand Up @@ -178,3 +178,18 @@ id update_user
2 李四
4 李四
1 张三
drop table if exists test;
create table test(a bit(24));
insert into test values('中');
select a from test where '中' like convert(a, char);
a
select a from test where false not like convert(a, char);
a
select a from test where false like convert(a, char);
a
truncate table test;
insert into test values(0xffffff);
select a from test where false not like convert(a, char);
Error 1105 (HY000): Cannot convert string '\xFF\xFF\xFF' from binary to utf8mb4
11 changes: 11 additions & 0 deletions tests/integrationtest/t/expression/cast.test
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,14 @@ insert into test values(3,'张三');
insert into test values(4,'李四');
select * from test order by cast(update_user as char) desc , id limit 3;

# issue #56494, cast bit as char
drop table if exists test;
create table test(a bit(24));
insert into test values('中');
select a from test where '中' like convert(a, char);
select a from test where false not like convert(a, char);
select a from test where false like convert(a, char);
truncate table test;
insert into test values(0xffffff);
-- error 1105
select a from test where false not like convert(a, char);

0 comments on commit 4ed280e

Please sign in to comment.