21
21
* @file Implementation of the Session class and API
25
#include "drizzled/session.h"
26
#include "drizzled/session/cache.h"
24
#include <drizzled/server_includes.h>
25
#include <drizzled/session.h>
27
26
#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"
27
#include <mysys/mysys_err.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
#include "drizzled/plugin/logging.h"
43
#include "drizzled/plugin/transactional_storage_engine.h"
44
#include "drizzled/plugin/query_rewrite.h"
45
42
#include "drizzled/probes.h"
46
43
#include "drizzled/table_proto.h"
47
#include "drizzled/db.h"
48
#include "drizzled/pthread_globals.h"
49
#include "drizzled/transaction_services.h"
50
#include "drizzled/drizzled.h"
52
#include "drizzled/table/instance.h"
54
#include "plugin/myisam/myisam.h"
55
#include "drizzled/internal/iocache.h"
56
#include "drizzled/internal/thread_var.h"
57
#include "drizzled/plugin/event_observer.h"
59
#include "drizzled/util/functors.h"
61
#include "drizzled/display.h"
64
45
#include <algorithm>
66
#include <boost/filesystem.hpp>
68
#include "drizzled/util/backtrace.h"
70
47
using namespace std;
48
using namespace drizzled;
72
namespace fs=boost::filesystem;
52
unsigned char *get_var_key(user_var_entry *entry, size_t *length, bool );
53
void free_user_var(user_var_entry *entry);
77
57
The following is used to initialise Table_ident with a internal
81
61
char empty_c_string[1]= {0}; /* used for not defined db */
83
63
const char * const Session::DEFAULT_WHERE= "field list";
64
extern pthread_key_t THR_Session;
65
extern pthread_key_t THR_Mem_root;
66
extern uint32_t max_used_connections;
67
extern drizzled::atomic<uint32_t> connection_count;
69
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
71
template class List<Key>;
72
template class List_iterator<Key>;
73
template class List<Key_part_spec>;
74
template class List_iterator<Key_part_spec>;
75
template class List<AlterDrop>;
76
template class List_iterator<AlterDrop>;
77
template class List<AlterColumn>;
78
template class List_iterator<AlterColumn>;
81
/****************************************************************************
83
****************************************************************************/
84
unsigned char *get_var_key(user_var_entry *entry, size_t *length, bool )
86
*length= entry->name.length;
87
return (unsigned char*) entry->name.str;
90
void free_user_var(user_var_entry *entry)
85
95
bool Key_part_spec::operator==(const Key_part_spec& other) const
87
97
return length == other.length &&
88
98
field_name.length == other.field_name.length &&
89
!my_strcasecmp(system_charset_info, field_name.str, other.field_name.str);
99
!strcmp(field_name.str, other.field_name.str);
92
Open_tables_state::Open_tables_state(uint64_t version_arg) :
102
Open_tables_state::Open_tables_state(uint64_t version_arg)
103
:version(version_arg), backups_available(false)
95
open_tables= temporary_tables= derived_tables= NULL;
96
extra_lock= lock= NULL;
105
reset_open_tables_state();
100
109
The following functions form part of the C plugin API
102
int mysql_tmpfile(const char *prefix)
111
extern "C" int mysql_tmpfile(const char *prefix)
104
113
char filename[FN_REFLEN];
105
int fd = internal::create_temp_file(filename, drizzle_tmpdir.c_str(), prefix, MYF(MY_WME));
114
File fd = create_temp_file(filename, drizzle_tmpdir, prefix, MYF(MY_WME));
107
116
unlink(filename);
124
134
@see Session::set_proc_info
126
void set_session_proc_info(Session *session, const char *info)
137
set_session_proc_info(Session *session, const char *info)
128
139
session->set_proc_info(info);
131
143
const char *get_session_proc_info(Session *session)
133
145
return session->get_proc_info();
136
void **Session::getEngineData(const plugin::MonitoredInTransaction *monitored)
138
return static_cast<void **>(&ha_data[monitored->getId()].ha_ptr);
141
ResourceContext *Session::getResourceContext(const plugin::MonitoredInTransaction *monitored,
144
return &ha_data[monitored->getId()].resource_context[index];
149
void **session_ha_data(const Session *session, const plugin::StorageEngine *engine)
151
return (void **) &session->ha_data[engine->slot].ha_ptr;
147
155
int64_t session_test_options(const Session *session, int64_t test_options)
149
157
return session->options & test_options;
152
161
int session_sql_command(const Session *session)
154
163
return (int) session->lex->sql_command;
157
enum_tx_isolation session_tx_isolation(const Session *session)
167
int session_tx_isolation(const Session *session)
159
return (enum_tx_isolation)session->variables.tx_isolation;
169
return (int) session->variables.tx_isolation;
162
Session::Session(plugin::Client *client_arg) :
172
Session::Session(plugin::Client *client_arg)
163
174
Open_tables_state(refresh_version),
164
175
mem_root(&main_mem_root),
167
query(new std::string),
168
_schema(new std::string("")),
170
177
client(client_arg),
172
179
scheduler_arg(NULL),
173
180
lock_id(&main_lock_id),
175
ha_data(plugin::num_trx_monitored_objects),
176
concurrent_execute_allowed(true),
177
182
arg_of_last_insert_id_function(false),
178
183
first_successful_insert_id_in_prev_stmt(0),
179
184
first_successful_insert_id_in_cur_stmt(0),
180
185
limit_found_rows(0),
181
_global_read_lock(NONE),
183
187
some_tables_deleted(false),
184
188
no_errors(false),
259
265
memset(&status_var, 0, sizeof(status_var));
261
267
/* Initialize sub structures */
262
memory::init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
268
init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
269
hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
270
(hash_get_key) get_var_key,
271
(hash_free_key) free_user_var, 0);
264
273
substitute_null_with_insert_id = false;
265
lock_info.init(); /* safety: will be reset after start */
274
thr_lock_info_init(&lock_info); /* safety: will be reset after start */
266
275
thr_lock_owner_init(&main_lock_id, &lock_info);
268
277
m_internal_handler= NULL;
270
plugin::EventObserver::registerSessionEvents(*this);
273
280
void Session::free_items()
276
/* This works because items are allocated with memory::sql_alloc() */
283
/* This works because items are allocated with sql_alloc() */
277
284
for (; free_list; free_list= next)
279
286
next= free_list->next;
302
309
return false; // 'false', as per coding style
305
void Session::setAbort(bool arg)
307
mysys_var->abort= arg;
310
void Session::lockOnSys()
316
boost_unique_lock_t scopedLock(mysys_var->mutex);
317
if (mysys_var->current_cond)
319
mysys_var->current_mutex->lock();
320
mysys_var->current_cond->notify_all();
321
mysys_var->current_mutex->unlock();
325
312
void Session::pop_internal_handler()
327
314
assert(m_internal_handler != NULL);
328
315
m_internal_handler= NULL;
331
void Session::get_xid(DRIZZLE_XID *xid)
333
*xid = *(DRIZZLE_XID *) &transaction.xid_state.xid;
318
#if defined(__cplusplus)
322
void *session_alloc(Session *session, unsigned int size)
324
return session->alloc(size);
327
void *session_calloc(Session *session, unsigned int size)
329
return session->calloc(size);
332
char *session_strdup(Session *session, const char *str)
334
return session->strdup(str);
337
char *session_strmake(Session *session, const char *str, unsigned int size)
339
return session->strmake(str, size);
342
void *session_memdup(Session *session, const void* str, unsigned int size)
344
return session->memdup(str, size);
347
void session_get_xid(const Session *session, DRIZZLE_XID *xid)
349
*xid = *(DRIZZLE_XID *) &session->transaction.xid_state.xid;
352
#if defined(__cplusplus)
336
356
/* Do operations that may take a long time */
396
404
plugin::StorageEngine::closeConnection(this);
397
405
plugin_sessionvar_cleanup(this);
399
warn_root.free_root(MYF(0));
407
free_root(&warn_root,MYF(0));
408
free_root(&transaction.mem_root,MYF(0));
400
409
mysys_var=0; // Safety (shouldn't be needed)
401
410
dbug_sentry= Session_SENTRY_GONE;
403
main_mem_root.free_root(MYF(0));
404
currentMemRoot().release();
405
currentSession().release();
407
plugin::Logging::postEndDo(this);
408
plugin::EventObserver::deregisterSessionEvents(*this);
410
for (PropertyMap::iterator iter= life_properties.begin(); iter != life_properties.end(); iter++)
412
delete (*iter).second;
414
life_properties.clear();
417
void Session::setClient(plugin::Client *client_arg)
420
client->setSession(this);
423
void Session::awake(Session::killed_state_t state_to_set)
425
if ((state_to_set == Session::KILL_QUERY) and (command == COM_SLEEP))
430
setKilled(state_to_set);
431
scheduler->killSession(this);
412
free_root(&main_mem_root, MYF(0));
413
pthread_setspecific(THR_Session, 0);
416
/* Ensure that no one is using Session */
417
pthread_mutex_unlock(&LOCK_delete);
418
pthread_mutex_destroy(&LOCK_delete);
422
Add all status variables to another status variable array
426
to_var add to this array
427
from_var from this array
430
This function assumes that all variables are long/ulong.
431
If this assumption will change, then we have to explictely add
432
the other variables after the while loop
434
void add_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var)
436
ulong *end= (ulong*) ((unsigned char*) to_var +
437
offsetof(STATUS_VAR, last_system_status_var) +
439
ulong *to= (ulong*) to_var, *from= (ulong*) from_var;
446
Add the difference between two status variable arrays to another one.
450
to_var add to this array
451
from_var from this array
452
dec_var minus this array
455
This function assumes that all variables are long/ulong.
457
void add_diff_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var,
460
ulong *end= (ulong*) ((unsigned char*) to_var + offsetof(STATUS_VAR,
461
last_system_status_var) +
463
ulong *to= (ulong*) to_var, *from= (ulong*) from_var, *dec= (ulong*) dec_var;
466
*(to++)+= *(from++) - *(dec++);
469
void Session::awake(Session::killed_state state_to_set)
471
Session_CHECK_SENTRY(this);
472
safe_mutex_assert_owner(&LOCK_delete);
474
killed= state_to_set;
433
475
if (state_to_set != Session::KILL_QUERY)
477
scheduler->killSession(this);
435
478
DRIZZLE_CONNECTION_DONE(thread_id);
440
boost_unique_lock_t scopedLock(mysys_var->mutex);
482
pthread_mutex_lock(&mysys_var->mutex);
443
484
This broadcast could be up in the air if the victim thread
444
485
exits the cond in the time between read and broadcast, but that is
445
486
ok since all we want to do is to make the victim thread get out
548
590
prepareForQueries();
550
while (not client->haveError() && getKilled() != KILL_CONNECTION)
592
while (! client->haveError() && killed != KILL_CONNECTION)
552
if (not executeStatement())
594
if (! executeStatement())
556
598
disconnect(0, true);
559
bool Session::schedule(Session::shared_ptr &arg)
601
bool Session::schedule()
561
arg->scheduler= plugin::Scheduler::getScheduler();
562
assert(arg->scheduler);
564
connection_count.increment();
566
if (connection_count > current_global_counters.max_used_connections)
568
current_global_counters.max_used_connections= connection_count;
571
current_global_counters.connections++;
572
arg->thread_id= arg->variables.pseudo_thread_id= global_thread_id++;
574
session::Cache::singleton().insert(arg);
576
if (unlikely(plugin::EventObserver::connectSession(*arg)))
578
// We should do something about an error...
581
if (plugin::Scheduler::getScheduler()->addSession(arg))
583
DRIZZLE_CONNECTION_START(arg->getSessionId());
603
scheduler= plugin::Scheduler::getScheduler();
608
if (connection_count > max_used_connections)
609
max_used_connections= connection_count;
611
thread_id= variables.pseudo_thread_id= global_thread_id++;
613
pthread_mutex_lock(&LOCK_thread_count);
614
session_list.push_back(this);
615
pthread_mutex_unlock(&LOCK_thread_count);
617
if (scheduler->addSession(this))
619
DRIZZLE_CONNECTION_START(thread_id);
584
620
char error_message_buff[DRIZZLE_ERRMSG_SIZE];
586
arg->setKilled(Session::KILL_CONNECTION);
622
killed= Session::KILL_CONNECTION;
588
arg->status_var.aborted_connects++;
624
statistic_increment(aborted_connects, &LOCK_status);
590
626
/* Can't use my_error() since store_globals has not been called. */
591
627
/* TODO replace will better error message */
592
628
snprintf(error_message_buff, sizeof(error_message_buff),
593
629
ER(ER_CANT_CREATE_THREAD), 1);
594
arg->client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
630
client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
604
Is this session viewable by the current user?
606
bool Session::isViewable() const
608
return plugin::Authorization::isAuthorized(current_session->getSecurityContext(),
614
const char* Session::enter_cond(boost::condition_variable_any &cond, boost::mutex &mutex, const char* msg)
616
const char* old_msg = get_proc_info();
617
safe_mutex_assert_owner(mutex);
618
mysys_var->current_mutex = &mutex;
619
mysys_var->current_cond = &cond;
620
this->set_proc_info(msg);
624
void Session::exit_cond(const char* old_msg)
627
Putting the mutex unlock in exit_cond() ensures that
628
mysys_var->current_mutex is always unlocked _before_ mysys_var->mutex is
629
locked (if that would not be the case, you'll get a deadlock if someone
630
does a Session::awake() on you).
632
mysys_var->current_mutex->unlock();
633
boost_unique_lock_t scopedLock(mysys_var->mutex);
634
mysys_var->current_mutex = 0;
635
mysys_var->current_cond = 0;
636
this->set_proc_info(old_msg);
639
637
bool Session::authenticate()
642
640
if (client->authenticate())
645
status_var.aborted_connects++;
643
statistic_increment(aborted_connects, &LOCK_status);
650
bool Session::checkUser(const std::string &passwd_str,
651
const std::string &in_db)
647
bool Session::checkUser(const char *passwd, uint32_t passwd_len, const char *in_db)
653
bool is_authenticated=
654
plugin::Authentication::isAuthenticated(getSecurityContext(),
649
LEX_STRING db_str= { (char *) in_db, in_db ? strlen(in_db) : 0 };
650
bool is_authenticated;
652
if (passwd_len != 0 && passwd_len != SCRAMBLE_LENGTH)
654
my_error(ER_HANDSHAKE_ERROR, MYF(0), security_ctx.ip.c_str());
658
is_authenticated= plugin::Authentication::isAuthenticated(this, passwd);
657
660
if (is_authenticated != true)
659
status_var.access_denied++;
660
/* isAuthenticated has pushed the error message */
662
my_error(ER_ACCESS_DENIED_ERROR, MYF(0),
663
security_ctx.user.c_str(),
664
security_ctx.ip.c_str(),
665
passwd_len ? ER(ER_YES) : ER(ER_NO));
670
security_ctx.skip_grants();
664
672
/* Change database if necessary */
665
if (not in_db.empty())
673
if (in_db && in_db[0])
667
SchemaIdentifier identifier(in_db);
668
if (mysql_change_db(this, identifier))
675
if (mysql_change_db(this, &db_str, false))
670
677
/* mysql_change_db() has pushed the error message. */
675
password= not passwd_str.empty();
682
password= test(passwd_len); // remember for error messages
677
684
/* Ready to handle queries */
884
883
@return NULL on failure, or pointer to the LEX_STRING object
886
885
LEX_STRING *Session::make_lex_string(LEX_STRING *lex_str,
887
const std::string &str,
888
bool allocate_lex_string)
890
return make_lex_string(lex_str, str.c_str(), str.length(), allocate_lex_string);
893
LEX_STRING *Session::make_lex_string(LEX_STRING *lex_str,
894
const char* str, uint32_t length,
895
bool allocate_lex_string)
886
const char* str, uint32_t length,
887
bool allocate_lex_string)
897
889
if (allocate_lex_string)
898
890
if (!(lex_str= (LEX_STRING *)alloc(sizeof(LEX_STRING))))
900
if (!(lex_str->str= mem_root->strmake_root(str, length)))
892
if (!(lex_str->str= strmake_root(mem_root, str, length)))
902
894
lex_str->length= length;
898
/* routings to adding tables to list of changed in transaction tables */
899
inline static void list_include(CHANGED_TableList** prev,
900
CHANGED_TableList* curr,
901
CHANGED_TableList* new_table)
906
(*prev)->next = curr;
910
/* add table to list of changed in transaction tables */
912
void Session::add_changed_table(Table *table)
914
assert((options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) &&
915
table->cursor->has_transactions());
916
add_changed_table(table->s->table_cache_key.str,
917
(long) table->s->table_cache_key.length);
921
void Session::add_changed_table(const char *key, long key_length)
923
CHANGED_TableList **prev_changed = &transaction.changed_tables;
924
CHANGED_TableList *curr = transaction.changed_tables;
926
for (; curr; prev_changed = &(curr->next), curr = curr->next)
928
int cmp = (long)curr->key_length - (long)key_length;
931
list_include(prev_changed, curr, changed_table_dup(key, key_length));
936
cmp = memcmp(curr->key, key, curr->key_length);
939
list_include(prev_changed, curr, changed_table_dup(key, key_length));
948
*prev_changed = changed_table_dup(key, key_length);
952
CHANGED_TableList* Session::changed_table_dup(const char *key, long key_length)
954
CHANGED_TableList* new_table =
955
(CHANGED_TableList*) trans_alloc(ALIGN_SIZE(sizeof(CHANGED_TableList))+
959
my_error(EE_OUTOFMEMORY, MYF(ME_BELL),
960
ALIGN_SIZE(sizeof(TableList)) + key_length + 1);
961
killed= KILL_CONNECTION;
965
new_table->key= ((char*)new_table)+ ALIGN_SIZE(sizeof(CHANGED_TableList));
967
new_table->key_length = key_length;
968
::memcpy(new_table->key, key, key_length);
906
973
int Session::send_explain_fields(select_result *result)
908
975
List<Item> field_list;
1038
static int create_file(Session *session,
1039
fs::path &target_path,
1040
file_exchange *exchange,
1041
internal::IO_CACHE *cache)
1097
static File create_file(Session *session, char *path, file_exchange *exchange, IO_CACHE *cache)
1043
fs::path to_file(exchange->file_name);
1046
if (not to_file.has_root_directory())
1100
uint32_t option= MY_UNPACK_FILENAME | MY_RELATIVE_PATH;
1102
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
1103
option|= MY_REPLACE_DIR; // Force use of db directory
1106
if (!dirname_length(exchange->file_name))
1048
target_path= fs::system_complete(getDataHomeCatalog());
1049
util::string::const_shared_ptr schema(session->schema());
1050
if (schema and not schema->empty())
1052
int count_elements= 0;
1053
for (fs::path::iterator iter= to_file.begin();
1054
iter != to_file.end();
1055
++iter, ++count_elements)
1058
if (count_elements == 1)
1060
target_path /= *schema;
1063
target_path /= to_file;
1108
strcpy(path, drizzle_real_data_home);
1109
if (! session->db.empty())
1110
strncat(path, session->db.c_str(), FN_REFLEN-strlen(drizzle_real_data_home)-1);
1111
(void) fn_format(path, exchange->file_name, path, "", option);
1067
target_path = exchange->file_name;
1070
if (not secure_file_priv.string().empty())
1072
if (target_path.file_string().substr(0, secure_file_priv.file_string().size()) != secure_file_priv.file_string())
1074
/* Write only allowed to dir or subdir specified by secure_file_priv */
1075
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
1080
if (!access(target_path.file_string().c_str(), F_OK))
1114
(void) fn_format(path, exchange->file_name, drizzle_real_data_home, "", option);
1116
if (opt_secure_file_priv &&
1117
strncmp(opt_secure_file_priv, path, strlen(opt_secure_file_priv)))
1119
/* Write only allowed to dir or subdir specified by secure_file_priv */
1120
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
1124
if (!access(path, F_OK))
1082
1126
my_error(ER_FILE_EXISTS_ERROR, MYF(0), exchange->file_name);
1085
1129
/* Create the file world readable */
1086
if ((file= internal::my_create(target_path.file_string().c_str(), 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
1130
if ((file= my_create(path, 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
1088
1133
(void) fchmod(file, 0666); // Because of umask()
1089
if (cache->init_io_cache(file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1135
(void) chmod(path, 0666);
1137
if (init_io_cache(cache, file, 0L, WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1091
internal::my_close(file, MYF(0));
1092
internal::my_delete(target_path.file_string().c_str(), MYF(0)); // Delete file on error, it was just created
1139
my_close(file, MYF(0));
1140
my_delete(path, MYF(0)); // Delete file on error, it was just created
1318
1369
uint32_t length=item->max_length-used_length;
1319
1370
for (; length > sizeof(space) ; length-=sizeof(space))
1321
if (my_b_write(cache,(unsigned char*) space,sizeof(space)))
1372
if (my_b_write(&cache,(unsigned char*) space,sizeof(space)))
1324
if (my_b_write(cache,(unsigned char*) space,length))
1375
if (my_b_write(&cache,(unsigned char*) space,length))
1328
1379
if (res && enclosed)
1330
if (my_b_write(cache, (unsigned char*) exchange->enclosed->ptr(),
1381
if (my_b_write(&cache, (unsigned char*) exchange->enclosed->ptr(),
1331
1382
exchange->enclosed->length()))
1334
1385
if (--items_left)
1336
if (my_b_write(cache, (unsigned char*) exchange->field_term->ptr(),
1387
if (my_b_write(&cache, (unsigned char*) exchange->field_term->ptr(),
1337
1388
field_term_length))
1341
if (my_b_write(cache,(unsigned char*) exchange->line_term->ptr(),
1392
if (my_b_write(&cache,(unsigned char*) exchange->line_term->ptr(),
1342
1393
exchange->line_term->length()))
1615
1657
memset(&status_var, 0, sizeof(status_var));
1619
void Session::set_db(const std::string &new_db)
1660
void Security_context::skip_grants()
1662
/* privileges for the user are unknown everything is allowed */
1666
/****************************************************************************
1667
Handling of open and locked tables states.
1669
This is used when we want to open/lock (and then close) some tables when
1670
we already have a set of tables open and locked. We use these methods for
1671
access to mysql.proc table to find definitions of stored routines.
1672
****************************************************************************/
1674
void Session::reset_n_backup_open_tables_state(Open_tables_state *backup)
1676
backup->set_open_tables_state(this);
1677
reset_open_tables_state();
1678
backups_available= false;
1682
void Session::restore_backup_open_tables_state(Open_tables_state *backup)
1685
Before we will throw away current open tables state we want
1686
to be sure that it was properly cleaned up.
1688
assert(open_tables == 0 && temporary_tables == 0 &&
1689
derived_tables == 0 &&
1691
set_open_tables_state(backup);
1695
bool Session::set_db(const char *new_db, size_t length)
1621
1697
/* Do not reallocate memory if current chunk is big enough. */
1622
if (new_db.length())
1624
_schema.reset(new std::string(new_db));
1628
_schema.reset(new std::string(""));
1708
Check the killed state of a user thread
1709
@param session user thread
1710
@retval 0 the user thread is active
1711
@retval 1 the user thread has been killed
1713
extern "C" int session_killed(const Session *session)
1715
return(session->killed);
1719
Return the session id of a user session
1720
@param pointer to Session object
1721
@return session's id
1723
extern "C" unsigned long session_get_thread_id(const Session *session)
1725
return (unsigned long) session->getSessionId();
1730
LEX_STRING *session_make_lex_string(Session *session, LEX_STRING *lex_str,
1731
const char *str, unsigned int size,
1732
int allocate_lex_string)
1734
return session->make_lex_string(lex_str, str, size,
1735
(bool) allocate_lex_string);
1738
const struct charset_info_st *session_charset(Session *session)
1740
return(session->charset());
1743
char **session_query(Session *session)
1745
return(&session->query);
1748
int session_non_transactional_update(const Session *session)
1750
return(session->transaction.all.modified_non_trans_table);
1753
void session_mark_transaction_to_rollback(Session *session, bool all)
1755
mark_transaction_to_rollback(session, all);
1634
1759
Mark transaction to rollback and mark error as fatal to a sub-statement.
1651
1776
plugin_sessionvar_cleanup(this);
1653
1778
/* If necessary, log any aborted or unauthorized connections */
1654
if (getKilled() || client->wasAborted())
1656
status_var.aborted_threads++;
1779
if (killed || client->wasAborted())
1780
statistic_increment(aborted_threads, &LOCK_status);
1659
1782
if (client->wasAborted())
1661
if (not getKilled() && variables.log_warnings > 1)
1784
if (! killed && variables.log_warnings > 1)
1663
SecurityContext *sctx= &security_ctx;
1786
Security_context *sctx= &security_ctx;
1665
1788
errmsg_printf(ERRMSG_LVL_WARN, ER(ER_NEW_ABORTING_CONNECTION)
1667
, (_schema->empty() ? "unconnected" : _schema->c_str())
1668
, sctx->getUser().empty() == false ? sctx->getUser().c_str() : "unauthenticated"
1669
, sctx->getIp().c_str()
1790
, (db.empty() ? "unconnected" : db.c_str())
1791
, sctx->user.empty() == false ? sctx->user.c_str() : "unauthenticated"
1670
1793
, (main_da.is_error() ? main_da.message() : ER(ER_UNKNOWN_ERROR)));
1674
1797
/* Close out our connection to the client */
1675
1798
if (should_lock)
1676
session::Cache::singleton().mutex().lock();
1678
setKilled(Session::KILL_CONNECTION);
1799
(void) pthread_mutex_lock(&LOCK_thread_count);
1800
killed= Session::KILL_CONNECTION;
1680
1801
if (client->isConnected())
1757
1883
passing non-zero value to end_slave via rli->save_temporary_tables
1758
1884
when no temp tables opened, see an invariant below.
1760
temporary_tables= table->getNext();
1886
temporary_tables= table->next;
1761
1887
if (temporary_tables)
1763
table->getNext()->setPrev(NULL);
1888
table->next->prev= NULL;
1890
close_temporary(table);
1770
Close and drop a temporary table
1894
Close and delete a temporary table
1773
1897
This dosn't unlink table from session->temporary
1774
1898
If this is needed, use close_temporary_table()
1777
void Open_tables_state::nukeTable(Table *table)
1901
void Session::close_temporary(Table *table)
1779
plugin::StorageEngine *table_type= table->getShare()->db_type();
1903
plugin::StorageEngine *table_type= table->s->db_type();
1781
1905
table->free_io_cache();
1782
table->delete_table();
1784
TableIdentifier identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName(), table->getShare()->getPath());
1785
rm_temporary_table(table_type, identifier);
1787
delete table->getMutableShare();
1906
table->closefrm(false);
1908
rm_temporary_table(table_type, table->s->path.str);
1910
table->s->free_table_share();
1789
1911
/* This makes me sad, but we're allocating it via malloc */
1793
1915
/** Clear most status variables. */
1794
1916
extern time_t flush_status_time;
1917
extern uint32_t max_used_connections;
1796
1919
void Session::refresh_status()
1921
pthread_mutex_lock(&LOCK_status);
1923
/* Add thread's status variabes to global status */
1924
add_to_status(&global_status_var, &status_var);
1798
1926
/* Reset thread's status variables */
1799
1927
memset(&status_var, 0, sizeof(status_var));
1929
/* Reset some global variables */
1930
reset_status_vars();
1932
/* Reset the counters of all key caches (default and named). */
1933
reset_key_cache_counters();
1801
1934
flush_status_time= time((time_t*) 0);
1802
current_global_counters.max_used_connections= 1; /* We set it to one, because we know we exist */
1803
current_global_counters.connections= 0;
1935
max_used_connections= 1; /* We set it to one, because we know we exist */
1936
pthread_mutex_unlock(&LOCK_status);
1806
1939
user_var_entry *Session::getVariable(LEX_STRING &name, bool create_if_not_exists)
1808
return getVariable(std::string(name.str, name.length), create_if_not_exists);
1811
user_var_entry *Session::getVariable(const std::string &name, bool create_if_not_exists)
1813
UserVarsRange ppp= user_vars.equal_range(name);
1815
for (UserVars::iterator iter= ppp.first;
1816
iter != ppp.second; ++iter)
1818
return (*iter).second;
1821
if (not create_if_not_exists)
1824
1941
user_var_entry *entry= NULL;
1825
entry= new (nothrow) user_var_entry(name.c_str(), query_id);
1830
std::pair<UserVars::iterator, bool> returnable= user_vars.insert(make_pair(name, entry));
1832
if (not returnable.second)
1943
entry= (user_var_entry*) hash_search(&user_vars, (unsigned char*) name.str, name.length);
1945
if ((entry == NULL) && create_if_not_exists)
1947
if (!hash_inited(&user_vars))
1949
entry= new (nothrow) user_var_entry(name.str, query_id);
1954
if (my_hash_insert(&user_vars, (unsigned char*) entry))
1957
free((char*) entry);
1840
void Session::setVariable(const std::string &name, const std::string &value)
1842
user_var_entry *updateable_var= getVariable(name.c_str(), true);
1844
updateable_var->update_hash(false,
1845
(void*)value.c_str(),
1846
static_cast<uint32_t>(value.length()), STRING_RESULT,
1848
DERIVATION_IMPLICIT, false);
1851
void Open_tables_state::mark_temp_tables_as_free_for_reuse()
1853
for (Table *table= temporary_tables ; table ; table= table->getNext())
1966
void Session::mark_temp_tables_as_free_for_reuse()
1968
for (Table *table= temporary_tables ; table ; table= table->next)
1855
if (table->query_id == getQueryId())
1970
if (table->query_id == query_id)
1857
1972
table->query_id= 0;
1858
1973
table->cursor->ha_reset();
1954
2095
if (open_tables_from_list(&tables, &counter))
1957
if (not lock_tables(tables, counter, &need_reopen))
2098
if (!lock_tables(tables, counter, &need_reopen))
1959
if (not need_reopen)
1961
2102
close_tables_for_reopen(&tables);
1963
2104
if ((mysql_handle_derived(lex, &mysql_derived_prepare) ||
2105
(fill_derived_tables() &&
1965
2106
mysql_handle_derived(lex, &mysql_derived_filling))))
1972
@note "best_effort" is used in cases were if a failure occurred on this
1973
operation it would not be surprising because we are only removing because there
1974
might be an issue (lame engines).
1977
bool Open_tables_state::rm_temporary_table(const TableIdentifier &identifier, bool best_effort)
1979
if (plugin::StorageEngine::dropTable(*static_cast<Session *>(this), identifier))
1981
if (not best_effort)
1984
identifier.getSQLPath(path);
1985
errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
1986
path.c_str(), errno);
1995
bool Open_tables_state::rm_temporary_table(plugin::StorageEngine *base, const TableIdentifier &identifier)
1999
if (plugin::StorageEngine::dropTable(*static_cast<Session *>(this), *base, identifier))
2002
identifier.getSQLPath(path);
2003
errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
2004
path.c_str(), errno);
2013
@note this will be removed, I am looking through Hudson to see if it is finding
2014
any tables that are missed during cleanup.
2016
void Open_tables_state::dumpTemporaryTableNames(const char *foo)
2020
if (not temporary_tables)
2023
cerr << "Begin Run: " << foo << "\n";
2024
for (table= temporary_tables; table; table= table->getNext())
2026
bool have_proto= false;
2028
message::Table *proto= table->getShare()->getTableProto();
2029
if (table->getShare()->getTableProto())
2032
const char *answer= have_proto ? "true" : "false";
2036
cerr << "\tTable Name " << table->getShare()->getSchemaName() << "." << table->getShare()->getTableName() << " : " << answer << "\n";
2037
cerr << "\t\t Proto " << proto->schema() << " " << proto->name() << "\n";
2041
cerr << "\tTabl;e Name " << table->getShare()->getSchemaName() << "." << table->getShare()->getTableName() << " : " << answer << "\n";
2046
bool Session::TableMessages::storeTableMessage(const TableIdentifier &identifier, message::Table &table_message)
2048
table_message_cache.insert(make_pair(identifier.getPath(), table_message));
2053
bool Session::TableMessages::removeTableMessage(const TableIdentifier &identifier)
2055
TableMessageCache::iterator iter;
2057
iter= table_message_cache.find(identifier.getPath());
2059
if (iter == table_message_cache.end())
2062
table_message_cache.erase(iter);
2067
bool Session::TableMessages::getTableMessage(const TableIdentifier &identifier, message::Table &table_message)
2069
TableMessageCache::iterator iter;
2071
iter= table_message_cache.find(identifier.getPath());
2073
if (iter == table_message_cache.end())
2076
table_message.CopyFrom(((*iter).second));
2081
bool Session::TableMessages::doesTableMessageExist(const TableIdentifier &identifier)
2083
TableMessageCache::iterator iter;
2085
iter= table_message_cache.find(identifier.getPath());
2087
if (iter == table_message_cache.end())
2095
bool Session::TableMessages::renameTableMessage(const TableIdentifier &from, const TableIdentifier &to)
2097
TableMessageCache::iterator iter;
2099
table_message_cache[to.getPath()]= table_message_cache[from.getPath()];
2101
iter= table_message_cache.find(to.getPath());
2103
if (iter == table_message_cache.end())
2108
(*iter).second.set_schema(to.getSchemaName());
2109
(*iter).second.set_name(to.getTableName());
2114
table::Instance *Session::getInstanceTable()
2116
temporary_shares.push_back(new table::Instance()); // This will not go into the tableshare cache, so no key is used.
2118
table::Instance *tmp_share= temporary_shares.back();
2127
Create a reduced Table object with properly set up Field list from a
2128
list of field definitions.
2130
The created table doesn't have a table Cursor associated with
2131
it, has no keys, no group/distinct, no copy_funcs array.
2132
The sole purpose of this Table object is to use the power of Field
2133
class to read/write data to/from table->getInsertRecord(). Then one can store
2134
the record in any container (RB tree, hash, etc).
2135
The table is created in Session mem_root, so are the table's fields.
2136
Consequently, if you don't BLOB fields, you don't need to free it.
2138
@param session connection handle
2139
@param field_list list of column definitions
2142
0 if out of memory, Table object in case of success
2144
table::Instance *Session::getInstanceTable(List<CreateField> &field_list)
2146
temporary_shares.push_back(new table::Instance(this, field_list)); // This will not go into the tableshare cache, so no key is used.
2148
table::Instance *tmp_share= temporary_shares.back();
2157
static const std::string NONE= "NONE";
2158
static const std::string GOT_GLOBAL_READ_LOCK= "HAS GLOBAL READ LOCK";
2159
static const std::string MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT= "HAS GLOBAL READ LOCK WITH BLOCKING COMMIT";
2161
const std::string &type(drizzled::Session::global_read_lock_t type)
2167
case Session::GOT_GLOBAL_READ_LOCK:
2168
return GOT_GLOBAL_READ_LOCK;
2169
case Session::MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT:
2170
return MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT;
2174
size_t max_string_length(drizzled::Session::global_read_lock_t)
2176
return MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT.size();
2179
} /* namespace display */
2181
} /* namespace drizzled */
2112
bool Session::openTables(TableList *tables, uint32_t flags)
2115
bool ret= fill_derived_tables();
2116
assert(ret == false);
2117
if (open_tables_from_list(&tables, &counter, flags) ||
2118
mysql_handle_derived(lex, &mysql_derived_prepare))
2123
bool Session::rm_temporary_table(plugin::StorageEngine *base, TableIdentifier &identifier)
2129
if (delete_table_proto_file(identifier.getPath()))
2132
if (base->doDropTable(*this, identifier.getPath()))
2135
errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
2136
identifier.getPath(), my_errno);
2141
bool Session::rm_temporary_table(plugin::StorageEngine *base, const char *path)
2147
if (delete_table_proto_file(path))
2150
if (base->doDropTable(*this, path))
2153
errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),