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(ulong 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)
159
return (enum_tx_isolation)session->variables.tx_isolation;
162
Session::Session(plugin::Client *client_arg) :
167
int session_tx_isolation(const Session *session)
169
return (int) session->variables.tx_isolation;
173
void session_inc_row_count(Session *session)
175
session->row_count++;
178
Session::Session(plugin::Client *client_arg)
163
180
Open_tables_state(refresh_version),
164
181
mem_root(&main_mem_root),
167
query(new std::string),
168
_schema(new std::string("")),
170
184
client(client_arg),
172
186
scheduler_arg(NULL),
173
187
lock_id(&main_lock_id),
175
ha_data(plugin::num_trx_monitored_objects),
176
concurrent_execute_allowed(true),
177
189
arg_of_last_insert_id_function(false),
178
190
first_successful_insert_id_in_prev_stmt(0),
179
191
first_successful_insert_id_in_cur_stmt(0),
180
192
limit_found_rows(0),
181
_global_read_lock(NONE),
183
194
some_tables_deleted(false),
184
195
no_errors(false),
259
272
memset(&status_var, 0, sizeof(status_var));
261
274
/* Initialize sub structures */
262
memory::init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
275
init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
276
hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
277
(hash_get_key) get_var_key,
278
(hash_free_key) free_user_var, 0);
264
280
substitute_null_with_insert_id = false;
265
lock_info.init(); /* safety: will be reset after start */
281
thr_lock_info_init(&lock_info); /* safety: will be reset after start */
266
282
thr_lock_owner_init(&main_lock_id, &lock_info);
268
284
m_internal_handler= NULL;
270
plugin::EventObserver::registerSessionEvents(*this);
273
287
void Session::free_items()
276
/* This works because items are allocated with memory::sql_alloc() */
290
/* This works because items are allocated with sql_alloc() */
277
291
for (; free_list; free_list= next)
279
293
next= free_list->next;
302
316
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
319
void Session::pop_internal_handler()
327
321
assert(m_internal_handler != NULL);
328
322
m_internal_handler= NULL;
331
void Session::get_xid(DRIZZLE_XID *xid)
333
*xid = *(DRIZZLE_XID *) &transaction.xid_state.xid;
325
#if defined(__cplusplus)
329
void *session_alloc(Session *session, unsigned int size)
331
return session->alloc(size);
334
void *session_calloc(Session *session, unsigned int size)
336
return session->calloc(size);
339
char *session_strdup(Session *session, const char *str)
341
return session->strdup(str);
344
char *session_strmake(Session *session, const char *str, unsigned int size)
346
return session->strmake(str, size);
349
void *session_memdup(Session *session, const void* str, unsigned int size)
351
return session->memdup(str, size);
354
void session_get_xid(const Session *session, DRIZZLE_XID *xid)
356
*xid = *(DRIZZLE_XID *) &session->transaction.xid_state.xid;
359
#if defined(__cplusplus)
336
363
/* Do operations that may take a long time */
350
TransactionServices &transaction_services= TransactionServices::singleton();
351
transaction_services.rollbackTransaction(this, true);
352
378
xid_cache_delete(&transaction.xid_state);
355
for (UserVars::iterator iter= user_vars.begin();
356
iter != user_vars.end();
359
user_var_entry *entry= (*iter).second;
380
hash_free(&user_vars);
365
381
close_temporary_tables();
367
383
if (global_read_lock)
369
unlockGlobalReadLock();
384
unlock_global_read_lock(this);
372
386
cleanup_done= true;
375
389
Session::~Session()
391
Session_CHECK_SENTRY(this);
392
add_to_status(&global_status_var, &status_var);
379
394
if (client->isConnected())
381
396
if (global_system_variables.log_warnings)
382
errmsg_printf(ERRMSG_LVL_WARN, ER(ER_FORCING_CLOSE),internal::my_progname,
397
errmsg_printf(ERRMSG_LVL_WARN, ER(ER_FORCING_CLOSE),my_progname,
384
(getSecurityContext().getUser().c_str() ?
385
getSecurityContext().getUser().c_str() : ""));
399
(security_ctx.user.c_str() ?
400
security_ctx.user.c_str() : ""));
386
401
disconnect(0, false);
396
411
plugin::StorageEngine::closeConnection(this);
397
412
plugin_sessionvar_cleanup(this);
399
warn_root.free_root(MYF(0));
419
free_root(&warn_root,MYF(0));
420
free_root(&transaction.mem_root,MYF(0));
400
421
mysys_var=0; // Safety (shouldn't be needed)
401
422
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);
424
free_root(&main_mem_root, MYF(0));
425
pthread_setspecific(THR_Session, 0);
428
/* Ensure that no one is using Session */
429
pthread_mutex_unlock(&LOCK_delete);
430
pthread_mutex_destroy(&LOCK_delete);
434
Add all status variables to another status variable array
438
to_var add to this array
439
from_var from this array
442
This function assumes that all variables are long/ulong.
443
If this assumption will change, then we have to explictely add
444
the other variables after the while loop
446
void add_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var)
448
ulong *end= (ulong*) ((unsigned char*) to_var +
449
offsetof(STATUS_VAR, last_system_status_var) +
451
ulong *to= (ulong*) to_var, *from= (ulong*) from_var;
458
Add the difference between two status variable arrays to another one.
462
to_var add to this array
463
from_var from this array
464
dec_var minus this array
467
This function assumes that all variables are long/ulong.
469
void add_diff_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var,
472
ulong *end= (ulong*) ((unsigned char*) to_var + offsetof(STATUS_VAR,
473
last_system_status_var) +
475
ulong *to= (ulong*) to_var, *from= (ulong*) from_var, *dec= (ulong*) dec_var;
478
*(to++)+= *(from++) - *(dec++);
481
void Session::awake(Session::killed_state state_to_set)
483
Session_CHECK_SENTRY(this);
484
safe_mutex_assert_owner(&LOCK_delete);
486
killed= state_to_set;
433
487
if (state_to_set != Session::KILL_QUERY)
489
scheduler->killSession(this);
435
490
DRIZZLE_CONNECTION_DONE(thread_id);
440
boost_unique_lock_t scopedLock(mysys_var->mutex);
494
pthread_mutex_lock(&mysys_var->mutex);
443
496
This broadcast could be up in the air if the victim thread
444
497
exits the cond in the time between read and broadcast, but that is
445
498
ok since all we want to do is to make the victim thread get out
548
602
prepareForQueries();
550
while (not client->haveError() && getKilled() != KILL_CONNECTION)
604
while (! client->haveError() && killed != KILL_CONNECTION)
552
if (not executeStatement())
606
if (! executeStatement())
556
610
disconnect(0, true);
559
bool Session::schedule(Session::shared_ptr &arg)
613
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());
615
scheduler= plugin::Scheduler::getScheduler();
620
if (connection_count > max_used_connections)
621
max_used_connections= connection_count;
623
thread_id= variables.pseudo_thread_id= global_thread_id++;
625
pthread_mutex_lock(&LOCK_thread_count);
626
session_list.push_back(this);
627
pthread_mutex_unlock(&LOCK_thread_count);
629
if (scheduler->addSession(this))
631
DRIZZLE_CONNECTION_START(thread_id);
584
632
char error_message_buff[DRIZZLE_ERRMSG_SIZE];
586
arg->setKilled(Session::KILL_CONNECTION);
634
killed= Session::KILL_CONNECTION;
588
arg->status_var.aborted_connects++;
636
statistic_increment(aborted_connects, &LOCK_status);
590
638
/* Can't use my_error() since store_globals has not been called. */
591
639
/* TODO replace will better error message */
592
640
snprintf(error_message_buff, sizeof(error_message_buff),
593
641
ER(ER_CANT_CREATE_THREAD), 1);
594
arg->client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
642
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
649
bool Session::authenticate()
642
652
if (client->authenticate())
645
status_var.aborted_connects++;
655
statistic_increment(aborted_connects, &LOCK_status);
650
bool Session::checkUser(const std::string &passwd_str,
651
const std::string &in_db)
659
bool Session::checkUser(const char *passwd, uint32_t passwd_len, const char *in_db)
653
bool is_authenticated=
654
plugin::Authentication::isAuthenticated(getSecurityContext(),
661
LEX_STRING db_str= { (char *) in_db, in_db ? strlen(in_db) : 0 };
662
bool is_authenticated;
665
Clear session->db as it points to something, that will be freed when
666
connection is closed. We don't want to accidentally free a wrong
667
pointer if connect failed. Also in case of 'CHANGE USER' failure,
668
current database will be switched to 'no database selected'.
672
if (passwd_len != 0 && passwd_len != SCRAMBLE_LENGTH)
674
my_error(ER_HANDSHAKE_ERROR, MYF(0), security_ctx.ip.c_str());
678
is_authenticated= plugin::Authentication::isAuthenticated(this, passwd);
657
680
if (is_authenticated != true)
659
status_var.access_denied++;
660
/* isAuthenticated has pushed the error message */
682
my_error(ER_ACCESS_DENIED_ERROR, MYF(0),
683
security_ctx.user.c_str(),
684
security_ctx.ip.c_str(),
685
passwd_len ? ER(ER_YES) : ER(ER_NO));
690
security_ctx.skip_grants();
664
692
/* Change database if necessary */
665
if (not in_db.empty())
693
if (in_db && in_db[0])
667
SchemaIdentifier identifier(in_db);
668
if (mysql_change_db(this, identifier))
695
if (mysql_change_db(this, &db_str, false))
670
697
/* mysql_change_db() has pushed the error message. */
675
password= not passwd_str.empty();
702
password= test(passwd_len); // remember for error messages
677
704
/* Ready to handle queries */
884
903
@return NULL on failure, or pointer to the LEX_STRING object
886
905
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)
906
const char* str, uint32_t length,
907
bool allocate_lex_string)
897
909
if (allocate_lex_string)
898
910
if (!(lex_str= (LEX_STRING *)alloc(sizeof(LEX_STRING))))
900
if (!(lex_str->str= mem_root->strmake_root(str, length)))
912
if (!(lex_str->str= strmake_root(mem_root, str, length)))
902
914
lex_str->length= length;
918
/* routings to adding tables to list of changed in transaction tables */
919
inline static void list_include(CHANGED_TableList** prev,
920
CHANGED_TableList* curr,
921
CHANGED_TableList* new_table)
926
(*prev)->next = curr;
930
/* add table to list of changed in transaction tables */
932
void Session::add_changed_table(Table *table)
934
assert((options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) &&
935
table->cursor->has_transactions());
936
add_changed_table(table->s->table_cache_key.str,
937
(long) table->s->table_cache_key.length);
941
void Session::add_changed_table(const char *key, long key_length)
943
CHANGED_TableList **prev_changed = &transaction.changed_tables;
944
CHANGED_TableList *curr = transaction.changed_tables;
946
for (; curr; prev_changed = &(curr->next), curr = curr->next)
948
int cmp = (long)curr->key_length - (long)key_length;
951
list_include(prev_changed, curr, changed_table_dup(key, key_length));
956
cmp = memcmp(curr->key, key, curr->key_length);
959
list_include(prev_changed, curr, changed_table_dup(key, key_length));
968
*prev_changed = changed_table_dup(key, key_length);
972
CHANGED_TableList* Session::changed_table_dup(const char *key, long key_length)
974
CHANGED_TableList* new_table =
975
(CHANGED_TableList*) trans_alloc(ALIGN_SIZE(sizeof(CHANGED_TableList))+
979
my_error(EE_OUTOFMEMORY, MYF(ME_BELL),
980
ALIGN_SIZE(sizeof(TableList)) + key_length + 1);
981
killed= KILL_CONNECTION;
985
new_table->key= ((char*)new_table)+ ALIGN_SIZE(sizeof(CHANGED_TableList));
987
new_table->key_length = key_length;
988
::memcpy(new_table->key, key, key_length);
906
993
int Session::send_explain_fields(select_result *result)
908
995
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)
1117
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())
1120
uint32_t option= MY_UNPACK_FILENAME | MY_RELATIVE_PATH;
1122
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
1123
option|= MY_REPLACE_DIR; // Force use of db directory
1126
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;
1128
strcpy(path, drizzle_real_data_home);
1130
strncat(path, session->db, FN_REFLEN-strlen(drizzle_real_data_home)-1);
1131
(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))
1134
(void) fn_format(path, exchange->file_name, drizzle_real_data_home, "", option);
1136
if (opt_secure_file_priv &&
1137
strncmp(opt_secure_file_priv, path, strlen(opt_secure_file_priv)))
1139
/* Write only allowed to dir or subdir specified by secure_file_priv */
1140
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
1144
if (!access(path, F_OK))
1082
1146
my_error(ER_FILE_EXISTS_ERROR, MYF(0), exchange->file_name);
1085
1149
/* 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)
1150
if ((file= my_create(path, 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
1088
1153
(void) fchmod(file, 0666); // Because of umask()
1089
if (cache->init_io_cache(file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1155
(void) chmod(path, 0666);
1157
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
1159
my_close(file, MYF(0));
1160
my_delete(path, MYF(0)); // Delete file on error, it was just created
1318
1389
uint32_t length=item->max_length-used_length;
1319
1390
for (; length > sizeof(space) ; length-=sizeof(space))
1321
if (my_b_write(cache,(unsigned char*) space,sizeof(space)))
1392
if (my_b_write(&cache,(unsigned char*) space,sizeof(space)))
1324
if (my_b_write(cache,(unsigned char*) space,length))
1395
if (my_b_write(&cache,(unsigned char*) space,length))
1328
1399
if (res && enclosed)
1330
if (my_b_write(cache, (unsigned char*) exchange->enclosed->ptr(),
1401
if (my_b_write(&cache, (unsigned char*) exchange->enclosed->ptr(),
1331
1402
exchange->enclosed->length()))
1334
1405
if (--items_left)
1336
if (my_b_write(cache, (unsigned char*) exchange->field_term->ptr(),
1407
if (my_b_write(&cache, (unsigned char*) exchange->field_term->ptr(),
1337
1408
field_term_length))
1341
if (my_b_write(cache,(unsigned char*) exchange->line_term->ptr(),
1412
if (my_b_write(&cache,(unsigned char*) exchange->line_term->ptr(),
1342
1413
exchange->line_term->length()))
1615
1677
memset(&status_var, 0, sizeof(status_var));
1619
void Session::set_db(const std::string &new_db)
1680
void Security_context::skip_grants()
1682
/* privileges for the user are unknown everything is allowed */
1686
/****************************************************************************
1687
Handling of open and locked tables states.
1689
This is used when we want to open/lock (and then close) some tables when
1690
we already have a set of tables open and locked. We use these methods for
1691
access to mysql.proc table to find definitions of stored routines.
1692
****************************************************************************/
1694
void Session::reset_n_backup_open_tables_state(Open_tables_state *backup)
1696
backup->set_open_tables_state(this);
1697
reset_open_tables_state();
1698
backups_available= false;
1702
void Session::restore_backup_open_tables_state(Open_tables_state *backup)
1705
Before we will throw away current open tables state we want
1706
to be sure that it was properly cleaned up.
1708
assert(open_tables == 0 && temporary_tables == 0 &&
1709
derived_tables == 0 &&
1711
set_open_tables_state(backup);
1715
bool Session::set_db(const char *new_db, size_t new_db_len)
1621
1717
/* Do not reallocate memory if current chunk is big enough. */
1622
if (new_db.length())
1624
_schema.reset(new std::string(new_db));
1718
if (db && new_db && db_length >= new_db_len)
1719
memcpy(db, new_db, new_db_len+1);
1628
_schema.reset(new std::string(""));
1726
db= (char *)malloc(new_db_len + 1);
1729
memcpy(db, new_db, new_db_len);
1736
db_length= db ? new_db_len : 0;
1737
return new_db && !db;
1742
Check the killed state of a user thread
1743
@param session user thread
1744
@retval 0 the user thread is active
1745
@retval 1 the user thread has been killed
1747
extern "C" int session_killed(const Session *session)
1749
return(session->killed);
1753
Return the session id of a user session
1754
@param pointer to Session object
1755
@return session's id
1757
extern "C" unsigned long session_get_thread_id(const Session *session)
1759
return (unsigned long) session->getSessionId();
1764
LEX_STRING *session_make_lex_string(Session *session, LEX_STRING *lex_str,
1765
const char *str, unsigned int size,
1766
int allocate_lex_string)
1768
return session->make_lex_string(lex_str, str, size,
1769
(bool) allocate_lex_string);
1772
const struct charset_info_st *session_charset(Session *session)
1774
return(session->charset());
1777
char **session_query(Session *session)
1779
return(&session->query);
1782
int session_non_transactional_update(const Session *session)
1784
return(session->transaction.all.modified_non_trans_table);
1787
void session_mark_transaction_to_rollback(Session *session, bool all)
1789
mark_transaction_to_rollback(session, all);
1634
1793
Mark transaction to rollback and mark error as fatal to a sub-statement.
1651
1810
plugin_sessionvar_cleanup(this);
1653
1812
/* If necessary, log any aborted or unauthorized connections */
1654
if (getKilled() || client->wasAborted())
1656
status_var.aborted_threads++;
1813
if (killed || client->wasAborted())
1814
statistic_increment(aborted_threads, &LOCK_status);
1659
1816
if (client->wasAborted())
1661
if (not getKilled() && variables.log_warnings > 1)
1818
if (! killed && variables.log_warnings > 1)
1663
SecurityContext *sctx= &security_ctx;
1820
Security_context *sctx= &security_ctx;
1665
1822
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()
1824
, (db ? db : "unconnected")
1825
, sctx->user.empty() == false ? sctx->user.c_str() : "unauthenticated"
1670
1827
, (main_da.is_error() ? main_da.message() : ER(ER_UNKNOWN_ERROR)));
1674
1831
/* Close out our connection to the client */
1675
1832
if (should_lock)
1676
session::Cache::singleton().mutex().lock();
1678
setKilled(Session::KILL_CONNECTION);
1833
(void) pthread_mutex_lock(&LOCK_thread_count);
1834
killed= Session::KILL_CONNECTION;
1680
1835
if (client->isConnected())
1757
1917
passing non-zero value to end_slave via rli->save_temporary_tables
1758
1918
when no temp tables opened, see an invariant below.
1760
temporary_tables= table->getNext();
1920
temporary_tables= table->next;
1761
1921
if (temporary_tables)
1763
table->getNext()->setPrev(NULL);
1922
table->next->prev= NULL;
1924
close_temporary(table, free_share, delete_table);
1770
Close and drop a temporary table
1928
Close and delete a temporary table
1773
1931
This dosn't unlink table from session->temporary
1774
1932
If this is needed, use close_temporary_table()
1777
void Open_tables_state::nukeTable(Table *table)
1935
void Session::close_temporary(Table *table, bool free_share, bool delete_table)
1779
plugin::StorageEngine *table_type= table->getShare()->db_type();
1937
plugin::StorageEngine *table_type= table->s->db_type();
1781
1939
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();
1789
/* This makes me sad, but we're allocating it via malloc */
1940
table->closefrm(false);
1943
rm_temporary_table(table_type, table->s->path.str);
1947
table->s->free_table_share();
1948
/* This makes me sad, but we're allocating it via malloc */
1793
1953
/** Clear most status variables. */
1794
1954
extern time_t flush_status_time;
1955
extern uint32_t max_used_connections;
1796
1957
void Session::refresh_status()
1959
pthread_mutex_lock(&LOCK_status);
1961
/* Add thread's status variabes to global status */
1962
add_to_status(&global_status_var, &status_var);
1798
1964
/* Reset thread's status variables */
1799
1965
memset(&status_var, 0, sizeof(status_var));
1967
/* Reset some global variables */
1968
reset_status_vars();
1970
/* Reset the counters of all key caches (default and named). */
1971
reset_key_cache_counters();
1801
1972
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;
1973
max_used_connections= 1; /* We set it to one, because we know we exist */
1974
pthread_mutex_unlock(&LOCK_status);
1806
1977
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
1979
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)
1981
entry= (user_var_entry*) hash_search(&user_vars, (unsigned char*) name.str, name.length);
1983
if ((entry == NULL) && create_if_not_exists)
1985
if (!hash_inited(&user_vars))
1987
entry= new (nothrow) user_var_entry(name.str, query_id);
1992
if (my_hash_insert(&user_vars, (unsigned char*) entry))
1995
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())
2004
void Session::mark_temp_tables_as_free_for_reuse()
2006
for (Table *table= temporary_tables ; table ; table= table->next)
1855
if (table->query_id == getQueryId())
2008
if (table->query_id == query_id)
1857
2010
table->query_id= 0;
1858
2011
table->cursor->ha_reset();
1954
2133
if (open_tables_from_list(&tables, &counter))
1957
if (not lock_tables(tables, counter, &need_reopen))
2136
if (!lock_tables(tables, counter, &need_reopen))
1959
if (not need_reopen)
1961
2140
close_tables_for_reopen(&tables);
1963
2142
if ((mysql_handle_derived(lex, &mysql_derived_prepare) ||
2143
(fill_derived_tables() &&
1965
2144
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)
2150
bool Session::openTables(TableList *tables, uint32_t flags)
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);
2153
bool ret= fill_derived_tables();
2154
assert(ret == false);
2155
if (open_tables_from_list(&tables, &counter, flags) ||
2156
mysql_handle_derived(lex, &mysql_derived_prepare))
1995
bool Open_tables_state::rm_temporary_table(plugin::StorageEngine *base, const TableIdentifier &identifier)
2161
bool Session::rm_temporary_table(plugin::StorageEngine *base, char *path)
1999
if (plugin::StorageEngine::dropTable(*static_cast<Session *>(this), *base, identifier))
2167
if (delete_table_proto_file(path))
2170
if (base->doDropTable(*this, path))
2002
identifier.getSQLPath(path);
2003
2173
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 */