tidb
tidb copied to clipboard
The results of condition = and <= have no implication to each other
Bug Report
When I use a more restrictive condition, the query results should be a subset of the previous one, but now there are values outside the set.
1. Minimal reproduce step (Required)
create table
create table table_3_utf8_undef (
`pk` int primary key,
`col_bigint_undef_signed` bigint ,
`col_bigint_undef_unsigned` bigint unsigned ,
`col_bigint_key_signed` bigint ,
`col_bigint_key_unsigned` bigint unsigned ,
`col_float_undef_signed` float ,
`col_float_undef_unsigned` float unsigned ,
`col_float_key_signed` float ,
`col_float_key_unsigned` float unsigned ,
`col_double_undef_signed` double ,
`col_double_undef_unsigned` double unsigned ,
`col_double_key_signed` double ,
`col_double_key_unsigned` double unsigned ,
`col_decimal(40, 20)_undef_signed` decimal(40, 20) ,
`col_decimal(40, 20)_undef_unsigned` decimal(40, 20) unsigned ,
`col_decimal(40, 20)_key_signed` decimal(40, 20) ,
`col_decimal(40, 20)_key_unsigned` decimal(40, 20) unsigned ,
`col_char(20)_undef_signed` char(20) ,
`col_char(20)_key_signed` char(20) ,
`col_varchar(20)_undef_signed` varchar(20) ,
`col_varchar(20)_key_signed` varchar(20) ,
key (`col_bigint_key_signed`),
key (`col_bigint_key_unsigned`),
key (`col_float_key_signed`),
key (`col_float_key_unsigned`),
key (`col_double_key_signed`),
key (`col_double_key_unsigned`),
key (`col_decimal(40, 20)_key_signed`),
key (`col_decimal(40, 20)_key_unsigned`),
key (`col_char(20)_key_signed`),
key (`col_varchar(20)_key_signed`)
) character set utf8 ;
insert into table_3_utf8_undef values (0,82.1847,1,39.0425,38.1089,-1,1,94.1106,1.009,12.991,19755,-13064,0,1,79.1429,-2,1,"well",'3
','-0','e'),(1,1,20.0078,-9.183,68.1957,1,2,1,0.0001,12.991,2,71.0510,1,-1,2,12.991,12.991,'3 ','1','3 ','-0'),(2,-2,1,-21247,1.009,2,1.009,0.0001,36.0002,-2,2,-0,0.0001,-2,0.1598,47.1515,1.009,'3 ','w','-1','e');
create table table_7_utf8_undef (
`pk` int primary key,
`col_bigint_undef_signed` bigint ,
`col_bigint_undef_unsigned` bigint unsigned ,
`col_bigint_key_signed` bigint ,
`col_bigint_key_unsigned` bigint unsigned ,
`col_float_undef_signed` float ,
`col_float_undef_unsigned` float unsigned ,
`col_float_key_signed` float ,
`col_float_key_unsigned` float unsigned ,
`col_double_undef_signed` double ,
`col_double_undef_unsigned` double unsigned ,
`col_double_key_signed` double ,
`col_double_key_unsigned` double unsigned ,
`col_decimal(40, 20)_undef_signed` decimal(40, 20) ,
`col_decimal(40, 20)_undef_unsigned` decimal(40, 20) unsigned ,
`col_decimal(40, 20)_key_signed` decimal(40, 20) ,
`col_decimal(40, 20)_key_unsigned` decimal(40, 20) unsigned ,
`col_char(20)_undef_signed` char(20) ,
`col_char(20)_key_signed` char(20) ,
`col_varchar(20)_undef_signed` varchar(20) ,
`col_varchar(20)_key_signed` varchar(20) ,
key (`col_bigint_key_signed`),
key (`col_bigint_key_unsigned`),
key (`col_float_key_signed`),
key (`col_float_key_unsigned`),
key (`col_double_key_signed`),
key (`col_double_key_unsigned`),
key (`col_decimal(40, 20)_key_signed`),
key (`col_decimal(40, 20)_key_unsigned`),
key (`col_char(20)_key_signed`),
key (`col_varchar(20)_key_signed`)
) character set utf8 ;
insert into table_7_utf8_undef values (0,-9.183,1,1.1384,2,15.1271,12.991,-2,0.0001,36.1270,79.1819,0.0001,0.0001,3.1387,52.0818,-0,0.0001,'1','3 ','0','0'),(1,79,12.991,107,2,-0.0001,0,1.009,1.009,34,1,-1,69.0208,1,2,120,12.991,'3 ','-1',"if",'b'),(2,-2,1,-9.183,1,12.991,0.0001,53,12.991,1.009,12.991,12.991,0.0001,-0.0001,12.991,0.0001,2,'3
','p','0','3 '),(3,-0.0001,12.991,1.009,1.009,-9.183,2,0,1,-2,1,2,1,2,1.009,2,12.991,'3
','0','k','0'),(4,1.009,0.0001,-1,12.991,2,47,2,0,12.991,12.991,1.009,0,1.009,1.009,-0.0001,6949,'-1',' 3','1','m'),(5,-0,1,0,0,0.0001,28.1237,12.991,0,12.991,12.991,-0,12.991,2,2,2,1.009,'0',' 3','0',' 3'),(6,45.0855,1,38.1166,1,1.009,80.0284,2,122,0.0001,0,-1,11130,0,1,1,0,"know",'-0','
3','3
');
query1:
WITH `MYWITH` AS ((SELECT (REPEAT(`f6`, 8)) AS `f1`,(DATE_ADD(~0, INTERVAL 1 HOUR_MICROSECOND)) AS `f2`,(0) AS `f3` FROM
(SELECT `col_double_key_unsigned` AS `f4`,`col_varchar(20)_key_signed` AS `f5`,`col_char(20)_key_signed` AS `f6` FROM `table_7_utf8_undef`
USE INDEX (`col_float_key_signed`, `col_decimal(40, 20)_key_signed`)) AS `t1` ORDER BY `f5`)
UNION ALL (SELECT (COLLATION(`f8`)) AS `f1`,(`f7`+SIGN(0.02087047389286014)) AS `f2`,(DATE_ADD(NULL, INTERVAL 1 HOUR_SECOND)) AS `f3`
FROM (SELECT `col_bigint_key_signed` AS `f7`,`col_double_key_signed` AS `f8`,`col_double_key_unsigned` AS `f9` FROM `table_7_utf8_undef`
USE INDEX (`col_float_key_unsigned`)) AS `t2`
WHERE ((((-`f8`)<=ANY
(SELECT `col_char(20)_key_signed` FROM `table_3_utf8_undef` IGNORE INDEX
(`col_double_key_unsigned`, `col_decimal(40, 20)_key_unsigned`))) IS TRUE) AND (NOT ((DATE_SUB(`f9`, INTERVAL 1 YEAR))>=(DATE_SUB(`f8`, INTERVAL 1 HOUR_MINUTE))))
AND ((CAST((`f8`) AS CHAR) NOT LIKE _UTF8MB4'%0%') IS FALSE)) IS FALSE HAVING ((((DATE_ADD(`f3`, INTERVAL 1 DAY_HOUR)) IN (LOG10(-7692179927919504847),LTRIM(`f1`),COT(-6524291123097959596)))
IS FALSE) OR (((`f3`)!=(CHARSET(`f3`))) IS FALSE) AND ((FROM_DAYS(8527277907550850100))<ALL (SELECT `col_char(20)_key_signed` FROM `table_3_utf8_undef`
USE INDEX (`col_float_key_unsigned`, `col_varchar(20)_key_signed`)))) IS FALSE)) SELECT * FROM `MYWITH`;
query2:
WITH `MYWITH` AS ((SELECT (REPEAT(`f6`, 8)) AS `f1`,(DATE_ADD(~0, INTERVAL 1 HOUR_MICROSECOND)) AS `f2`,(0) AS `f3` FROM
(SELECT `col_double_key_unsigned` AS `f4`,`col_varchar(20)_key_signed` AS `f5`,`col_char(20)_key_signed` AS `f6` FROM `table_7_utf8_undef`
USE INDEX (`col_float_key_signed`, `col_decimal(40, 20)_key_signed`)) AS `t1` ORDER BY `f5`)
UNION ALL (SELECT (COLLATION(`f8`)) AS `f1`,(`f7`+SIGN(0.02087047389286014)) AS `f2`,(DATE_ADD(NULL, INTERVAL 1 HOUR_SECOND)) AS `f3`
FROM (SELECT `col_bigint_key_signed` AS `f7`,`col_double_key_signed` AS `f8`,`col_double_key_unsigned` AS `f9` FROM `table_7_utf8_undef`
USE INDEX (`col_float_key_unsigned`)) AS `t2`
WHERE ((((-`f8`)=ANY
(SELECT `col_char(20)_key_signed` FROM `table_3_utf8_undef` IGNORE INDEX
(`col_double_key_unsigned`, `col_decimal(40, 20)_key_unsigned`))) IS TRUE) AND (NOT ((DATE_SUB(`f9`, INTERVAL 1 YEAR))>=(DATE_SUB(`f8`, INTERVAL 1 HOUR_MINUTE))))
AND ((CAST((`f8`) AS CHAR) NOT LIKE _UTF8MB4'%0%') IS FALSE)) IS FALSE HAVING ((((DATE_ADD(`f3`, INTERVAL 1 DAY_HOUR)) IN (LOG10(-7692179927919504847),LTRIM(`f1`),COT(-6524291123097959596)))
IS FALSE) OR (((`f3`)!=(CHARSET(`f3`))) IS FALSE) AND ((FROM_DAYS(8527277907550850100))<ALL (SELECT `col_char(20)_key_signed` FROM `table_3_utf8_undef`
USE INDEX (`col_float_key_unsigned`, `col_varchar(20)_key_signed`)))) IS FALSE)) SELECT * FROM `MYWITH`;
2. What did you expect to see? (Required)
Because = is more binding than <=, result1 should contain result2
3. What did you see instead (Required)
result1:
+------------------+------+------+
| f1 | f2 | f3 |
+------------------+------+------+
| binary | 108 | NULL |
| binary | -8 | NULL |
| binary | 2 | NULL |
| binary | 39 | NULL |
| 33333333 | NULL | 0 |
| -1-1-1-1-1-1-1-1 | NULL | 0 |
| pppppppp | NULL | 0 |
| 00000000 | NULL | 0 |
| 33333333 | NULL | 0 |
| 33333333 | NULL | 0 |
| -0-0-0-0-0-0-0-0 | NULL | 0 |
+------------------+------+------+
11 rows in set, 30 warnings (0.010 sec)
result2:
+------------------+------+------+
| f1 | f2 | f3 |
+------------------+------+------+
| 33333333 | NULL | 0 |
| -1-1-1-1-1-1-1-1 | NULL | 0 |
| pppppppp | NULL | 0 |
| 00000000 | NULL | 0 |
| 33333333 | NULL | 0 |
| 33333333 | NULL | 0 |
| -0-0-0-0-0-0-0-0 | NULL | 0 |
| binary | 2 | NULL |
| binary | 108 | NULL |
| binary | -8 | NULL |
| binary | 2 | NULL |
| binary | 0 | NULL |
| binary | 39 | NULL |
+------------------+------+------+
13 rows in set, 20 warnings (0.005 sec)
4. What is your TiDB version? (Required)
8.0.11-TiDB-v7.5.0
Could you please confirm whether the simplification process we applied has been helpful for developers in diagnosing and addressing this issue?
query1:
(SELECT (`f7`+SIGN(0.02087047389286014)) AS `f2`,(DATE_ADD(NULL, INTERVAL 1 HOUR_SECOND)) AS `f3` FROM
(SELECT `col_bigint_key_signed` AS `f7`,`col_double_key_signed` AS `f8` FROM `table_7_utf8_undef`) AS `t2` WHERE
((-`f8`)<=ANY (SELECT `col_char(20)_key_signed` FROM `table_3_utf8_undef` ))
HAVING (DATE_ADD(`f3`, INTERVAL 1 DAY_HOUR ) IS FALSE) IS FALSE);
result1:
+------+------+
| f2 | f3 |
+------+------+
| 2 | NULL |
| -8 | NULL |
| 2 | NULL |
| 0 | NULL |
| 1 | NULL |
+------+------+
5 rows in set, 7 warnings (0.002 sec)
query2:
(SELECT (`f7`+SIGN(0.02087047389286014)) AS `f2`,(DATE_ADD(NULL, INTERVAL 1 HOUR_SECOND)) AS `f3` FROM
(SELECT `col_bigint_key_signed` AS `f7`,`col_double_key_signed` AS `f8` FROM `table_7_utf8_undef`) AS `t2` WHERE
((-`f8`)=ANY (SELECT `col_char(20)_key_signed` FROM `table_3_utf8_undef` ) )
HAVING (DATE_ADD(`f3`, INTERVAL 1 DAY_HOUR ) IS FALSE) IS FALSE);
result2:
+------+------+
| f2 | f3 |
+------+------+
| 108 | NULL |
| 1 | NULL |
| 39 | NULL |
+------+------+
3 rows in set, 7 warnings (0.003 sec)
Could you please confirm whether the simplification process we applied has been helpful for developers in diagnosing and addressing this issue?
query1:
(SELECT (`f7`+SIGN(0.02087047389286014)) AS `f2`,(DATE_ADD(NULL, INTERVAL 1 HOUR_SECOND)) AS `f3` FROM (SELECT `col_bigint_key_signed` AS `f7`,`col_double_key_signed` AS `f8` FROM `table_7_utf8_undef`) AS `t2` WHERE ((-`f8`)<=ANY (SELECT `col_char(20)_key_signed` FROM `table_3_utf8_undef` )) HAVING (DATE_ADD(`f3`, INTERVAL 1 DAY_HOUR ) IS FALSE) IS FALSE);
result1:
+------+------+ | f2 | f3 | +------+------+ | 2 | NULL | | -8 | NULL | | 2 | NULL | | 0 | NULL | | 1 | NULL | +------+------+ 5 rows in set, 7 warnings (0.002 sec)
query2:
(SELECT (`f7`+SIGN(0.02087047389286014)) AS `f2`,(DATE_ADD(NULL, INTERVAL 1 HOUR_SECOND)) AS `f3` FROM (SELECT `col_bigint_key_signed` AS `f7`,`col_double_key_signed` AS `f8` FROM `table_7_utf8_undef`) AS `t2` WHERE ((-`f8`)=ANY (SELECT `col_char(20)_key_signed` FROM `table_3_utf8_undef` ) ) HAVING (DATE_ADD(`f3`, INTERVAL 1 DAY_HOUR ) IS FALSE) IS FALSE);
result2:
+------+------+ | f2 | f3 | +------+------+ | 108 | NULL | | 1 | NULL | | 39 | NULL | +------+------+ 3 rows in set, 7 warnings (0.003 sec)
@akuluasan I think the simplified version can help us rule out the CTE.
Analyze:
mysql> SELECT `col_bigint_key_signed` AS `f7`,`col_double_key_signed` FROM `table_7_utf8_undef` WHERE( (-col_double_key_signed) <=ANY(SELECT `col_char(20)_key_signed` FROM `table_3_utf8_undef`)) ;
+------+-----------------------+
| f7 | col_double_key_signed |
+------+-----------------------+
| 1 | 0.0001 |
| -9 | 12.991 |
| 1 | 2 |
| -1 | 1.009 |
| 0 | 0 |
+------+-----------------------+
5 rows in set, 7 warnings (0.00 sec)
mysql> SELECT `col_bigint_key_signed` AS `f7`,`col_double_key_signed` FROM `table_7_utf8_undef` WHERE( (-col_double_key_signed) =ANY(SELECT `col_char(20)_key_signed` FROM `table_3_utf8_undef`)) ;
+------+-----------------------+
| f7 | col_double_key_signed |
+------+-----------------------+
| 107 | -1 |
| 0 | 0 |
| 38 | -1 |
+------+-----------------------+
3 rows in set, 7 warnings (0.00 sec)
<=ANY
will rewrite to <= Max
.
And
mysql> SELECT `col_char(20)_key_signed` FROM `table_3_utf8_undef`;
+-------------------------+
| col_char(20)_key_signed |
+-------------------------+
| 1 |
| 3
|
| w |
+-------------------------+
3 rows in set (0.00 sec)
mysql> SELECT max(`col_char(20)_key_signed`) FROM `table_3_utf8_undef`;
+--------------------------------+
| max(`col_char(20)_key_signed`) |
+--------------------------------+
| w |
+--------------------------------+
1 row in set (0.01 sec)
w will cast to 0 when compared with the -f8
Thanks for the Analyze!
Related to https://github.com/pingcap/tidb/pull/20062, https://github.com/pingcap/tidb/issues/52755
/severity major
Analyze:
mysql> SELECT `col_bigint_key_signed` AS `f7`,`col_double_key_signed` FROM `table_7_utf8_undef` WHERE( (-col_double_key_signed) <=ANY(SELECT `col_char(20)_key_signed` FROM `table_3_utf8_undef`)) ; +------+-----------------------+ | f7 | col_double_key_signed | +------+-----------------------+ | 1 | 0.0001 | | -9 | 12.991 | | 1 | 2 | | -1 | 1.009 | | 0 | 0 | +------+-----------------------+ 5 rows in set, 7 warnings (0.00 sec) mysql> SELECT `col_bigint_key_signed` AS `f7`,`col_double_key_signed` FROM `table_7_utf8_undef` WHERE( (-col_double_key_signed) =ANY(SELECT `col_char(20)_key_signed` FROM `table_3_utf8_undef`)) ; +------+-----------------------+ | f7 | col_double_key_signed | +------+-----------------------+ | 107 | -1 | | 0 | 0 | | 38 | -1 | +------+-----------------------+ 3 rows in set, 7 warnings (0.00 sec)
<=ANY
will rewrite to<= Max
.And
mysql> SELECT `col_char(20)_key_signed` FROM `table_3_utf8_undef`; +-------------------------+ | col_char(20)_key_signed | +-------------------------+ | 1 | | 3 | | w | +-------------------------+ 3 rows in set (0.00 sec) mysql> SELECT max(`col_char(20)_key_signed`) FROM `table_3_utf8_undef`; +--------------------------------+ | max(`col_char(20)_key_signed`) | +--------------------------------+ | w | +--------------------------------+ 1 row in set (0.01 sec)
w will cast to 0 when compared with the
-f8
From this analyze, it seems not proper to rewrite this ANY to <= max, because it's not fully equivalent when implicit casting exists. Change to planner issue.
/remove-sig execution
/sig planner
The <= ANY rewrite to <= MAX is a correctly rewrite.
But the key issue is that planner should cast ANY to the double type, and then compute the max function.
× <=cast(max(col_char(20)_key_signed
) as double)
✔️ <=max(cast(col_char(20)_key_signed
as double))
Reproduce step
mysql> create table table_3_utf8_undef (`col_char(20)_key_signed` char(20));
Query OK, 0 rows affected (0.09 sec)
mysql> insert into table_3_utf8_undef values ('1');
Query OK, 1 row affected (0.01 sec)
mysql> insert into table_3_utf8_undef values ('3');
Query OK, 1 row affected (0.00 sec)
mysql> insert into table_3_utf8_undef values (' ');
Query OK, 1 row affected (0.00 sec)
mysql> insert into table_3_utf8_undef values ('w');
Query OK, 1 row affected (0.00 sec)
mysql> select * from table_3_utf8_undef;
+-------------------------+
| col_char(20)_key_signed |
+-------------------------+
| 1 |
| 3 |
| |
| w |
+-------------------------+
4 rows in set (0.00 sec)
mysql> SELECT max(`col_char(20)_key_signed`) FROM `table_3_utf8_undef`;
+--------------------------------+
| max(`col_char(20)_key_signed`) |
+--------------------------------+
| w |
+--------------------------------+
1 row in set (0.00 sec)
mysql> create table table_7_utf8_undef (`col_double_key_signed` double);
Query OK, 0 rows affected (0.09 sec)
mysql> insert into table_7_utf8_undef values (0.0001);
Query OK, 1 row affected (0.01 sec)
mysql> insert into table_7_utf8_undef values (0);
Query OK, 1 row affected (0.00 sec)
mysql> insert into table_7_utf8_undef values (2);
Query OK, 1 row affected (0.00 sec)
mysql> insert into table_7_utf8_undef values (-1);
Query OK, 1 row affected (0.01 sec)
mysql> SELECT `col_double_key_signed` FROM `table_7_utf8_undef` WHERE( (-col_double_key_signed) <=ANY(SELECT `col_char(20)_key_signed` FROM `table_3_utf8_undef`)) ;
+-----------------------+
| col_double_key_signed |
+-----------------------+
| 0.0001 |
| 0 |
| 2 |
+-----------------------+
3 rows in set, 4 warnings (0.00 sec)
mysql> SELECT `col_double_key_signed` FROM `table_7_utf8_undef` WHERE( (-col_double_key_signed) =ANY(SELECT `col_char(20)_key_signed` FROM `table_3_utf8_undef`)) ;
+-----------------------+
| col_double_key_signed |
+-----------------------+
| 0 |
| -1 |
+-----------------------+
2 rows in set, 4 warnings (0.01 sec)
mysql> select tidb_version();
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| tidb_version() |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Release Version: v8.0.0
Edition: Community
Git Commit Hash: 8ba1fa452b1ccdbfb85879ea94b9254aabba2916
Git Branch: HEAD
UTC Build Time: 2024-03-28 14:22:34
GoVersion: go1.21.6
Race Enabled: false
Check Table Before Drop: false
Store: tikv |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.01 sec)
Still have the same problem in v6.5
mysql> SELECT `col_double_key_signed` FROM `table_7_utf8_undef` WHERE( (-col_double_key_signed) <=ANY(SELECT `col_char(20)_key_signed` FROM `table_3_utf8_undef`)) ;
+-----------------------+
| col_double_key_signed |
+-----------------------+
| 0.0001 |
| 0 |
| 2 |
+-----------------------+
3 rows in set, 4 warnings (0.01 sec)
mysql> SELECT `col_double_key_signed` FROM `table_7_utf8_undef` WHERE( (-col_double_key_signed) =ANY(SELECT `col_char(20)_key_signed` FROM `table_3_utf8_undef`)) ;
+-----------------------+
| col_double_key_signed |
+-----------------------+
| 0 |
| -1 |
+-----------------------+
2 rows in set, 4 warnings (0.00 sec)
mysql> select tidb_version();
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| tidb_version() |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Release Version: v6.5.0
Edition: Community
Git Commit Hash: 706c3fa3c526cdba5b3e9f066b1a568fb96c56e3
Git Branch: heads/refs/tags/v6.5.0
UTC Build Time: 2022-12-27 03:42:38
GoVersion: go1.19.3
Race Enabled: false
TiKV Min Version: 6.2.0-alpha
Check Table Before Drop: false
Store: tikv |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.01 sec)