summaryrefslogtreecommitdiff
path: root/sql/item_subselect.cc
diff options
context:
space:
mode:
authorIgor Babaev <igor@askmonty.org>2016-08-30 16:14:51 -0700
committerIgor Babaev <igor@askmonty.org>2016-08-30 16:14:51 -0700
commit2250e9ea261f661cb73c147a28f4d30655d7483d (patch)
tree04673b47943fdb137f8fe5bafdb64a24887f8c0f /sql/item_subselect.cc
parentcb1e44219b9beae92e104cfe5e67aab3073dd8aa (diff)
parent4ca7b226c05ae883accec64b1afe6d60daf1b323 (diff)
downloadmariadb-git-2250e9ea261f661cb73c147a28f4d30655d7483d.tar.gz
Merge 10.2 into 10.2-mdev9864.
Diffstat (limited to 'sql/item_subselect.cc')
-rw-r--r--sql/item_subselect.cc107
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> &parameters)
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,