diff options
author | Sergey Petrunya <psergey@askmonty.org> | 2013-11-12 17:37:32 +0400 |
---|---|---|
committer | Sergey Petrunya <psergey@askmonty.org> | 2013-11-12 17:37:32 +0400 |
commit | 88bf8b9c8fbfb79ac1690fa96467de9bbb9052e7 (patch) | |
tree | 7ee35d607cd75492e61ea65f6c6002dd8dfc1cd2 | |
parent | d79d0c4045f5b93ded001ca6b963727b3362cd15 (diff) | |
download | mariadb-git-88bf8b9c8fbfb79ac1690fa96467de9bbb9052e7.tar.gz |
MDEV-5257: MIN/MAX Optimization (Select tables optimized away) does not work for DateTime
- MIN/MAX optimizer does a check whether a "field CMP const" comparison uses a constant
that's longer than the field it is compared to. Make this check only for string columns,
also compare character lengths, not byte lengths.
-rw-r--r-- | mysql-test/r/func_group.result | 44 | ||||
-rw-r--r-- | mysql-test/t/func_group.test | 53 | ||||
-rw-r--r-- | sql/opt_sum.cc | 24 |
3 files changed, 118 insertions, 3 deletions
diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result index 9049589b6db..8e50c045775 100644 --- a/mysql-test/r/func_group.result +++ b/mysql-test/r/func_group.result @@ -2186,3 +2186,47 @@ AVG(DISTINCT outr.col_int_nokey) 7.5000 DROP TABLE t1; # End of the bug#57932 +# +# MDEV-5257: MIN/MAX Optimization (Select tables optimized away) does not work for DateTime +# MDEV-3855: MIN/MAX optimization doesnt work for int_col > INET_ATON +# (correct the fix for Bug #884175) +# +CREATE TABLE `t1` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` datetime DEFAULT NULL, +PRIMARY KEY (`a`), +KEY `idx_b` (`b`) +); +INSERT INTO `t1` (b) VALUES ('2013-01-06 23:59:59'); +INSERT INTO `t1` (b) VALUES ('2013-02-06 23:59:59'); +INSERT INTO `t1` (b) VALUES ('2013-03-06 23:59:59'); +INSERT INTO `t1` (b) VALUES ('2013-04-06 23:59:59'); +INSERT INTO `t1` (b) VALUES ('2013-05-06 23:59:59'); +INSERT INTO `t1` (b) VALUES ('2013-06-06 23:59:59'); +INSERT INTO `t1` (b) VALUES ('2013-07-06 23:59:59'); +# The following should produce "Select tables optimized away" +EXPLAIN SELECT MIN(b) FROM t1 WHERE b <= '2013-11-06 23:59:59'; +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 +set names utf8; +# Should be the same as above: +EXPLAIN SELECT MIN(b) FROM t1 WHERE b <= '2013-11-06 23:59:59'; +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 +DROP TABLE t1; +CREATE TABLE `t1` ( +`a` int(11) NOT NULL AUTO_INCREMENT, +`b` bigint(20) DEFAULT NULL, +PRIMARY KEY (`a`), +KEY `idx_b` (`b`) +); +insert into t1 (b) values (INET_ATON('192.168.0.1')); +insert into t1 (b) values (INET_ATON('192.168.0.2')); +insert into t1 (b) values (INET_ATON('192.168.0.3')); +insert into t1 (b) values (INET_ATON('192.168.0.4')); +insert into t1 (b) values (INET_ATON('192.168.200.200')); +# should show "Select tables optimized away" +explain select MIN(b) from t1 where b >= inet_aton('192.168.119.32'); +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 +DROP TABLE t1; diff --git a/mysql-test/t/func_group.test b/mysql-test/t/func_group.test index 0c2f28ab25d..cf5f00c3ee1 100644 --- a/mysql-test/t/func_group.test +++ b/mysql-test/t/func_group.test @@ -1465,3 +1465,56 @@ SELECT AVG(DISTINCT outr.col_int_nokey) FROM t1 AS outr LEFT JOIN t1 AS outr2 ON outr.col_int_nokey = outr2.col_int_nokey; DROP TABLE t1; --echo # End of the bug#57932 + + +--echo # +--echo # MDEV-5257: MIN/MAX Optimization (Select tables optimized away) does not work for DateTime +--echo # MDEV-3855: MIN/MAX optimization doesnt work for int_col > INET_ATON +--echo # (correct the fix for Bug #884175) +--echo # + +CREATE TABLE `t1` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` datetime DEFAULT NULL, + PRIMARY KEY (`a`), + KEY `idx_b` (`b`) +); + +INSERT INTO `t1` (b) VALUES ('2013-01-06 23:59:59'); +INSERT INTO `t1` (b) VALUES ('2013-02-06 23:59:59'); +INSERT INTO `t1` (b) VALUES ('2013-03-06 23:59:59'); +INSERT INTO `t1` (b) VALUES ('2013-04-06 23:59:59'); +INSERT INTO `t1` (b) VALUES ('2013-05-06 23:59:59'); +INSERT INTO `t1` (b) VALUES ('2013-06-06 23:59:59'); +INSERT INTO `t1` (b) VALUES ('2013-07-06 23:59:59'); + +--echo # The following should produce "Select tables optimized away" +EXPLAIN SELECT MIN(b) FROM t1 WHERE b <= '2013-11-06 23:59:59'; + +-- connect (con1,localhost,root,,) +-- connection con1 +set names utf8; +-- echo # Should be the same as above: +EXPLAIN SELECT MIN(b) FROM t1 WHERE b <= '2013-11-06 23:59:59'; + +--connection default +--disconnect con1 + +DROP TABLE t1; + +CREATE TABLE `t1` ( + `a` int(11) NOT NULL AUTO_INCREMENT, + `b` bigint(20) DEFAULT NULL, + PRIMARY KEY (`a`), + KEY `idx_b` (`b`) +); + +insert into t1 (b) values (INET_ATON('192.168.0.1')); +insert into t1 (b) values (INET_ATON('192.168.0.2')); +insert into t1 (b) values (INET_ATON('192.168.0.3')); +insert into t1 (b) values (INET_ATON('192.168.0.4')); +insert into t1 (b) values (INET_ATON('192.168.200.200')); +--echo # should show "Select tables optimized away" +explain select MIN(b) from t1 where b >= inet_aton('192.168.119.32'); +DROP TABLE t1; + diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc index 069fe6452e8..aa8b17a2c85 100644 --- a/sql/opt_sum.cc +++ b/sql/opt_sum.cc @@ -479,6 +479,24 @@ int opt_sum_query(THD *thd, } +/* + Check if both item1 and item2 are strings, and item1 has fewer characters + than item2. +*/ + +static bool check_item1_shorter_item2(Item *item1, Item *item2) +{ + if (item1->cmp_type() == STRING_RESULT && + item2->cmp_type() == STRING_RESULT) + { + int len1= item1->max_length / item1->collation.collation->mbmaxlen; + int len2= item2->max_length / item2->collation.collation->mbmaxlen; + return len1 < len2; + } + return false; /* When the check is not applicable, it means "not bigger" */ +} + + /** Test if the predicate compares a field with constants. @@ -509,7 +527,7 @@ bool simple_pred(Item_func *func_item, Item **args, bool *inv_order) if (!(item= it++)) return 0; args[0]= item->real_item(); - if (args[0]->max_length < args[1]->max_length) + if (check_item1_shorter_item2(args[0], args[1])) return 0; if (it++) return 0; @@ -544,7 +562,7 @@ bool simple_pred(Item_func *func_item, Item **args, bool *inv_order) } else return 0; - if (args[0]->max_length < args[1]->max_length) + if (check_item1_shorter_item2(args[0], args[1])) return 0; break; case 3: @@ -559,7 +577,7 @@ bool simple_pred(Item_func *func_item, Item **args, bool *inv_order) if (!item->const_item()) return 0; args[i]= item; - if (args[0]->max_length < args[i]->max_length) + if (check_item1_shorter_item2(args[0], args[1])) return 0; } } |