Bug #70886 MIN/MAX optimizer doesn't take into account type conversions
Submitted: 12 Nov 2013 10:42 Modified: 12 Nov 2013 11:01
Reporter: Sergey Petrunya Email Updates:
Status: Verified Impact on me:
None 
Category:MySQL Server: Optimizer Severity:S3 (Non-critical)
Version:5.5.32, 5.6 OS:Any
Assigned to: CPU Architecture:Any

[12 Nov 2013 10:42] Sergey Petrunya
Description:
MIN/MAX optimizer doesn't take into account type conversions. This means that queries may return different values depending on whether the table has an index.

I am attaching a testcase to demonstrate the problem. This particular testcase looks artificial and unrealistic (who stores INT values in a char column), but this is only to make the problem apparent.  One can come up with cases with subtler differences (e.g. use different collations, datetime comparisons, etc) where the queries will look like they make sense but result will be incorrect.

How to repeat:
create table t2 ( a char(10) not null, key(a)) engine=innodb;

insert into t2 values ('foo-123');
insert into t2 values ('-1234');
insert into t2 values ('-99');
insert into t2 values ('-99999');

MySQL [test]> select max(a) from t2 where a < 432;
+--------+
| max(a) |
+--------+
| -99999 |
+--------+
1 row in set (0.00 sec)

MySQL [test]> select max(a) from t2 ignore index(a) where a < 432;
+---------+
| max(a)  |
+---------+
| foo-123 |
+---------+
1 row in set, 4 warnings (0.00 sec)

MySQL [test]> explain select max(a) from t2 where a < 432;
+----+-------------+-------+------+---------------+------+---------+------+------+------------------------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra                        |
+----+-------------+-------+------+---------------+------+---------+------+------+------------------------------+
|  1 | SIMPLE      | NULL  | NULL | NULL          | NULL | NULL    | NULL | NULL | Select tables optimized away |
+----+-------------+-------+------+---------------+------+---------+------+------+------------------------------+
1 row in set (0.01 sec)

MySQL [test]> explain select max(a) from t2 ignore index(a) where a < 432;
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | t2    | ALL  | NULL          | NULL | NULL    | NULL |    7 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)

MySQL [test]> 

Suggested fix:
select max(...) is a deterministic function and so must always return the same result regardless of what indexes are present.
[12 Nov 2013 11:01] MySQL Verification Team
Hello Sergey,

Thank you for the bug report and test case.
Verified as described.

Thanks,
Umesh