Commit ed027d65 authored by Sergei Petrunia's avatar Sergei Petrunia

MDEV-33747: Optimization of (SELECT) IN (SELECT ...) executes subquery at prepare stage

Make IN->EXISTS rewrite not to compute constant left expression if it
has a subquery in it.
parent 17573166
...@@ -3292,4 +3292,33 @@ a ...@@ -3292,4 +3292,33 @@ a
2 2
DEALLOCATE PREPARE stmt; DEALLOCATE PREPARE stmt;
DROP TABLE t1,t2,t3; DROP TABLE t1,t2,t3;
#
# MDEV-33747: Optimization of (SELECT) IN (SELECT ...) executes subquery at prepare stage
#
create table t1 (a int, b int);
insert into t1 select seq, seq from seq_1_to_200;
create table t2 as select * from t1;
create table t3 as select * from t1;
analyze table t1,t2,t3;
Table Op Msg_type Msg_text
test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
test.t2 analyze status Engine-independent statistics collected
test.t2 analyze status OK
test.t3 analyze status Engine-independent statistics collected
test.t3 analyze status OK
select @@expensive_subquery_limit < 200 as DEFAULTS_ARE_SUITABLE;
DEFAULTS_ARE_SUITABLE
1
flush status;
explain select * from t1 where a<3 or (select max(a) from t2) in (select b from t3);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 200 Using where
3 SUBQUERY t3 ALL NULL NULL NULL NULL 200 Using where
2 SUBQUERY t2 ALL NULL NULL NULL NULL 200
# Must show 0. If this shows 200, this means subquery was executed and you have a bug:
show status like 'Handler_read_rnd_next%';
Variable_name Value
Handler_read_rnd_next 0
drop table t1,t2,t3;
# End of 10.4 tests # End of 10.4 tests
...@@ -2666,4 +2666,19 @@ DEALLOCATE PREPARE stmt; ...@@ -2666,4 +2666,19 @@ DEALLOCATE PREPARE stmt;
DROP TABLE t1,t2,t3; DROP TABLE t1,t2,t3;
--echo #
--echo # MDEV-33747: Optimization of (SELECT) IN (SELECT ...) executes subquery at prepare stage
--echo #
create table t1 (a int, b int);
insert into t1 select seq, seq from seq_1_to_200;
create table t2 as select * from t1;
create table t3 as select * from t1;
analyze table t1,t2,t3;
select @@expensive_subquery_limit < 200 as DEFAULTS_ARE_SUITABLE;
flush status;
explain select * from t1 where a<3 or (select max(a) from t2) in (select b from t3);
--echo # Must show 0. If this shows 200, this means subquery was executed and you have a bug:
show status like 'Handler_read_rnd_next%';
drop table t1,t2,t3;
--echo # End of 10.4 tests --echo # End of 10.4 tests
...@@ -1363,7 +1363,13 @@ bool Item_in_optimizer::fix_left(THD *thd) ...@@ -1363,7 +1363,13 @@ bool Item_in_optimizer::fix_left(THD *thd)
copy_with_sum_func(args[0]); copy_with_sum_func(args[0]);
with_param= args[0]->with_param || args[1]->with_param; with_param= args[0]->with_param || args[1]->with_param;
with_field= args[0]->with_field; with_field= args[0]->with_field;
if ((const_item_cache= args[0]->const_item()))
/*
If left expression is a constant, cache its value.
But don't do that if that involves computing a subquery, as we are in a
prepare-phase rewrite.
*/
if ((const_item_cache= args[0]->const_item()) && !args[0]->with_subquery())
{ {
cache->store(args[0]); cache->store(args[0]);
cache->cache_value(); cache->cache_value();
......
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