Commit e60d786d authored by monty@mysql.com's avatar monty@mysql.com

Ensure we free all items for prepared statements

Before the fix in ~Prepared_statments we got a memory leak when executing mysql_client_test.test
Note that test 'variables.test' fails.
This will be fixed when Jimw pushes the fix for Bug 10351
parent 16853d5f
...@@ -1023,7 +1023,7 @@ static void init_default_directories() ...@@ -1023,7 +1023,7 @@ static void init_default_directories()
} }
else else
{ {
/' No parent directory (strange). Use current dir + '\' '*/ /* No parent directory (strange). Use current dir + '\' */
last[1]= 0; last[1]= 0;
} }
break; break;
......
...@@ -2188,6 +2188,7 @@ bool Item_param::set_from_user_var(THD *thd, const user_var_entry *entry) ...@@ -2188,6 +2188,7 @@ bool Item_param::set_from_user_var(THD *thd, const user_var_entry *entry)
void Item_param::reset() void Item_param::reset()
{ {
DBUG_ENTER("Item_param::reset");
/* Shrink string buffer if it's bigger than max possible CHAR column */ /* Shrink string buffer if it's bigger than max possible CHAR column */
if (str_value.alloced_length() > MAX_CHAR_WIDTH) if (str_value.alloced_length() > MAX_CHAR_WIDTH)
str_value.free(); str_value.free();
...@@ -2212,6 +2213,7 @@ void Item_param::reset() ...@@ -2212,6 +2213,7 @@ void Item_param::reset()
DBUG_ASSERTS(state != NO_VALUE) in all Item_param::get_* DBUG_ASSERTS(state != NO_VALUE) in all Item_param::get_*
methods). methods).
*/ */
DBUG_VOID_RETURN;
} }
......
...@@ -1682,10 +1682,12 @@ static bool init_param_array(Prepared_statement *stmt) ...@@ -1682,10 +1682,12 @@ static bool init_param_array(Prepared_statement *stmt)
static void cleanup_stmt_and_thd_after_use(Statement *stmt, THD *thd) static void cleanup_stmt_and_thd_after_use(Statement *stmt, THD *thd)
{ {
DBUG_ENTER("cleanup_stmt_and_thd_after_use");
stmt->lex->unit.cleanup(); stmt->lex->unit.cleanup();
cleanup_items(stmt->free_list); cleanup_items(stmt->free_list);
thd->rollback_item_tree_changes(); thd->rollback_item_tree_changes();
thd->cleanup_after_query(); thd->cleanup_after_query();
DBUG_VOID_RETURN;
} }
/* /*
...@@ -1982,7 +1984,8 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length) ...@@ -1982,7 +1984,8 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_execute"))) if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_execute")))
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
DBUG_PRINT("exec_query:", ("%s", stmt->query)); DBUG_PRINT("exec_query", ("%s", stmt->query));
DBUG_PRINT("info",("stmt: %p", stmt));
/* Check if we got an error when sending long data */ /* Check if we got an error when sending long data */
if (stmt->state == Query_arena::ERROR) if (stmt->state == Query_arena::ERROR)
...@@ -2125,6 +2128,8 @@ void mysql_sql_stmt_execute(THD *thd, LEX_STRING *stmt_name) ...@@ -2125,6 +2128,8 @@ void mysql_sql_stmt_execute(THD *thd, LEX_STRING *stmt_name)
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
DBUG_PRINT("info",("stmt: %p", stmt));
/* Must go before setting variables, as it clears thd->user_var_events */ /* Must go before setting variables, as it clears thd->user_var_events */
mysql_reset_thd_for_next_command(thd); mysql_reset_thd_for_next_command(thd);
thd->set_n_backup_statement(stmt, &stmt_backup); thd->set_n_backup_statement(stmt, &stmt_backup);
...@@ -2445,19 +2450,26 @@ void Prepared_statement::setup_set_params() ...@@ -2445,19 +2450,26 @@ void Prepared_statement::setup_set_params()
Prepared_statement::~Prepared_statement() Prepared_statement::~Prepared_statement()
{ {
DBUG_ENTER("Prepared_statement::~Prepared_statement");
DBUG_PRINT("enter",("stmt: %p cursor: %p", this, cursor));
if (cursor) if (cursor)
{ {
if (cursor->is_open()) if (cursor->is_open())
{ {
cursor->close(FALSE); cursor->close(FALSE);
free_items(); cleanup_items(free_list);
thd->rollback_item_tree_changes();
free_root(cursor->mem_root, MYF(0)); free_root(cursor->mem_root, MYF(0));
} }
cursor->Cursor::~Cursor(); cursor->Cursor::~Cursor();
} }
else /*
free_items(); We have to call free on the items even if cleanup is called as some items,
like Item_param, don't free everything until free_items()
*/
free_items();
delete lex->result; delete lex->result;
DBUG_VOID_RETURN;
} }
...@@ -2469,6 +2481,9 @@ Query_arena::Type Prepared_statement::type() const ...@@ -2469,6 +2481,9 @@ Query_arena::Type Prepared_statement::type() const
void Prepared_statement::close_cursor() void Prepared_statement::close_cursor()
{ {
DBUG_ENTER("Prepared_statement::close_cursor");
DBUG_PRINT("enter",("stmt: %p", this));
if (cursor && cursor->is_open()) if (cursor && cursor->is_open())
{ {
thd->change_list= cursor->change_list; thd->change_list= cursor->change_list;
...@@ -2483,4 +2498,5 @@ void Prepared_statement::close_cursor() ...@@ -2483,4 +2498,5 @@ void Prepared_statement::close_cursor()
mysql_stmt_send_long_data() call. mysql_stmt_send_long_data() call.
*/ */
reset_stmt_params(this); reset_stmt_params(this);
DBUG_VOID_RETURN;
} }
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