Skip to content

Commit 7e97163

Browse files
committed
Fixed the bug mdev-12817/mdev-12820.
This patch is a correction of the patch for bug mdev-12670. With the current code handling semi-joins the following must be taken into account. Conversion of an IN subquery predicate into semi-join has to be blocked if the predicate occurs: (a) in the ON expression of an outer join (b) in the ON expression of an inner join embedded directly or indirectly in the inner nest of an outer join. The patch for mdev-12670 blocked conversion to semi-joins only in the case (a), but not in the case (b). This patch blocks the conversion in both cases.
1 parent 934b831 commit 7e97163

File tree

4 files changed

+168
-1
lines changed

4 files changed

+168
-1
lines changed

mysql-test/r/subselect_sj.result

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3099,4 +3099,58 @@ id select_type table type possible_keys key key_len ref rows Extra
30993099
1 PRIMARY t2 range idx idx 5 NULL 2 Using where; Using index; Using join buffer (flat, BNL join)
31003100
drop table t1,t2;
31013101
set optimizer_switch= @tmp_mdev12675;
3102+
#
3103+
# MDEV-12817: subquery NOT subject to semi-join optimizations
3104+
# in ON expression of INNER JOIN
3105+
#
3106+
CREATE TABLE t1 (c1 int) ENGINE=MyISAM;
3107+
INSERT INTO t1 VALUES (1),(2);
3108+
CREATE TABLE t2 (c2 int) ENGINE=MyISAM;
3109+
INSERT INTO t2 VALUES (3),(4);
3110+
CREATE TABLE t3 (c3 int) ENGINE=MyISAM;
3111+
INSERT INTO t3 VALUES (5),(6);
3112+
CREATE TABLE t4 (c4 int) ENGINE=MyISAM;
3113+
INSERT INTO t4 VALUES (7),(8);
3114+
SELECT c1
3115+
FROM t1
3116+
LEFT JOIN
3117+
( t2 INNER JOIN t3 ON ( 1 IN ( SELECT c4 FROM t4 ) ) )
3118+
ON (c1 = c3);
3119+
c1
3120+
1
3121+
2
3122+
EXPLAIN EXTENDED SELECT c1
3123+
FROM t1
3124+
LEFT JOIN
3125+
( t2 INNER JOIN t3 ON ( 1 IN ( SELECT c4 FROM t4 ) ) )
3126+
ON (c1 = c3);
3127+
id select_type table type possible_keys key key_len ref rows filtered Extra
3128+
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
3129+
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where
3130+
1 PRIMARY t3 ALL NULL NULL NULL NULL 2 100.00 Using where
3131+
2 SUBQUERY t4 ALL NULL NULL NULL NULL 2 100.00 Using where
3132+
Warnings:
3133+
Note 1003 select `test`.`t1`.`c1` AS `c1` from `test`.`t1` left join (`test`.`t2` join `test`.`t3`) on(((`test`.`t3`.`c3` = `test`.`t1`.`c1`) and <cache>(<in_optimizer>(1,<exists>(select `test`.`t4`.`c4` from `test`.`t4` where (1 = `test`.`t4`.`c4`)))))) where 1
3134+
# mdev-12820
3135+
SELECT *
3136+
FROM t1
3137+
LEFT JOIN
3138+
( ( SELECT * FROM t2 WHERE c2 IN ( SELECT c3 FROM t3 ) ) AS sq INNER JOIN t4 )
3139+
ON (c1 = c2);
3140+
c1 c2 c4
3141+
1 NULL NULL
3142+
2 NULL NULL
3143+
EXPLAIN EXTENDED SELECT *
3144+
FROM t1
3145+
LEFT JOIN
3146+
( ( SELECT * FROM t2 WHERE c2 IN ( SELECT c3 FROM t3 ) ) AS sq INNER JOIN t4 )
3147+
ON (c1 = c2);
3148+
id select_type table type possible_keys key key_len ref rows filtered Extra
3149+
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00
3150+
1 SIMPLE t2 ALL NULL NULL NULL NULL 2 100.00 Using where
3151+
1 SIMPLE t4 ALL NULL NULL NULL NULL 2 100.00
3152+
3 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 2 100.00 Using where
3153+
Warnings:
3154+
Note 1003 select `test`.`t1`.`c1` AS `c1`,`test`.`t2`.`c2` AS `c2`,`test`.`t4`.`c4` AS `c4` from `test`.`t1` left join (`test`.`t2` join `test`.`t4`) on(((`test`.`t2`.`c2` = `test`.`t1`.`c1`) and <in_optimizer>(`test`.`t1`.`c1`,<exists>(select `test`.`t3`.`c3` from `test`.`t3` where (<cache>(`test`.`t2`.`c2`) = `test`.`t3`.`c3`))))) where 1
3155+
DROP TABLE t1,t2,t3,t4;
31023156
set optimizer_switch=@subselect_sj_tmp;

mysql-test/r/subselect_sj_jcl6.result

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3113,6 +3113,60 @@ id select_type table type possible_keys key key_len ref rows Extra
31133113
1 PRIMARY t2 range idx idx 5 NULL 2 Using where; Using index; Using join buffer (flat, BNL join)
31143114
drop table t1,t2;
31153115
set optimizer_switch= @tmp_mdev12675;
3116+
#
3117+
# MDEV-12817: subquery NOT subject to semi-join optimizations
3118+
# in ON expression of INNER JOIN
3119+
#
3120+
CREATE TABLE t1 (c1 int) ENGINE=MyISAM;
3121+
INSERT INTO t1 VALUES (1),(2);
3122+
CREATE TABLE t2 (c2 int) ENGINE=MyISAM;
3123+
INSERT INTO t2 VALUES (3),(4);
3124+
CREATE TABLE t3 (c3 int) ENGINE=MyISAM;
3125+
INSERT INTO t3 VALUES (5),(6);
3126+
CREATE TABLE t4 (c4 int) ENGINE=MyISAM;
3127+
INSERT INTO t4 VALUES (7),(8);
3128+
SELECT c1
3129+
FROM t1
3130+
LEFT JOIN
3131+
( t2 INNER JOIN t3 ON ( 1 IN ( SELECT c4 FROM t4 ) ) )
3132+
ON (c1 = c3);
3133+
c1
3134+
1
3135+
2
3136+
EXPLAIN EXTENDED SELECT c1
3137+
FROM t1
3138+
LEFT JOIN
3139+
( t2 INNER JOIN t3 ON ( 1 IN ( SELECT c4 FROM t4 ) ) )
3140+
ON (c1 = c3);
3141+
id select_type table type possible_keys key key_len ref rows filtered Extra
3142+
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00
3143+
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (flat, BNL join)
3144+
1 PRIMARY t3 ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (incremental, BNL join)
3145+
2 SUBQUERY t4 ALL NULL NULL NULL NULL 2 100.00 Using where
3146+
Warnings:
3147+
Note 1003 select `test`.`t1`.`c1` AS `c1` from `test`.`t1` left join (`test`.`t2` join `test`.`t3`) on(((`test`.`t3`.`c3` = `test`.`t1`.`c1`) and <cache>(<in_optimizer>(1,<exists>(select `test`.`t4`.`c4` from `test`.`t4` where (1 = `test`.`t4`.`c4`)))))) where 1
3148+
# mdev-12820
3149+
SELECT *
3150+
FROM t1
3151+
LEFT JOIN
3152+
( ( SELECT * FROM t2 WHERE c2 IN ( SELECT c3 FROM t3 ) ) AS sq INNER JOIN t4 )
3153+
ON (c1 = c2);
3154+
c1 c2 c4
3155+
1 NULL NULL
3156+
2 NULL NULL
3157+
EXPLAIN EXTENDED SELECT *
3158+
FROM t1
3159+
LEFT JOIN
3160+
( ( SELECT * FROM t2 WHERE c2 IN ( SELECT c3 FROM t3 ) ) AS sq INNER JOIN t4 )
3161+
ON (c1 = c2);
3162+
id select_type table type possible_keys key key_len ref rows filtered Extra
3163+
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00
3164+
1 SIMPLE t2 ALL NULL NULL NULL NULL 2 100.00 Using where; Using join buffer (flat, BNL join)
3165+
1 SIMPLE t4 ALL NULL NULL NULL NULL 2 100.00 Using join buffer (incremental, BNL join)
3166+
3 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 2 100.00 Using where
3167+
Warnings:
3168+
Note 1003 select `test`.`t1`.`c1` AS `c1`,`test`.`t2`.`c2` AS `c2`,`test`.`t4`.`c4` AS `c4` from `test`.`t1` left join (`test`.`t2` join `test`.`t4`) on(((`test`.`t2`.`c2` = `test`.`t1`.`c1`) and <in_optimizer>(`test`.`t1`.`c1`,<exists>(select `test`.`t3`.`c3` from `test`.`t3` where (<cache>(`test`.`t2`.`c2`) = `test`.`t3`.`c3`))))) where 1
3169+
DROP TABLE t1,t2,t3,t4;
31163170
set optimizer_switch=@subselect_sj_tmp;
31173171
#
31183172
# BUG#49129: Wrong result with IN-subquery with join_cache_level=6 and firstmatch=off

mysql-test/t/subselect_sj.test

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2801,5 +2801,45 @@ select a from t1 join t2 on b between 1 and 2 and a in (select b from t2);
28012801
drop table t1,t2;
28022802
set optimizer_switch= @tmp_mdev12675;
28032803

2804+
--echo #
2805+
--echo # MDEV-12817: subquery NOT subject to semi-join optimizations
2806+
--echo # in ON expression of INNER JOIN
2807+
--echo #
2808+
2809+
CREATE TABLE t1 (c1 int) ENGINE=MyISAM;
2810+
INSERT INTO t1 VALUES (1),(2);
2811+
2812+
CREATE TABLE t2 (c2 int) ENGINE=MyISAM;
2813+
INSERT INTO t2 VALUES (3),(4);
2814+
2815+
CREATE TABLE t3 (c3 int) ENGINE=MyISAM;
2816+
INSERT INTO t3 VALUES (5),(6);
2817+
2818+
CREATE TABLE t4 (c4 int) ENGINE=MyISAM;
2819+
INSERT INTO t4 VALUES (7),(8);
2820+
2821+
let $q1=
2822+
SELECT c1
2823+
FROM t1
2824+
LEFT JOIN
2825+
( t2 INNER JOIN t3 ON ( 1 IN ( SELECT c4 FROM t4 ) ) )
2826+
ON (c1 = c3);
2827+
2828+
eval $q1;
2829+
eval EXPLAIN EXTENDED $q1;
2830+
2831+
let $q2=
2832+
SELECT *
2833+
FROM t1
2834+
LEFT JOIN
2835+
( ( SELECT * FROM t2 WHERE c2 IN ( SELECT c3 FROM t3 ) ) AS sq INNER JOIN t4 )
2836+
ON (c1 = c2);
2837+
2838+
--echo # mdev-12820
2839+
eval $q2;
2840+
eval EXPLAIN EXTENDED $q2;
2841+
2842+
DROP TABLE t1,t2,t3,t4;
2843+
28042844
# The following command must be the last one the file
28052845
set optimizer_switch=@subselect_sj_tmp;

sql/opt_subselect.cc

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1103,7 +1103,26 @@ bool convert_join_subqueries_to_semijoins(JOIN *join)
11031103
do
11041104
{
11051105
embedded= embedding;
1106-
if (test(embedded->outer_join))
1106+
bool block_conversion_to_sj= false;
1107+
if (embedded->on_expr)
1108+
{
1109+
/*
1110+
Conversion of an IN subquery predicate into semi-join
1111+
is blocked now if the predicate occurs:
1112+
- in the ON expression of an outer join
1113+
- in the ON expression of an inner join embedded directly
1114+
or indirectly in the inner nest of an outer join
1115+
*/
1116+
for (TABLE_LIST *tl= embedded; tl; tl= tl->embedding)
1117+
{
1118+
if (tl->outer_join)
1119+
{
1120+
block_conversion_to_sj= true;
1121+
break;
1122+
}
1123+
}
1124+
}
1125+
if (block_conversion_to_sj)
11071126
{
11081127
Item *cond= embedded->on_expr;
11091128
if (!cond)

0 commit comments

Comments
 (0)