Commit 79f852a0 authored by Oleksandr Byelkin's avatar Oleksandr Byelkin

MDEV-10050: Crash in subselect

thd should not be taken earlier then fix_field and reset on fix_fields if it is needed.
parent ef92aaf9
...@@ -79,7 +79,6 @@ void Item_subselect::init(st_select_lex *select_lex, ...@@ -79,7 +79,6 @@ void Item_subselect::init(st_select_lex *select_lex,
DBUG_PRINT("enter", ("select_lex: 0x%lx this: 0x%lx", DBUG_PRINT("enter", ("select_lex: 0x%lx this: 0x%lx",
(ulong) select_lex, (ulong) this)); (ulong) select_lex, (ulong) this));
unit= select_lex->master_unit(); unit= select_lex->master_unit();
thd= unit->thd;
if (unit->item) if (unit->item)
{ {
...@@ -90,7 +89,7 @@ void Item_subselect::init(st_select_lex *select_lex, ...@@ -90,7 +89,7 @@ void Item_subselect::init(st_select_lex *select_lex,
engine= unit->item->engine; engine= unit->item->engine;
own_engine= FALSE; own_engine= FALSE;
parsing_place= unit->item->parsing_place; parsing_place= unit->item->parsing_place;
thd->change_item_tree((Item**)&unit->item, this); unit->thd->change_item_tree((Item**)&unit->item, this);
engine->change_result(this, result, TRUE); engine->change_result(this, result, TRUE);
} }
else else
...@@ -104,9 +103,9 @@ void Item_subselect::init(st_select_lex *select_lex, ...@@ -104,9 +103,9 @@ void Item_subselect::init(st_select_lex *select_lex,
NO_MATTER : NO_MATTER :
outer_select->parsing_place); outer_select->parsing_place);
if (unit->is_union()) if (unit->is_union())
engine= new subselect_union_engine(thd, unit, result, this); engine= new subselect_union_engine(unit, result, this);
else 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(); SELECT_LEX *upper= unit->outer_select();
...@@ -220,6 +219,10 @@ bool Item_subselect::fix_fields(THD *thd_param, Item **ref) ...@@ -220,6 +219,10 @@ bool Item_subselect::fix_fields(THD *thd_param, Item **ref)
uint8 uncacheable; uint8 uncacheable;
bool res; bool res;
thd= thd_param;
DBUG_ASSERT(unit->thd == thd);
status_var_increment(thd_param->status_var.feature_subquery); status_var_increment(thd_param->status_var.feature_subquery);
DBUG_ASSERT(fixed == 0); DBUG_ASSERT(fixed == 0);
...@@ -242,7 +245,7 @@ bool Item_subselect::fix_fields(THD *thd_param, Item **ref) ...@@ -242,7 +245,7 @@ bool Item_subselect::fix_fields(THD *thd_param, Item **ref)
return TRUE; return TRUE;
if (!(res= engine->prepare())) if (!(res= engine->prepare(thd)))
{ {
// all transformation is done (used by prepared statements) // all transformation is done (used by prepared statements)
changed= 1; changed= 1;
...@@ -2651,7 +2654,10 @@ bool Item_in_subselect::fix_fields(THD *thd_arg, Item **ref) ...@@ -2651,7 +2654,10 @@ bool Item_in_subselect::fix_fields(THD *thd_arg, Item **ref)
{ {
uint outer_cols_num; uint outer_cols_num;
List<Item> *inner_cols; List<Item> *inner_cols;
char const *save_where= thd->where; char const *save_where= thd_arg->where;
thd= thd_arg;
DBUG_ASSERT(unit->thd == thd);
if (test_strategy(SUBS_SEMI_JOIN)) if (test_strategy(SUBS_SEMI_JOIN))
return !( (*ref)= new Item_int(1)); return !( (*ref)= new Item_int(1));
...@@ -2769,7 +2775,8 @@ bool Item_in_subselect::setup_mat_engine() ...@@ -2769,7 +2775,8 @@ bool Item_in_subselect::setup_mat_engine()
if (!(mat_engine= new subselect_hash_sj_engine(thd, this, select_engine))) if (!(mat_engine= new subselect_hash_sj_engine(thd, this, select_engine)))
DBUG_RETURN(TRUE); 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())) engine->get_identifier()))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
...@@ -2885,10 +2892,10 @@ void subselect_engine::set_thd(THD *thd_arg) ...@@ -2885,10 +2892,10 @@ void subselect_engine::set_thd(THD *thd_arg)
subselect_single_select_engine:: 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, select_result_interceptor *result_arg,
Item_subselect *item_arg) Item_subselect *item_arg)
:subselect_engine(thd_arg, item_arg, result_arg), :subselect_engine(item_arg, result_arg),
prepared(0), executed(0), prepared(0), executed(0),
select_lex(select), join(0) select_lex(select), join(0)
{ {
...@@ -2966,10 +2973,10 @@ void subselect_uniquesubquery_engine::cleanup() ...@@ -2966,10 +2973,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, select_result_interceptor *result_arg,
Item_subselect *item_arg) Item_subselect *item_arg)
:subselect_engine(thd_arg, item_arg, result_arg) :subselect_engine(item_arg, result_arg)
{ {
unit= u; unit= u;
unit->item= item_arg; unit->item= item_arg;
...@@ -3002,10 +3009,11 @@ subselect_union_engine::subselect_union_engine(THD *thd_arg, st_select_lex_unit ...@@ -3002,10 +3009,11 @@ subselect_union_engine::subselect_union_engine(THD *thd_arg, st_select_lex_unit
@retval 1 if error @retval 1 if error
*/ */
int subselect_single_select_engine::prepare() int subselect_single_select_engine::prepare(THD *thd)
{ {
if (prepared) if (prepared)
return 0; return 0;
set_thd(thd);
if (select_lex->join) if (select_lex->join)
{ {
select_lex->cleanup(); select_lex->cleanup();
...@@ -3034,12 +3042,13 @@ int subselect_single_select_engine::prepare() ...@@ -3034,12 +3042,13 @@ int subselect_single_select_engine::prepare()
return 0; 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); return unit->prepare(thd, result, SELECT_NO_UNLOCK);
} }
int subselect_uniquesubquery_engine::prepare() int subselect_uniquesubquery_engine::prepare(THD *)
{ {
/* Should never be called. */ /* Should never be called. */
DBUG_ASSERT(FALSE); DBUG_ASSERT(FALSE);
...@@ -4499,13 +4508,14 @@ subselect_hash_sj_engine::~subselect_hash_sj_engine() ...@@ -4499,13 +4508,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 Create and optimize the JOIN that will be used to materialize
the subquery if not yet created. the subquery if not yet created.
*/ */
return materialize_engine->prepare(); set_thd(thd_arg);
return materialize_engine->prepare(thd);
} }
...@@ -4877,7 +4887,7 @@ int subselect_hash_sj_engine::exec() ...@@ -4877,7 +4887,7 @@ int subselect_hash_sj_engine::exec()
if (strategy == PARTIAL_MATCH_MERGE) if (strategy == PARTIAL_MATCH_MERGE)
{ {
pm_engine= pm_engine=
new subselect_rowid_merge_engine(thd, (subselect_uniquesubquery_engine*) new subselect_rowid_merge_engine((subselect_uniquesubquery_engine*)
lookup_engine, tmp_table, lookup_engine, tmp_table,
count_pm_keys, count_pm_keys,
has_covering_null_row, has_covering_null_row,
...@@ -4886,6 +4896,7 @@ int subselect_hash_sj_engine::exec() ...@@ -4886,6 +4896,7 @@ int subselect_hash_sj_engine::exec()
item, result, item, result,
semi_join_conds->argument_list()); semi_join_conds->argument_list());
if (!pm_engine || if (!pm_engine ||
pm_engine->prepare(thd) ||
((subselect_rowid_merge_engine*) pm_engine)-> ((subselect_rowid_merge_engine*) pm_engine)->
init(nn_key_parts, &partial_match_key_parts)) init(nn_key_parts, &partial_match_key_parts))
{ {
...@@ -4903,13 +4914,14 @@ int subselect_hash_sj_engine::exec() ...@@ -4903,13 +4914,14 @@ int subselect_hash_sj_engine::exec()
if (strategy == PARTIAL_MATCH_SCAN) if (strategy == PARTIAL_MATCH_SCAN)
{ {
if (!(pm_engine= if (!(pm_engine=
new subselect_table_scan_engine(thd, (subselect_uniquesubquery_engine*) new subselect_table_scan_engine((subselect_uniquesubquery_engine*)
lookup_engine, tmp_table, lookup_engine, tmp_table,
item, result, item, result,
semi_join_conds->argument_list(), semi_join_conds->argument_list(),
has_covering_null_row, has_covering_null_row,
has_covering_null_columns, has_covering_null_columns,
count_columns_with_nulls))) count_columns_with_nulls)) ||
pm_engine->prepare(thd))
{ {
/* This is an irrecoverable error. */ /* This is an irrecoverable error. */
res= 1; res= 1;
...@@ -5356,14 +5368,14 @@ void Ordered_key::print(String *str) ...@@ -5356,14 +5368,14 @@ void Ordered_key::print(String *str)
subselect_partial_match_engine::subselect_partial_match_engine( 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, TABLE *tmp_table_arg, Item_subselect *item_arg,
select_result_interceptor *result_arg, select_result_interceptor *result_arg,
List<Item> *equi_join_conds_arg, List<Item> *equi_join_conds_arg,
bool has_covering_null_row_arg, bool has_covering_null_row_arg,
bool has_covering_null_columns_arg, bool has_covering_null_columns_arg,
uint count_columns_with_nulls_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), tmp_table(tmp_table_arg), lookup_engine(engine_arg),
equi_join_conds(equi_join_conds_arg), equi_join_conds(equi_join_conds_arg),
has_covering_null_row(has_covering_null_row_arg), has_covering_null_row(has_covering_null_row_arg),
...@@ -5976,7 +5988,7 @@ bool subselect_rowid_merge_engine::partial_match() ...@@ -5976,7 +5988,7 @@ bool subselect_rowid_merge_engine::partial_match()
subselect_table_scan_engine::subselect_table_scan_engine( 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, TABLE *tmp_table_arg,
Item_subselect *item_arg, Item_subselect *item_arg,
select_result_interceptor *result_arg, select_result_interceptor *result_arg,
...@@ -5984,7 +5996,7 @@ subselect_table_scan_engine::subselect_table_scan_engine( ...@@ -5984,7 +5996,7 @@ subselect_table_scan_engine::subselect_table_scan_engine(
bool has_covering_null_row_arg, bool has_covering_null_row_arg,
bool has_covering_null_columns_arg, bool has_covering_null_columns_arg,
uint count_columns_with_nulls_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, result_arg, equi_join_conds_arg,
has_covering_null_row_arg, has_covering_null_row_arg,
has_covering_null_columns_arg, has_covering_null_columns_arg,
......
...@@ -715,7 +715,7 @@ class subselect_engine: public Sql_alloc ...@@ -715,7 +715,7 @@ class subselect_engine: public Sql_alloc
INDEXSUBQUERY_ENGINE, HASH_SJ_ENGINE, INDEXSUBQUERY_ENGINE, HASH_SJ_ENGINE,
ROWID_MERGE_ENGINE, TABLE_SCAN_ENGINE}; ROWID_MERGE_ENGINE, TABLE_SCAN_ENGINE};
subselect_engine(THD *thd_arg, Item_subselect *si, subselect_engine(Item_subselect *si,
select_result_interceptor *res) select_result_interceptor *res)
{ {
result= res; result= res;
...@@ -723,7 +723,6 @@ class subselect_engine: public Sql_alloc ...@@ -723,7 +723,6 @@ class subselect_engine: public Sql_alloc
cmp_type= res_type= STRING_RESULT; cmp_type= res_type= STRING_RESULT;
res_field_type= MYSQL_TYPE_VAR_STRING; res_field_type= MYSQL_TYPE_VAR_STRING;
maybe_null= 0; maybe_null= 0;
set_thd(thd_arg);
} }
virtual ~subselect_engine() {}; // to satisfy compiler virtual ~subselect_engine() {}; // to satisfy compiler
virtual void cleanup()= 0; virtual void cleanup()= 0;
...@@ -734,7 +733,7 @@ class subselect_engine: public Sql_alloc ...@@ -734,7 +733,7 @@ class subselect_engine: public Sql_alloc
*/ */
void set_thd(THD *thd_arg); void set_thd(THD *thd_arg);
THD * get_thd() { return thd; } THD * get_thd() { return thd; }
virtual int prepare()= 0; virtual int prepare(THD *)= 0;
virtual void fix_length_and_dec(Item_cache** row)= 0; virtual void fix_length_and_dec(Item_cache** row)= 0;
/* /*
Execute the engine Execute the engine
...@@ -789,11 +788,11 @@ class subselect_single_select_engine: public subselect_engine ...@@ -789,11 +788,11 @@ class subselect_single_select_engine: public subselect_engine
st_select_lex *select_lex; /* corresponding select_lex */ st_select_lex *select_lex; /* corresponding select_lex */
JOIN * join; /* corresponding JOIN structure */ JOIN * join; /* corresponding JOIN structure */
public: public:
subselect_single_select_engine(THD *thd_arg, st_select_lex *select, subselect_single_select_engine(st_select_lex *select,
select_result_interceptor *result, select_result_interceptor *result,
Item_subselect *item); Item_subselect *item);
void cleanup(); void cleanup();
int prepare(); int prepare(THD *thd);
void fix_length_and_dec(Item_cache** row); void fix_length_and_dec(Item_cache** row);
int exec(); int exec();
uint cols(); uint cols();
...@@ -823,11 +822,11 @@ class subselect_union_engine: public subselect_engine ...@@ -823,11 +822,11 @@ class subselect_union_engine: public subselect_engine
{ {
st_select_lex_unit *unit; /* corresponding unit structure */ st_select_lex_unit *unit; /* corresponding unit structure */
public: public:
subselect_union_engine(THD *thd_arg, st_select_lex_unit *u, subselect_union_engine(st_select_lex_unit *u,
select_result_interceptor *result, select_result_interceptor *result,
Item_subselect *item); Item_subselect *item);
void cleanup(); void cleanup();
int prepare(); int prepare(THD *);
void fix_length_and_dec(Item_cache** row); void fix_length_and_dec(Item_cache** row);
int exec(); int exec();
uint cols(); uint cols();
...@@ -880,11 +879,11 @@ class subselect_uniquesubquery_engine: public subselect_engine ...@@ -880,11 +879,11 @@ class subselect_uniquesubquery_engine: public subselect_engine
// constructor can assign THD because it will be called after JOIN::prepare // constructor can assign THD because it will be called after JOIN::prepare
subselect_uniquesubquery_engine(THD *thd_arg, st_join_table *tab_arg, subselect_uniquesubquery_engine(THD *thd_arg, st_join_table *tab_arg,
Item_subselect *subs, Item *where) Item_subselect *subs, Item *where)
:subselect_engine(thd_arg, subs, 0), tab(tab_arg), cond(where) :subselect_engine(subs, 0), tab(tab_arg), cond(where)
{} {}
~subselect_uniquesubquery_engine(); ~subselect_uniquesubquery_engine();
void cleanup(); void cleanup();
int prepare(); int prepare(THD *);
void fix_length_and_dec(Item_cache** row); void fix_length_and_dec(Item_cache** row);
int exec(); int exec();
uint cols() { return 1; } uint cols() { return 1; }
...@@ -1012,7 +1011,7 @@ class subselect_hash_sj_engine : public subselect_engine ...@@ -1012,7 +1011,7 @@ class subselect_hash_sj_engine : public subselect_engine
subselect_hash_sj_engine(THD *thd, Item_subselect *in_predicate, subselect_hash_sj_engine(THD *thd, Item_subselect *in_predicate,
subselect_single_select_engine *old_engine) subselect_single_select_engine *old_engine)
: subselect_engine(thd, in_predicate, NULL), : subselect_engine(in_predicate, NULL),
tmp_table(NULL), is_materialized(FALSE), materialize_engine(old_engine), tmp_table(NULL), is_materialized(FALSE), materialize_engine(old_engine),
materialize_join(NULL), semi_join_conds(NULL), lookup_engine(NULL), materialize_join(NULL), semi_join_conds(NULL), lookup_engine(NULL),
count_partial_match_columns(0), count_null_only_columns(0), count_partial_match_columns(0), count_null_only_columns(0),
...@@ -1022,7 +1021,7 @@ class subselect_hash_sj_engine : public subselect_engine ...@@ -1022,7 +1021,7 @@ class subselect_hash_sj_engine : public subselect_engine
bool init(List<Item> *tmp_columns, uint subquery_id); bool init(List<Item> *tmp_columns, uint subquery_id);
void cleanup(); void cleanup();
int prepare(); int prepare(THD *);
int exec(); int exec();
virtual void print(String *str, enum_query_type query_type); virtual void print(String *str, enum_query_type query_type);
uint cols() uint cols()
...@@ -1301,15 +1300,14 @@ class subselect_partial_match_engine : public subselect_engine ...@@ -1301,15 +1300,14 @@ class subselect_partial_match_engine : public subselect_engine
protected: protected:
virtual bool partial_match()= 0; virtual bool partial_match()= 0;
public: public:
subselect_partial_match_engine(THD *thd_arg, subselect_partial_match_engine(subselect_uniquesubquery_engine *engine_arg,
subselect_uniquesubquery_engine *engine_arg,
TABLE *tmp_table_arg, Item_subselect *item_arg, TABLE *tmp_table_arg, Item_subselect *item_arg,
select_result_interceptor *result_arg, select_result_interceptor *result_arg,
List<Item> *equi_join_conds_arg, List<Item> *equi_join_conds_arg,
bool has_covering_null_row_arg, bool has_covering_null_row_arg,
bool has_covering_null_columns_arg, bool has_covering_null_columns_arg,
uint count_columns_with_nulls_arg); uint count_columns_with_nulls_arg);
int prepare() { return 0; } int prepare(THD *thd_arg) { set_thd(thd_arg); return 0; }
int exec(); int exec();
void fix_length_and_dec(Item_cache**) {} void fix_length_and_dec(Item_cache**) {}
uint cols() { /* TODO: what is the correct value? */ return 1; } uint cols() { /* TODO: what is the correct value? */ return 1; }
...@@ -1396,8 +1394,7 @@ class subselect_rowid_merge_engine: public subselect_partial_match_engine ...@@ -1396,8 +1394,7 @@ class subselect_rowid_merge_engine: public subselect_partial_match_engine
bool exists_complementing_null_row(MY_BITMAP *keys_to_complement); bool exists_complementing_null_row(MY_BITMAP *keys_to_complement);
bool partial_match(); bool partial_match();
public: public:
subselect_rowid_merge_engine(THD *thd_arg, subselect_rowid_merge_engine(subselect_uniquesubquery_engine *engine_arg,
subselect_uniquesubquery_engine *engine_arg,
TABLE *tmp_table_arg, uint merge_keys_count_arg, TABLE *tmp_table_arg, uint merge_keys_count_arg,
bool has_covering_null_row_arg, bool has_covering_null_row_arg,
bool has_covering_null_columns_arg, bool has_covering_null_columns_arg,
...@@ -1405,7 +1402,7 @@ class subselect_rowid_merge_engine: public subselect_partial_match_engine ...@@ -1405,7 +1402,7 @@ class subselect_rowid_merge_engine: public subselect_partial_match_engine
Item_subselect *item_arg, Item_subselect *item_arg,
select_result_interceptor *result_arg, select_result_interceptor *result_arg,
List<Item> *equi_join_conds_arg) List<Item> *equi_join_conds_arg)
:subselect_partial_match_engine(thd_arg, engine_arg, tmp_table_arg, :subselect_partial_match_engine(engine_arg, tmp_table_arg,
item_arg, result_arg, equi_join_conds_arg, item_arg, result_arg, equi_join_conds_arg,
has_covering_null_row_arg, has_covering_null_row_arg,
has_covering_null_columns_arg, has_covering_null_columns_arg,
...@@ -1424,8 +1421,7 @@ class subselect_table_scan_engine: public subselect_partial_match_engine ...@@ -1424,8 +1421,7 @@ class subselect_table_scan_engine: public subselect_partial_match_engine
protected: protected:
bool partial_match(); bool partial_match();
public: public:
subselect_table_scan_engine(THD *thd_arg, subselect_table_scan_engine(subselect_uniquesubquery_engine *engine_arg,
subselect_uniquesubquery_engine *engine_arg,
TABLE *tmp_table_arg, Item_subselect *item_arg, TABLE *tmp_table_arg, Item_subselect *item_arg,
select_result_interceptor *result_arg, select_result_interceptor *result_arg,
List<Item> *equi_join_conds_arg, List<Item> *equi_join_conds_arg,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment