From a21e24c2bcbefa7c0fcd13dc54ed1b288f8e5aec Mon Sep 17 00:00:00 2001 From: Ti Chi Robot Date: Tue, 20 Sep 2022 11:35:01 +0800 Subject: [PATCH] fix: the results of tikv and tiflash are different (#5839) (#5869) close pingcap/tiflash#5849, close pingcap/tidb#37258 --- dbms/src/Functions/FunctionsLogical.h | 18 +++++++++++++++++- tests/fullstack-test/expr/logical_op.test | 17 +++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/dbms/src/Functions/FunctionsLogical.h b/dbms/src/Functions/FunctionsLogical.h index 82aa25884eb..edb2f792ea2 100644 --- a/dbms/src/Functions/FunctionsLogical.h +++ b/dbms/src/Functions/FunctionsLogical.h @@ -138,7 +138,23 @@ struct AssociativeOperationImpl { if (Op::isSaturable()) { - UInt8 a = vec[i]; + // cast a: UInt8 -> bool -> UInt8 is a trick + // TiFlash converts columns with non-UInt8 type to UInt8 type and sets value to 0 or 1 + // which correspond to false or true. However, for columns with UInt8 type, + // no more convertion will be executed on them and the values stored + // in them are 'origin' which means that they won't be converted to 0 or 1. + // For example: + // Input column with non-UInt8 type: + // column_values = {-2, 0, 2} + // then, they will be converted to: + // vec = {1, 0, 1} (here vec stores converted values) + // + // Input column with UInt8 type: + // column_values = {1, 0, 2} + // then, the vec will be: + // vec = {1, 0, 2} (error, we only want 0 or 1) + // See issue: https://github.com/pingcap/tidb/issues/37258 + bool a = static_cast(vec[i]); return Op::isSaturatedValue(a) ? a : continuation.apply(i); } else diff --git a/tests/fullstack-test/expr/logical_op.test b/tests/fullstack-test/expr/logical_op.test index b64b4ff35e3..438f881d2cb 100644 --- a/tests/fullstack-test/expr/logical_op.test +++ b/tests/fullstack-test/expr/logical_op.test @@ -1,19 +1,24 @@ mysql> drop table if exists test.t1; mysql> drop table if exists test.t2; mysql> drop table if exists test.t3; +mysql> drop table if exists test.t4; mysql> create table test.t1(a char(20),b double); mysql> create table test.t2(a char(20)); mysql> create table test.t3(a int); +mysql> create table test.t4(a tinyint(45) unsigned NOT NULL, b bigint(20) NOT NULL); mysql> insert into test.t1 values(1,null),('j',0),(1,12.991),(0,0),(0,0),('they',1.009),('can',-99),(0,12.991),(1,-9.183),(null,1); mysql> insert into test.t2 values(0),(0),(0),(0),(0),(0),(1),('with'),('see'),(null); mysql> insert into test.t3 values(0),(1); +mysql> insert into test.t4 values(65, 1),(66, 2), (67, 3), (0, 0); mysql> alter table test.t1 set tiflash replica 1; mysql> alter table test.t2 set tiflash replica 1; mysql> alter table test.t3 set tiflash replica 1; +mysql> alter table test.t4 set tiflash replica 1; func> wait_table test t1 func> wait_table test t2 func> wait_table test t3 +func> wait_table test t4 mysql> set session tidb_isolation_read_engines='tiflash'; select count(*) from test.t1 where (b between null and 100) is null; +----------+ @@ -67,6 +72,18 @@ mysql> set tidb_enforce_mpp=1; set tidb_isolation_read_engines='tiflash'; select mysql> set tidb_enforce_mpp=1; set tidb_isolation_read_engines='tiflash'; select count(*) from test.t3 group by a having ifnull(null,count(*)) and min(null); # empty +# issue 5849 +mysql> set tidb_enforce_mpp=1; set tidb_isolation_read_engines='tiflash'; select a or b from test.t4; ++--------+ +| a or b | ++--------+ +| 1 | +| 1 | +| 1 | +| 0 | ++--------+ + #mysql> drop table if exists test.t1; #mysql> drop table if exists test.t2; #mysql> drop table if exists test.t3; +#mysql> drop table if exists test.t4;