From 77c4c4d8ea042fc1f3cb16aa0681e8516c0cc923 Mon Sep 17 00:00:00 2001 From: Sergey Petrunya Date: Sat, 28 May 2011 20:34:04 +0400 Subject: [PATCH] post-merge fixes: get MWL#90 code to work with MWL#89's way of processing prepared statements: - conversion subquery_predicate -> TABLE_LIST is once per-statement - However, the code must take into account that materialized temptable is dropped and re-created on each execution (the tricky part is that at start of n-th EXECUTE we have TABLE_LIST object but not its TABLE object) - IN-equality is injected into WHERE on every execution. --- sql/item_subselect.cc | 1 + sql/item_subselect.h | 2 ++ sql/opt_subselect.cc | 5 ++-- sql/sql_base.cc | 36 +++++++++++++++++++++++++---- sql/sql_select.cc | 54 +++++++++++++++++++++++++++++++++++++++++++ sql/table.h | 1 + 6 files changed, 93 insertions(+), 6 deletions(-) diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 5941c857328..922f6e44601 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -4064,6 +4064,7 @@ bool subselect_hash_sj_engine::make_semi_join_conds() context->init(); context->first_name_resolution_table= context->last_name_resolution_table= tmp_table_ref; + semi_join_conds_context= context; for (uint i= 0; i < item_in->left_expr->cols(); i++) { diff --git a/sql/item_subselect.h b/sql/item_subselect.h index ad98949f78e..bb1198eb054 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -839,6 +839,8 @@ public: not equal to the search key in SQL terms. */ Item_cond_and *semi_join_conds; + Name_resolution_context *semi_join_conds_context; + subselect_hash_sj_engine(THD *thd, Item_subselect *in_predicate, subselect_single_select_engine *old_engine) diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index 1bbdbf14ea4..95c30a873b3 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -1397,6 +1397,7 @@ static bool convert_subq_to_jtbm(JOIN *parent_join, jtbm->table->tablenr= parent_join->table_count; jtbm->table->map= table_map(1) << (parent_join->table_count); + jtbm->jtbm_table_no= jtbm->table->tablenr; parent_join->table_count++; DBUG_ASSERT(parent_join->table_count < MAX_TABLES); @@ -1409,7 +1410,7 @@ static bool convert_subq_to_jtbm(JOIN *parent_join, create_subquery_temptable_name(tbl_alias, hash_sj_engine->materialize_join-> select_lex->select_number); jtbm->alias= tbl_alias; - +#if 0 /* Inject sj_on_expr into the parent's WHERE or ON */ if (emb_tbl_nest) { @@ -1426,7 +1427,7 @@ static bool convert_subq_to_jtbm(JOIN *parent_join, parent_join->conds->fix_fields(parent_join->thd, &parent_join->conds); parent_join->select_lex->where= parent_join->conds; } - +#endif /* Don't unlink the child subselect, as the subquery will be used. */ DBUG_RETURN(FALSE); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index c24fca1fb9a..49e12a8205f 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -7768,7 +7768,14 @@ bool setup_tables(THD *thd, Name_resolution_context *context, first_select_table= 0; tablenr= 0; } - setup_table_map(table, table_list, tablenr); + + if (table_list->jtbm_subselect) + { + table_list->jtbm_table_no= tablenr; + } + else + setup_table_map(table, table_list, tablenr); + if (table_list->process_index_hints(table)) DBUG_RETURN(1); } @@ -7797,17 +7804,38 @@ bool setup_tables(THD *thd, Name_resolution_context *context, if (res) DBUG_RETURN(1); } + if (table_list->jtbm_subselect) { - Item *item= table_list->jtbm_subselect; - if (item->fix_fields(thd, &item)) + Item *item= table_list->jtbm_subselect->optimizer; + if (table_list->jtbm_subselect->optimizer->fix_fields(thd, &item)) { my_error(ER_TOO_MANY_TABLES,MYF(0),MAX_TABLES); /* psergey-todo: WHY ER_TOO_MANY_TABLES ???*/ DBUG_RETURN(1); } - DBUG_ASSERT(item == table_list->jtbm_subselect); + DBUG_ASSERT(item == table_list->jtbm_subselect->optimizer); + /* + { + Item_in_subselect *subq_pred= table_list->jtbm_subselect; + double rows; + double read_time; + + // psergey-merge: disable IN->EXISTS for JTBM subqueries, for now. + subq_pred->in_strategy &= ~SUBS_IN_TO_EXISTS; + subq_pred->optimize(&rows, &read_time); + + subq_pred->jtbm_read_time= read_time; + subq_pred->jtbm_record_count=rows; + subq_pred->is_jtbm_merged= TRUE; + } + // The following call should never ever be made on its own anymore: if (table_list->jtbm_subselect->setup_mat_engine()) // dont_switch_arena=FALSE DBUG_RETURN(1); + */ + //psergey-merge: fix prepared statements: + //subselect_hash_sj_engine *mat_engine= + // (subselect_hash_sj_engine*)table_list->jtbm_subselect->engine; + //table= table_list->table= mat_engine->tmp_table; } } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index a07900d328b..fb5afc7055c 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -766,6 +766,57 @@ err: } +void +inject_jtbm_conds(JOIN *join, List *join_list, Item **join_where) +{ + TABLE_LIST *table; + NESTED_JOIN *nested_join; + List_iterator li(*join_list); + DBUG_ENTER("inject_jtbm_conds"); + + + while ((table= li++)) + { + Item_in_subselect *item; + + if ((item= table->jtbm_subselect)) + { + Item_in_subselect *subq_pred= item; + double rows; + double read_time; + + // psergey-merge: disable IN->EXISTS for JTBM subqueries, for now. + subq_pred->in_strategy &= ~SUBS_IN_TO_EXISTS; + subq_pred->optimize(&rows, &read_time); + + subq_pred->jtbm_read_time= read_time; + subq_pred->jtbm_record_count=rows; + subq_pred->is_jtbm_merged= TRUE; + + subselect_hash_sj_engine *hash_sj_engine= + ((subselect_hash_sj_engine*)item->engine); + + + //repeat of convert_subq_to_jtbm: + table->table= hash_sj_engine->tmp_table; + + setup_table_map(table->table, table, table->jtbm_table_no); + + Item *sj_conds= hash_sj_engine->semi_join_conds; + + (*join_where)= and_items(*join_where, sj_conds); + (*join_where)->fix_fields(join->thd, join_where); + //parent_join->select_lex->where= parent_join->conds; + } + + if ((nested_join= table->nested_join)) + { + inject_jtbm_conds(join, &nested_join->join_list, join_where); + } + } + DBUG_VOID_RETURN; +} + /** global select optimisation. @@ -856,6 +907,9 @@ JOIN::optimize() if (arena) thd->restore_active_arena(arena, &backup); } + + //psergey-merge + inject_jtbm_conds(this, join_list, &conds); conds= optimize_cond(this, conds, join_list, &cond_value, &cond_equal); if (thd->is_error()) diff --git a/sql/table.h b/sql/table.h index da925c2db56..9bb9b5beb6b 100644 --- a/sql/table.h +++ b/sql/table.h @@ -1272,6 +1272,7 @@ struct TABLE_LIST /* If this is a jtbm semi-join object: corresponding subselect predicate */ Item_in_subselect *jtbm_subselect; + uint jtbm_table_no; SJ_MATERIALIZATION_INFO *sj_mat_info;