summaryrefslogtreecommitdiff
path: root/sql/sql_class.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_class.cc')
-rw-r--r--sql/sql_class.cc151
1 files changed, 112 insertions, 39 deletions
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index da64479abf2..456b58ee95e 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -158,12 +158,13 @@ bool foreign_key_prefix(Key *a, Key *b)
** Thread specific functions
****************************************************************************/
-THD::THD():user_time(0), current_arena(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),
- spcont(NULL)
+THD::THD()
+ :user_time(0), 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), bootstrap(0), spcont(NULL)
{
+ current_arena= this;
host= user= priv_user= db= ip= 0;
catalog= (char*)"std"; // the only catalog we have for now
host_or_ip= "connecting host";
@@ -450,8 +451,21 @@ void THD::awake(THD::killed_state state_to_set)
exits the cond in the time between read and broadcast, but that is
ok since all we want to do is to make the victim thread get out
of waiting on current_cond.
+ If we see a non-zero current_cond: it cannot be an old value (because
+ then exit_cond() should have run and it can't because we have mutex); so
+ it is the true value but maybe current_mutex is not yet non-zero (we're
+ in the middle of enter_cond() and there is a "memory order
+ inversion"). So we test the mutex too to not lock 0.
+
+ Note that there is a small chance we fail to kill. If victim has locked
+ current_mutex, but hasn't yet entered enter_cond() (which means that
+ current_cond and current_mutex are 0), then the victim will not get
+ a signal and it may wait "forever" on the cond (until
+ we issue a second KILL or the status it's waiting for happens).
+ It's true that we have set its thd->killed but it may not
+ see it immediately and so may have time to reach the cond_wait().
*/
- if (mysys_var->current_cond)
+ if (mysys_var->current_cond && mysys_var->current_mutex)
{
pthread_mutex_lock(mysys_var->current_mutex);
pthread_cond_broadcast(mysys_var->current_cond);
@@ -710,6 +724,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);
@@ -815,6 +835,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)
@@ -860,8 +906,10 @@ static File create_file(THD *thd, char *path, sql_exchange *exchange,
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
option|= MY_REPLACE_DIR; // Force use of db directory
#endif
- (void) fn_format(path, exchange->file_name, thd->db ? thd->db : "", "",
- option);
+
+ strxnmov(path, FN_REFLEN, mysql_real_data_home, thd->db ? thd->db : "",
+ NullS);
+ (void) fn_format(path, exchange->file_name, path, "", option);
if (!access(path, F_OK))
{
my_error(ER_FILE_EXISTS_ERROR, MYF(0), exchange->file_name);
@@ -1065,18 +1113,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
***************************************************************************/
@@ -1130,18 +1166,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;
@@ -1316,8 +1340,16 @@ 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)
+ :free_list(0),
+ state(INITIALIZED)
{
init_sql_alloc(&mem_root,
thd->variables.query_alloc_block_size,
@@ -1325,18 +1357,28 @@ Item_arena::Item_arena(THD* thd)
}
+/* This constructor is called when Item_arena is a subobject of THD */
+
Item_arena::Item_arena()
- :free_list(0)
+ :free_list(0),
+ state(CONVENTIONAL_EXECUTION)
{
- bzero((char *) &mem_root, sizeof(mem_root));
+ clear_alloc_root(&mem_root);
}
Item_arena::Item_arena(bool init_mem_root)
- :free_list(0)
+ :free_list(0),
+ state(INITIALIZED)
{
if (init_mem_root)
- bzero((char *) &mem_root, sizeof(mem_root));
+ clear_alloc_root(&mem_root);
+}
+
+Item_arena::Type Item_arena::type() const
+{
+ DBUG_ASSERT(0); /* Should never be called */
+ return STATEMENT;
}
@@ -1380,7 +1422,7 @@ Statement::Statement()
}
-Statement::Type Statement::type() const
+Item_arena::Type Statement::type() const
{
return STATEMENT;
}
@@ -1398,6 +1440,36 @@ void Statement::set_statement(Statement *stmt)
}
+void
+Statement::set_n_backup_statement(Statement *stmt, Statement *backup)
+{
+ backup->set_statement(this);
+ set_statement(stmt);
+}
+
+
+void Statement::restore_backup_statement(Statement *stmt, Statement *backup)
+{
+ stmt->set_statement(this);
+ set_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);
@@ -1417,6 +1489,7 @@ void Item_arena::set_item_arena(Item_arena *set)
{
mem_root= set->mem_root;
free_list= set->free_list;
+ state= set->state;
}
Statement::~Statement()
@@ -1460,7 +1533,7 @@ Statement_map::Statement_map() :
hash_init(&st_hash, default_charset_info, START_STMT_HASH_SIZE, 0, 0,
get_statement_id_as_hash_key,
delete_statement_as_hash_key, MYF(0));
- hash_init(&names_hash, &my_charset_bin, START_NAME_HASH_SIZE, 0, 0,
+ hash_init(&names_hash, system_charset_info, START_NAME_HASH_SIZE, 0, 0,
(hash_get_key) get_stmt_name_hash_key,
NULL,MYF(0));
}