diff --git a/expression/bench_test.go b/expression/bench_test.go index f5cd8a00df..297c1ebf5c 100644 --- a/expression/bench_test.go +++ b/expression/bench_test.go @@ -1796,21 +1796,6 @@ func (s *testVectorizeSuite2) TestVecEvalBool(c *C) { } } -func (s *testVectorizeSuite2) TestVecToBool(c *C) { - ctx := mock.NewContext() - buf := chunk.NewColumn(eType2FieldType(types.ETString), 2) - buf.ReserveString(1) - buf.AppendString("999999999999999999923") - c.Assert(toBool(ctx.GetSessionVars().StmtCtx, types.ETString, buf, []int{0, 1}, []int8{0, 0}), NotNil) - buf.ReserveString(1) - buf.AppendString("23") - c.Assert(toBool(ctx.GetSessionVars().StmtCtx, types.ETString, buf, []int{0, 1}, []int8{0, 0}), IsNil) - buf.ReserveString(2) - buf.AppendString("999999999999999999923") - buf.AppendString("23") - c.Assert(toBool(ctx.GetSessionVars().StmtCtx, types.ETString, buf, []int{0, 1}, []int8{0, 0}), NotNil) -} - func BenchmarkVecEvalBool(b *testing.B) { ctx := mock.NewContext() selected := make([]bool, 0, 1024) diff --git a/expression/expression.go b/expression/expression.go index 2770474310..ba77f8772d 100644 --- a/expression/expression.go +++ b/expression/expression.go @@ -427,12 +427,9 @@ func toBool(sc *stmtctx.StatementContext, eType types.EvalType, buf *chunk.Colum if buf.IsNull(i) { isZero[i] = -1 } else { - iVal, err := types.StrToInt(sc, buf.GetString(i)) + iVal, err := types.StrToFloat(sc, buf.GetString(i)) if err != nil { - iVal, err = HandleOverflowOnSelection(sc, iVal, err) - if err != nil { - return err - } + return err } if iVal == 0 { isZero[i] = 0 diff --git a/expression/integration_test.go b/expression/integration_test.go index c814f9c396..44eb9d2707 100755 --- a/expression/integration_test.go +++ b/expression/integration_test.go @@ -6101,6 +6101,37 @@ func (s *testIntegrationSerialSuite) TestCollateDDL(c *C) { tk.MustExec("drop database t;") } +func (s *testIntegrationSuite) TestIssue15986(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t0") + tk.MustExec("CREATE TABLE t0(c0 int)") + tk.MustExec("INSERT INTO t0 VALUES (0)") + tk.MustQuery("SELECT t0.c0 FROM t0 WHERE CHAR(204355900);").Check(testkit.Rows("0")) + tk.MustQuery("SELECT t0.c0 FROM t0 WHERE not CHAR(204355900);").Check(testkit.Rows()) + tk.MustQuery("SELECT t0.c0 FROM t0 WHERE '.0';").Check(testkit.Rows()) + tk.MustQuery("SELECT t0.c0 FROM t0 WHERE not '.0';").Check(testkit.Rows("0")) + // If the number does not exceed the range of float64 and its value is not 0, it will be converted to true. + tk.MustQuery("select * from t0 where '.000000000000000000000000000000000000000000000000000000" + + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + + "0000000000000000000000000000000000000000000000000000000000000000009';").Check(testkit.Rows("0")) + tk.MustQuery("select * from t0 where not '.000000000000000000000000000000000000000000000000000000" + + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + + "0000000000000000000000000000000000000000000000000000000000000000009';").Check(testkit.Rows()) + + // If the number is truncated beyond the range of float64, it will be converted to true when the truncated result is 0. + tk.MustQuery("select * from t0 where '.0000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000009';").Check(testkit.Rows()) + tk.MustQuery("select * from t0 where not '.0000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000009';").Check(testkit.Rows("0")) +} + func (s *testIntegrationSuite) TestNegativeZeroForHashJoin(c *C) { tk := testkit.NewTestKit(c, s.store) tk.MustExec("use test;") diff --git a/types/datum.go b/types/datum.go index 132ce47738..725aa61670 100644 --- a/types/datum.go +++ b/types/datum.go @@ -1437,7 +1437,7 @@ func (d *Datum) ToBool(sc *stmtctx.StatementContext) (int64, error) { case KindFloat64: isZero = RoundFloat(d.GetFloat64()) == 0 case KindString, KindBytes: - iVal, err1 := StrToInt(sc, d.GetString()) + iVal, err1 := StrToFloat(sc, d.GetString()) isZero, err = iVal == 0, err1 case KindMysqlTime: isZero = d.GetMysqlTime().IsZero() diff --git a/types/datum_test.go b/types/datum_test.go index 1693eaa509..13dff4726c 100644 --- a/types/datum_test.go +++ b/types/datum_test.go @@ -72,9 +72,9 @@ func (ts *testDatumSuite) TestToBool(c *C) { testDatumToBool(c, float64(0.5), 1) testDatumToBool(c, float64(0.499), 0) testDatumToBool(c, "", 0) - testDatumToBool(c, "0.1", 0) + testDatumToBool(c, "0.1", 1) testDatumToBool(c, []byte{}, 0) - testDatumToBool(c, []byte("0.1"), 0) + testDatumToBool(c, []byte("0.1"), 1) testDatumToBool(c, NewBinaryLiteralFromUint(0, -1), 0) testDatumToBool(c, Enum{Name: "a", Value: 1}, 1) testDatumToBool(c, Set{Name: "a", Value: 1}, 1)