From d9c5bf64d0dd123180a60642337956face1c1e3d Mon Sep 17 00:00:00 2001 From: Ti Chi Robot Date: Tue, 28 May 2024 17:58:21 +0800 Subject: [PATCH] expression: fix wrong result when convert float to unsigned (#53590) (#53621) close pingcap/tidb#41736 --- expression/builtin_compare.go | 6 ++++ sessionctx/stmtctx/stmtctx.go | 5 +++- .../integrationtest/r/expression/cast.result | 30 +++++++++++++++++++ tests/integrationtest/t/expression/cast.test | 13 ++++++++ 4 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 tests/integrationtest/r/expression/cast.result create mode 100644 tests/integrationtest/t/expression/cast.test diff --git a/expression/builtin_compare.go b/expression/builtin_compare.go index 2da9c799bb20c..74d7c60043df5 100644 --- a/expression/builtin_compare.go +++ b/expression/builtin_compare.go @@ -1481,6 +1481,12 @@ func RefineComparedConstant(ctx sessionctx.Context, targetFieldType types.FieldT targetFieldType = *types.NewFieldType(mysql.TypeLonglong) } var intDatum types.Datum + // To make sure return zero when underflow happens. + oriFlag := sc.IsRefineComparedConstant + sc.IsRefineComparedConstant = true + defer func() { + sc.IsRefineComparedConstant = oriFlag + }() intDatum, err = dt.ConvertTo(sc, &targetFieldType) if err != nil { if terror.ErrorEqual(err, types.ErrOverflow) { diff --git a/sessionctx/stmtctx/stmtctx.go b/sessionctx/stmtctx/stmtctx.go index d8e0bc7cd5fb7..e621a05e549e6 100644 --- a/sessionctx/stmtctx/stmtctx.go +++ b/sessionctx/stmtctx/stmtctx.go @@ -181,6 +181,9 @@ type StatementContext struct { IsStaleness bool InRestrictedSQL bool ViewDepth int32 + + IsRefineComparedConstant bool + // mu struct holds variables that change during execution. mu struct { sync.Mutex @@ -994,7 +997,7 @@ func (sc *StatementContext) GetExecDetails() execdetails.ExecDetails { // This is the case for `insert`, `update`, `alter table`, `create table` and `load data infile` statements, when not in strict SQL mode. // see https://dev.mysql.com/doc/refman/5.7/en/out-of-range-and-overflow.html func (sc *StatementContext) ShouldClipToZero() bool { - return sc.InInsertStmt || sc.InLoadDataStmt || sc.InUpdateStmt || sc.InCreateOrAlterStmt || sc.IsDDLJobInQueue + return sc.InInsertStmt || sc.InLoadDataStmt || sc.InUpdateStmt || sc.InCreateOrAlterStmt || sc.IsDDLJobInQueue || sc.IsRefineComparedConstant } // ShouldIgnoreOverflowError indicates whether we should ignore the error when type conversion overflows, diff --git a/tests/integrationtest/r/expression/cast.result b/tests/integrationtest/r/expression/cast.result new file mode 100644 index 0000000000000..c7938cb727e72 --- /dev/null +++ b/tests/integrationtest/r/expression/cast.result @@ -0,0 +1,30 @@ +drop table if exists t0; +create table t0(c0 tinyint(1) unsigned not null ); +insert into t0 values (1); +select * from t0 where case 0 when t0.c0 > -1.194192591e9 then null else 1 end; +c0 +1 +select t0.c0 > -1.194192591e9 from t0; +t0.c0 > -1.194192591e9 +1 +select t0.c0 < -1.194192591e9 from t0; +t0.c0 < -1.194192591e9 +0 +select -1.194192591e9 > t0.c0 from t0; +-1.194192591e9 > t0.c0 +0 +select -1.194192591e9 < t0.c0 from t0; +-1.194192591e9 < t0.c0 +1 +select t0.c0 > 1.194192591e9 from t0; +t0.c0 > 1.194192591e9 +0 +select t0.c0 < 1.194192591e9 from t0; +t0.c0 < 1.194192591e9 +1 +select 1.194192591e9 > t0.c0 from t0; +1.194192591e9 > t0.c0 +1 +select 1.194192591e9 < t0.c0 from t0; +1.194192591e9 < t0.c0 +0 diff --git a/tests/integrationtest/t/expression/cast.test b/tests/integrationtest/t/expression/cast.test new file mode 100644 index 0000000000000..6876072d60365 --- /dev/null +++ b/tests/integrationtest/t/expression/cast.test @@ -0,0 +1,13 @@ +# TestNegFloatConvertToUnsigned +drop table if exists t0; +create table t0(c0 tinyint(1) unsigned not null ); +insert into t0 values (1); +select * from t0 where case 0 when t0.c0 > -1.194192591e9 then null else 1 end; +select t0.c0 > -1.194192591e9 from t0; +select t0.c0 < -1.194192591e9 from t0; +select -1.194192591e9 > t0.c0 from t0; +select -1.194192591e9 < t0.c0 from t0; +select t0.c0 > 1.194192591e9 from t0; +select t0.c0 < 1.194192591e9 from t0; +select 1.194192591e9 > t0.c0 from t0; +select 1.194192591e9 < t0.c0 from t0;