Commit 88bf8b9c authored by Sergey Petrunya's avatar Sergey Petrunya

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.
parent d79d0c40
...@@ -2186,3 +2186,47 @@ AVG(DISTINCT outr.col_int_nokey) ...@@ -2186,3 +2186,47 @@ AVG(DISTINCT outr.col_int_nokey)
7.5000 7.5000
DROP TABLE t1; DROP TABLE t1;
# End of the bug#57932 # 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;
...@@ -1465,3 +1465,56 @@ SELECT AVG(DISTINCT outr.col_int_nokey) FROM t1 AS outr LEFT JOIN t1 AS outr2 ON ...@@ -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; outr.col_int_nokey = outr2.col_int_nokey;
DROP TABLE t1; DROP TABLE t1;
--echo # End of the bug#57932 --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;
...@@ -479,6 +479,24 @@ int opt_sum_query(THD *thd, ...@@ -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. 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) ...@@ -509,7 +527,7 @@ bool simple_pred(Item_func *func_item, Item **args, bool *inv_order)
if (!(item= it++)) if (!(item= it++))
return 0; return 0;
args[0]= item->real_item(); 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; return 0;
if (it++) if (it++)
return 0; return 0;
...@@ -544,7 +562,7 @@ bool simple_pred(Item_func *func_item, Item **args, bool *inv_order) ...@@ -544,7 +562,7 @@ bool simple_pred(Item_func *func_item, Item **args, bool *inv_order)
} }
else else
return 0; return 0;
if (args[0]->max_length < args[1]->max_length) if (check_item1_shorter_item2(args[0], args[1]))
return 0; return 0;
break; break;
case 3: case 3:
...@@ -559,7 +577,7 @@ bool simple_pred(Item_func *func_item, Item **args, bool *inv_order) ...@@ -559,7 +577,7 @@ bool simple_pred(Item_func *func_item, Item **args, bool *inv_order)
if (!item->const_item()) if (!item->const_item())
return 0; return 0;
args[i]= item; args[i]= item;
if (args[0]->max_length < args[i]->max_length) if (check_item1_shorter_item2(args[0], args[1]))
return 0; return 0;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment