Skip to content

Commit 97fb1f2

Browse files
committed
Fixed bug mdev-10053.
The implementation of the walk method for the class Item_in_subselect was missing. As a result the method never traversed the left operand of any IN subquery predicate. Item_exists_subselect::exists2in_processor() that performs the Exist-To-In transformation calls the walk method to collect info on outer references. As the walk method did not traverse the left operands of the IN subqueries the outer references there were not taken into account and some subqueries that were actually correlated were marked as uncorrelated. It could lead to an attempt of the materialization of such a subquery. Also added a cleanup for some test cases merged from 5.5.
1 parent 26ed68d commit 97fb1f2

File tree

6 files changed

+101
-12
lines changed

6 files changed

+101
-12
lines changed

mysql-test/r/subselect_exists2in.result

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -884,5 +884,55 @@ a
884884
deallocate prepare stmt;
885885
drop view v1;
886886
drop table t1,t2;
887+
#
888+
#MDEV-10053: EXIST to IN transformation turned down
889+
#
890+
CREATE TABLE t1 (
891+
pk INT, f1 INT NOT NULL, f2 VARCHAR(3), f3 INT NULL, PRIMARY KEY(pk))
892+
ENGINE=MyISAM;
893+
INSERT INTO t1 VALUES (1,1,'foo',8), (2,5,'bar',7);
894+
set @optimizer_switch_save=@@optimizer_switch;
895+
set optimizer_switch='exists_to_in=off';
896+
explain extended SELECT STRAIGHT_JOIN sq1.f2
897+
FROM ( SELECT * FROM t1 ) AS sq1
898+
WHERE EXISTS ( SELECT * FROM t1 AS sq2
899+
WHERE sq1.`pk` IN ( SELECT f1 FROM t1 ) AND sq2.f1 = sq1.f1 );
900+
id select_type table type possible_keys key key_len ref rows filtered Extra
901+
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00 Using where
902+
3 DEPENDENT SUBQUERY <subquery4> eq_ref distinct_key distinct_key 4 func 1 100.00
903+
3 DEPENDENT SUBQUERY sq2 ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (flat, BNL join)
904+
4 MATERIALIZED t1 ALL NULL NULL NULL NULL 2 100.00
905+
Warnings:
906+
Note 1276 Field or reference 'sq1.pk' of SELECT #3 was resolved in SELECT #1
907+
Note 1276 Field or reference 'sq1.f1' of SELECT #3 was resolved in SELECT #1
908+
Note 1003 select straight_join `test`.`t1`.`f2` AS `f2` from `test`.`t1` where <expr_cache><`test`.`t1`.`f1`,`test`.`t1`.`pk`>(exists(select 1 from `test`.`t1` `sq2` semi join (`test`.`t1`) where ((`test`.`sq2`.`f1` = `test`.`t1`.`f1`) and (`test`.`t1`.`pk` = `test`.`t1`.`f1`))))
909+
SELECT STRAIGHT_JOIN sq1.f2
910+
FROM ( SELECT * FROM t1 ) AS sq1
911+
WHERE EXISTS ( SELECT * FROM t1 AS sq2
912+
WHERE sq1.`pk` IN ( SELECT f1 FROM t1 ) AND sq2.f1 = sq1.f1 );
913+
f2
914+
foo
915+
set optimizer_switch='exists_to_in=on';
916+
explain extended SELECT STRAIGHT_JOIN sq1.f2
917+
FROM ( SELECT * FROM t1 ) AS sq1
918+
WHERE EXISTS ( SELECT * FROM t1 AS sq2
919+
WHERE sq1.`pk` IN ( SELECT f1 FROM t1 ) AND sq2.f1 = sq1.f1 );
920+
id select_type table type possible_keys key key_len ref rows filtered Extra
921+
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00 Using where
922+
3 DEPENDENT SUBQUERY <subquery4> eq_ref distinct_key distinct_key 4 func 1 100.00
923+
3 DEPENDENT SUBQUERY sq2 ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (flat, BNL join)
924+
4 MATERIALIZED t1 ALL NULL NULL NULL NULL 2 100.00
925+
Warnings:
926+
Note 1276 Field or reference 'sq1.pk' of SELECT #3 was resolved in SELECT #1
927+
Note 1276 Field or reference 'sq1.f1' of SELECT #3 was resolved in SELECT #1
928+
Note 1003 select straight_join `test`.`t1`.`f2` AS `f2` from `test`.`t1` where <expr_cache><`test`.`t1`.`f1`,`test`.`t1`.`pk`>(<in_optimizer>(`test`.`t1`.`f1`,<exists>(select `test`.`sq2`.`f1` from `test`.`t1` `sq2` semi join (`test`.`t1`) where ((`test`.`t1`.`pk` = `test`.`t1`.`f1`) and (<cache>(`test`.`t1`.`f1`) = `test`.`sq2`.`f1`)))))
929+
SELECT STRAIGHT_JOIN sq1.f2
930+
FROM ( SELECT * FROM t1 ) AS sq1
931+
WHERE EXISTS ( SELECT * FROM t1 AS sq2
932+
WHERE sq1.`pk` IN ( SELECT f1 FROM t1 ) AND sq2.f1 = sq1.f1 );
933+
f2
934+
foo
935+
set optimizer_switch= @optimizer_switch_save;
936+
DROP TABLE t1;
887937
# End of 10.0 tests
888938
set optimizer_switch=default;

mysql-test/r/subselect_mat.result

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2166,7 +2166,6 @@ drop table t1;
21662166
#
21672167
# MDEV-12429: IN subquery used in WHERE of EXISTS subquery
21682168
#
2169-
set optimizer_switch='exists_to_in=off';
21702169
CREATE TABLE t1 (
21712170
pk INT, f1 INT NOT NULL, f2 VARCHAR(3), f3 INT NULL, PRIMARY KEY(pk)) ENGINE=MyISAM;
21722171
INSERT INTO t1 VALUES (1,1,'foo',8), (2,5,'bar',7);
@@ -2175,6 +2174,8 @@ WHERE EXISTS ( SELECT * FROM t1 AS sq2
21752174
WHERE sq1.`pk` IN ( SELECT f1 FROM t1 ) AND sq2.f1 = sq1.f1 );
21762175
f2
21772176
foo
2177+
set @save_optimizer_switch= @@optimizer_switch;
2178+
set optimizer_switch='exists_to_in=off';
21782179
EXPLAIN
21792180
SELECT sq1.f2 FROM t1 AS sq1
21802181
WHERE EXISTS ( SELECT * FROM t1 AS sq2
@@ -2185,7 +2186,6 @@ id select_type table type possible_keys key key_len ref rows Extra
21852186
2 DEPENDENT SUBQUERY sq2 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join)
21862187
3 MATERIALIZED t1 ALL NULL NULL NULL NULL 2
21872188
# this checks the result set above
2188-
set @save_optimizer_switch= @@optimizer_switch;
21892189
set optimizer_switch= 'materialization=off,semijoin=off';
21902190
SELECT sq1.f2 FROM t1 AS sq1
21912191
WHERE EXISTS ( SELECT * FROM t1 AS sq2
@@ -2197,13 +2197,14 @@ DROP TABLE t1;
21972197
#
21982198
# MDEV-12145: IN subquery used in WHERE of EXISTS subquery
21992199
#
2200-
set optimizer_switch='exists_to_in=off';
22012200
CREATE TABLE t1 (f1 INT) ENGINE=MyISAM;
22022201
INSERT INTO t1 VALUES (4),(6);
22032202
CREATE TABLE t2 (i2 INT, KEY(i2)) ENGINE=MyISAM;
22042203
INSERT INTO t2 VALUES (8),(7),(1);
22052204
CREATE TABLE t3 (f3 INT, i3 INT, KEY(i3)) ENGINE=MyISAM;
22062205
INSERT INTO t3 VALUES (8,0),(6,3),(2,8),(3,8),(1,6),(0,0),(1,0),(1,5);
2206+
set @save_optimizer_switch= @@optimizer_switch;
2207+
set optimizer_switch='exists_to_in=off';
22072208
SELECT * FROM t1
22082209
WHERE EXISTS ( SELECT * FROM t2, t3
22092210
WHERE i3 = i2 AND f1 IN ( SELECT f3 FROM t3 ) );
@@ -2223,7 +2224,6 @@ Warnings:
22232224
Note 1276 Field or reference 'test.t1.f1' of SELECT #2 was resolved in SELECT #1
22242225
Note 1003 select `test`.`t1`.`f1` AS `f1` from `test`.`t1` where <expr_cache><`test`.`t1`.`f1`>(exists(select 1 from `test`.`t2` semi join (`test`.`t3`) join `test`.`t3` where ((`test`.`t3`.`i3` = `test`.`t2`.`i2`) and (`test`.`t1`.`f1` = `test`.`t3`.`f3`))))
22252226
# this checks the result set above
2226-
set @save_optimizer_switch= @@optimizer_switch;
22272227
set optimizer_switch= 'materialization=off,semijoin=off';
22282228
SELECT * FROM t1
22292229
WHERE EXISTS ( SELECT * FROM t2, t3

mysql-test/r/subselect_sj_mat.result

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2206,7 +2206,6 @@ drop table t1;
22062206
#
22072207
# MDEV-12429: IN subquery used in WHERE of EXISTS subquery
22082208
#
2209-
set optimizer_switch='exists_to_in=off';
22102209
CREATE TABLE t1 (
22112210
pk INT, f1 INT NOT NULL, f2 VARCHAR(3), f3 INT NULL, PRIMARY KEY(pk)) ENGINE=MyISAM;
22122211
INSERT INTO t1 VALUES (1,1,'foo',8), (2,5,'bar',7);
@@ -2215,6 +2214,8 @@ WHERE EXISTS ( SELECT * FROM t1 AS sq2
22152214
WHERE sq1.`pk` IN ( SELECT f1 FROM t1 ) AND sq2.f1 = sq1.f1 );
22162215
f2
22172216
foo
2217+
set @save_optimizer_switch= @@optimizer_switch;
2218+
set optimizer_switch='exists_to_in=off';
22182219
EXPLAIN
22192220
SELECT sq1.f2 FROM t1 AS sq1
22202221
WHERE EXISTS ( SELECT * FROM t1 AS sq2
@@ -2225,7 +2226,6 @@ id select_type table type possible_keys key key_len ref rows Extra
22252226
2 DEPENDENT SUBQUERY sq2 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join)
22262227
3 MATERIALIZED t1 ALL NULL NULL NULL NULL 2
22272228
# this checks the result set above
2228-
set @save_optimizer_switch= @@optimizer_switch;
22292229
set optimizer_switch= 'materialization=off,semijoin=off';
22302230
SELECT sq1.f2 FROM t1 AS sq1
22312231
WHERE EXISTS ( SELECT * FROM t1 AS sq2
@@ -2237,13 +2237,14 @@ DROP TABLE t1;
22372237
#
22382238
# MDEV-12145: IN subquery used in WHERE of EXISTS subquery
22392239
#
2240-
set optimizer_switch='exists_to_in=off';
22412240
CREATE TABLE t1 (f1 INT) ENGINE=MyISAM;
22422241
INSERT INTO t1 VALUES (4),(6);
22432242
CREATE TABLE t2 (i2 INT, KEY(i2)) ENGINE=MyISAM;
22442243
INSERT INTO t2 VALUES (8),(7),(1);
22452244
CREATE TABLE t3 (f3 INT, i3 INT, KEY(i3)) ENGINE=MyISAM;
22462245
INSERT INTO t3 VALUES (8,0),(6,3),(2,8),(3,8),(1,6),(0,0),(1,0),(1,5);
2246+
set @save_optimizer_switch= @@optimizer_switch;
2247+
set optimizer_switch='exists_to_in=off';
22472248
SELECT * FROM t1
22482249
WHERE EXISTS ( SELECT * FROM t2, t3
22492250
WHERE i3 = i2 AND f1 IN ( SELECT f3 FROM t3 ) );
@@ -2263,7 +2264,6 @@ Warnings:
22632264
Note 1276 Field or reference 'test.t1.f1' of SELECT #2 was resolved in SELECT #1
22642265
Note 1003 select `test`.`t1`.`f1` AS `f1` from `test`.`t1` where <expr_cache><`test`.`t1`.`f1`>(exists(select 1 from `test`.`t2` semi join (`test`.`t3`) join `test`.`t3` where ((`test`.`t3`.`i3` = `test`.`t2`.`i2`) and (`test`.`t1`.`f1` = `test`.`t3`.`f3`))))
22652266
# this checks the result set above
2266-
set @save_optimizer_switch= @@optimizer_switch;
22672267
set optimizer_switch= 'materialization=off,semijoin=off';
22682268
SELECT * FROM t1
22692269
WHERE EXISTS ( SELECT * FROM t2, t3

mysql-test/t/subselect_exists2in.test

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -758,6 +758,34 @@ deallocate prepare stmt;
758758
drop view v1;
759759
drop table t1,t2;
760760

761+
--echo #
762+
--echo #MDEV-10053: EXIST to IN transformation turned down
763+
--echo #
764+
765+
CREATE TABLE t1 (
766+
pk INT, f1 INT NOT NULL, f2 VARCHAR(3), f3 INT NULL, PRIMARY KEY(pk))
767+
ENGINE=MyISAM;
768+
INSERT INTO t1 VALUES (1,1,'foo',8), (2,5,'bar',7);
769+
770+
let $q=
771+
SELECT STRAIGHT_JOIN sq1.f2
772+
FROM ( SELECT * FROM t1 ) AS sq1
773+
WHERE EXISTS ( SELECT * FROM t1 AS sq2
774+
WHERE sq1.`pk` IN ( SELECT f1 FROM t1 ) AND sq2.f1 = sq1.f1 );
775+
776+
set @optimizer_switch_save=@@optimizer_switch;
777+
778+
set optimizer_switch='exists_to_in=off';
779+
eval explain extended $q;
780+
eval $q;
781+
set optimizer_switch='exists_to_in=on';
782+
eval explain extended $q;
783+
eval $q;
784+
785+
set optimizer_switch= @optimizer_switch_save;
786+
787+
DROP TABLE t1;
788+
761789
--echo # End of 10.0 tests
762790

763791
#restore defaults

mysql-test/t/subselect_sj_mat.test

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1861,7 +1861,6 @@ drop table t1;
18611861
--echo # MDEV-12429: IN subquery used in WHERE of EXISTS subquery
18621862
--echo #
18631863

1864-
set optimizer_switch='exists_to_in=off';
18651864
CREATE TABLE t1 (
18661865
pk INT, f1 INT NOT NULL, f2 VARCHAR(3), f3 INT NULL, PRIMARY KEY(pk)) ENGINE=MyISAM;
18671866
INSERT INTO t1 VALUES (1,1,'foo',8), (2,5,'bar',7);
@@ -1870,17 +1869,20 @@ SELECT sq1.f2 FROM t1 AS sq1
18701869
WHERE EXISTS ( SELECT * FROM t1 AS sq2
18711870
WHERE sq1.`pk` IN ( SELECT f1 FROM t1 ) AND sq2.f1 = sq1.f1 );
18721871

1872+
set @save_optimizer_switch= @@optimizer_switch;
1873+
1874+
set optimizer_switch='exists_to_in=off';
18731875
EXPLAIN
18741876
SELECT sq1.f2 FROM t1 AS sq1
18751877
WHERE EXISTS ( SELECT * FROM t1 AS sq2
18761878
WHERE sq1.`pk` IN ( SELECT f1 FROM t1 ) AND sq2.f1 = sq1.f1 );
18771879

18781880
--echo # this checks the result set above
1879-
set @save_optimizer_switch= @@optimizer_switch;
18801881
set optimizer_switch= 'materialization=off,semijoin=off';
18811882
SELECT sq1.f2 FROM t1 AS sq1
18821883
WHERE EXISTS ( SELECT * FROM t1 AS sq2
18831884
WHERE sq1.`pk` IN ( SELECT f1 FROM t1 ) AND sq2.f1 = sq1.f1 );
1885+
18841886
set optimizer_switch= @save_optimizer_switch;
18851887

18861888
DROP TABLE t1;
@@ -1889,7 +1891,6 @@ DROP TABLE t1;
18891891
--echo # MDEV-12145: IN subquery used in WHERE of EXISTS subquery
18901892
--echo #
18911893

1892-
set optimizer_switch='exists_to_in=off';
18931894
CREATE TABLE t1 (f1 INT) ENGINE=MyISAM;
18941895
INSERT INTO t1 VALUES (4),(6);
18951896

@@ -1899,6 +1900,9 @@ INSERT INTO t2 VALUES (8),(7),(1);
18991900
CREATE TABLE t3 (f3 INT, i3 INT, KEY(i3)) ENGINE=MyISAM;
19001901
INSERT INTO t3 VALUES (8,0),(6,3),(2,8),(3,8),(1,6),(0,0),(1,0),(1,5);
19011902

1903+
set @save_optimizer_switch= @@optimizer_switch;
1904+
1905+
set optimizer_switch='exists_to_in=off';
19021906
SELECT * FROM t1
19031907
WHERE EXISTS ( SELECT * FROM t2, t3
19041908
WHERE i3 = i2 AND f1 IN ( SELECT f3 FROM t3 ) );
@@ -1908,11 +1912,11 @@ SELECT * FROM t1
19081912
WHERE i3 = i2 AND f1 IN ( SELECT f3 FROM t3 ) );
19091913

19101914
--echo # this checks the result set above
1911-
set @save_optimizer_switch= @@optimizer_switch;
19121915
set optimizer_switch= 'materialization=off,semijoin=off';
19131916
SELECT * FROM t1
19141917
WHERE EXISTS ( SELECT * FROM t2, t3
19151918
WHERE i3 = i2 AND f1 IN ( SELECT f3 FROM t3 ) );
1919+
19161920
set optimizer_switch= @save_optimizer_switch;
19171921

19181922
DROP TABLE t1,t2,t3;

sql/item_subselect.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -705,6 +705,13 @@ class Item_in_subselect :public Item_exists_subselect
705705
in_strategy= (SUBS_STRATEGY_CHOSEN | strategy);
706706
DBUG_VOID_RETURN;
707707
}
708+
709+
bool walk(Item_processor processor, bool walk_subquery, uchar *arg)
710+
{
711+
return left_expr->walk(processor, walk_subquery, arg) ||
712+
Item_subselect::walk(processor, walk_subquery, arg);
713+
}
714+
708715
bool exists2in_processor(uchar *opt_arg __attribute__((unused)))
709716
{
710717
return 0;

0 commit comments

Comments
 (0)