diff options
Diffstat (limited to 'sql/item_subselect.cc')
-rw-r--r-- | sql/item_subselect.cc | 78 |
1 files changed, 51 insertions, 27 deletions
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 28d33ac4f7c..8bb12ce0ac8 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -86,7 +86,6 @@ void Item_subselect::init(st_select_lex *select_lex, DBUG_PRINT("enter", ("select_lex: 0x%lx this: 0x%lx", (ulong) select_lex, (ulong) this)); unit= select_lex->master_unit(); - thd= unit->thd; if (unit->item) { @@ -105,7 +104,7 @@ void Item_subselect::init(st_select_lex *select_lex, Item can be changed in JOIN::prepare while engine in JOIN::optimize => we do not copy old_engine here */ - thd->change_item_tree((Item**)&unit->item, this); + unit->thd->change_item_tree((Item**)&unit->item, this); engine->change_result(this, result, TRUE); } } @@ -120,9 +119,9 @@ void Item_subselect::init(st_select_lex *select_lex, NO_MATTER : outer_select->parsing_place); if (unit->is_union()) - engine= new subselect_union_engine(thd, unit, result, this); + engine= new subselect_union_engine(unit, result, this); else - engine= new subselect_single_select_engine(thd, select_lex, result, this); + engine= new subselect_single_select_engine(select_lex, result, this); } { SELECT_LEX *upper= unit->outer_select(); @@ -239,6 +238,10 @@ bool Item_subselect::fix_fields(THD *thd_param, Item **ref) uint8 uncacheable; bool res; + thd= thd_param; + + DBUG_ASSERT(unit->thd == thd); + status_var_increment(thd_param->status_var.feature_subquery); DBUG_ASSERT(fixed == 0); @@ -261,7 +264,7 @@ bool Item_subselect::fix_fields(THD *thd_param, Item **ref) return TRUE; - if (!(res= engine->prepare())) + if (!(res= engine->prepare(thd))) { // all transformation is done (used by prepared statements) changed= 1; @@ -565,22 +568,34 @@ bool Item_subselect::is_expensive() for (SELECT_LEX *sl= unit->first_select(); sl; sl= sl->next_select()) { JOIN *cur_join= sl->join; + + /* not optimized subquery */ if (!cur_join) - continue; + return true; + + /* very simple subquery */ + if (!cur_join->tables_list && !sl->first_inner_unit()) + return false; + + /* + If the subquery is not optimised or in the process of optimization + it supposed to be expensive + */ + if (!cur_join->optimized) + return true; /* Subqueries whose result is known after optimization are not expensive. Such subqueries have all tables optimized away, thus have no join plan. */ - if (cur_join->optimized && - (cur_join->zero_result_cause || !cur_join->tables_list)) + if ((cur_join->zero_result_cause || !cur_join->tables_list)) return false; /* If a subquery is not optimized we cannot estimate its cost. A subquery is considered optimized if it has a join plan. */ - if (!(cur_join->optimized && cur_join->join_tab)) + if (!cur_join->join_tab) return true; if (sl->first_inner_unit()) @@ -3163,9 +3178,12 @@ bool Item_in_subselect::fix_fields(THD *thd_arg, Item **ref) { uint outer_cols_num; List<Item> *inner_cols; - char const *save_where= thd->where; + char const *save_where= thd_arg->where; DBUG_ENTER("Item_in_subselect::fix_fields"); + thd= thd_arg; + DBUG_ASSERT(unit->thd == thd); + if (test_strategy(SUBS_SEMI_JOIN)) DBUG_RETURN( !( (*ref)= new (thd->mem_root) Item_int(thd, 1)) ); @@ -3282,7 +3300,8 @@ bool Item_in_subselect::setup_mat_engine() if (!(mat_engine= new subselect_hash_sj_engine(thd, this, select_engine))) DBUG_RETURN(TRUE); - if (mat_engine->init(&select_engine->join->fields_list, + if (mat_engine->prepare(thd) || + mat_engine->init(&select_engine->join->fields_list, engine->get_identifier())) DBUG_RETURN(TRUE); @@ -3399,10 +3418,10 @@ void subselect_engine::set_thd(THD *thd_arg) subselect_single_select_engine:: -subselect_single_select_engine(THD *thd_arg, st_select_lex *select, +subselect_single_select_engine(st_select_lex *select, select_result_interceptor *result_arg, Item_subselect *item_arg) - :subselect_engine(thd_arg, item_arg, result_arg), + :subselect_engine(item_arg, result_arg), prepared(0), executed(0), select_lex(select), join(0) { @@ -3483,10 +3502,10 @@ void subselect_uniquesubquery_engine::cleanup() } -subselect_union_engine::subselect_union_engine(THD *thd_arg, st_select_lex_unit *u, +subselect_union_engine::subselect_union_engine(st_select_lex_unit *u, select_result_interceptor *result_arg, Item_subselect *item_arg) - :subselect_engine(thd_arg, item_arg, result_arg) + :subselect_engine(item_arg, result_arg) { unit= u; unit->item= item_arg; @@ -3519,10 +3538,11 @@ subselect_union_engine::subselect_union_engine(THD *thd_arg, st_select_lex_unit @retval 1 if error */ -int subselect_single_select_engine::prepare() +int subselect_single_select_engine::prepare(THD *thd) { if (prepared) return 0; + set_thd(thd); if (select_lex->join) { select_lex->cleanup(); @@ -3550,12 +3570,13 @@ int subselect_single_select_engine::prepare() return 0; } -int subselect_union_engine::prepare() +int subselect_union_engine::prepare(THD *thd_arg) { + set_thd(thd_arg); return unit->prepare(thd, result, SELECT_NO_UNLOCK); } -int subselect_uniquesubquery_engine::prepare() +int subselect_uniquesubquery_engine::prepare(THD *) { /* Should never be called. */ DBUG_ASSERT(FALSE); @@ -5012,13 +5033,14 @@ subselect_hash_sj_engine::~subselect_hash_sj_engine() } -int subselect_hash_sj_engine::prepare() +int subselect_hash_sj_engine::prepare(THD *thd_arg) { /* Create and optimize the JOIN that will be used to materialize the subquery if not yet created. */ - return materialize_engine->prepare(); + set_thd(thd_arg); + return materialize_engine->prepare(thd); } @@ -5393,7 +5415,7 @@ int subselect_hash_sj_engine::exec() if (strategy == PARTIAL_MATCH_MERGE) { pm_engine= - new subselect_rowid_merge_engine(thd, (subselect_uniquesubquery_engine*) + new subselect_rowid_merge_engine((subselect_uniquesubquery_engine*) lookup_engine, tmp_table, count_pm_keys, has_covering_null_row, @@ -5402,6 +5424,7 @@ int subselect_hash_sj_engine::exec() item, result, semi_join_conds->argument_list()); if (!pm_engine || + pm_engine->prepare(thd) || ((subselect_rowid_merge_engine*) pm_engine)-> init(nn_key_parts, &partial_match_key_parts)) { @@ -5419,13 +5442,14 @@ int subselect_hash_sj_engine::exec() if (strategy == PARTIAL_MATCH_SCAN) { if (!(pm_engine= - new subselect_table_scan_engine(thd, (subselect_uniquesubquery_engine*) + new subselect_table_scan_engine((subselect_uniquesubquery_engine*) lookup_engine, tmp_table, item, result, semi_join_conds->argument_list(), has_covering_null_row, has_covering_null_columns, - count_columns_with_nulls))) + count_columns_with_nulls)) || + pm_engine->prepare(thd)) { /* This is an irrecoverable error. */ res= 1; @@ -5874,14 +5898,14 @@ void Ordered_key::print(String *str) subselect_partial_match_engine::subselect_partial_match_engine( - THD *thd_arg, subselect_uniquesubquery_engine *engine_arg, + subselect_uniquesubquery_engine *engine_arg, TABLE *tmp_table_arg, Item_subselect *item_arg, select_result_interceptor *result_arg, List<Item> *equi_join_conds_arg, bool has_covering_null_row_arg, bool has_covering_null_columns_arg, uint count_columns_with_nulls_arg) - :subselect_engine(thd_arg, item_arg, result_arg), + :subselect_engine(item_arg, result_arg), tmp_table(tmp_table_arg), lookup_engine(engine_arg), equi_join_conds(equi_join_conds_arg), has_covering_null_row(has_covering_null_row_arg), @@ -6494,7 +6518,7 @@ end: subselect_table_scan_engine::subselect_table_scan_engine( - THD *thd_arg, subselect_uniquesubquery_engine *engine_arg, + subselect_uniquesubquery_engine *engine_arg, TABLE *tmp_table_arg, Item_subselect *item_arg, select_result_interceptor *result_arg, @@ -6502,7 +6526,7 @@ subselect_table_scan_engine::subselect_table_scan_engine( bool has_covering_null_row_arg, bool has_covering_null_columns_arg, uint count_columns_with_nulls_arg) - :subselect_partial_match_engine(thd_arg, engine_arg, tmp_table_arg, item_arg, + :subselect_partial_match_engine(engine_arg, tmp_table_arg, item_arg, result_arg, equi_join_conds_arg, has_covering_null_row_arg, has_covering_null_columns_arg, |