diff --git a/pkg/expression/builtin_cast.go b/pkg/expression/builtin_cast.go index f4419dc96c4b54..c1a9aec8eae50d 100644 --- a/pkg/expression/builtin_cast.go +++ b/pkg/expression/builtin_cast.go @@ -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 { diff --git a/pkg/expression/builtin_convert_charset.go b/pkg/expression/builtin_convert_charset.go index 24b4acd054bd69..33524d80dcdb73 100644 --- a/pkg/expression/builtin_convert_charset.go +++ b/pkg/expression/builtin_convert_charset.go @@ -173,6 +173,7 @@ type builtinInternalFromBinarySig struct { func (b *builtinInternalFromBinarySig) Clone() builtinFunc { newSig := &builtinInternalFromBinarySig{} newSig.cloneFrom(&b.baseBuiltinFunc) + newSig.cannotConvertStringAsWarning = b.cannotConvertStringAsWarning return newSig } diff --git a/tests/integrationtest/r/expression/cast.result b/tests/integrationtest/r/expression/cast.result index 1d237ebfd87e0f..147b93ee4260c7 100644 --- a/tests/integrationtest/r/expression/cast.result +++ b/tests/integrationtest/r/expression/cast.result @@ -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 diff --git a/tests/integrationtest/t/expression/cast.test b/tests/integrationtest/t/expression/cast.test index 7af48437383a91..cc5926168b1e04 100644 --- a/tests/integrationtest/t/expression/cast.test +++ b/tests/integrationtest/t/expression/cast.test @@ -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);