mirror of
https://github.com/MariaDB/server.git
synced 2025-09-11 05:52:26 +03:00
Fix for Bug#5034 "prepared "select 1 into @arg15", second
execute crashes server": we were deleting lex->result after each execute, but prepared statements assumed that it's left intact. The fix adds cleanup() method to select_result hierarchy, so that result objects can be reused. Plus we now need to delete result objects more wisely. mysql-test/r/ps.result: Test results fixed: test case for bug#5034 mysql-test/t/ps.test: A test case for bug#5034, few followups sql/sql_class.cc: - fix warning in THD::THD - implementation of cleanup() for select_result hierarchy - select_export::send_eof was identical to select_dump::send_eof: moved to the base class select_to_file. - Statement::end_statement() to end lex, free items, and delete possible select_result sql/sql_class.h: - select_result::cleanup() declaration - sql/sql_insert.cc: - implementation of select_insert::cleanup(): currently we always create a new instance of select_insert/ select_create on each execute. sql/sql_lex.cc: - with more complicated logic of freeing lex->result it's easier to have it non-zero only if it points to a valid result. sql/sql_lex.h: Now st_lex::st_lex is not empty. sql/sql_parse.cc: mysql_execute_command(): - delete select_result *result only if it was created in this function. - use end_statement() to cleanup lex and thd in the end of each statement. - no need to save THD::lock if this is explain. This save apparently left from times when derived tables were materialized here, not in open_and_lock_tables. sql/sql_prepare.cc: - call result->cleanup() in reset_stmt_for_execute - now Statement is responsible for freeing its lex->result. sql/sql_select.cc: handle_select(): - don't delete result, it might be needed for next executions - result is never null
This commit is contained in:
@@ -155,10 +155,10 @@ bool foreign_key_prefix(Key *a, Key *b)
|
||||
** Thread specific functions
|
||||
****************************************************************************/
|
||||
|
||||
THD::THD():user_time(0), current_arena(this), is_fatal_error(0),
|
||||
last_insert_id_used(0),
|
||||
THD::THD():user_time(0), current_arena(this), global_read_lock(0),
|
||||
is_fatal_error(0), last_insert_id_used(0),
|
||||
insert_id_used(0), rand_used(0), time_zone_used(0),
|
||||
in_lock_tables(0), global_read_lock(0), bootstrap(0)
|
||||
in_lock_tables(0), bootstrap(0)
|
||||
{
|
||||
host= user= priv_user= db= ip=0;
|
||||
host_or_ip= "connecting host";
|
||||
@@ -703,6 +703,12 @@ void select_result::send_error(uint errcode,const char *err)
|
||||
::send_error(thd, errcode, err);
|
||||
}
|
||||
|
||||
|
||||
void select_result::cleanup()
|
||||
{
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
static String default_line_term("\n",default_charset_info);
|
||||
static String default_escaped("\\",default_charset_info);
|
||||
static String default_field_term("\t",default_charset_info);
|
||||
@@ -808,6 +814,32 @@ void select_to_file::send_error(uint errcode,const char *err)
|
||||
}
|
||||
|
||||
|
||||
bool select_to_file::send_eof()
|
||||
{
|
||||
int error= test(end_io_cache(&cache));
|
||||
if (my_close(file,MYF(MY_WME)))
|
||||
error= 1;
|
||||
if (!error)
|
||||
::send_ok(thd,row_count);
|
||||
file= -1;
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
void select_to_file::cleanup()
|
||||
{
|
||||
/* In case of error send_eof() may be not called: close the file here. */
|
||||
if (file >= 0)
|
||||
{
|
||||
(void) end_io_cache(&cache);
|
||||
(void) my_close(file,MYF(0));
|
||||
file= -1;
|
||||
}
|
||||
path[0]= '\0';
|
||||
row_count= 0;
|
||||
}
|
||||
|
||||
|
||||
select_to_file::~select_to_file()
|
||||
{
|
||||
if (file >= 0)
|
||||
@@ -1058,18 +1090,6 @@ err:
|
||||
}
|
||||
|
||||
|
||||
bool select_export::send_eof()
|
||||
{
|
||||
int error=test(end_io_cache(&cache));
|
||||
if (my_close(file,MYF(MY_WME)))
|
||||
error=1;
|
||||
if (!error)
|
||||
::send_ok(thd,row_count);
|
||||
file= -1;
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
** Dump of select to a binary file
|
||||
***************************************************************************/
|
||||
@@ -1123,18 +1143,6 @@ err:
|
||||
}
|
||||
|
||||
|
||||
bool select_dump::send_eof()
|
||||
{
|
||||
int error=test(end_io_cache(&cache));
|
||||
if (my_close(file,MYF(MY_WME)))
|
||||
error=1;
|
||||
if (!error)
|
||||
::send_ok(thd,row_count);
|
||||
file= -1;
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
select_subselect::select_subselect(Item_subselect *item_arg)
|
||||
{
|
||||
item= item_arg;
|
||||
@@ -1301,6 +1309,13 @@ int select_dumpvar::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
|
||||
}
|
||||
|
||||
|
||||
void select_dumpvar::cleanup()
|
||||
{
|
||||
vars.empty();
|
||||
row_count=0;
|
||||
}
|
||||
|
||||
|
||||
Item_arena::Item_arena(THD* thd)
|
||||
:free_list(0),
|
||||
state(INITIALIZED)
|
||||
@@ -1405,6 +1420,21 @@ void Statement::restore_backup_statement(Statement *stmt, Statement *backup)
|
||||
}
|
||||
|
||||
|
||||
void Statement::end_statement()
|
||||
{
|
||||
/* Cleanup SQL processing state to resuse this statement in next query. */
|
||||
lex_end(lex);
|
||||
delete lex->result;
|
||||
lex->result= 0;
|
||||
free_items(free_list);
|
||||
free_list= 0;
|
||||
/*
|
||||
Don't free mem_root, as mem_root is freed in the end of dispatch_command
|
||||
(once for any command).
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
void Item_arena::set_n_backup_item_arena(Item_arena *set, Item_arena *backup)
|
||||
{
|
||||
backup->set_item_arena(this);
|
||||
|
Reference in New Issue
Block a user