diff options
Diffstat (limited to 'sql/opt_subselect.cc')
-rw-r--r-- | sql/opt_subselect.cc | 31 |
1 files changed, 30 insertions, 1 deletions
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index 0335a663ec3..dd6c2c50b32 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -1105,7 +1105,26 @@ bool convert_join_subqueries_to_semijoins(JOIN *join) do { embedded= embedding; - if (MY_TEST(embedded->outer_join)) + bool block_conversion_to_sj= false; + if (embedded->on_expr) + { + /* + Conversion of an IN subquery predicate into semi-join + is blocked now if the predicate occurs: + - in the ON expression of an outer join + - in the ON expression of an inner join embedded directly + or indirectly in the inner nest of an outer join + */ + for (TABLE_LIST *tl= embedded; tl; tl= tl->embedding) + { + if (tl->outer_join) + { + block_conversion_to_sj= true; + break; + } + } + } + if (block_conversion_to_sj) { Item *cond= embedded->on_expr; if (!cond) @@ -1144,6 +1163,16 @@ bool convert_join_subqueries_to_semijoins(JOIN *join) in_subq->block_conversion_to_sj(); } } + + if (join->select_options & SELECT_STRAIGHT_JOIN) + { + /* Block conversion to semijoins for all candidates */ + li.rewind(); + while ((in_subq= li++)) + { + in_subq->block_conversion_to_sj(); + } + } li.rewind(); /* First, convert child join's subqueries. We proceed bottom-up here */ |