diff options
author | Igor Babaev <igor@askmonty.org> | 2016-08-30 16:14:51 -0700 |
---|---|---|
committer | Igor Babaev <igor@askmonty.org> | 2016-08-30 16:14:51 -0700 |
commit | 2250e9ea261f661cb73c147a28f4d30655d7483d (patch) | |
tree | 04673b47943fdb137f8fe5bafdb64a24887f8c0f /sql/item_subselect.cc | |
parent | cb1e44219b9beae92e104cfe5e67aab3073dd8aa (diff) | |
parent | 4ca7b226c05ae883accec64b1afe6d60daf1b323 (diff) | |
download | mariadb-git-2250e9ea261f661cb73c147a28f4d30655d7483d.tar.gz |
Merge 10.2 into 10.2-mdev9864.
Diffstat (limited to 'sql/item_subselect.cc')
-rw-r--r-- | sql/item_subselect.cc | 107 |
1 files changed, 65 insertions, 42 deletions
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 7d458282825..fde85e4a120 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; @@ -324,7 +327,7 @@ end: } -bool Item_subselect::enumerate_field_refs_processor(uchar *arg) +bool Item_subselect::enumerate_field_refs_processor(void *arg) { List_iterator<Ref_to_outside> it(upper_refs); Ref_to_outside *upper; @@ -337,7 +340,7 @@ bool Item_subselect::enumerate_field_refs_processor(uchar *arg) return FALSE; } -bool Item_subselect::mark_as_eliminated_processor(uchar *arg) +bool Item_subselect::mark_as_eliminated_processor(void *arg) { eliminated= TRUE; return FALSE; @@ -354,7 +357,7 @@ bool Item_subselect::mark_as_eliminated_processor(uchar *arg) FALSE to force the evaluation of the processor for the subsequent items. */ -bool Item_subselect::eliminate_subselect_processor(uchar *arg) +bool Item_subselect::eliminate_subselect_processor(void *arg) { unit->item= NULL; unit->exclude_from_tree(); @@ -374,7 +377,7 @@ bool Item_subselect::eliminate_subselect_processor(uchar *arg) FALSE to force the evaluation of the processor for the subsequent items. */ -bool Item_subselect::set_fake_select_as_master_processor(uchar *arg) +bool Item_subselect::set_fake_select_as_master_processor(void *arg) { SELECT_LEX *fake_select= (SELECT_LEX*) arg; /* @@ -522,8 +525,7 @@ void Item_subselect::recalc_used_tables(st_select_lex *new_parent, Field_fixer fixer; fixer.used_tables= 0; fixer.new_parent= new_parent; - upper->item->walk(&Item::enumerate_field_refs_processor, FALSE, - (uchar*)&fixer); + upper->item->walk(&Item::enumerate_field_refs_processor, 0, &fixer); used_tables_cache |= fixer.used_tables; upper->item->walk(&Item::update_table_bitmaps_processor, FALSE, NULL); /* @@ -566,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()) @@ -601,7 +615,7 @@ bool Item_subselect::is_expensive() bool Item_subselect::walk(Item_processor processor, bool walk_subquery, - uchar *argument) + void *argument) { if (!(unit->uncacheable & ~UNCACHEABLE_DEPENDENT) && engine->is_executed() && !unit->describe) @@ -700,7 +714,7 @@ void Item_subselect::get_cache_parameters(List<Item> ¶meters) unit->first_select()->nest_level, // nest_level TRUE // collect }; - walk(&Item::collect_outer_ref_processor, TRUE, (uchar*)&prm); + walk(&Item::collect_outer_ref_processor, TRUE, &prm); } int Item_in_subselect::optimize(double *out_rows, double *cost) @@ -1781,7 +1795,7 @@ Item_in_subselect::single_value_transformer(JOIN *join) select and is not outer anymore. */ where_item->walk(&Item::remove_dependence_processor, 0, - (uchar *) select_lex->outer_select()); + select_lex->outer_select()); /* fix_field of substitution item will be done in time of substituting. @@ -2214,7 +2228,7 @@ Item_in_subselect::row_value_transformer(JOIN *join) /* The uncacheable property controls a number of actions, e.g. whether to save/restore (via init_save_join_tab/restore_tmp) the original JOIN for - plans with a temp table where the original JOIN was overriden by + plans with a temp table where the original JOIN was overridden by make_simple_join. The UNCACHEABLE_EXPLAIN is ignored by EXPLAIN, thus non-correlated subqueries will not appear as such to EXPLAIN. */ @@ -2510,7 +2524,7 @@ bool Item_in_subselect::create_in_to_exists_cond(JOIN *join_arg) /* The uncacheable property controls a number of actions, e.g. whether to save/restore (via init_save_join_tab/restore_tmp) the original JOIN for - plans with a temp table where the original JOIN was overriden by + plans with a temp table where the original JOIN was overridden by make_simple_join. The UNCACHEABLE_EXPLAIN is ignored by EXPLAIN, thus non-correlated subqueries will not appear as such to EXPLAIN. */ @@ -2747,7 +2761,7 @@ alloc_err: @return TRUE in case of error and FALSE otherwise. */ -bool Item_exists_subselect::exists2in_processor(uchar *opt_arg) +bool Item_exists_subselect::exists2in_processor(void *opt_arg) { THD *thd= (THD *)opt_arg; SELECT_LEX *first_select=unit->first_select(), *save_select; @@ -2797,7 +2811,7 @@ bool Item_exists_subselect::exists2in_processor(uchar *opt_arg) unit->first_select()->nest_level, // nest_level FALSE // collect }; - walk(&Item::collect_outer_ref_processor, TRUE, (uchar*)&prm); + walk(&Item::collect_outer_ref_processor, TRUE, &prm); DBUG_ASSERT(prm.count > 0); DBUG_ASSERT(prm.count >= (uint)eqs.elements()); will_be_correlated= prm.count > (uint)eqs.elements(); @@ -2935,7 +2949,7 @@ bool Item_exists_subselect::exists2in_processor(uchar *opt_arg) uint i; for (i= 0; i < (uint)eqs.elements(); i++) if (eqs.at(i).outer_exp-> - walk(&Item::find_item_processor, TRUE, (uchar*)upper->item)) + walk(&Item::find_item_processor, TRUE, upper->item)) break; if (i == (uint)eqs.elements() && (in_subs->upper_refs.push_back(upper, thd->stmt_arena->mem_root))) @@ -3166,9 +3180,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)) ); @@ -3285,7 +3302,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); @@ -3402,10 +3420,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) { @@ -3486,10 +3504,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; @@ -3522,10 +3540,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(); @@ -3553,12 +3572,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); @@ -4624,7 +4644,7 @@ subselect_hash_sj_engine::choose_partial_match_strategy( /* Choose according to global optimizer switch. If only one of the switches is 'ON', then the remaining strategy is the only possible one. The only cases - when this will be overriden is when the total size of all buffers for the + when this will be overridden is when the total size of all buffers for the merge strategy is bigger than the 'rowid_merge_buff_size' system variable, or if there isn't enough physical memory to allocate the buffers. */ @@ -5015,13 +5035,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); } @@ -5396,7 +5417,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, @@ -5405,6 +5426,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)) { @@ -5422,13 +5444,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; @@ -5877,14 +5900,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), @@ -6497,7 +6520,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, @@ -6505,7 +6528,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, |