summaryrefslogtreecommitdiff
path: root/sql/opt_subselect.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/opt_subselect.cc')
-rw-r--r--sql/opt_subselect.cc61
1 files changed, 36 insertions, 25 deletions
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index 99f75d9ad2f..88b1428f2b1 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -1613,8 +1613,15 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred)
{
SELECT_LEX *parent_lex= parent_join->select_lex;
TABLE_LIST *emb_tbl_nest= NULL;
+ TABLE_LIST *orig_tl;
List<TABLE_LIST> *emb_join_list= &parent_lex->top_join_list;
THD *thd= parent_join->thd;
+ SELECT_LEX *save_lex;
+ Item **left;
+ Item *left_exp;
+ Item *left_exp_orig;
+
+ uint ncols;
DBUG_ENTER("convert_subq_to_sj");
/*
@@ -1774,18 +1781,18 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred)
because view's tables are inserted after the view)
*/
- for (tl= (TABLE_LIST*)(parent_lex->table_list.first); tl->next_local; tl= tl->next_local)
+ for (orig_tl= (TABLE_LIST*)(parent_lex->table_list.first);
+ orig_tl->next_local;
+ orig_tl= orig_tl->next_local)
{}
- tl->next_local= subq_lex->join->tables_list;
+ orig_tl->next_local= subq_lex->join->tables_list;
/* A theory: no need to re-connect the next_global chain */
/* 3. Remove the original subquery predicate from the WHERE/ON */
- // The subqueries were replaced for Item_int(1) earlier
- subq_pred->reset_strategy(SUBS_SEMI_JOIN); // for subsequent executions
- /*TODO: also reset the 'with_subquery' there. */
+ /*TODO: also reset the 'm_with_subquery' there. */
/* n. Adjust the parent_join->table_count counter */
uint table_no= parent_join->table_count;
@@ -1820,16 +1827,18 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred)
Put the subquery's WHERE into semi-join's sj_on_expr
Add the subquery-induced equalities too.
*/
- SELECT_LEX *save_lex= thd->lex->current_select;
+ save_lex= thd->lex->current_select;
+ table_map subq_pred_used_tables;
+
thd->lex->current_select=subq_lex;
- Item **left= subq_pred->left_exp_ptr();
+ left= subq_pred->left_exp_ptr();
if ((*left)->fix_fields_if_needed(thd, left))
- DBUG_RETURN(TRUE);
- Item *left_exp= *left;
- Item *left_exp_orig= subq_pred->left_exp_orig();
+ goto restore_tl_and_exit;
+ left_exp= *left;
+ left_exp_orig= subq_pred->left_exp_orig();
thd->lex->current_select=save_lex;
- table_map subq_pred_used_tables= subq_pred->used_tables();
+ subq_pred_used_tables= subq_pred->used_tables();
sj_nest->nested_join->sj_corr_tables= subq_pred_used_tables;
sj_nest->nested_join->sj_depends_on= subq_pred_used_tables |
left_exp->used_tables();
@@ -1850,7 +1859,7 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred)
Item_direct_view_refs doesn't substitute itself with anything in
Item_direct_view_ref::fix_fields.
*/
- uint ncols= sj_nest->sj_in_exprs= left_exp->cols();
+ ncols= sj_nest->sj_in_exprs= left_exp->cols();
sj_nest->nested_join->sj_outer_expr_list.empty();
reset_equality_number_for_subq_conds(sj_nest->sj_on_expr);
@@ -1872,7 +1881,7 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred)
new (thd->mem_root) Item_func_eq(thd, left_exp_orig,
subq_lex->ref_pointer_array[0]);
if (!item_eq)
- DBUG_RETURN(TRUE);
+ goto restore_tl_and_exit;
if (left_exp_orig != left_exp)
thd->change_item_tree(item_eq->arguments(), left_exp);
item_eq->in_equality_no= 0;
@@ -1893,7 +1902,7 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred)
Item_func_eq(thd, left_exp_orig->element_index(i),
subq_lex->ref_pointer_array[i]);
if (!item_eq)
- DBUG_RETURN(TRUE);
+ goto restore_tl_and_exit;
DBUG_ASSERT(left_exp->element_index(i)->fixed());
if (left_exp_orig->element_index(i) !=
left_exp->element_index(i))
@@ -1912,13 +1921,13 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred)
Item_row *row= new (thd->mem_root) Item_row(thd, subq_lex->pre_fix);
/* fix fields on subquery was call so they should be the same */
if (!row)
- DBUG_RETURN(TRUE);
+ goto restore_tl_and_exit;
DBUG_ASSERT(ncols == row->cols());
nested_join->sj_outer_expr_list.push_back(left);
Item_func_eq *item_eq=
new (thd->mem_root) Item_func_eq(thd, left_exp_orig, row);
if (!item_eq)
- DBUG_RETURN(TRUE);
+ goto restore_tl_and_exit;
for (uint i= 0; i < row->cols(); i++)
{
if (row->element_index(i) != subq_lex->ref_pointer_array[i])
@@ -1937,9 +1946,7 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred)
we have in here).
*/
if (sj_nest->sj_on_expr->fix_fields_if_needed(thd, &sj_nest->sj_on_expr))
- {
- DBUG_RETURN(TRUE);
- }
+ goto restore_tl_and_exit;
/*
Walk through sj nest's WHERE and ON expressions and call
@@ -1964,9 +1971,7 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred)
emb_tbl_nest->on_expr->top_level_item();
if (emb_tbl_nest->on_expr->fix_fields_if_needed(thd,
&emb_tbl_nest->on_expr))
- {
- DBUG_RETURN(TRUE);
- }
+ goto restore_tl_and_exit;
}
else
{
@@ -1980,9 +1985,8 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred)
save_lex= thd->lex->current_select;
thd->lex->current_select=parent_join->select_lex;
if (parent_join->conds->fix_fields_if_needed(thd, &parent_join->conds))
- {
- DBUG_RETURN(1);
- }
+ goto restore_tl_and_exit;
+
thd->lex->current_select=save_lex;
parent_join->select_lex->where= parent_join->conds;
}
@@ -1995,9 +1999,16 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred)
parent_lex->ftfunc_list->push_front(ifm, thd->mem_root);
}
+ // The subqueries were replaced for Item_int(1) earlier
+ subq_pred->reset_strategy(SUBS_SEMI_JOIN); // for subsequent executions
+
parent_lex->have_merged_subqueries= TRUE;
/* Fatal error may have been set to by fix_after_pullout() */
DBUG_RETURN(thd->is_fatal_error);
+
+restore_tl_and_exit:
+ orig_tl->next_local= NULL;
+ DBUG_RETURN(TRUE);
}