diff options
Diffstat (limited to 'sql/item_subselect.cc')
-rw-r--r-- | sql/item_subselect.cc | 401 |
1 files changed, 227 insertions, 174 deletions
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index fa398dc6e21..227d84dd213 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -48,9 +48,9 @@ const char *exists_outer_expr_name= "<exists outer expr>"; int check_and_do_in_subquery_rewrites(JOIN *join); -Item_subselect::Item_subselect(): - Item_result_field(), Used_tables_and_const_cache(), - value_assigned(0), own_engine(0), thd(0), old_engine(0), +Item_subselect::Item_subselect(THD *thd_arg): + Item_result_field(thd_arg), Used_tables_and_const_cache(), + value_assigned(0), own_engine(0), thd(0), old_engine(0), have_to_be_excluded(0), inside_first_fix_fields(0), done_first_fix_fields(FALSE), expr_cache(0), forced_const(FALSE), substitution(0), engine(0), eliminated(FALSE), @@ -478,6 +478,7 @@ void Item_subselect::recalc_used_tables(st_select_lex *new_parent, { List_iterator_fast<Ref_to_outside> it(upper_refs); Ref_to_outside *upper; + DBUG_ENTER("recalc_used_tables"); used_tables_cache= 0; while ((upper= it++)) @@ -537,6 +538,8 @@ void Item_subselect::recalc_used_tables(st_select_lex *new_parent, he has done const table detection, and that will be our chance to update const_tables_cache. */ + DBUG_PRINT("exit", ("used_tables_cache: %llx", used_tables_cache)); + DBUG_VOID_RETURN; } @@ -875,7 +878,7 @@ bool Item_subselect::const_item() const Item *Item_subselect::get_tmp_table_item(THD *thd_arg) { if (!with_sum_func && !const_item()) - return new Item_field(result_field); + return new (thd->mem_root) Item_field(thd_arg, result_field); return copy_or_same(thd_arg); } @@ -896,7 +899,7 @@ void Item_subselect::update_used_tables() void Item_subselect::print(String *str, enum_query_type query_type) { - if (query_type == QT_EXPLAIN) + if (query_type & QT_ITEM_SUBSELECT_ID_ONLY) { str->append("(subquery#"); if (unit && unit->first_select()) @@ -922,12 +925,11 @@ void Item_subselect::print(String *str, enum_query_type query_type) } -Item_singlerow_subselect::Item_singlerow_subselect(THD *thd_arg, st_select_lex *select_lex) - :Item_subselect(), value(0) +Item_singlerow_subselect::Item_singlerow_subselect(THD *thd, st_select_lex *select_lex): + Item_subselect(thd), value(0) { DBUG_ENTER("Item_singlerow_subselect::Item_singlerow_subselect"); - init(select_lex, new (thd_arg->mem_root) select_singlerow_subselect(thd_arg, - this)); + init(select_lex, new (thd->mem_root) select_singlerow_subselect(thd, this)); maybe_null= 1; max_columns= UINT_MAX; DBUG_VOID_RETURN; @@ -953,16 +955,16 @@ Item_singlerow_subselect::invalidate_and_restore_select_lex() DBUG_RETURN(result); } -Item_maxmin_subselect::Item_maxmin_subselect(THD *thd_param, +Item_maxmin_subselect::Item_maxmin_subselect(THD *thd, Item_subselect *parent, st_select_lex *select_lex, - bool max_arg) - :Item_singlerow_subselect(), was_values(TRUE) + bool max_arg): + Item_singlerow_subselect(thd), was_values(TRUE) { DBUG_ENTER("Item_maxmin_subselect::Item_maxmin_subselect"); max= max_arg; init(select_lex, - new (thd_param->mem_root) select_max_min_finder_subselect(thd_param, + new (thd->mem_root) select_max_min_finder_subselect(thd, this, max_arg, parent->substype() == Item_subselect::ALL_SUBS)); max_columns= 1; maybe_null= 1; @@ -975,12 +977,6 @@ Item_maxmin_subselect::Item_maxmin_subselect(THD *thd_param, used_tables_cache= parent->get_used_tables_cache(); const_item_cache= parent->const_item(); - /* - this subquery always creates during preparation, so we can assign - thd here - */ - thd= thd_param; - DBUG_VOID_RETURN; } @@ -1020,7 +1016,7 @@ void Item_maxmin_subselect::no_rows_in_result() */ if (parsing_place != SELECT_LIST || const_item()) return; - value= Item_cache::get_cache(new Item_null()); + value= Item_cache::get_cache(thd, new (thd->mem_root) Item_null(thd)); null_value= 0; was_values= 0; make_const(); @@ -1038,7 +1034,7 @@ void Item_singlerow_subselect::no_rows_in_result() */ if (parsing_place != SELECT_LIST || const_item()) return; - value= Item_cache::get_cache(new Item_null()); + value= Item_cache::get_cache(thd, new (thd->mem_root) Item_null(thd)); reset(); make_const(); } @@ -1105,7 +1101,8 @@ Item_singlerow_subselect::select_transformer(JOIN *join) if (thd->lex->describe) { char warn_buff[MYSQL_ERRMSG_SIZE]; - sprintf(warn_buff, ER(ER_SELECT_REDUCED), select_lex->select_number); + sprintf(warn_buff, ER_THD(thd, ER_SELECT_REDUCED), + select_lex->select_number); push_warning(thd, Sql_condition::WARN_LEVEL_NOTE, ER_SELECT_REDUCED, warn_buff); } @@ -1191,17 +1188,22 @@ void Item_singlerow_subselect::fix_length_and_dec() this item - otherwise */ -Item* Item_singlerow_subselect::expr_cache_insert_transformer(uchar *thd_arg) +Item* Item_singlerow_subselect::expr_cache_insert_transformer(THD *tmp_thd, + uchar *unused) { - THD *thd= (THD*) thd_arg; DBUG_ENTER("Item_singlerow_subselect::expr_cache_insert_transformer"); + DBUG_ASSERT(thd == tmp_thd); + if (expr_cache) DBUG_RETURN(expr_cache); - if (expr_cache_is_needed(thd) && - (expr_cache= set_expr_cache(thd))) + if (expr_cache_is_needed(tmp_thd) && + (expr_cache= set_expr_cache(tmp_thd))) + { + init_expr_cache_tracker(tmp_thd); DBUG_RETURN(expr_cache); + } DBUG_RETURN(this); } @@ -1345,13 +1347,13 @@ bool Item_singlerow_subselect::get_date(MYSQL_TIME *ltime,ulonglong fuzzydate) } -Item_exists_subselect::Item_exists_subselect(THD *thd_arg, +Item_exists_subselect::Item_exists_subselect(THD *thd, st_select_lex *select_lex): - Item_subselect(), upper_not(NULL), abort_on_null(0), + Item_subselect(thd), upper_not(NULL), abort_on_null(0), emb_on_expr_nest(NULL), optimizer(0), exists_transformed(0) { DBUG_ENTER("Item_exists_subselect::Item_exists_subselect"); - init(select_lex, new (thd_arg->mem_root) select_exists_subselect(thd_arg, this)); + init(select_lex, new (thd->mem_root) select_exists_subselect(thd, this)); max_columns= UINT_MAX; null_value= FALSE; //can't be NULL maybe_null= 0; //can't be NULL @@ -1382,9 +1384,9 @@ bool Item_in_subselect::test_limit(st_select_lex_unit *unit_arg) return(0); } -Item_in_subselect::Item_in_subselect(THD *thd_arg, Item * left_exp, +Item_in_subselect::Item_in_subselect(THD *thd, Item * left_exp, st_select_lex *select_lex): - Item_exists_subselect(), left_expr_cache(0), first_execution(TRUE), + Item_exists_subselect(thd), left_expr_cache(0), first_execution(TRUE), in_strategy(SUBS_NOT_TRANSFORMED), pushed_cond_guards(NULL), is_jtbm_merged(FALSE), is_jtbm_const_tab(FALSE), is_flattenable_semijoin(FALSE), is_registered_semijoin(FALSE), @@ -1394,8 +1396,7 @@ Item_in_subselect::Item_in_subselect(THD *thd_arg, Item * left_exp, DBUG_PRINT("info", ("in_strategy: %u", (uint)in_strategy)); left_expr= left_exp; func= &eq_creator; - init(select_lex, new (thd_arg->mem_root) select_exists_subselect(thd_arg, - this)); + init(select_lex, new (thd->mem_root) select_exists_subselect(thd, this)); max_columns= UINT_MAX; maybe_null= 1; reset(); @@ -1409,17 +1410,16 @@ int Item_in_subselect::get_identifier() return engine->get_identifier(); } -Item_allany_subselect::Item_allany_subselect(THD *thd_arg, Item * left_exp, +Item_allany_subselect::Item_allany_subselect(THD *thd, Item * left_exp, chooser_compare_func_creator fc, st_select_lex *select_lex, - bool all_arg) - :Item_in_subselect(), func_creator(fc), all(all_arg) + bool all_arg): + Item_in_subselect(thd), func_creator(fc), all(all_arg) { DBUG_ENTER("Item_allany_subselect::Item_allany_subselect"); left_expr= left_exp; func= func_creator(all_arg); - init(select_lex, new (thd_arg->mem_root) select_exists_subselect(thd_arg, - this)); + init(select_lex, new (thd->mem_root) select_exists_subselect(thd, this)); max_columns= 1; abort_on_null= 0; reset(); @@ -1451,7 +1451,7 @@ void Item_exists_subselect::fix_length_and_dec() an IN always requires LIMIT 1) */ thd->change_item_tree(&unit->global_parameters()->select_limit, - new Item_int((int32) 1)); + new (thd->mem_root) Item_int(thd, (int32) 1)); DBUG_PRINT("info", ("Set limit to 1")); DBUG_VOID_RETURN; } @@ -1487,17 +1487,21 @@ void Item_in_subselect::fix_length_and_dec() this item - otherwise */ -Item* Item_exists_subselect::expr_cache_insert_transformer(uchar *thd_arg) +Item* Item_exists_subselect::expr_cache_insert_transformer(THD *tmp_thd, + uchar *unused) { - THD *thd= (THD*) thd_arg; DBUG_ENTER("Item_exists_subselect::expr_cache_insert_transformer"); + DBUG_ASSERT(thd == tmp_thd); if (expr_cache) DBUG_RETURN(expr_cache); - if (substype() == EXISTS_SUBS && expr_cache_is_needed(thd) && - (expr_cache= set_expr_cache(thd))) + if (substype() == EXISTS_SUBS && expr_cache_is_needed(tmp_thd) && + (expr_cache= set_expr_cache(tmp_thd))) + { + init_expr_cache_tracker(tmp_thd); DBUG_RETURN(expr_cache); + } DBUG_RETURN(this); } @@ -1779,12 +1783,13 @@ Item_in_subselect::single_value_transformer(JOIN *join) of the statement. Thus one of 'substitution' arguments can be broken in case of PS. */ - substitution= func->create(thd->mem_root, left_expr, where_item); + substitution= func->create(thd, left_expr, where_item); have_to_be_excluded= 1; if (thd->lex->describe) { char warn_buff[MYSQL_ERRMSG_SIZE]; - sprintf(warn_buff, ER(ER_SELECT_REDUCED), select_lex->select_number); + sprintf(warn_buff, ER_THD(thd, ER_SELECT_REDUCED), + select_lex->select_number); push_warning(thd, Sql_condition::WARN_LEVEL_NOTE, ER_SELECT_REDUCED, warn_buff); } @@ -1817,7 +1822,7 @@ Item_in_subselect::single_value_transformer(JOIN *join) As far as Item_in_optimizer does not substitute itself on fix_fields we can use same item for all selects. */ - expr= new Item_direct_ref(&select_lex->context, + expr= new (thd->mem_root) Item_direct_ref(thd, &select_lex->context, (Item**)optimizer->get_cache(), (char *)"<no matter>", (char *)in_left_expr_name); @@ -1855,7 +1860,6 @@ bool Item_allany_subselect::transform_into_max_min(JOIN *join) if (!test_strategy(SUBS_MAXMIN_INJECTED | SUBS_MAXMIN_ENGINE)) DBUG_RETURN(false); Item **place= optimizer->arguments() + 1; - THD *thd= join->thd; SELECT_LEX *select_lex= join->select_lex; Item *subs; @@ -1886,7 +1890,7 @@ bool Item_allany_subselect::transform_into_max_min(JOIN *join) (ALL && (> || =>)) || (ANY && (< || =<)) for ALL condition is inverted */ - item= new Item_sum_max(*select_lex->ref_pointer_array); + item= new (thd->mem_root) Item_sum_max(thd, *select_lex->ref_pointer_array); } else { @@ -1894,7 +1898,7 @@ bool Item_allany_subselect::transform_into_max_min(JOIN *join) (ALL && (< || =<)) || (ANY && (> || =>)) for ALL condition is inverted */ - item= new Item_sum_min(*select_lex->ref_pointer_array); + item= new (thd->mem_root) Item_sum_min(thd, *select_lex->ref_pointer_array); } if (upper_item) upper_item->set_sum_test(item); @@ -1935,7 +1939,7 @@ bool Item_allany_subselect::transform_into_max_min(JOIN *join) else { Item_maxmin_subselect *item; - subs= item= new Item_maxmin_subselect(thd, this, select_lex, func->l_op()); + subs= item= new (thd->mem_root) Item_maxmin_subselect(thd, this, select_lex, func->l_op()); if (upper_item) upper_item->set_sub_test(item); /* @@ -1948,7 +1952,7 @@ bool Item_allany_subselect::transform_into_max_min(JOIN *join) The swap is needed for expressions of type 'f1 < ALL ( SELECT ....)' where we want to evaluate the sub query even if f1 would be null. */ - subs= func->create_swap(thd->mem_root, *(optimizer->get_cache()), subs); + subs= func->create_swap(thd, *(optimizer->get_cache()), subs); thd->change_item_tree(place, subs); if (subs->fix_fields(thd, &subs)) DBUG_RETURN(true); @@ -2021,7 +2025,7 @@ bool Item_allany_subselect::is_maxmin_applicable(JOIN *join) */ bool -Item_in_subselect::create_single_in_to_exists_cond(JOIN * join, +Item_in_subselect::create_single_in_to_exists_cond(JOIN *join, Item **where_item, Item **having_item) { @@ -2031,7 +2035,6 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN * join, during JOIN::optimize: this->tmp_having= this->having; this->having= 0; */ Item* join_having= join->having ? join->having : join->tmp_having; - DBUG_ENTER("Item_in_subselect::create_single_in_to_exists_cond"); *where_item= NULL; @@ -2040,8 +2043,9 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN * join, if (join_having || select_lex->with_sum_func || select_lex->group_list.elements) { - Item *item= func->create(thd->mem_root, expr, + Item *item= func->create(thd, expr, new (thd->mem_root) Item_ref_null_helper( + thd, &select_lex->context, this, select_lex-> @@ -2054,7 +2058,7 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN * join, We can encounter "NULL IN (SELECT ...)". Wrap the added condition within a trig_cond. */ - item= new Item_func_trig_cond(item, get_cond_guard(0)); + item= new (thd->mem_root) Item_func_trig_cond(thd, item, get_cond_guard(0)); } if (!join_having) @@ -2072,13 +2076,13 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN * join, Item *having= item; Item *orig_item= item; - item= func->create(thd->mem_root, expr, item); + item= func->create(thd, expr, item); if (!abort_on_null && orig_item->maybe_null) { - having= new (thd->mem_root) Item_is_not_null_test(this, having); + having= new (thd->mem_root) Item_is_not_null_test(thd, this, having); if (left_expr->maybe_null) { - if (!(having= new (thd->mem_root) Item_func_trig_cond(having, + if (!(having= new (thd->mem_root) Item_func_trig_cond(thd, having, get_cond_guard(0)))) DBUG_RETURN(true); } @@ -2087,8 +2091,8 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN * join, DBUG_RETURN(true); *having_item= having; - item= new (thd->mem_root) Item_cond_or(item, - new (thd->mem_root) Item_func_isnull(orig_item)); + item= new (thd->mem_root) Item_cond_or(thd, item, + new (thd->mem_root) Item_func_isnull(thd, orig_item)); } /* If we may encounter NULL IN (SELECT ...) and care whether subquery @@ -2096,7 +2100,7 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN * join, */ if (!abort_on_null && left_expr->maybe_null) { - if (!(item= new (thd->mem_root) Item_func_trig_cond(item, + if (!(item= new (thd->mem_root) Item_func_trig_cond(thd, item, get_cond_guard(0)))) DBUG_RETURN(true); } @@ -2116,8 +2120,8 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN * join, if (select_lex->master_unit()->is_union()) { Item *new_having= - func->create(thd->mem_root, expr, - new (thd->mem_root) Item_ref_null_helper( + func->create(thd, expr, + new (thd->mem_root) Item_ref_null_helper(thd, &select_lex->context, this, select_lex->ref_pointer_array, @@ -2125,7 +2129,7 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN * join, (char *)"<result>")); if (!abort_on_null && left_expr->maybe_null) { - if (!(new_having= new (thd->mem_root) Item_func_trig_cond(new_having, + if (!(new_having= new (thd->mem_root) Item_func_trig_cond(thd, new_having, get_cond_guard(0)))) DBUG_RETURN(true); } @@ -2298,48 +2302,56 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join, check_cols(left_expr->element_index(i)->cols())) DBUG_RETURN(true); Item *item_eq= - new Item_func_eq(new - Item_direct_ref(&select_lex->context, - (*optimizer->get_cache())-> - addr(i), - (char *)"<no matter>", - (char *)in_left_expr_name), - new - Item_ref(&select_lex->context, - select_lex->ref_pointer_array + i, + new (thd->mem_root) + Item_func_eq(thd, new (thd->mem_root) + Item_direct_ref(thd, &select_lex->context, + (*optimizer->get_cache())-> + addr(i), + (char *)"<no matter>", + (char *)in_left_expr_name), + new (thd->mem_root) + Item_ref(thd, &select_lex->context, + select_lex->ref_pointer_array + i, + (char *)"<no matter>", + (char *)"<list ref>")); + Item *item_isnull= + new (thd->mem_root) + Item_func_isnull(thd, + new (thd->mem_root) + Item_ref(thd, &select_lex->context, + select_lex->ref_pointer_array+i, (char *)"<no matter>", (char *)"<list ref>")); - Item *item_isnull= - new Item_func_isnull(new - Item_ref(&select_lex->context, - select_lex->ref_pointer_array+i, - (char *)"<no matter>", - (char *)"<list ref>")); - Item *col_item= new Item_cond_or(item_eq, item_isnull); + Item *col_item= new (thd->mem_root) + Item_cond_or(thd, item_eq, item_isnull); if (!abort_on_null && left_expr->element_index(i)->maybe_null) { - if (!(col_item= new Item_func_trig_cond(col_item, get_cond_guard(i)))) + if (!(col_item= new (thd->mem_root) + Item_func_trig_cond(thd, col_item, get_cond_guard(i)))) DBUG_RETURN(true); } - *having_item= and_items(*having_item, col_item); + *having_item= and_items(thd, *having_item, col_item); Item *item_nnull_test= - new Item_is_not_null_test(this, - new Item_ref(&select_lex->context, - select_lex-> - ref_pointer_array + i, - (char *)"<no matter>", - (char *)"<list ref>")); + new (thd->mem_root) + Item_is_not_null_test(thd, this, + new (thd->mem_root) + Item_ref(thd, &select_lex->context, + select_lex-> + ref_pointer_array + i, + (char *)"<no matter>", + (char *)"<list ref>")); if (!abort_on_null && left_expr->element_index(i)->maybe_null) { if (!(item_nnull_test= - new Item_func_trig_cond(item_nnull_test, get_cond_guard(i)))) + new (thd->mem_root) + Item_func_trig_cond(thd, item_nnull_test, get_cond_guard(i)))) DBUG_RETURN(true); } - item_having_part2= and_items(item_having_part2, item_nnull_test); + item_having_part2= and_items(thd, item_having_part2, item_nnull_test); item_having_part2->top_level_item(); } - *having_item= and_items(*having_item, item_having_part2); + *having_item= and_items(thd, *having_item, item_having_part2); } else { @@ -2354,54 +2366,59 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join, if (select_lex->ref_pointer_array[i]-> check_cols(left_expr->element_index(i)->cols())) DBUG_RETURN(true); - item= - new Item_func_eq(new - Item_direct_ref(&select_lex->context, - (*optimizer->get_cache())-> - addr(i), - (char *)"<no matter>", - (char *)in_left_expr_name), - new - Item_direct_ref(&select_lex->context, - select_lex-> - ref_pointer_array+i, - (char *)"<no matter>", - (char *)"<list ref>")); + item= new (thd->mem_root) + Item_func_eq(thd, + new (thd->mem_root) + Item_direct_ref(thd, &select_lex->context, + (*optimizer->get_cache())-> + addr(i), + (char *)"<no matter>", + (char *)in_left_expr_name), + new (thd->mem_root) + Item_direct_ref(thd, &select_lex->context, + select_lex-> + ref_pointer_array+i, + (char *)"<no matter>", + (char *)"<list ref>")); if (!abort_on_null && select_lex->ref_pointer_array[i]->maybe_null) { Item *having_col_item= - new Item_is_not_null_test(this, - new - Item_ref(&select_lex->context, - select_lex->ref_pointer_array + i, - (char *)"<no matter>", - (char *)"<list ref>")); + new (thd->mem_root) + Item_is_not_null_test(thd, this, + new (thd->mem_root) + Item_ref(thd, &select_lex->context, + select_lex->ref_pointer_array + i, + (char *)"<no matter>", + (char *)"<list ref>")); - item_isnull= new - Item_func_isnull(new - Item_direct_ref(&select_lex->context, + item_isnull= new (thd->mem_root) + Item_func_isnull(thd, + new (thd->mem_root) + Item_direct_ref(thd, &select_lex->context, select_lex-> ref_pointer_array+i, (char *)"<no matter>", (char *)"<list ref>")); - item= new Item_cond_or(item, item_isnull); + item= new (thd->mem_root) Item_cond_or(thd, item, item_isnull); if (left_expr->element_index(i)->maybe_null) { - if (!(item= new Item_func_trig_cond(item, get_cond_guard(i)))) + if (!(item= new (thd->mem_root) + Item_func_trig_cond(thd, item, get_cond_guard(i)))) DBUG_RETURN(true); - if (!(having_col_item= - new Item_func_trig_cond(having_col_item, get_cond_guard(i)))) + if (!(having_col_item= new (thd->mem_root) + Item_func_trig_cond(thd, having_col_item, get_cond_guard(i)))) DBUG_RETURN(true); } - *having_item= and_items(*having_item, having_col_item); + *having_item= and_items(thd, *having_item, having_col_item); } if (!abort_on_null && left_expr->element_index(i)->maybe_null) { - if (!(item= new Item_func_trig_cond(item, get_cond_guard(i)))) + if (!(item= new (thd->mem_root) + Item_func_trig_cond(thd, item, get_cond_guard(i)))) DBUG_RETURN(true); } - *where_item= and_items(*where_item, item); + *where_item= and_items(thd, *where_item, item); } } @@ -2531,7 +2548,7 @@ bool Item_in_subselect::inject_in_to_exists_cond(JOIN *join_arg) and_args->disjoin((List<Item> *) &join_arg->cond_equal->current_level); } - where_item= and_items(join_arg->conds, where_item); + where_item= and_items(thd, join_arg->conds, where_item); if (!where_item->fixed && where_item->fix_fields(thd, 0)) DBUG_RETURN(true); // TIMOUR TODO: call optimize_cond() for the new where clause @@ -2548,7 +2565,7 @@ bool Item_in_subselect::inject_in_to_exists_cond(JOIN *join_arg) Item_equal *elem; while ((elem= li++)) { - and_args->push_back(elem); + and_args->push_back(elem, thd->mem_root); } } } @@ -2556,7 +2573,7 @@ bool Item_in_subselect::inject_in_to_exists_cond(JOIN *join_arg) if (having_item) { Item* join_having= join_arg->having ? join_arg->having:join_arg->tmp_having; - having_item= and_items(join_having, having_item); + having_item= and_items(thd, join_having, having_item); if (fix_having(having_item, select_lex)) DBUG_RETURN(true); // TIMOUR TODO: call optimize_cond() for the new having clause @@ -2565,7 +2582,8 @@ bool Item_in_subselect::inject_in_to_exists_cond(JOIN *join_arg) join_arg->having= select_lex->having; } join_arg->thd->change_item_tree(&unit->global_parameters()->select_limit, - new Item_int((int32) 1)); + new (thd->mem_root) + Item_int(thd, (int32) 1)); unit->select_limit_cnt= 1; DBUG_RETURN(false); @@ -2592,7 +2610,7 @@ bool Item_exists_subselect::select_prepare_to_be_in() Query_arena *arena, backup; bool result; arena= thd->activate_stmt_arena_if_needed(&backup); - result= (!(optimizer= new Item_in_optimizer(new Item_int(1), this))); + result= (!(optimizer= new (thd->mem_root) Item_in_optimizer(thd, new (thd->mem_root) Item_int(thd, 1), this))); if (arena) thd->restore_active_arena(arena, &backup); if (result) @@ -2805,20 +2823,24 @@ bool Item_exists_subselect::exists2in_processor(uchar *opt_arg) it.replace(local_field); else { - first_select->item_list.push_back(local_field); + first_select->item_list.push_back(local_field, thd->mem_root); first_select->join->all_fields.elements++; } first_select->ref_pointer_array[i]= (Item *)local_field; /* remove the parts from condition */ if (!upper_not || !local_field->maybe_null) - *eq_ref= new Item_int(1); + *eq_ref= new (thd->mem_root) Item_int(thd, 1); else { - *eq_ref= new Item_func_isnotnull( - new Item_field(thd, - ((Item_field*)(local_field->real_item()))->context, - ((Item_field*)(local_field->real_item()))->field)); + *eq_ref= new (thd->mem_root) + Item_func_isnotnull(thd, + new (thd->mem_root) + Item_field(thd, + ((Item_field*)(local_field-> + real_item()))->context, + ((Item_field*)(local_field-> + real_item()))->field)); if((*eq_ref)->fix_fields(thd, (Item **)eq_ref)) { res= TRUE; @@ -2827,7 +2849,7 @@ bool Item_exists_subselect::exists2in_processor(uchar *opt_arg) } outer_exp->fix_after_pullout(unit->outer_select(), &outer_exp); outer_exp->update_used_tables(); - outer.push_back(outer_exp); + outer.push_back(outer_exp, thd->mem_root); } } @@ -2838,7 +2860,7 @@ bool Item_exists_subselect::exists2in_processor(uchar *opt_arg) left_exp= outer_exp; else { - if (!(left_exp= new Item_row(outer))) + if (!(left_exp= new (thd->mem_root) Item_row(thd, outer))) { res= TRUE; goto out; @@ -2850,7 +2872,7 @@ bool Item_exists_subselect::exists2in_processor(uchar *opt_arg) first_select->select_limit= NULL; if (!(in_subs= new (thd->mem_root) Item_in_subselect(thd, left_exp, - first_select))) + first_select))) { res= TRUE; goto out; @@ -2880,10 +2902,11 @@ bool Item_exists_subselect::exists2in_processor(uchar *opt_arg) As far as Item_ref_in_optimizer do not substitute itself on fix_fields we can use same item for all selects. */ - in_subs->expr= new Item_direct_ref(&first_select->context, - (Item**)optimizer->get_cache(), - (char *)"<no matter>", - (char *)in_left_expr_name); + in_subs->expr= new (thd->mem_root) + Item_direct_ref(thd, &first_select->context, + (Item**)optimizer->get_cache(), + (char *)"<no matter>", + (char *)in_left_expr_name); if (in_subs->fix_fields(thd, optimizer->arguments() + 1)) { res= TRUE; @@ -2945,14 +2968,17 @@ bool Item_exists_subselect::exists2in_processor(uchar *opt_arg) if (eqs.elements() == 1) { exp= (optimizer->arguments()[0]->maybe_null ? - (Item*) - new Item_cond_and( - new Item_func_isnotnull( - new Item_direct_ref(&unit->outer_select()->context, - optimizer->arguments(), - (char *)"<no matter>", - (char *)exists_outer_expr_name)), - optimizer) : + (Item*) new (thd->mem_root) + Item_cond_and(thd, + new (thd->mem_root) + Item_func_isnotnull(thd, + new (thd->mem_root) + Item_direct_ref(thd, + &unit->outer_select()->context, + optimizer->arguments(), + (char *)"<no matter>", + (char *)exists_outer_expr_name)), + optimizer) : (Item *)optimizer); } else @@ -2968,18 +2994,21 @@ bool Item_exists_subselect::exists2in_processor(uchar *opt_arg) if (optimizer->arguments()[0]->maybe_null) { and_list-> - push_front( - new Item_func_isnotnull( - new Item_direct_ref(&unit->outer_select()->context, - optimizer->arguments()[0]->addr(i), - (char *)"<no matter>", - (char *)exists_outer_expr_name))); + push_front(new (thd->mem_root) + Item_func_isnotnull(thd, + new (thd->mem_root) + Item_direct_ref(thd, + &unit->outer_select()->context, + optimizer->arguments()[0]->addr(i), + (char *)"<no matter>", + (char *)exists_outer_expr_name)), + thd->mem_root); } } if (and_list->elements > 0) { - and_list->push_front(optimizer); - exp= new Item_cond_and(*and_list); + and_list->push_front(optimizer, thd->mem_root); + exp= new (thd->mem_root) Item_cond_and(thd, *and_list); } else exp= optimizer; @@ -3054,7 +3083,7 @@ Item_in_subselect::select_in_like_transformer(JOIN *join) arena= thd->activate_stmt_arena_if_needed(&backup); if (!optimizer) { - result= (!(optimizer= new Item_in_optimizer(left_expr, this))); + result= (!(optimizer= new (thd->mem_root) Item_in_optimizer(thd, left_expr, this))); if (result) goto out; } @@ -3116,12 +3145,12 @@ void Item_in_subselect::print(String *str, enum_query_type query_type) Item_subselect::print(str, query_type); } -bool Item_exists_subselect::fix_fields(THD *thd_arg, Item **ref) +bool Item_exists_subselect::fix_fields(THD *thd, Item **ref) { DBUG_ENTER("Item_exists_subselect::fix_fields"); if (exists_transformed) - DBUG_RETURN( !( (*ref)= new Item_int(1))); - DBUG_RETURN(Item_subselect::fix_fields(thd_arg, ref)); + DBUG_RETURN( !( (*ref)= new (thd->mem_root) Item_int(thd, 1))); + DBUG_RETURN(Item_subselect::fix_fields(thd, ref)); } @@ -3132,7 +3161,7 @@ bool Item_in_subselect::fix_fields(THD *thd_arg, Item **ref) DBUG_ENTER("Item_in_subselect::fix_fields"); if (test_strategy(SUBS_SEMI_JOIN)) - DBUG_RETURN( !( (*ref)= new Item_int(1)) ); + DBUG_RETURN( !( (*ref)= new (thd->mem_root) Item_int(thd, 1)) ); /* Check if the outer and inner IN operands match in those cases when we @@ -3283,7 +3312,8 @@ bool Item_in_subselect::init_left_expr_cache() Cached_item *cur_item_cache= new_Cached_item(thd, left_expr->element_index(i), FALSE); - if (!cur_item_cache || left_expr_cache->push_front(cur_item_cache)) + if (!cur_item_cache || left_expr_cache->push_front(cur_item_cache, + thd->mem_root)) return TRUE; } return FALSE; @@ -3563,9 +3593,9 @@ void subselect_engine::set_row(List<Item> &item_list, Item_cache **row) item->decimals= sel_item->decimals; item->unsigned_flag= sel_item->unsigned_flag; maybe_null= sel_item->maybe_null; - if (!(row[i]= Item_cache::get_cache(sel_item, sel_item->cmp_type()))) + if (!(row[i]= Item_cache::get_cache(thd, sel_item, sel_item->cmp_type()))) return; - row[i]->setup(sel_item); + row[i]->setup(thd, sel_item); //psergey-backport-timours: row[i]->store(sel_item); } if (item_list.elements > 1) @@ -4581,7 +4611,7 @@ subselect_hash_sj_engine::get_strategy_using_data() void subselect_hash_sj_engine::choose_partial_match_strategy( bool has_non_null_key, bool has_covering_null_row, - MY_BITMAP *partial_match_key_parts) + MY_BITMAP *partial_match_key_parts_arg) { ulonglong pm_buff_size; @@ -4632,7 +4662,7 @@ subselect_hash_sj_engine::choose_partial_match_strategy( { pm_buff_size= rowid_merge_buff_size(has_non_null_key, has_covering_null_row, - partial_match_key_parts); + partial_match_key_parts_arg); if (pm_buff_size > thd->variables.rowid_merge_buff_size) strategy= PARTIAL_MATCH_SCAN; } @@ -4886,7 +4916,7 @@ bool subselect_hash_sj_engine::make_semi_join_conds() DBUG_ENTER("subselect_hash_sj_engine::make_semi_join_conds"); DBUG_ASSERT(semi_join_conds == NULL); - if (!(semi_join_conds= new Item_cond_and)) + if (!(semi_join_conds= new (thd->mem_root) Item_cond_and(thd))) DBUG_RETURN(TRUE); if (!(tmp_table_ref= (TABLE_LIST*) thd->alloc(sizeof(TABLE_LIST)))) @@ -4906,14 +4936,17 @@ bool subselect_hash_sj_engine::make_semi_join_conds() for (uint i= 0; i < item_in->left_expr->cols(); i++) { - Item_func_eq *eq_cond; /* New equi-join condition for the current column. */ + /* New equi-join condition for the current column. */ + Item_func_eq *eq_cond; /* Item for the corresponding field from the materialized temp table. */ Item_field *right_col_item; - if (!(right_col_item= new Item_field(thd, context, tmp_table->field[i])) || - !(eq_cond= new Item_func_eq(item_in->left_expr->element_index(i), - right_col_item)) || - (((Item_cond_and*)semi_join_conds)->add(eq_cond))) + if (!(right_col_item= new (thd->mem_root) + Item_field(thd, context, tmp_table->field[i])) || + !(eq_cond= new (thd->mem_root) + Item_func_eq(thd, item_in->left_expr->element_index(i), + right_col_item)) || + (((Item_cond_and*)semi_join_conds)->add(eq_cond, thd->mem_root))) { delete semi_join_conds; semi_join_conds= NULL; @@ -5518,9 +5551,9 @@ bool Ordered_key::init(MY_BITMAP *columns_to_index) { if (!bitmap_is_set(columns_to_index, i)) continue; - cur_tmp_field= new Item_field(tbl->field[i]); + cur_tmp_field= new (thd->mem_root) Item_field(thd, tbl->field[i]); /* Create the predicate (tmp_column[i] < outer_ref[i]). */ - fn_less_than= new Item_func_lt(cur_tmp_field, + fn_less_than= new (thd->mem_root) Item_func_lt(thd, cur_tmp_field, search_key->element_index(i)); fn_less_than->fix_fields(thd, (Item**) &fn_less_than); key_columns[cur_key_col]= cur_tmp_field; @@ -5552,9 +5585,9 @@ bool Ordered_key::init(int col_idx) key_columns= (Item_field**) thd->alloc(sizeof(Item_field*)); compare_pred= (Item_func_lt**) thd->alloc(sizeof(Item_func_lt*)); - key_columns[0]= new Item_field(tbl->field[col_idx]); + key_columns[0]= new (thd->mem_root) Item_field(thd, tbl->field[col_idx]); /* Create the predicate (tmp_column[i] < outer_ref[i]). */ - compare_pred[0]= new Item_func_lt(key_columns[0], + compare_pred[0]= new (thd->mem_root) Item_func_lt(thd, key_columns[0], search_key->element_index(col_idx)); compare_pred[0]->fix_fields(thd, (Item**)&compare_pred[0]); @@ -6556,3 +6589,23 @@ void subselect_table_scan_engine::cleanup() { } + +/* + Create an execution tracker for the expression cache we're using for this + subselect; add the tracker to the query plan. +*/ + +void Item_subselect::init_expr_cache_tracker(THD *thd) +{ + if(!expr_cache) + return; + + Explain_query *qw= thd->lex->explain; + DBUG_ASSERT(qw); + Explain_node *node= qw->get_node(unit->first_select()->select_number); + if (!node) + return; + DBUG_ASSERT(expr_cache->type() == Item::EXPR_CACHE_ITEM); + node->cache_tracker= ((Item_cache_wrapper *)expr_cache)->init_tracker(qw->mem_root); +} + |