From 46eef1ede2ddfceaa056a71ea52ecacdde2bc44e Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Mon, 23 Jan 2017 19:40:22 -0800 Subject: [PATCH] Fixed bug mdev-11859. As the function Item_subselect::fix_fields does it the function Item_subselect::update_used_tables must ignore UNCACHEABLE_EXPLAIN when deciding whether the subquery item should be considered as a constant item. --- mysql-test/r/ps.result | 70 ++++++++++++++++++++++++++++++++++++++++++ mysql-test/t/ps.test | 33 ++++++++++++++++++++ sql/item_subselect.cc | 2 +- 3 files changed, 104 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index bb8b76faa49..f954583a097 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -4103,4 +4103,74 @@ NULL NULL deallocate prepare stmt; drop table t1,t2,t3,t4; +# +# MDEV-11859: the plans for the first and the second executions +# of PS are not the same +# +create table t1 (id int, c varchar(3), key idx(c))engine=myisam; +insert into t1 values (3,'bar'), (1,'xxx'), (2,'foo'), (5,'yyy'); +prepare stmt1 from +"explain extended + select * from t1 where (1, 2) in ( select 3, 4 ) or c = 'foo'"; +execute stmt1; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY t1 ref idx idx 6 const 1 100.00 Using index condition +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`c` AS `c` from `test`.`t1` where (`test`.`t1`.`c` = 'foo') +execute stmt1; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY t1 ref idx idx 6 const 1 100.00 Using index condition +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`c` AS `c` from `test`.`t1` where (`test`.`t1`.`c` = 'foo') +deallocate prepare stmt1; +prepare stmt1 from +"select * from t1 where (1, 2) in ( select 3, 4 ) or c = 'foo'"; +flush status; +execute stmt1; +id c +2 foo +show status like '%Handler_read%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 1 +Handler_read_last 0 +Handler_read_next 1 +Handler_read_prev 0 +Handler_read_rnd 0 +Handler_read_rnd_deleted 0 +Handler_read_rnd_next 0 +flush status; +execute stmt1; +id c +2 foo +show status like '%Handler_read%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 1 +Handler_read_last 0 +Handler_read_next 1 +Handler_read_prev 0 +Handler_read_rnd 0 +Handler_read_rnd_deleted 0 +Handler_read_rnd_next 0 +deallocate prepare stmt1; +prepare stmt2 from +"explain extended + select * from t1 where (1, 2) in ( select 3, 4 )"; +execute stmt2; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`c` AS `c` from `test`.`t1` where 0 +execute stmt2; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`c` AS `c` from `test`.`t1` where 0 +deallocate prepare stmt2; +drop table t1; # End of 5.5 tests diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index 1516acca01e..cfd810fd625 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -3680,5 +3680,38 @@ EXECUTE stmt; deallocate prepare stmt; drop table t1,t2,t3,t4; +--echo # +--echo # MDEV-11859: the plans for the first and the second executions +--echo # of PS are not the same +--echo # + +create table t1 (id int, c varchar(3), key idx(c))engine=myisam; +insert into t1 values (3,'bar'), (1,'xxx'), (2,'foo'), (5,'yyy'); + +prepare stmt1 from +"explain extended + select * from t1 where (1, 2) in ( select 3, 4 ) or c = 'foo'"; +execute stmt1; +execute stmt1; +deallocate prepare stmt1; + +prepare stmt1 from +"select * from t1 where (1, 2) in ( select 3, 4 ) or c = 'foo'"; +flush status; +execute stmt1; +show status like '%Handler_read%'; +flush status; +execute stmt1; +show status like '%Handler_read%'; +deallocate prepare stmt1; + +prepare stmt2 from +"explain extended + select * from t1 where (1, 2) in ( select 3, 4 )"; +execute stmt2; +execute stmt2; +deallocate prepare stmt2; + +drop table t1; --echo # End of 5.5 tests diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 5750de713e6..5e00220db55 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -878,7 +878,7 @@ void Item_subselect::update_used_tables() if (!forced_const) { recalc_used_tables(parent_select, FALSE); - if (!engine->uncacheable()) + if (!(engine->uncacheable() & ~UNCACHEABLE_EXPLAIN)) { // did all used tables become static? if (!(used_tables_cache & ~engine->upper_select_const_tables()))