From: Roy Lyseng Date: November 9 2010 3:29pm Subject: bzr commit into mysql-next-mr-bugfixing branch (roy.lyseng:3280) Bug#56080 List-Archive: http://lists.mysql.com/commits/123297 X-Bug: 56080 Message-Id: <20101109152956.690311F2@tyr67.norway.sun.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============7311569775745545827==" --===============7311569775745545827== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline #At file:///home/rl136806/mysql/repo/mysql-work3/ based on revid:olav.sandstaa@stripped 3280 Roy Lyseng 2010-11-09 Bug#56080: Assertion 'inited=INDEX in sql/handler.h The problem occurs because some TABLE objects are associated with the optimizer execution structures even after close_thread_tables() has been called. In turn, this means that final cleanup of some TABLE objects is done from within THD::cleanup_after_query(). At this point in time, the TABLE objects may already have been given to another session, meaning that we may end another session's index or table scan. The safest solution seems to be to always perform a thorough cleanup of all execution data structures, including releasing the TABLE objects, before close_thread_tables() is called. In other words, this will have to be done at the end of each execution. However, this is currently not possible in the implementation of subquery materialization. This part of the optimizer assigns some objects, including a TABLE object, for the lifetime of the statement object, and not for each execution. This gives an odd situation, where some parts of the data structures are set up for reuse and others are not. Combine this with the fact that the user may decide to use another strategy for a subsequent subquery execution, the "permanent" data structures may not even be used later. It is therefore reasonable to allocate materialization execution structures for the lifetime of one execution. It means that the functions init_permanent() and init_runtime() of class subselect_hash_sj_engine are combined into one setup() function. In addition, the function Item_subselect::cleanup() will be called when the cleanup() function for the underlying query expression is called, and this function will cleanup and destroy the materialization data structures, so that the subquery item object is ready for a new optimization process in the next round of execution. However, the EXPLAIN functionality relies on these data structures being present when explaining a query containing a materialized subquery. Thus, we have two conflicting requirements for query cleanup: - For maximum efficiency we should release resources as early as possible after execution. - We cannot release resources that are needed for EXPLAIN queries. One solution to this problem is to split resource cleanup in two: 1. Delete JOIN objects as soon as possible - this makes sense because TABLE objects are associated with them through JOIN_TAB. But notice that JOIN objects may be needed for EXPLAIN queries... 2. Cleanup query expression objects (ie st_select_lex and st_select_lex_unit) later (in practice at end of query execution). Because this bug was caused by a race condition, no simple test case has been made. mysql-test/r/union.result Change in EXPLAIN EXTENDED output that shows an optimized predicate in the two query specifications within a UNION in a subquery. AFAIK, this is similar to how a non-subquery is reported, so the change is an improvement. sql/ha_partition.cc Comment change. sql/item_subselect.cc In Item_subselect::cleanup(), "new" engine is always deleted after an execution. Item_in_subselect::setup_engine() now builds the materialization engine for one execution only. Specific arena is no longer needed. In subselect_union_engine::cleanup(), call to unit->reinit_exec_mechanism is deleted because it is redundant. Implementation of cleanup() functions for subclasses of subselect_engine has been refactored. subselect_hash_sj_engine::setup() replaces init_permanent() and init_runtime(). For class subselect_hash_sj_engine, freeing of the temporary result table is moved from the destructor to ::cleanup(). Some changes necessary because of interface changes. sql/item_subselect.h Some cleanup of the subselect_engine classes: - All virtual functions now marked virtual in all derived classes. - Functions that returned bool result are now declared accordingly. - Slight cleanup of private/protected/public performed. - Improved constructors. sql/sql_lex.h Change in friend declaration. sql/sql_select.cc Function JOIN::reinit() is renamed to JOIN::reset(). JOIN::destroy() will now delete connection to associated tables. The st_select_lex_unit object is no longer cleaned up as early as before, but instead relying on the general cleanup of lex->unit in mysql_execute_command(). sql/sql_select.h A few small interface changes. sql/sql_union.cc Cleaned up some confusing error handling in st_select_lex_unit::exec() and st_select_lex::cleanup(). modified: mysql-test/r/union.result sql/ha_partition.cc sql/item_subselect.cc sql/item_subselect.h sql/sql_lex.h sql/sql_parse.cc sql/sql_plugin.cc sql/sql_plugin.h sql/sql_select.cc sql/sql_select.h sql/sql_union.cc === modified file 'mysql-test/r/union.result' --- a/mysql-test/r/union.result 2010-08-18 10:18:27 +0000 +++ b/mysql-test/r/union.result 2010-11-09 15:29:16 +0000 @@ -480,7 +480,7 @@ id select_type table type possible_keys 2 UNION t2 const PRIMARY PRIMARY 4 const 1 100.00 NULL UNION RESULT ALL NULL NULL NULL NULL NULL NULL Warnings: -Note 1003 (select '1' AS `a`,'1' AS `b` from `test`.`t1` where ('1' = 1)) union (select '1' AS `a`,'10' AS `b` from `test`.`t2` where ('1' = 1)) +Note 1003 (select '1' AS `a`,'1' AS `b` from `test`.`t1` where 1) union (select '1' AS `a`,'10' AS `b` from `test`.`t2` where 1) (select * from t1 where a=5) union (select * from t2 where a=1); a b 1 10 === modified file 'sql/ha_partition.cc' --- a/sql/ha_partition.cc 2010-10-21 11:34:17 +0000 +++ b/sql/ha_partition.cc 2010-11-09 15:29:16 +0000 @@ -3336,7 +3336,7 @@ int ha_partition::delete_row(const uchar Called from item_sum.cc by Item_func_group_concat::clear(), Item_sum_count_distinct::clear(), and Item_func_group_concat::clear(). Called from sql_delete.cc by mysql_delete(). - Called from sql_select.cc by JOIN::reinit(). + Called from sql_select.cc by JOIN::reset(). Called from sql_union.cc by st_select_lex_unit::exec(). */ === modified file 'sql/item_subselect.cc' --- a/sql/item_subselect.cc 2010-10-27 10:28:09 +0000 +++ b/sql/item_subselect.cc 2010-11-09 15:29:16 +0000 @@ -120,7 +120,10 @@ void Item_subselect::cleanup() if (old_engine) { if (engine) + { engine->cleanup(); + delete engine; + } engine= old_engine; old_engine= 0; } @@ -293,8 +296,6 @@ bool Item_subselect::walk(Item_processor bool Item_subselect::exec() { - int res; - /* Do not execute subselect in case of a fatal error or if the query has been killed. @@ -308,7 +309,7 @@ bool Item_subselect::exec() */ DBUG_EXECUTE_IF("subselect_exec_fail", return 1;); - res= engine->exec(); + const bool res= engine->exec(); if (engine_changed) { @@ -1905,10 +1906,6 @@ void Item_in_subselect::fix_after_pullou of this Item's execution. The method creates a new engine for materialized execution, and initializes the engine. - The initialization of the new engine is divided in two parts - a permanent - one that lives across prepared statements, and one that is repeated for each - execution. - @returns @retval TRUE memory allocation error occurred, or was not able to create temporary table @@ -1917,43 +1914,30 @@ void Item_in_subselect::fix_after_pullou bool Item_in_subselect::setup_engine() { - subselect_hash_sj_engine *hash_engine; DBUG_ENTER("Item_in_subselect::setup_engine"); - if (engine->engine_type() == subselect_engine::SINGLE_SELECT_ENGINE) - { - /* Create/initialize objects in permanent memory. */ - Query_arena *arena= thd->stmt_arena; - Query_arena backup; - if (arena->is_conventional()) - arena= 0; - else - thd->set_n_backup_active_arena(arena, &backup); + /* Currently, the decision whether to materialize is already taken. */ + if (exec_method != Item_exists_subselect::EXEC_MATERIALIZATION) + DBUG_RETURN(FALSE); - subselect_single_select_engine *old_engine= - static_cast(engine); - if (!(hash_engine= new subselect_hash_sj_engine(thd, this, - old_engine)) || - hash_engine->init_permanent(unit->get_unit_column_types())) - { - /* - For some reason we cannot use materialization for this IN predicate. - Delete all materialization-related objects, and return error. - */ - delete hash_engine; - if (arena) - thd->restore_active_arena(arena, &backup); - DBUG_RETURN(TRUE); - } - engine= hash_engine; + DBUG_ASSERT(engine->engine_type() == subselect_engine::SINGLE_SELECT_ENGINE); - if (arena) - thd->restore_active_arena(arena, &backup); - } - else + old_engine= engine; + + if (!(engine= new subselect_hash_sj_engine(thd, this, + static_cast(old_engine)))) + DBUG_RETURN(TRUE); + if (((subselect_hash_sj_engine *) engine) + ->setup(unit->get_unit_column_types())) { - DBUG_ASSERT(engine->engine_type() == subselect_engine::HASH_SJ_ENGINE); - hash_engine= static_cast(engine); + /* + For some reason we cannot use materialization for this IN predicate. + Delete all materialization-related objects, and return error. + */ + delete engine; + engine= old_engine; + old_engine= NULL; + DBUG_RETURN(TRUE); } /* @@ -1966,10 +1950,7 @@ bool Item_in_subselect::setup_engine() */ unit->global_parameters->select_limit= NULL; - /* Initializations done in runtime memory, repeated for each execution. */ - const bool res= hash_engine->init_runtime(); - - DBUG_RETURN(res); + DBUG_RETURN(FALSE); } @@ -2106,7 +2087,6 @@ void subselect_single_select_engine::cle void subselect_union_engine::cleanup() { DBUG_ENTER("subselect_union_engine::cleanup"); - unit->reinit_exec_mechanism(); result->cleanup(); DBUG_VOID_RETURN; } @@ -2140,16 +2120,6 @@ bool subselect_union_engine::no_rows() } -void subselect_uniquesubquery_engine::cleanup() -{ - DBUG_ENTER("subselect_uniquesubquery_engine::cleanup"); - /* Tell handler we don't need the index anymore */ - if (tab->table->file->inited) - tab->table->file->ha_index_end(); - DBUG_VOID_RETURN; -} - - subselect_union_engine::subselect_union_engine(st_select_lex_unit *u, select_result_interceptor *result_arg, Item_subselect *item_arg) @@ -2186,7 +2156,7 @@ subselect_union_engine::subselect_union_ @retval 1 if error */ -int subselect_single_select_engine::prepare() +bool subselect_single_select_engine::prepare() { if (prepared) return 0; @@ -2213,12 +2183,14 @@ int subselect_single_select_engine::prep return 0; } -int subselect_union_engine::prepare() + +bool subselect_union_engine::prepare() { return unit->prepare(thd, result, SELECT_NO_UNLOCK); } -int subselect_uniquesubquery_engine::prepare() + +bool subselect_uniquesubquery_engine::prepare() { /* Should never be called. */ DBUG_ASSERT(FALSE); @@ -2311,7 +2283,7 @@ int rr_sequential(READ_RECORD *info); int join_read_always_key_or_null(JOIN_TAB *tab); int join_read_next_same_or_null(READ_RECORD *info); -int subselect_single_select_engine::exec() +bool subselect_single_select_engine::exec() { DBUG_ENTER("subselect_single_select_engine::exec"); char const *save_where= thd->where; @@ -2340,12 +2312,7 @@ int subselect_single_select_engine::exec select_lex->uncacheable != UNCACHEABLE_EXPLAIN && executed) { - if (join->reinit()) - { - thd->where= save_where; - thd->lex->current_select= save_select; - DBUG_RETURN(1); - } + join->reset(); item->reset(); item->assigned((executed= 0)); } @@ -2410,10 +2377,10 @@ int subselect_single_select_engine::exec DBUG_RETURN(0); } -int subselect_union_engine::exec() +bool subselect_union_engine::exec() { char const *save_where= thd->where; - int res= unit->exec(); + const bool res= unit->exec(); thd->where= save_where; return res; } @@ -2437,7 +2404,7 @@ int subselect_union_engine::exec() TRUE - Error */ -int subselect_uniquesubquery_engine::scan_table() +bool subselect_uniquesubquery_engine::scan_table() { int error; TABLE *table= tab->table; @@ -2602,7 +2569,7 @@ bool subselect_uniquesubquery_engine::co TRUE - an error occured while scanning */ -int subselect_uniquesubquery_engine::exec() +bool subselect_uniquesubquery_engine::exec() { DBUG_ENTER("subselect_uniquesubquery_engine::exec"); int error; @@ -2705,7 +2672,7 @@ int subselect_uniquesubquery_engine::exe 1 */ -int subselect_indexsubquery_engine::exec() +bool subselect_indexsubquery_engine::exec() { DBUG_ENTER("subselect_indexsubquery_engine::exec"); int error; @@ -3133,8 +3100,7 @@ bool subselect_uniquesubquery_engine::no /** - Create all structures needed for IN execution that can live between PS - reexecution. + Create all structures needed for subquery execution using hash semijoin. @detail - Create a temporary table to store the result of the IN subquery. The @@ -3152,7 +3118,7 @@ bool subselect_uniquesubquery_engine::no @retval FALSE otherwise */ -bool subselect_hash_sj_engine::init_permanent(List *tmp_columns) +bool subselect_hash_sj_engine::setup(List *tmp_columns) { /* The result sink where we will materialize the subquery result. */ select_union *tmp_result_sink; @@ -3162,7 +3128,7 @@ bool subselect_hash_sj_engine::init_perm uint tmp_key_parts; /* Number of keyparts in tmp_key. */ Item_in_subselect *item_in= (Item_in_subselect *) item; - DBUG_ENTER("subselect_hash_sj_engine::init_permanent"); + DBUG_ENTER("subselect_hash_sj_engine::setup"); /* 1. Create/initialize materialization related objects. */ @@ -3208,8 +3174,8 @@ bool subselect_hash_sj_engine::init_perm Make sure there is only one index on the temp table, and it doesn't have the extra key part created when s->uniques > 0. */ - DBUG_ASSERT(tmp_table->s->keys == 1 && tmp_columns->elements == tmp_key_parts); - + DBUG_ASSERT(tmp_table->s->keys == 1 && + tmp_columns->elements == tmp_key_parts); /* 2. Create/initialize execution related objects. */ @@ -3304,43 +3270,22 @@ bool subselect_hash_sj_engine::init_perm if (cond->fix_fields(thd, &cond)) DBUG_RETURN(TRUE); - DBUG_RETURN(FALSE); -} - - -/** - Initialize members of the engine that need to be re-initilized at each - execution. - - @retval TRUE if a memory allocation error occurred - @retval FALSE if success -*/ - -bool subselect_hash_sj_engine::init_runtime() -{ /* Create and optimize the JOIN that will be used to materialize the subquery if not yet created. */ materialize_engine->prepare(); - /* - Repeat name resolution for 'cond' since cond is not part of any - clause of the query, and it is not 'fixed' during JOIN::prepare. - */ - if (cond && !cond->fixed && cond->fix_fields(thd, &cond)) - return TRUE; /* Let our engine reuse this query plan for materialization. */ - materialize_join= materialize_engine->join; - materialize_join->change_result(result); - return FALSE; + materialize_engine->join->change_result(result); + + DBUG_RETURN(FALSE); } subselect_hash_sj_engine::~subselect_hash_sj_engine() { delete result; - if (tab) - free_tmp_table(thd, tab->table); + DBUG_ASSERT(!tab); } @@ -3353,10 +3298,15 @@ subselect_hash_sj_engine::~subselect_has void subselect_hash_sj_engine::cleanup() { - is_materialized= FALSE; + DBUG_ENTER("subselect_hash_sj_engine::cleanup"); + is_materialized= false; result->cleanup(); /* Resets the temp table as well. */ + if (tab->table->file->inited) + tab->table->file->ha_index_end(); // Close the scan over the index + free_tmp_table(thd, tab->table); + tab= NULL; materialize_engine->cleanup(); - subselect_uniquesubquery_engine::cleanup(); + DBUG_VOID_RETURN; } @@ -3371,7 +3321,7 @@ void subselect_hash_sj_engine::cleanup() @retval FALSE otherwise */ -int subselect_hash_sj_engine::exec() +bool subselect_hash_sj_engine::exec() { Item_in_subselect *item_in= (Item_in_subselect *) item; @@ -3383,17 +3333,17 @@ int subselect_hash_sj_engine::exec() */ if (!is_materialized) { - int res= 0; + bool res= false; SELECT_LEX *save_select= thd->lex->current_select; thd->lex->current_select= materialize_engine->select_lex; - if ((res= materialize_join->optimize())) + if ((res= materialize_engine->join->optimize())) goto err; /* purecov: inspected */ if (materialize_engine->save_join_if_explain()) goto err; - materialize_join->exec(); - if ((res= test(materialize_join->error || thd->is_fatal_error))) + materialize_engine->join->exec(); + if ((res= test(materialize_engine->join->error || thd->is_fatal_error))) goto err; /* === modified file 'sql/item_subselect.h' --- a/sql/item_subselect.h 2010-10-15 10:32:50 +0000 +++ b/sql/item_subselect.h 2010-11-09 15:29:16 +0000 @@ -44,7 +44,8 @@ typedef Comp_creator* (*chooser_compare_ class Item_subselect :public Item_result_field { - my_bool value_assigned; /* value already assigned to subselect */ +private: + bool value_assigned; /* value already assigned to subselect */ public: /* thread handler, will be assigned in fix_fields only */ THD *thd; @@ -109,7 +110,7 @@ public: select_result_interceptor *result); ~Item_subselect(); - void cleanup(); + virtual void cleanup(); virtual void reset() { null_value= 1; @@ -191,10 +192,10 @@ public: Item_singlerow_subselect(st_select_lex *select_lex); Item_singlerow_subselect() :Item_subselect(), value(0), row (0) {} - void cleanup(); + virtual void cleanup(); subs_type substype() { return SINGLEROW_SUBS; } - void reset(); + virtual void reset(); trans_res select_transformer(JOIN *join); void store(uint i, Item* item); double val_real(); @@ -241,7 +242,7 @@ public: Item_maxmin_subselect(THD *thd, Item_subselect *parent, st_select_lex *select_lex, bool max); virtual void print(String *str, enum_query_type query_type); - void cleanup(); + virtual void cleanup(); bool any_value() { return was_values; } void register_value() { was_values= TRUE; } void reset_value_registration() { was_values= FALSE; } @@ -293,7 +294,7 @@ public: return RES_OK; } subs_type substype() { return EXISTS_SUBS; } - void reset() + virtual void reset() { value= 0; } @@ -381,9 +382,9 @@ public: optimizer(NULL), was_null(FALSE), abort_on_null(FALSE), pushed_cond_guards(NULL), upper_item(NULL) {} - void cleanup(); + virtual void cleanup(); subs_type substype() { return IN_SUBS; } - void reset() + virtual void reset() { value= 0; null_value= 0; @@ -456,15 +457,13 @@ public: INDEXSUBQUERY_ENGINE, HASH_SJ_ENGINE}; subselect_engine(Item_subselect *si, select_result_interceptor *res) - :thd(0) - { - result= res; - item= si; - res_type= STRING_RESULT; - res_field_type= MYSQL_TYPE_VAR_STRING; - maybe_null= 0; - } + :result(res), thd(NULL), item(si), res_type(STRING_RESULT), + res_field_type(MYSQL_TYPE_VAR_STRING), maybe_null(FALSE) + {} virtual ~subselect_engine() {}; // to satisfy compiler + /** + Cleanup engine after complete query execution, free all resources. + */ virtual void cleanup()= 0; /* @@ -472,8 +471,8 @@ public: Should be called before prepare(). */ void set_thd(THD *thd_arg); - THD * get_thd() { return thd; } - virtual int prepare()= 0; + THD * get_thd() const { return thd; } + virtual bool prepare()= 0; virtual void fix_length_and_dec(Item_cache** row)= 0; /* Execute the engine @@ -495,11 +494,11 @@ public: 1 - Either an execution error, or the engine was "changed", and the caller should call exec() again for the new engine. */ - virtual int exec()= 0; + virtual bool exec()= 0; virtual uint cols()= 0; /* return number of columns in select */ virtual uint8 uncacheable()= 0; /* query is uncacheable */ - enum Item_result type() { return res_type; } - enum_field_types field_type() { return res_field_type; } + virtual const enum Item_result type() const { return res_type; } + virtual const enum_field_types field_type() const { return res_field_type; } virtual void exclude()= 0; virtual bool may_be_null() { return maybe_null; }; virtual table_map upper_select_const_tables()= 0; @@ -520,29 +519,30 @@ protected: class subselect_single_select_engine: public subselect_engine { - my_bool prepared; /* simple subselect is prepared */ - my_bool optimized; /* simple subselect is optimized */ - my_bool executed; /* simple subselect is executed */ +private: + bool prepared; /* simple subselect is prepared */ + bool executed; /* simple subselect is executed */ st_select_lex *select_lex; /* corresponding select_lex */ JOIN * join; /* corresponding JOIN structure */ public: subselect_single_select_engine(st_select_lex *select, select_result_interceptor *result, Item_subselect *item); - void cleanup(); - int prepare(); - void fix_length_and_dec(Item_cache** row); - int exec(); - uint cols(); - uint8 uncacheable(); - void exclude(); - table_map upper_select_const_tables(); + virtual void cleanup(); + virtual bool prepare(); + virtual void fix_length_and_dec(Item_cache** row); + virtual bool exec(); + virtual uint cols(); + virtual uint8 uncacheable(); + virtual void exclude(); + virtual table_map upper_select_const_tables(); virtual void print (String *str, enum_query_type query_type); - bool change_result(Item_subselect *si, select_result_interceptor *result); - bool no_tables(); - bool may_be_null(); - bool is_executed() const { return executed; } - bool no_rows(); + virtual bool change_result(Item_subselect *si, + select_result_interceptor *result); + virtual bool no_tables(); + virtual bool may_be_null(); + virtual bool is_executed() const { return executed; } + virtual bool no_rows(); virtual enum_engine_type engine_type() { return SINGLE_SELECT_ENGINE; } bool save_join_if_explain(); @@ -553,24 +553,26 @@ public: class subselect_union_engine: public subselect_engine { +private: st_select_lex_unit *unit; /* corresponding unit structure */ public: subselect_union_engine(st_select_lex_unit *u, select_result_interceptor *result, Item_subselect *item); - void cleanup(); - int prepare(); - void fix_length_and_dec(Item_cache** row); - int exec(); - uint cols(); - uint8 uncacheable(); - void exclude(); - table_map upper_select_const_tables(); + virtual void cleanup(); + virtual bool prepare(); + virtual void fix_length_and_dec(Item_cache** row); + virtual bool exec(); + virtual uint cols(); + virtual uint8 uncacheable(); + virtual void exclude(); + virtual table_map upper_select_const_tables(); virtual void print (String *str, enum_query_type query_type); - bool change_result(Item_subselect *si, select_result_interceptor *result); - bool no_tables(); - bool is_executed() const; - bool no_rows(); + virtual bool change_result(Item_subselect *si, + select_result_interceptor *result); + virtual bool no_tables(); + virtual bool is_executed() const; + virtual bool no_rows(); virtual enum_engine_type engine_type() { return UNION_ENGINE; } }; @@ -615,26 +617,28 @@ public: { set_thd(thd_arg); } - void cleanup(); - int prepare(); - void fix_length_and_dec(Item_cache** row); - int exec(); - uint cols() { return 1; } - uint8 uncacheable() { return UNCACHEABLE_DEPENDENT; } - void exclude(); - table_map upper_select_const_tables() { return 0; } + virtual void cleanup() {} + virtual bool prepare(); + virtual void fix_length_and_dec(Item_cache** row); + virtual bool exec(); + virtual uint cols() { return 1; } + virtual uint8 uncacheable() { return UNCACHEABLE_DEPENDENT; } + virtual void exclude(); + virtual table_map upper_select_const_tables() { return 0; } virtual void print (String *str, enum_query_type query_type); - bool change_result(Item_subselect *si, select_result_interceptor *result); - bool no_tables(); - int scan_table(); + virtual bool change_result(Item_subselect *si, + select_result_interceptor *result); + virtual bool no_tables(); + bool scan_table(); bool copy_ref_key(); - bool no_rows() { return empty_result_set; } + virtual bool no_rows() { return empty_result_set; } virtual enum_engine_type engine_type() { return UNIQUESUBQUERY_ENGINE; } }; class subselect_indexsubquery_engine: public subselect_uniquesubquery_engine { +private: /* FALSE for 'ref', TRUE for 'ref-or-null'. */ bool check_null; /* @@ -677,7 +681,7 @@ public: check_null(chk_null), having(having_arg) {} - int exec(); + virtual bool exec(); virtual void print (String *str, enum_query_type query_type); virtual enum_engine_type engine_type() { return INDEXSUBQUERY_ENGINE; } }; @@ -712,21 +716,17 @@ inline bool Item_subselect::is_uncacheab class subselect_hash_sj_engine: public subselect_uniquesubquery_engine { -protected: +private: /* TRUE if the subquery was materialized into a temp table. */ bool is_materialized; /* The old engine already chosen at parse time and stored in permanent memory. - Through this member we can re-create and re-prepare materialize_join for - each execution of a prepared statement. We also reuse the functionality - of subselect_single_select_engine::[prepare | cols]. + Through this member we can re-create and re-prepare the join object + used to materialize the subquery for each execution of a prepared + statement. We also reuse the functionality of + subselect_single_select_engine::[prepare | cols]. */ subselect_single_select_engine *materialize_engine; - /* - QEP to execute the subquery and materialize its result into a - temporary table. Created during the first call to exec(). - */ - JOIN *materialize_join; /* Temp table context of the outer select's JOIN. */ TMP_TABLE_PARAM *tmp_param; @@ -735,20 +735,19 @@ public: subselect_single_select_engine *old_engine) :subselect_uniquesubquery_engine(thd, NULL, in_predicate, NULL), is_materialized(FALSE), materialize_engine(old_engine), - materialize_join(NULL), tmp_param(NULL) + tmp_param(NULL) {} ~subselect_hash_sj_engine(); - bool init_permanent(List *tmp_columns); - bool init_runtime(); - void cleanup(); - int prepare() + bool setup(List *tmp_columns); + virtual void cleanup(); + virtual bool prepare() { return materialize_engine->prepare(); } - int exec(); - void print (String *str, enum_query_type query_type); - uint cols() + virtual bool exec(); + virtual void print (String *str, enum_query_type query_type); + virtual uint cols() { return materialize_engine->cols(); } === modified file 'sql/sql_lex.h' --- a/sql/sql_lex.h 2010-10-25 16:07:05 +0000 +++ b/sql/sql_lex.h 2010-11-09 15:29:16 +0000 @@ -596,7 +596,7 @@ public: inline bool is_union (); friend void lex_start(THD *thd); - friend int subselect_union_engine::exec(); + friend bool subselect_union_engine::exec(); List *get_unit_column_types(); }; === modified file 'sql/sql_parse.cc' --- a/sql/sql_parse.cc 2010-10-27 14:46:44 +0000 +++ b/sql/sql_parse.cc 2010-11-09 15:29:16 +0000 @@ -5551,6 +5551,8 @@ void mysql_parse(THD *thd, char *rawbuf, thd->end_statement(); thd->cleanup_after_query(); DBUG_ASSERT(thd->change_list.is_empty()); + //sql_print_error("Query: %*s", length, rawbuf); + //report_memory_plugin(); } DBUG_VOID_RETURN; === modified file 'sql/sql_plugin.cc' --- a/sql/sql_plugin.cc 2010-11-05 22:14:29 +0000 +++ b/sql/sql_plugin.cc 2010-11-09 15:29:16 +0000 @@ -1554,6 +1554,19 @@ error: DBUG_RETURN(TRUE); } +void report_memory_plugin() + +{ + struct st_plugin_int *p; + + for (uint i= 0; i < plugin_array.elements; i++) + { + p= *dynamic_element(&plugin_array, i, struct st_plugin_int **); + if (!strcmp(p->name.str, "MEMORY")) + sql_print_error("Plugin '%s' has ref_count=%d", + p->name.str, p->ref_count); + } +} void plugin_shutdown(void) { === modified file 'sql/sql_plugin.h' --- a/sql/sql_plugin.h 2010-10-07 17:34:38 +0000 +++ b/sql/sql_plugin.h 2010-11-09 15:29:16 +0000 @@ -160,4 +160,5 @@ typedef my_bool (plugin_foreach_func)(TH #define plugin_foreach(A,B,C,D) plugin_foreach_with_mask(A,B,C,PLUGIN_IS_READY,D) extern bool plugin_foreach_with_mask(THD *thd, plugin_foreach_func *func, int type, uint state_mask, void *arg); +void report_memory_plugin(); #endif === modified file 'sql/sql_select.cc' --- a/sql/sql_select.cc 2010-11-05 22:19:41 +0000 +++ b/sql/sql_select.cc 2010-11-09 15:29:16 +0000 @@ -2626,10 +2626,14 @@ void JOIN::restore_tmp() } -int -JOIN::reinit() +/** + Reset the state of this join object so that it is ready for a + new execution. +*/ + +void JOIN::reset() { - DBUG_ENTER("JOIN::reinit"); + DBUG_ENTER("JOIN::reset"); unit->offset_limit_cnt= (ha_rows)(select_lex->offset_limit ? select_lex->offset_limit->val_uint() : @@ -2677,7 +2681,7 @@ JOIN::reinit() func->clear(); } - DBUG_RETURN(0); + DBUG_VOID_RETURN; } /** @@ -3309,14 +3313,12 @@ JOIN::exec() /** - Clean up join. + Clean up and destroy join object. - @return - Return error that hold JOIN. + @return false if previous execution was successful, and true otherwise */ -int -JOIN::destroy() +bool JOIN::destroy() { DBUG_ENTER("JOIN::destroy"); select_lex->join= 0; @@ -3342,6 +3344,11 @@ JOIN::destroy() cond_equal= 0; cleanup(1); + if (join_tab) + { + for (JOIN_TAB *tab= join_tab; tab < join_tab+tables; tab++) + tab->table= NULL; + } /* Cleanup items referencing temporary table columns */ cleanup_item_list(tmp_all_fields1); cleanup_item_list(tmp_all_fields3); @@ -3358,7 +3365,7 @@ JOIN::destroy() delete_dynamic(&keyuse); delete procedure; - DBUG_RETURN(error); + DBUG_RETURN(test(error)); } @@ -3500,6 +3507,8 @@ mysql_select(THD *thd, Item ***rref_poin select_lex->where= join->conds_history; select_lex->having= join->having_history; } + if (select_options & SELECT_DESCRIBE) + free_join= 0; err: if (free_join) @@ -4133,9 +4142,7 @@ bool JOIN::setup_subquery_materializatio subquery_predicate->substype() == Item_subselect::IN_SUBS) { Item_in_subselect *in_subs= (Item_in_subselect*) subquery_predicate; - if (in_subs->exec_method == - Item_exists_subselect::EXEC_MATERIALIZATION && - in_subs->setup_engine()) + if (in_subs->setup_engine()) return TRUE; } } @@ -11181,7 +11188,12 @@ bool error_if_full_join(JOIN *join) /** - cleanup JOIN_TAB. + Cleanup table of join operation. + + @note + Notice that this is not a complete cleanup. In some situations, the + object may be reused after a cleanup operation, hence we cannot set + the table pointer to NULL in this function. */ void JOIN_TAB::cleanup() @@ -23029,7 +23041,6 @@ bool mysql_explain_union(THD *thd, SELEC unit->fake_select_lex->options|= SELECT_DESCRIBE; if (!(res= unit->prepare(thd, result, SELECT_NO_UNLOCK | SELECT_DESCRIBE))) res= unit->exec(); - res|= unit->cleanup(); } else { === modified file 'sql/sql_select.h' --- a/sql/sql_select.h 2010-11-05 22:19:41 +0000 +++ b/sql/sql_select.h 2010-11-09 15:29:16 +0000 @@ -1916,9 +1916,9 @@ public: Item *having, ORDER *proc_param, SELECT_LEX *select, SELECT_LEX_UNIT *unit); int optimize(); - int reinit(); + void reset(); void exec(); - int destroy(); + bool destroy(); void restore_tmp(); bool alloc_func_list(); bool flatten_subqueries(); === modified file 'sql/sql_union.cc' --- a/sql/sql_union.cc 2010-10-25 09:18:21 +0000 +++ b/sql/sql_union.cc 2010-11-09 15:29:16 +0000 @@ -223,7 +223,7 @@ bool st_select_lex_unit::prepare(THD *th DBUG_RETURN(TRUE); } sl->join->select_options|= SELECT_DESCRIBE; - sl->join->reinit(); + sl->join->reset(); } } DBUG_RETURN(FALSE); @@ -495,7 +495,10 @@ bool st_select_lex_unit::exec() thd->lex->current_select= sl; if (optimized) - saved_error= sl->join->reinit(); + { + saved_error= false; + sl->join->reset(); + } else { set_limit(sl); @@ -642,7 +645,8 @@ bool st_select_lex_unit::exec() else { join->examined_rows= 0; - saved_error= join->reinit(); + saved_error= false; + join->reset(); join->exec(); } } @@ -664,16 +668,25 @@ bool st_select_lex_unit::exec() } +/** + Cleanup this query expression object after preparation or one round + of execution. After the cleanup, the object can be reused for a + new round of execution, but a new optimization will be needed before + the execution. + + @return false if previous execution was successful, and true otherwise +*/ + bool st_select_lex_unit::cleanup() { - int error= 0; + bool error= false; DBUG_ENTER("st_select_lex_unit::cleanup"); if (cleaned) { DBUG_RETURN(FALSE); } - cleaned= 1; + cleaned= true; if (union_result) { @@ -811,6 +824,13 @@ List *st_select_lex_unit::get_unit return &sl->item_list; } + +/** + Cleanup after preparation or one round of execution. + + @return false if previous execution was successful, and true otherwise +*/ + bool st_select_lex::cleanup() { bool error= FALSE; @@ -826,7 +846,7 @@ bool st_select_lex::cleanup() for (SELECT_LEX_UNIT *lex_unit= first_inner_unit(); lex_unit ; lex_unit= lex_unit->next_unit()) { - error= (bool) ((uint) error | (uint) lex_unit->cleanup()); + error|= lex_unit->cleanup(); } non_agg_fields.empty(); inner_refs_list.empty(); --===============7311569775745545827== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/roy.lyseng@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: roy.lyseng@stripped # target_branch: file:///home/rl136806/mysql/repo/mysql-work3/ # testament_sha1: de2ac8478aed1b90120f5b1fa6a92640d79eae5b # timestamp: 2010-11-09 16:29:56 +0100 # base_revision_id: olav.sandstaa@stripped\ # xfeds9y2q8b1qxuo # # Begin bundle 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 1GjMPd2dS4Mkfda6EHxTODsj/i7kinChITKwPvg= --===============7311569775745545827==--