From 2e2016582e9caa7dce4184f36285d4910b0aee2f Mon Sep 17 00:00:00 2001 From: guo-shaoge Date: Mon, 27 May 2024 17:49:30 +0800 Subject: [PATCH 1/4] expression: fix wrong result when convert float to unsigned Signed-off-by: guo-shaoge --- pkg/expression/builtin_compare.go | 5 ++++- pkg/expression/integration_test/integration_test.go | 11 +++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/pkg/expression/builtin_compare.go b/pkg/expression/builtin_compare.go index d20797b8cdaf8..370f94bd5c925 100644 --- a/pkg/expression/builtin_compare.go +++ b/pkg/expression/builtin_compare.go @@ -1428,7 +1428,10 @@ func RefineComparedConstant(ctx BuildContext, targetFieldType types.FieldType, c targetFieldType = *types.NewFieldType(mysql.TypeLonglong) } var intDatum types.Datum - intDatum, err = dt.ConvertTo(evalCtx.TypeCtx(), &targetFieldType) + // Enable AllowNegativeToUnsigned to make sure return 0 when underflow happens. + oriTypeCtx := evalCtx.TypeCtx() + newTypeCtx := oriTypeCtx.WithFlags(oriTypeCtx.Flags().WithAllowNegativeToUnsigned(false)) + intDatum, err = dt.ConvertTo(newTypeCtx, &targetFieldType) if err != nil { if terror.ErrorEqual(err, types.ErrOverflow) { return &Constant{ diff --git a/pkg/expression/integration_test/integration_test.go b/pkg/expression/integration_test/integration_test.go index f8ef22f18a856..9b2eb85dd4ee8 100644 --- a/pkg/expression/integration_test/integration_test.go +++ b/pkg/expression/integration_test/integration_test.go @@ -3032,3 +3032,14 @@ func TestIssue43527(t *testing.T) { "SELECT @total := @total + d FROM (SELECT d FROM test) AS temp, (SELECT @total := b FROM test) AS T1 where @total >= 100", ).Check(testkit.Rows("200", "300", "400", "500")) } + +func TestNegFloatConvertToUnsigned(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t0") + tk.MustExec("create table t0(c0 tinyint(1) unsigned not null )") + tk.MustExec("insert into t0 values (1)") + tk.MustQuery("select * from t0 where case 0 when (t0.c0)>(-1.194192591e9) then null else 1 end;").Check(testkit.Rows("1")) + tk.MustQuery("select (t0.c0)>(-1.194192591e9) from t0;").Check(testkit.Rows("1")) +} From 9d0507db91d67f799f2bae4d2caa41ca1e9d2f9a Mon Sep 17 00:00:00 2001 From: guo-shaoge Date: Mon, 27 May 2024 18:01:24 +0800 Subject: [PATCH 2/4] bazel Signed-off-by: guo-shaoge --- pkg/expression/integration_test/BUILD.bazel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/expression/integration_test/BUILD.bazel b/pkg/expression/integration_test/BUILD.bazel index 1e47b89a78cbc..8d15c35a41453 100644 --- a/pkg/expression/integration_test/BUILD.bazel +++ b/pkg/expression/integration_test/BUILD.bazel @@ -8,7 +8,7 @@ go_test( "main_test.go", ], flaky = True, - shard_count = 26, + shard_count = 27, deps = [ "//pkg/config", "//pkg/domain", From 0531b23ae0b69343f1658727bd37150d09727a48 Mon Sep 17 00:00:00 2001 From: guo-shaoge Date: Mon, 27 May 2024 19:36:53 +0800 Subject: [PATCH 3/4] comment Signed-off-by: guo-shaoge --- pkg/expression/builtin_compare.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/expression/builtin_compare.go b/pkg/expression/builtin_compare.go index 370f94bd5c925..ec771ad9ee8aa 100644 --- a/pkg/expression/builtin_compare.go +++ b/pkg/expression/builtin_compare.go @@ -1428,7 +1428,7 @@ func RefineComparedConstant(ctx BuildContext, targetFieldType types.FieldType, c targetFieldType = *types.NewFieldType(mysql.TypeLonglong) } var intDatum types.Datum - // Enable AllowNegativeToUnsigned to make sure return 0 when underflow happens. + // Disable AllowNegativeToUnsigned to make sure return 0 when underflow happens. oriTypeCtx := evalCtx.TypeCtx() newTypeCtx := oriTypeCtx.WithFlags(oriTypeCtx.Flags().WithAllowNegativeToUnsigned(false)) intDatum, err = dt.ConvertTo(newTypeCtx, &targetFieldType) From d52311dd96626778c9cafb99c0163bc8847476a8 Mon Sep 17 00:00:00 2001 From: guo-shaoge Date: Tue, 28 May 2024 10:18:03 +0800 Subject: [PATCH 4/4] fix case Signed-off-by: guo-shaoge --- pkg/expression/integration_test/BUILD.bazel | 2 +- .../integration_test/integration_test.go | 11 ------- .../integrationtest/r/expression/cast.result | 30 +++++++++++++++++++ tests/integrationtest/t/expression/cast.test | 14 +++++++++ 4 files changed, 45 insertions(+), 12 deletions(-) diff --git a/pkg/expression/integration_test/BUILD.bazel b/pkg/expression/integration_test/BUILD.bazel index 8d15c35a41453..1e47b89a78cbc 100644 --- a/pkg/expression/integration_test/BUILD.bazel +++ b/pkg/expression/integration_test/BUILD.bazel @@ -8,7 +8,7 @@ go_test( "main_test.go", ], flaky = True, - shard_count = 27, + shard_count = 26, deps = [ "//pkg/config", "//pkg/domain", diff --git a/pkg/expression/integration_test/integration_test.go b/pkg/expression/integration_test/integration_test.go index 9b2eb85dd4ee8..f8ef22f18a856 100644 --- a/pkg/expression/integration_test/integration_test.go +++ b/pkg/expression/integration_test/integration_test.go @@ -3032,14 +3032,3 @@ func TestIssue43527(t *testing.T) { "SELECT @total := @total + d FROM (SELECT d FROM test) AS temp, (SELECT @total := b FROM test) AS T1 where @total >= 100", ).Check(testkit.Rows("200", "300", "400", "500")) } - -func TestNegFloatConvertToUnsigned(t *testing.T) { - store := testkit.CreateMockStore(t) - tk := testkit.NewTestKit(t, store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t0") - tk.MustExec("create table t0(c0 tinyint(1) unsigned not null )") - tk.MustExec("insert into t0 values (1)") - tk.MustQuery("select * from t0 where case 0 when (t0.c0)>(-1.194192591e9) then null else 1 end;").Check(testkit.Rows("1")) - tk.MustQuery("select (t0.c0)>(-1.194192591e9) from t0;").Check(testkit.Rows("1")) -} diff --git a/tests/integrationtest/r/expression/cast.result b/tests/integrationtest/r/expression/cast.result index d54c9aea37ea1..76c9977dc52fb 100644 --- a/tests/integrationtest/r/expression/cast.result +++ b/tests/integrationtest/r/expression/cast.result @@ -118,3 +118,33 @@ select null as a union all select 'a' as a; a NULL a +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 index 854daad9756b5..03843628ab9e6 100644 --- a/tests/integrationtest/t/expression/cast.test +++ b/tests/integrationtest/t/expression/cast.test @@ -73,3 +73,17 @@ select cast(cast('14:15' as time) as year) = YEAR(CURDATE()); explain select null as a union all select 'a' as a; --sorted_result select null as a union all select 'a' as a; + +# 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;