24
24
#include "config.h"
25
#include "drizzled/session.h"
25
#include <drizzled/session.h>
26
26
#include "drizzled/session_list.h"
27
27
#include <sys/stat.h>
28
#include "drizzled/error.h"
29
#include "drizzled/gettext.h"
30
#include "drizzled/query_id.h"
31
#include "drizzled/data_home.h"
32
#include "drizzled/sql_base.h"
33
#include "drizzled/lock.h"
34
#include "drizzled/item/cache.h"
35
#include "drizzled/item/float.h"
36
#include "drizzled/item/return_int.h"
37
#include "drizzled/item/empty_string.h"
38
#include "drizzled/show.h"
39
#include "drizzled/plugin/client.h"
28
#include <drizzled/error.h>
29
#include <drizzled/gettext.h>
30
#include <drizzled/query_id.h>
31
#include <drizzled/data_home.h>
32
#include <drizzled/sql_base.h>
33
#include <drizzled/lock.h>
34
#include <drizzled/item/cache.h>
35
#include <drizzled/item/float.h>
36
#include <drizzled/item/return_int.h>
37
#include <drizzled/item/empty_string.h>
38
#include <drizzled/show.h>
39
#include <drizzled/plugin/client.h>
40
40
#include "drizzled/plugin/scheduler.h"
41
41
#include "drizzled/plugin/authentication.h"
42
42
#include "drizzled/plugin/logging.h"
48
48
#include "drizzled/transaction_services.h"
49
49
#include "drizzled/drizzled.h"
51
#include "drizzled/table/instance.h"
51
#include "drizzled/table_share_instance.h"
53
53
#include "plugin/myisam/myisam.h"
54
54
#include "drizzled/internal/iocache.h"
55
#include "drizzled/internal/thread_var.h"
56
55
#include "drizzled/plugin/event_observer.h"
58
#include "drizzled/util/functors.h"
60
#include "drizzled/display.h"
63
58
#include <algorithm>
65
#include <boost/filesystem.hpp>
67
#include "drizzled/util/backtrace.h"
69
61
using namespace std;
71
namespace fs=boost::filesystem;
80
70
char empty_c_string[1]= {0}; /* used for not defined db */
82
72
const char * const Session::DEFAULT_WHERE= "field list";
73
extern pthread_key_t THR_Session;
74
extern pthread_key_t THR_Mem_root;
77
/****************************************************************************
79
****************************************************************************/
80
static unsigned char *get_var_key(user_var_entry *entry, size_t *length, bool)
82
*length= entry->name.length;
83
return (unsigned char*) entry->name.str;
86
static void free_user_var(user_var_entry *entry)
84
91
bool Key_part_spec::operator==(const Key_part_spec& other) const
153
160
return (int) session->lex->sql_command;
156
enum_tx_isolation session_tx_isolation(const Session *session)
163
int session_tx_isolation(const Session *session)
158
return (enum_tx_isolation)session->variables.tx_isolation;
165
return (int) session->variables.tx_isolation;
161
168
Session::Session(plugin::Client *client_arg) :
162
169
Open_tables_state(refresh_version),
163
170
mem_root(&main_mem_root),
166
query(new std::string),
168
173
client(client_arg),
170
175
scheduler_arg(NULL),
171
176
lock_id(&main_lock_id),
173
178
ha_data(plugin::num_trx_monitored_objects),
174
concurrent_execute_allowed(true),
175
179
arg_of_last_insert_id_function(false),
176
180
first_successful_insert_id_in_prev_stmt(0),
177
181
first_successful_insert_id_in_cur_stmt(0),
178
182
limit_found_rows(0),
179
_global_read_lock(NONE),
181
184
some_tables_deleted(false),
182
185
no_errors(false),
259
259
/* Initialize sub structures */
260
260
memory::init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
261
hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
262
(hash_get_key) get_var_key,
263
(hash_free_key) free_user_var, 0);
262
265
substitute_null_with_insert_id = false;
263
lock_info.init(); /* safety: will be reset after start */
266
thr_lock_info_init(&lock_info); /* safety: will be reset after start */
264
267
thr_lock_owner_init(&main_lock_id, &lock_info);
266
269
m_internal_handler= NULL;
300
303
return false; // 'false', as per coding style
303
void Session::setAbort(bool arg)
305
mysys_var->abort= arg;
308
void Session::lockOnSys()
314
boost_unique_lock_t scopedLock(mysys_var->mutex);
315
if (mysys_var->current_cond)
317
mysys_var->current_mutex->lock();
318
mysys_var->current_cond->notify_all();
319
mysys_var->current_mutex->unlock();
323
306
void Session::pop_internal_handler()
325
308
assert(m_internal_handler != NULL);
399
371
dbug_sentry= Session_SENTRY_GONE;
401
373
main_mem_root.free_root(MYF(0));
402
currentMemRoot().release();
403
currentSession().release();
374
pthread_setspecific(THR_Session, 0);
405
376
plugin::Logging::postEndDo(this);
406
377
plugin::EventObserver::deregisterSessionEvents(*this);
408
for (PropertyMap::iterator iter= life_properties.begin(); iter != life_properties.end(); iter++)
410
delete (*iter).second;
412
life_properties.clear();
415
drizzled::util::custom_backtrace();
419
void Session::setClient(plugin::Client *client_arg)
422
client->setSession(this);
425
void Session::awake(Session::killed_state_t state_to_set)
379
/* Ensure that no one is using Session */
380
pthread_mutex_unlock(&LOCK_delete);
381
pthread_mutex_destroy(&LOCK_delete);
385
Add all status variables to another status variable array
389
to_var add to this array
390
from_var from this array
393
This function assumes that all variables are long/ulong.
394
If this assumption will change, then we have to explictely add
395
the other variables after the while loop
397
void add_to_status(system_status_var *to_var, system_status_var *from_var)
399
ulong *end= (ulong*) ((unsigned char*) to_var +
400
offsetof(system_status_var, last_system_status_var) +
402
ulong *to= (ulong*) to_var, *from= (ulong*) from_var;
409
Add the difference between two status variable arrays to another one.
413
to_var add to this array
414
from_var from this array
415
dec_var minus this array
418
This function assumes that all variables are long/ulong.
420
void add_diff_to_status(system_status_var *to_var, system_status_var *from_var,
421
system_status_var *dec_var)
423
ulong *end= (ulong*) ((unsigned char*) to_var + offsetof(system_status_var,
424
last_system_status_var) +
426
ulong *to= (ulong*) to_var, *from= (ulong*) from_var, *dec= (ulong*) dec_var;
429
*(to++)+= *(from++) - *(dec++);
432
void Session::awake(Session::killed_state state_to_set)
427
434
this->checkSentry();
435
safe_mutex_assert_owner(&LOCK_delete);
429
setKilled(state_to_set);
437
killed= state_to_set;
430
438
if (state_to_set != Session::KILL_QUERY)
432
440
scheduler->killSession(this);
565
569
current_global_counters.max_used_connections= connection_count;
568
current_global_counters.connections++;
569
arg->thread_id= arg->variables.pseudo_thread_id= global_thread_id++;
571
session::Cache::singleton().insert(arg);
573
if (unlikely(plugin::EventObserver::connectSession(*arg)))
575
// We should do something about an error...
578
if (plugin::Scheduler::getScheduler()->addSession(arg))
580
DRIZZLE_CONNECTION_START(arg->getSessionId());
572
thread_id= variables.pseudo_thread_id= global_thread_id++;
574
pthread_mutex_lock(&LOCK_thread_count);
575
getSessionList().push_back(this);
576
pthread_mutex_unlock(&LOCK_thread_count);
578
if (scheduler->addSession(this))
580
DRIZZLE_CONNECTION_START(thread_id);
581
581
char error_message_buff[DRIZZLE_ERRMSG_SIZE];
583
arg->setKilled(Session::KILL_CONNECTION);
583
killed= Session::KILL_CONNECTION;
585
arg->status_var.aborted_connects++;
585
status_var_increment(current_global_counters.aborted_connects);
587
587
/* Can't use my_error() since store_globals has not been called. */
588
588
/* TODO replace will better error message */
589
589
snprintf(error_message_buff, sizeof(error_message_buff),
590
590
ER(ER_CANT_CREATE_THREAD), 1);
591
arg->client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
591
client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
601
Is this session viewable by the current user?
603
bool Session::isViewable() const
605
return plugin::Authorization::isAuthorized(current_session->getSecurityContext(),
611
const char* Session::enter_cond(boost::condition_variable_any &cond, boost::mutex &mutex, const char* msg)
599
const char* Session::enter_cond(pthread_cond_t *cond,
600
pthread_mutex_t* mutex,
613
603
const char* old_msg = get_proc_info();
614
604
safe_mutex_assert_owner(mutex);
615
mysys_var->current_mutex = &mutex;
616
mysys_var->current_cond = &cond;
605
mysys_var->current_mutex = mutex;
606
mysys_var->current_cond = cond;
617
607
this->set_proc_info(msg);
626
616
locked (if that would not be the case, you'll get a deadlock if someone
627
617
does a Session::awake() on you).
629
mysys_var->current_mutex->unlock();
630
boost_unique_lock_t scopedLock(mysys_var->mutex);
619
pthread_mutex_unlock(mysys_var->current_mutex);
620
pthread_mutex_lock(&mysys_var->mutex);
631
621
mysys_var->current_mutex = 0;
632
622
mysys_var->current_cond = 0;
633
623
this->set_proc_info(old_msg);
624
pthread_mutex_unlock(&mysys_var->mutex);
636
627
bool Session::authenticate()
639
630
if (client->authenticate())
642
status_var.aborted_connects++;
633
status_var_increment(current_global_counters.aborted_connects);
647
bool Session::checkUser(const std::string &passwd_str,
648
const std::string &in_db)
637
bool Session::checkUser(const char *passwd, uint32_t passwd_len, const char *in_db)
639
const string passwd_str(passwd, passwd_len);
650
640
bool is_authenticated=
651
641
plugin::Authentication::isAuthenticated(getSecurityContext(),
654
644
if (is_authenticated != true)
656
status_var.access_denied++;
657
646
/* isAuthenticated has pushed the error message */
661
650
/* Change database if necessary */
662
if (not in_db.empty())
651
if (in_db && in_db[0])
664
653
SchemaIdentifier identifier(in_db);
665
654
if (mysql_change_db(this, identifier))
691
680
main_da.reset_diagnostics_area();
693
682
if (client->readCommand(&l_packet, &packet_length) == false)
698
if (getKilled() == KILL_CONNECTION)
701
685
if (packet_length == 0)
704
l_command= static_cast<enum_server_command>(l_packet[0]);
688
l_command= (enum enum_server_command) (unsigned char) l_packet[0];
706
690
if (command >= COM_END)
707
691
command= COM_END; // Wrong command
709
693
assert(packet_length);
710
return not dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
694
return ! dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
713
697
bool Session::readAndStoreQuery(const char *in_packet, uint32_t in_packet_length)
1028
static int create_file(Session *session,
1029
fs::path &target_path,
1030
file_exchange *exchange,
1031
internal::IO_CACHE *cache)
1011
static int create_file(Session *session, char *path, file_exchange *exchange, internal::IO_CACHE *cache)
1033
fs::path to_file(exchange->file_name);
1036
if (not to_file.has_root_directory())
1014
uint32_t option= MY_UNPACK_FILENAME | MY_RELATIVE_PATH;
1016
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
1017
option|= MY_REPLACE_DIR; // Force use of db directory
1020
if (!internal::dirname_length(exchange->file_name))
1038
target_path= fs::system_complete(getDataHomeCatalog());
1039
if (not session->db.empty())
1041
int count_elements= 0;
1042
for (fs::path::iterator iter= to_file.begin();
1043
iter != to_file.end();
1044
++iter, ++count_elements)
1047
if (count_elements == 1)
1049
target_path /= session->db;
1052
target_path /= to_file;
1022
strcpy(path, data_home_real);
1023
if (! session->db.empty())
1024
strncat(path, session->db.c_str(), FN_REFLEN-strlen(data_home_real)-1);
1025
(void) internal::fn_format(path, exchange->file_name, path, "", option);
1056
target_path = exchange->file_name;
1059
if (not secure_file_priv.string().empty())
1061
if (target_path.file_string().substr(0, secure_file_priv.file_string().size()) != secure_file_priv.file_string())
1063
/* Write only allowed to dir or subdir specified by secure_file_priv */
1064
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
1069
if (!access(target_path.file_string().c_str(), F_OK))
1028
(void) internal::fn_format(path, exchange->file_name, data_home_real, "", option);
1030
if (opt_secure_file_priv &&
1031
strncmp(opt_secure_file_priv, path, strlen(opt_secure_file_priv)))
1033
/* Write only allowed to dir or subdir specified by secure_file_priv */
1034
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
1038
if (!access(path, F_OK))
1071
1040
my_error(ER_FILE_EXISTS_ERROR, MYF(0), exchange->file_name);
1074
1043
/* Create the file world readable */
1075
if ((file= internal::my_create(target_path.file_string().c_str(), 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
1044
if ((file= internal::my_create(path, 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
1077
1046
(void) fchmod(file, 0666); // Because of umask()
1078
if (cache->init_io_cache(file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1047
if (init_io_cache(cache, file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1080
1049
internal::my_close(file, MYF(0));
1081
internal::my_delete(target_path.file_string().c_str(), MYF(0)); // Delete file on error, it was just created
1050
internal::my_delete(path, MYF(0)); // Delete file on error, it was just created
1307
1273
for (; length > sizeof(space) ; length-=sizeof(space))
1309
1275
if (my_b_write(cache,(unsigned char*) space,sizeof(space)))
1312
1278
if (my_b_write(cache,(unsigned char*) space,length))
1316
1282
if (res && enclosed)
1318
1284
if (my_b_write(cache, (unsigned char*) exchange->enclosed->ptr(),
1319
1285
exchange->enclosed->length()))
1322
1288
if (--items_left)
1324
1290
if (my_b_write(cache, (unsigned char*) exchange->field_term->ptr(),
1325
1291
field_term_length))
1329
1295
if (my_b_write(cache,(unsigned char*) exchange->line_term->ptr(),
1330
1296
exchange->line_term->length()))
1439
1406
switch (val_item->result_type())
1441
1408
case REAL_RESULT:
1442
op= &select_max_min_finder_subselect::cmp_real;
1409
op= &select_max_min_finder_subselect::cmp_real;
1444
1411
case INT_RESULT:
1445
op= &select_max_min_finder_subselect::cmp_int;
1412
op= &select_max_min_finder_subselect::cmp_int;
1447
1414
case STRING_RESULT:
1448
op= &select_max_min_finder_subselect::cmp_str;
1415
op= &select_max_min_finder_subselect::cmp_str;
1450
1417
case DECIMAL_RESULT:
1451
1418
op= &select_max_min_finder_subselect::cmp_decimal;
1453
1420
case ROW_RESULT:
1454
1421
// This case should never be choosen
1459
1426
cache->store(val_item);
1628
1612
plugin_sessionvar_cleanup(this);
1630
1614
/* If necessary, log any aborted or unauthorized connections */
1631
if (getKilled() || client->wasAborted())
1615
if (killed || client->wasAborted())
1633
status_var.aborted_threads++;
1617
status_var_increment(current_global_counters.aborted_threads);
1636
1620
if (client->wasAborted())
1638
if (not getKilled() && variables.log_warnings > 1)
1622
if (! killed && variables.log_warnings > 1)
1640
1624
SecurityContext *sctx= &security_ctx;
1751
1726
If this is needed, use close_temporary_table()
1754
void Open_tables_state::nukeTable(Table *table)
1729
void Session::nukeTable(Table *table)
1756
1731
plugin::StorageEngine *table_type= table->getShare()->db_type();
1758
1733
table->free_io_cache();
1759
table->delete_table();
1734
table->delete_table(false);
1761
1736
TableIdentifier identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName(), table->getShare()->getPath());
1762
1737
rm_temporary_table(table_type, identifier);
1773
1748
void Session::refresh_status()
1750
pthread_mutex_lock(&LOCK_status);
1752
/* Add thread's status variabes to global status */
1753
add_to_status(&global_status_var, &status_var);
1775
1755
/* Reset thread's status variables */
1776
1756
memset(&status_var, 0, sizeof(status_var));
1758
/* Reset some global variables */
1759
reset_status_vars();
1761
/* Reset the counters of all key caches (default and named). */
1762
reset_key_cache_counters();
1778
1763
flush_status_time= time((time_t*) 0);
1779
1764
current_global_counters.max_used_connections= 1; /* We set it to one, because we know we exist */
1780
current_global_counters.connections= 0;
1765
pthread_mutex_unlock(&LOCK_status);
1783
1768
user_var_entry *Session::getVariable(LEX_STRING &name, bool create_if_not_exists)
1785
return getVariable(std::string(name.str, name.length), create_if_not_exists);
1788
user_var_entry *Session::getVariable(const std::string &name, bool create_if_not_exists)
1790
UserVarsRange ppp= user_vars.equal_range(name);
1792
for (UserVars::iterator iter= ppp.first;
1793
iter != ppp.second; ++iter)
1795
return (*iter).second;
1798
if (not create_if_not_exists)
1801
1770
user_var_entry *entry= NULL;
1802
entry= new (nothrow) user_var_entry(name.c_str(), query_id);
1807
std::pair<UserVars::iterator, bool> returnable= user_vars.insert(make_pair(name, entry));
1809
if (not returnable.second)
1772
entry= (user_var_entry*) hash_search(&user_vars, (unsigned char*) name.str, name.length);
1774
if ((entry == NULL) && create_if_not_exists)
1776
if (!hash_inited(&user_vars))
1778
entry= new (nothrow) user_var_entry(name.str, query_id);
1783
if (my_hash_insert(&user_vars, (unsigned char*) entry))
1817
void Session::setVariable(const std::string &name, const std::string &value)
1819
user_var_entry *updateable_var= getVariable(name.c_str(), true);
1821
updateable_var->update_hash(false,
1822
(void*)value.c_str(),
1823
static_cast<uint32_t>(value.length()), STRING_RESULT,
1825
DERIVATION_IMPLICIT, false);
1828
void Open_tables_state::mark_temp_tables_as_free_for_reuse()
1830
for (Table *table= temporary_tables ; table ; table= table->getNext())
1795
void Session::mark_temp_tables_as_free_for_reuse()
1797
for (Table *table= temporary_tables ; table ; table= table->next)
1832
if (table->query_id == getQueryId())
1799
if (table->query_id == query_id)
1834
1801
table->query_id= 0;
1835
1802
table->cursor->ha_reset();
1893
1861
handled either before writing a query log event (inside
1894
1862
binlog_query()) or when preparing a pending event.
1864
mysql_unlock_tables(this, lock);
1900
1868
Note that we need to hold LOCK_open while changing the
1901
1869
open_tables list. Another thread may work on it.
1902
(See: table::Cache::singleton().removeTable(), mysql_wait_completed_table())
1870
(See: remove_table_from_cache(), mysql_wait_completed_table())
1903
1871
Closing a MERGE child before the parent would be fatal if the
1904
1872
other thread tries to abort the MERGE lock in between.
1938
1906
close_tables_for_reopen(&tables);
1940
1908
if ((mysql_handle_derived(lex, &mysql_derived_prepare) ||
1909
(fill_derived_tables() &&
1942
1910
mysql_handle_derived(lex, &mysql_derived_filling))))
1949
@note "best_effort" is used in cases were if a failure occurred on this
1950
operation it would not be surprising because we are only removing because there
1951
might be an issue (lame engines).
1916
bool Session::openTables(TableList *tables, uint32_t flags)
1919
bool ret= fill_derived_tables();
1920
assert(ret == false);
1921
if (open_tables_from_list(&tables, &counter, flags) ||
1922
mysql_handle_derived(lex, &mysql_derived_prepare))
1954
bool Open_tables_state::rm_temporary_table(TableIdentifier &identifier, bool best_effort)
1927
bool Session::rm_temporary_table(TableIdentifier &identifier)
1956
if (plugin::StorageEngine::dropTable(*static_cast<Session *>(this), identifier))
1929
if (plugin::StorageEngine::dropTable(*this, identifier))
1958
if (not best_effort)
1960
errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
1961
identifier.getSQLPath().c_str(), errno);
1931
errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
1932
identifier.getSQLPath().c_str(), errno);
1933
dumpTemporaryTableNames("rm_temporary_table()");
1970
bool Open_tables_state::rm_temporary_table(plugin::StorageEngine *base, TableIdentifier &identifier)
1941
bool Session::rm_temporary_table(plugin::StorageEngine *base, TableIdentifier &identifier)
1974
if (plugin::StorageEngine::dropTable(*static_cast<Session *>(this), *base, identifier))
1945
if (plugin::StorageEngine::dropTable(*this, *base, identifier))
1976
1947
errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
1977
1948
identifier.getSQLPath().c_str(), errno);
1949
dumpTemporaryTableNames("rm_temporary_table()");
2085
table::Instance *Session::getInstanceTable()
2057
TableShareInstance *Session::getTemporaryShare()
2087
temporary_shares.push_back(new table::Instance()); // This will not go into the tableshare cache, so no key is used.
2059
temporary_shares.push_back(new TableShareInstance()); // This will not go into the tableshare cache, so no key is used.
2089
table::Instance *tmp_share= temporary_shares.back();
2061
TableShareInstance *tmp_share= temporary_shares.back();
2091
2063
assert(tmp_share);
2093
2065
return tmp_share;
2098
Create a reduced Table object with properly set up Field list from a
2099
list of field definitions.
2101
The created table doesn't have a table Cursor associated with
2102
it, has no keys, no group/distinct, no copy_funcs array.
2103
The sole purpose of this Table object is to use the power of Field
2104
class to read/write data to/from table->getInsertRecord(). Then one can store
2105
the record in any container (RB tree, hash, etc).
2106
The table is created in Session mem_root, so are the table's fields.
2107
Consequently, if you don't BLOB fields, you don't need to free it.
2109
@param session connection handle
2110
@param field_list list of column definitions
2113
0 if out of memory, Table object in case of success
2115
table::Instance *Session::getInstanceTable(List<CreateField> &field_list)
2068
TableShareInstance *Session::getTemporaryShare(const char *tmpname_arg)
2117
temporary_shares.push_back(new table::Instance(this, field_list)); // This will not go into the tableshare cache, so no key is used.
2119
table::Instance *tmp_share= temporary_shares.back();
2070
assert(tmpname_arg);
2072
temporary_shares.push_back(new TableShareInstance(tmpname_arg)); // This will not go into the tableshare cache, so no key is used.
2074
TableShareInstance *tmp_share= temporary_shares.back();
2121
2076
assert(tmp_share);