24
24
#include "config.h"
26
#include <drizzled/copy_field.h>
27
#include "drizzled/session.h"
28
#include "drizzled/session/cache.h"
29
#include "drizzled/error.h"
30
#include "drizzled/gettext.h"
31
#include "drizzled/query_id.h"
32
#include "drizzled/data_home.h"
33
#include "drizzled/sql_base.h"
34
#include "drizzled/lock.h"
35
#include "drizzled/item/cache.h"
36
#include "drizzled/item/float.h"
37
#include "drizzled/item/return_int.h"
38
#include "drizzled/item/empty_string.h"
39
#include "drizzled/show.h"
40
#include "drizzled/plugin/client.h"
25
#include <drizzled/session.h>
26
#include "drizzled/session_list.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>
41
40
#include "drizzled/plugin/scheduler.h"
42
41
#include "drizzled/plugin/authentication.h"
43
#include "drizzled/plugin/logging.h"
44
42
#include "drizzled/plugin/transactional_storage_engine.h"
45
#include "drizzled/plugin/query_rewrite.h"
46
43
#include "drizzled/probes.h"
47
44
#include "drizzled/table_proto.h"
48
45
#include "drizzled/db.h"
49
46
#include "drizzled/pthread_globals.h"
50
47
#include "drizzled/transaction_services.h"
51
#include "drizzled/drizzled.h"
53
#include "drizzled/identifier.h"
55
#include <drizzled/refresh_version.h>
57
#include "drizzled/table/singular.h"
59
49
#include "plugin/myisam/myisam.h"
60
50
#include "drizzled/internal/iocache.h"
61
#include "drizzled/internal/thread_var.h"
62
#include "drizzled/plugin/event_observer.h"
64
#include "drizzled/util/functors.h"
66
#include "drizzled/display.h"
68
53
#include <algorithm>
73
#include <boost/filesystem.hpp>
74
#include <boost/checked_delete.hpp>
76
#include "drizzled/util/backtrace.h"
78
56
using namespace std;
80
namespace fs=boost::filesystem;
62
unsigned char *get_var_key(user_var_entry *entry, size_t *length, bool );
63
void free_user_var(user_var_entry *entry);
85
67
The following is used to initialise Table_ident with a internal
89
71
char empty_c_string[1]= {0}; /* used for not defined db */
91
73
const char * const Session::DEFAULT_WHERE= "field list";
74
extern pthread_key_t THR_Session;
75
extern pthread_key_t THR_Mem_root;
76
extern uint32_t max_used_connections;
77
extern atomic<uint32_t> connection_count;
80
/****************************************************************************
82
****************************************************************************/
83
unsigned char *get_var_key(user_var_entry *entry, size_t *length, bool )
85
*length= entry->name.length;
86
return (unsigned char*) entry->name.str;
89
void free_user_var(user_var_entry *entry)
93
94
bool Key_part_spec::operator==(const Key_part_spec& other) const
95
96
return length == other.length &&
96
97
field_name.length == other.field_name.length &&
97
!my_strcasecmp(system_charset_info, field_name.str, other.field_name.str);
98
!strcmp(field_name.str, other.field_name.str);
100
Open_tables_state::Open_tables_state(uint64_t version_arg) :
101
Open_tables_state::Open_tables_state(uint64_t version_arg)
102
:version(version_arg), backups_available(false)
103
open_tables= temporary_tables= derived_tables= NULL;
104
extra_lock= lock= NULL;
104
reset_open_tables_state();
108
108
The following functions form part of the C plugin API
110
int tmpfile(const char *prefix)
110
extern "C" int mysql_tmpfile(const char *prefix)
112
112
char filename[FN_REFLEN];
113
int fd = internal::create_temp_file(filename, drizzle_tmpdir.c_str(), prefix, MYF(MY_WME));
113
int fd = internal::create_temp_file(filename, drizzle_tmpdir, prefix, MYF(MY_WME));
115
115
unlink(filename);
121
void **Session::getEngineData(const plugin::MonitoredInTransaction *monitored)
123
return static_cast<void **>(&ha_data[monitored->getId()].ha_ptr);
126
ResourceContext *Session::getResourceContext(const plugin::MonitoredInTransaction *monitored,
122
int session_tablespace_op(const Session *session)
124
return test(session->tablespace_op);
128
Set the process info field of the Session structure.
130
This function is used by plug-ins. Internally, the
131
Session::set_proc_info() function should be used.
133
@see Session::set_proc_info
136
set_session_proc_info(Session *session, const char *info)
138
session->set_proc_info(info);
142
const char *get_session_proc_info(Session *session)
144
return session->get_proc_info();
147
void **Session::getEngineData(const plugin::StorageEngine *engine)
149
return static_cast<void **>(&ha_data[engine->slot].ha_ptr);
152
ResourceContext *Session::getResourceContext(const plugin::StorageEngine *engine,
129
return &ha_data[monitored->getId()].resource_context[index];
155
return &ha_data[engine->getSlot()].resource_context[index];
132
159
int64_t session_test_options(const Session *session, int64_t test_options)
134
161
return session->options & test_options;
137
Session::Session(plugin::Client *client_arg, catalog::Instance::shared_ptr catalog_arg) :
165
int session_sql_command(const Session *session)
167
return (int) session->lex->sql_command;
171
int session_tx_isolation(const Session *session)
173
return (int) session->variables.tx_isolation;
176
Session::Session(plugin::Client *client_arg)
138
178
Open_tables_state(refresh_version),
139
179
mem_root(&main_mem_root),
142
query(new std::string),
143
_schema(new std::string("")),
144
182
client(client_arg),
146
184
scheduler_arg(NULL),
147
185
lock_id(&main_lock_id),
149
security_ctx(identifier::User::make_shared()),
150
_where(Session::DEFAULT_WHERE),
151
dbug_sentry(Session_SENTRY_MAGIC),
153
command(COM_CONNECT),
155
_epoch(boost::gregorian::date(1970,1,1)),
156
_connect_time(boost::posix_time::microsec_clock::universal_time()),
158
ha_data(plugin::num_trx_monitored_objects),
161
concurrent_execute_allowed(true),
162
187
arg_of_last_insert_id_function(false),
163
188
first_successful_insert_id_in_prev_stmt(0),
164
189
first_successful_insert_id_in_cur_stmt(0),
165
190
limit_found_rows(0),
166
options(session_startup_options),
169
examined_row_count(0),
173
statement_id_counter(0),
177
_global_read_lock(NONE),
178
count_cuted_fields(CHECK_FIELD_ERROR_FOR_NULL),
180
192
some_tables_deleted(false),
181
193
no_errors(false),
183
195
is_fatal_error(false),
184
196
transaction_rollback_request(false),
185
197
is_fatal_sub_stmt_error(0),
198
derived_tables_processing(false),
186
199
tablespace_op(false),
187
derived_tables_processing(false),
190
202
transaction_message(NULL),
191
statement_message(NULL),
192
session_event_observers(NULL),
193
_catalog(catalog_arg),
203
statement_message(NULL)
205
memset(process_list_info, 0, PROCESS_LIST_WIDTH);
196
206
client->setSession(this);
201
211
will be re-initialized in init_for_queries().
203
213
memory::init_sql_alloc(&main_mem_root, memory::ROOT_MIN_BLOCK_SIZE, 0);
215
count_cuted_fields= CHECK_FIELD_IGNORE;
204
220
cuted_fields= sent_row_count= row_count= 0L;
222
statement_id_counter= 0UL;
205
223
// Must be reset to handle error with Session's created for init of mysqld
206
224
lex->current_select= 0;
225
start_time=(time_t) 0;
227
utime_after_lock= 0L;
207
228
memset(&variables, 0, sizeof(variables));
208
scoreboard_index= -1;
209
cleanup_done= abort_on_warning= no_warnings_for_error= false;
211
/* query_cache init */
233
memset(ha_data, 0, sizeof(ha_data));
235
dbug_sentry=Session_SENTRY_MAGIC;
236
cleanup_done= abort_on_warning= no_warnings_for_error= false;
237
pthread_mutex_init(&LOCK_delete, MY_MUTEX_INIT_FAST);
215
239
/* Variables with default values */
216
240
proc_info="login";
241
where= Session::DEFAULT_WHERE;
242
command= COM_CONNECT;
218
244
plugin_sessionvar_init(this);
234
261
session_tx_isolation= (enum_tx_isolation) variables.tx_isolation;
235
262
warn_list.empty();
236
263
memset(warn_count, 0, sizeof(warn_count));
237
265
memset(&status_var, 0, sizeof(status_var));
239
267
/* Initialize sub structures */
240
268
memory::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);
242
273
substitute_null_with_insert_id = false;
243
lock_info.init(); /* safety: will be reset after start */
274
thr_lock_info_init(&lock_info); /* safety: will be reset after start */
244
275
thr_lock_owner_init(&main_lock_id, &lock_info);
246
277
m_internal_handler= NULL;
248
plugin::EventObserver::registerSessionEvents(*this);
251
280
void Session::free_items()
280
309
return false; // 'false', as per coding style
283
void Session::setAbort(bool arg)
285
mysys_var->abort= arg;
288
void Session::lockOnSys()
294
boost_unique_lock_t scopedLock(mysys_var->mutex);
295
if (mysys_var->current_cond)
297
mysys_var->current_mutex->lock();
298
mysys_var->current_cond->notify_all();
299
mysys_var->current_mutex->unlock();
303
312
void Session::pop_internal_handler()
305
314
assert(m_internal_handler != NULL);
306
315
m_internal_handler= NULL;
309
void Session::get_xid(DRIZZLE_XID *xid)
311
*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)
314
356
/* Do operations that may take a long time */
328
370
TransactionServices &transaction_services= TransactionServices::singleton();
329
transaction_services.rollbackTransaction(*this, true);
371
transaction_services.ha_rollback_trans(this, true);
330
372
xid_cache_delete(&transaction.xid_state);
333
for (UserVars::iterator iter= user_vars.begin();
334
iter != user_vars.end();
337
user_var_entry *entry= (*iter).second;
338
boost::checked_delete(entry);
374
hash_free(&user_vars);
343
375
close_temporary_tables();
345
377
if (global_read_lock)
347
unlockGlobalReadLock();
378
unlock_global_read_lock(this);
350
380
cleanup_done= true;
353
383
Session::~Session()
385
Session_CHECK_SENTRY(this);
386
add_to_status(&global_status_var, &status_var);
357
if (client and client->isConnected())
388
if (client->isConnected())
359
assert(security_ctx);
360
390
if (global_system_variables.log_warnings)
362
errmsg_printf(error::WARN, ER(ER_FORCING_CLOSE),
363
internal::my_progname,
365
security_ctx->username().c_str());
391
errmsg_printf(ERRMSG_LVL_WARN, ER(ER_FORCING_CLOSE),internal::my_progname,
393
(getSecurityContext().getUser().c_str() ?
394
getSecurityContext().getUser().c_str() : ""));
395
disconnect(0, false);
371
398
/* Close connection */
375
boost::checked_delete(client);
379
402
if (cleanup_done == false)
382
405
plugin::StorageEngine::closeConnection(this);
383
406
plugin_sessionvar_cleanup(this);
385
warn_root.free_root(MYF(0));
408
free_root(&warn_root,MYF(0));
386
409
mysys_var=0; // Safety (shouldn't be needed)
387
410
dbug_sentry= Session_SENTRY_GONE;
389
main_mem_root.free_root(MYF(0));
390
currentMemRoot().release();
391
currentSession().release();
393
plugin::Logging::postEndDo(this);
394
plugin::EventObserver::deregisterSessionEvents(*this);
397
void Session::setClient(plugin::Client *client_arg)
400
client->setSession(this);
403
void Session::awake(Session::killed_state_t state_to_set)
405
if ((state_to_set == Session::KILL_QUERY) and (command == COM_SLEEP))
410
setKilled(state_to_set);
411
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(system_status_var *to_var, system_status_var *from_var)
436
ulong *end= (ulong*) ((unsigned char*) to_var +
437
offsetof(system_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(system_status_var *to_var, system_status_var *from_var,
458
system_status_var *dec_var)
460
ulong *end= (ulong*) ((unsigned char*) to_var + offsetof(system_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;
413
475
if (state_to_set != Session::KILL_QUERY)
477
scheduler->killSession(this);
415
478
DRIZZLE_CONNECTION_DONE(thread_id);
420
boost_unique_lock_t scopedLock(mysys_var->mutex);
482
pthread_mutex_lock(&mysys_var->mutex);
423
484
This broadcast could be up in the air if the victim thread
424
485
exits the cond in the time between read and broadcast, but that is
425
486
ok since all we want to do is to make the victim thread get out
522
580
if (initGlobals() || authenticate())
528
586
prepareForQueries();
530
while (not client->haveError() && getKilled() != KILL_CONNECTION)
588
while (! client->haveError() && killed != KILL_CONNECTION)
532
if (not executeStatement())
590
if (! executeStatement())
539
bool Session::schedule(Session::shared_ptr &arg)
597
bool Session::schedule()
541
arg->scheduler= plugin::Scheduler::getScheduler();
542
assert(arg->scheduler);
546
long current_connections= connection_count;
548
if (current_connections > 0 and static_cast<uint64_t>(current_connections) > current_global_counters.max_used_connections)
550
current_global_counters.max_used_connections= static_cast<uint64_t>(connection_count);
553
current_global_counters.connections++;
554
arg->thread_id= arg->variables.pseudo_thread_id= global_thread_id++;
556
session::Cache::singleton().insert(arg);
558
if (unlikely(plugin::EventObserver::connectSession(*arg)))
560
// We should do something about an error...
563
if (plugin::Scheduler::getScheduler()->addSession(arg))
565
DRIZZLE_CONNECTION_START(arg->getSessionId());
599
scheduler= plugin::Scheduler::getScheduler();
602
connection_count.increment();
604
if (connection_count > max_used_connections)
605
max_used_connections= connection_count;
607
thread_id= variables.pseudo_thread_id= global_thread_id++;
609
pthread_mutex_lock(&LOCK_thread_count);
610
getSessionList().push_back(this);
611
pthread_mutex_unlock(&LOCK_thread_count);
613
if (scheduler->addSession(this))
615
DRIZZLE_CONNECTION_START(thread_id);
566
616
char error_message_buff[DRIZZLE_ERRMSG_SIZE];
568
arg->setKilled(Session::KILL_CONNECTION);
618
killed= Session::KILL_CONNECTION;
570
arg->status_var.aborted_connects++;
620
statistic_increment(aborted_connects, &LOCK_status);
572
622
/* Can't use my_error() since store_globals has not been called. */
573
623
/* TODO replace will better error message */
574
624
snprintf(error_message_buff, sizeof(error_message_buff),
575
625
ER(ER_CANT_CREATE_THREAD), 1);
576
arg->client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
626
client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
609
651
locked (if that would not be the case, you'll get a deadlock if someone
610
652
does a Session::awake() on you).
612
mysys_var->current_mutex->unlock();
613
boost_unique_lock_t scopedLock(mysys_var->mutex);
654
pthread_mutex_unlock(mysys_var->current_mutex);
655
pthread_mutex_lock(&mysys_var->mutex);
614
656
mysys_var->current_mutex = 0;
615
657
mysys_var->current_cond = 0;
616
658
this->set_proc_info(old_msg);
659
pthread_mutex_unlock(&mysys_var->mutex);
619
662
bool Session::authenticate()
621
665
if (client->authenticate())
624
status_var.aborted_connects++;
668
statistic_increment(aborted_connects, &LOCK_status);
629
bool Session::checkUser(const std::string &passwd_str,
630
const std::string &in_db)
672
bool Session::checkUser(const char *passwd, uint32_t passwd_len, const char *in_db)
632
bool is_authenticated=
633
plugin::Authentication::isAuthenticated(user(), passwd_str);
674
LEX_STRING db_str= { (char *) in_db, in_db ? strlen(in_db) : 0 };
675
bool is_authenticated;
677
if (passwd_len != 0 && passwd_len != SCRAMBLE_LENGTH)
679
my_error(ER_HANDSHAKE_ERROR, MYF(0), getSecurityContext().getIp().c_str());
683
is_authenticated= plugin::Authentication::isAuthenticated(this, passwd);
635
685
if (is_authenticated != true)
637
status_var.access_denied++;
638
/* isAuthenticated has pushed the error message */
687
my_error(ER_ACCESS_DENIED_ERROR, MYF(0),
688
getSecurityContext().getUser().c_str(),
689
getSecurityContext().getIp().c_str(),
690
passwd_len ? ER(ER_YES) : ER(ER_NO));
642
695
/* Change database if necessary */
643
if (not in_db.empty())
696
if (in_db && in_db[0])
645
identifier::Schema identifier(in_db);
646
if (change_db(this, identifier))
698
if (mysql_change_db(this, &db_str, false))
648
/* change_db() has pushed the error message. */
700
/* mysql_change_db() has pushed the error message. */
653
password= not passwd_str.empty();
705
password= test(passwd_len); // remember for error messages
655
707
/* Ready to handle queries */
1014
static int create_file(Session *session,
1015
fs::path &target_path,
1016
file_exchange *exchange,
1017
internal::IO_CACHE *cache)
1050
static int create_file(Session *session, char *path, file_exchange *exchange, internal::IO_CACHE *cache)
1019
fs::path to_file(exchange->file_name);
1022
if (not to_file.has_root_directory())
1053
uint32_t option= MY_UNPACK_FILENAME | MY_RELATIVE_PATH;
1055
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
1056
option|= MY_REPLACE_DIR; // Force use of db directory
1059
if (!internal::dirname_length(exchange->file_name))
1024
target_path= fs::system_complete(getDataHomeCatalog());
1025
util::string::const_shared_ptr schema(session->schema());
1026
if (schema and not schema->empty())
1028
int count_elements= 0;
1029
for (fs::path::iterator iter= to_file.begin();
1030
iter != to_file.end();
1031
++iter, ++count_elements)
1034
if (count_elements == 1)
1036
target_path /= *schema;
1039
target_path /= to_file;
1061
strcpy(path, drizzle_real_data_home);
1062
if (! session->db.empty())
1063
strncat(path, session->db.c_str(), FN_REFLEN-strlen(drizzle_real_data_home)-1);
1064
(void) internal::fn_format(path, exchange->file_name, path, "", option);
1043
target_path = exchange->file_name;
1046
if (not secure_file_priv.string().empty())
1048
if (target_path.file_string().substr(0, secure_file_priv.file_string().size()) != secure_file_priv.file_string())
1050
/* Write only allowed to dir or subdir specified by secure_file_priv */
1051
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
1056
if (!access(target_path.file_string().c_str(), F_OK))
1067
(void) internal::fn_format(path, exchange->file_name, drizzle_real_data_home, "", option);
1069
if (opt_secure_file_priv &&
1070
strncmp(opt_secure_file_priv, path, strlen(opt_secure_file_priv)))
1072
/* Write only allowed to dir or subdir specified by secure_file_priv */
1073
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
1077
if (!access(path, F_OK))
1058
1079
my_error(ER_FILE_EXISTS_ERROR, MYF(0), exchange->file_name);
1061
1082
/* Create the file world readable */
1062
if ((file= internal::my_create(target_path.file_string().c_str(), 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
1083
if ((file= internal::my_create(path, 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
1064
1085
(void) fchmod(file, 0666); // Because of umask()
1065
if (cache->init_io_cache(file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1086
if (init_io_cache(cache, file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1067
1088
internal::my_close(file, MYF(0));
1068
internal::my_delete(target_path.file_string().c_str(), MYF(0)); // Delete file on error, it was just created
1089
internal::my_delete(path, MYF(0)); // Delete file on error, it was just created
1480
1505
bool select_max_min_finder_subselect::cmp_decimal()
1482
1507
Item *maxmin= ((Item_singlerow_subselect *)item)->element_index(0);
1483
type::Decimal cval, *cvalue= cache->val_decimal(&cval);
1484
type::Decimal mval, *mvalue= maxmin->val_decimal(&mval);
1508
my_decimal cval, *cvalue= cache->val_decimal(&cval);
1509
my_decimal mval, *mvalue= maxmin->val_decimal(&mval);
1486
1511
return (cache->null_value && !maxmin->null_value) ||
1487
1512
(!cache->null_value && !maxmin->null_value &&
1488
class_decimal_cmp(cvalue, mvalue) > 0) ;
1513
my_decimal_cmp(cvalue, mvalue) > 0) ;
1489
1514
return (maxmin->null_value && !cache->null_value) ||
1490
1515
(!cache->null_value && !maxmin->null_value &&
1491
class_decimal_cmp(cvalue,mvalue) < 0);
1516
my_decimal_cmp(cvalue,mvalue) < 0);
1494
1519
bool select_max_min_finder_subselect::cmp_str()
1595
void Session::set_db(const std::string &new_db)
1609
/****************************************************************************
1610
Handling of open and locked tables states.
1612
This is used when we want to open/lock (and then close) some tables when
1613
we already have a set of tables open and locked. We use these methods for
1614
access to mysql.proc table to find definitions of stored routines.
1615
****************************************************************************/
1617
void Session::reset_n_backup_open_tables_state(Open_tables_state *backup)
1619
backup->set_open_tables_state(this);
1620
reset_open_tables_state();
1621
backups_available= false;
1625
void Session::restore_backup_open_tables_state(Open_tables_state *backup)
1628
Before we will throw away current open tables state we want
1629
to be sure that it was properly cleaned up.
1631
assert(open_tables == 0 && temporary_tables == 0 &&
1632
derived_tables == 0 &&
1634
set_open_tables_state(backup);
1637
bool Session::set_db(const char *new_db, size_t length)
1597
1639
/* Do not reallocate memory if current chunk is big enough. */
1598
if (new_db.length())
1600
_schema.reset(new std::string(new_db));
1604
_schema.reset(new std::string(""));
1652
Check the killed state of a user thread
1653
@param session user thread
1654
@retval 0 the user thread is active
1655
@retval 1 the user thread has been killed
1657
extern "C" int session_killed(const Session *session)
1659
return(session->killed);
1663
Return the session id of a user session
1664
@param pointer to Session object
1665
@return session's id
1667
extern "C" unsigned long session_get_thread_id(const Session *session)
1669
return (unsigned long) session->getSessionId();
1673
const struct charset_info_st *session_charset(Session *session)
1675
return(session->charset());
1678
int session_non_transactional_update(const Session *session)
1680
return(session->transaction.all.hasModifiedNonTransData());
1683
void session_mark_transaction_to_rollback(Session *session, bool all)
1685
mark_transaction_to_rollback(session, all);
1610
1689
Mark transaction to rollback and mark error as fatal to a sub-statement.
1612
1691
@param session Thread handle
1613
1692
@param all true <=> rollback main transaction.
1615
void Session::markTransactionForRollback(bool all)
1694
void mark_transaction_to_rollback(Session *session, bool all)
1617
is_fatal_sub_stmt_error= true;
1618
transaction_rollback_request= all;
1698
session->is_fatal_sub_stmt_error= true;
1699
session->transaction_rollback_request= all;
1621
void Session::disconnect(enum error_t errcode)
1703
void Session::disconnect(uint32_t errcode, bool should_lock)
1623
1705
/* Allow any plugins to cleanup their session variables */
1624
1706
plugin_sessionvar_cleanup(this);
1626
1708
/* If necessary, log any aborted or unauthorized connections */
1627
if (getKilled() || client->wasAborted())
1629
status_var.aborted_threads++;
1709
if (killed || client->wasAborted())
1710
statistic_increment(aborted_threads, &LOCK_status);
1632
1712
if (client->wasAborted())
1634
if (not getKilled() && variables.log_warnings > 1)
1714
if (! killed && variables.log_warnings > 1)
1636
errmsg_printf(error::WARN, ER(ER_NEW_ABORTING_CONNECTION)
1716
SecurityContext *sctx= &security_ctx;
1718
errmsg_printf(ERRMSG_LVL_WARN, ER(ER_NEW_ABORTING_CONNECTION)
1638
, (_schema->empty() ? "unconnected" : _schema->c_str())
1639
, security_ctx->username().empty() == false ? security_ctx->username().c_str() : "unauthenticated"
1640
, security_ctx->address().c_str()
1720
, (db.empty() ? "unconnected" : db.c_str())
1721
, sctx->getUser().empty() == false ? sctx->getUser().c_str() : "unauthenticated"
1722
, sctx->getIp().c_str()
1641
1723
, (main_da.is_error() ? main_da.message() : ER(ER_UNKNOWN_ERROR)));
1645
setKilled(Session::KILL_CONNECTION);
1727
/* Close out our connection to the client */
1729
(void) pthread_mutex_lock(&LOCK_thread_count);
1730
killed= Session::KILL_CONNECTION;
1647
1731
if (client->isConnected())
1649
if (errcode != EE_OK)
1651
1735
/*my_error(errcode, ER(errcode));*/
1652
1736
client->sendError(errcode, ER(errcode));
1654
1738
client->close();
1741
(void) pthread_mutex_unlock(&LOCK_thread_count);
1658
1744
void Session::reset_for_next_command()
1719
1803
passing non-zero value to end_slave via rli->save_temporary_tables
1720
1804
when no temp tables opened, see an invariant below.
1722
temporary_tables= table->getNext();
1806
temporary_tables= table->next;
1723
1807
if (temporary_tables)
1725
table->getNext()->setPrev(NULL);
1808
table->next->prev= NULL;
1810
close_temporary(table);
1732
Close and drop a temporary table
1814
Close and delete a temporary table
1735
1817
This dosn't unlink table from session->temporary
1736
1818
If this is needed, use close_temporary_table()
1739
void Open_tables_state::nukeTable(Table *table)
1821
void Session::close_temporary(Table *table)
1741
plugin::StorageEngine *table_type= table->getShare()->db_type();
1823
plugin::StorageEngine *table_type= table->s->db_type();
1743
1825
table->free_io_cache();
1744
table->delete_table();
1746
identifier::Table identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName(), table->getShare()->getPath());
1747
rm_temporary_table(table_type, identifier);
1749
boost::checked_delete(table->getMutableShare());
1751
boost::checked_delete(table);
1826
table->closefrm(false);
1828
rm_temporary_table(table_type, table->s->path.str);
1830
table->s->free_table_share();
1832
/* This makes me sad, but we're allocating it via malloc */
1754
1836
/** Clear most status variables. */
1755
1837
extern time_t flush_status_time;
1838
extern uint32_t max_used_connections;
1757
1840
void Session::refresh_status()
1842
pthread_mutex_lock(&LOCK_status);
1844
/* Add thread's status variabes to global status */
1845
add_to_status(&global_status_var, &status_var);
1759
1847
/* Reset thread's status variables */
1760
1848
memset(&status_var, 0, sizeof(status_var));
1850
/* Reset some global variables */
1851
reset_status_vars();
1853
/* Reset the counters of all key caches (default and named). */
1854
reset_key_cache_counters();
1762
1855
flush_status_time= time((time_t*) 0);
1763
current_global_counters.max_used_connections= 1; /* We set it to one, because we know we exist */
1764
current_global_counters.connections= 0;
1856
max_used_connections= 1; /* We set it to one, because we know we exist */
1857
pthread_mutex_unlock(&LOCK_status);
1767
1860
user_var_entry *Session::getVariable(LEX_STRING &name, bool create_if_not_exists)
1769
return getVariable(std::string(name.str, name.length), create_if_not_exists);
1772
user_var_entry *Session::getVariable(const std::string &name, bool create_if_not_exists)
1777
UserVars::iterator iter= user_vars.find(name);
1778
if (iter != user_vars.end())
1779
return (*iter).second;
1781
if (not create_if_not_exists)
1784
1862
user_var_entry *entry= NULL;
1785
entry= new (nothrow) user_var_entry(name.c_str(), query_id);
1790
std::pair<UserVars::iterator, bool> returnable= user_vars.insert(make_pair(name, entry));
1792
if (not returnable.second)
1864
entry= (user_var_entry*) hash_search(&user_vars, (unsigned char*) name.str, name.length);
1866
if ((entry == NULL) && create_if_not_exists)
1794
boost::checked_delete(entry);
1868
if (!hash_inited(&user_vars))
1870
entry= new (nothrow) user_var_entry(name.str, query_id);
1875
if (my_hash_insert(&user_vars, (unsigned char*) entry))
1878
free((char*) entry);
1800
void Session::setVariable(const std::string &name, const std::string &value)
1802
user_var_entry *updateable_var= getVariable(name.c_str(), true);
1805
updateable_var->update_hash(false,
1806
(void*)value.c_str(),
1807
static_cast<uint32_t>(value.length()), STRING_RESULT,
1809
DERIVATION_IMPLICIT, false);
1813
void Open_tables_state::mark_temp_tables_as_free_for_reuse()
1815
for (Table *table= temporary_tables ; table ; table= table->getNext())
1817
if (table->query_id == getQueryId())
1887
void Session::mark_temp_tables_as_free_for_reuse()
1889
for (Table *table= temporary_tables ; table ; table= table->next)
1891
if (table->query_id == query_id)
1819
1893
table->query_id= 0;
1820
1894
table->cursor->ha_reset();
1916
2017
if (open_tables_from_list(&tables, &counter))
1919
if (not lock_tables(tables, counter, &need_reopen))
2020
if (!lock_tables(tables, counter, &need_reopen))
1922
if (not need_reopen)
1925
2024
close_tables_for_reopen(&tables);
1928
if ((handle_derived(lex, &derived_prepare) || (handle_derived(lex, &derived_filling))))
1935
@note "best_effort" is used in cases were if a failure occurred on this
1936
operation it would not be surprising because we are only removing because there
1937
might be an issue (lame engines).
1940
bool Open_tables_state::rm_temporary_table(const identifier::Table &identifier, bool best_effort)
1942
if (not plugin::StorageEngine::dropTable(*static_cast<Session *>(this), identifier))
1944
if (not best_effort)
1947
identifier.getSQLPath(path);
1948
errmsg_printf(error::WARN, _("Could not remove temporary table: '%s', error: %d"),
1949
path.c_str(), errno);
1958
bool Open_tables_state::rm_temporary_table(plugin::StorageEngine *base, const identifier::Table &identifier)
1960
drizzled::error_t error;
1963
if (not plugin::StorageEngine::dropTable(*static_cast<Session *>(this), *base, identifier, error))
1966
identifier.getSQLPath(path);
1967
errmsg_printf(error::WARN, _("Could not remove temporary table: '%s', error: %d"),
1968
path.c_str(), error);
1977
@note this will be removed, I am looking through Hudson to see if it is finding
1978
any tables that are missed during cleanup.
1980
void Open_tables_state::dumpTemporaryTableNames(const char *foo)
1984
if (not temporary_tables)
1987
cerr << "Begin Run: " << foo << "\n";
1988
for (table= temporary_tables; table; table= table->getNext())
1990
bool have_proto= false;
1992
message::Table *proto= table->getShare()->getTableMessage();
1993
if (table->getShare()->getTableMessage())
1996
const char *answer= have_proto ? "true" : "false";
2000
cerr << "\tTable Name " << table->getShare()->getSchemaName() << "." << table->getShare()->getTableName() << " : " << answer << "\n";
2001
cerr << "\t\t Proto " << proto->schema() << " " << proto->name() << "\n";
2005
cerr << "\tTabl;e Name " << table->getShare()->getSchemaName() << "." << table->getShare()->getTableName() << " : " << answer << "\n";
2010
table::Singular *Session::getInstanceTable()
2012
temporary_shares.push_back(new table::Singular()); // This will not go into the tableshare cache, so no key is used.
2014
table::Singular *tmp_share= temporary_shares.back();
2023
Create a reduced Table object with properly set up Field list from a
2024
list of field definitions.
2026
The created table doesn't have a table Cursor associated with
2027
it, has no keys, no group/distinct, no copy_funcs array.
2028
The sole purpose of this Table object is to use the power of Field
2029
class to read/write data to/from table->getInsertRecord(). Then one can store
2030
the record in any container (RB tree, hash, etc).
2031
The table is created in Session mem_root, so are the table's fields.
2032
Consequently, if you don't BLOB fields, you don't need to free it.
2034
@param session connection handle
2035
@param field_list list of column definitions
2038
0 if out of memory, Table object in case of success
2040
table::Singular *Session::getInstanceTable(List<CreateField> &field_list)
2042
temporary_shares.push_back(new table::Singular(this, field_list)); // This will not go into the tableshare cache, so no key is used.
2044
table::Singular *tmp_share= temporary_shares.back();
2053
static const std::string NONE= "NONE";
2054
static const std::string GOT_GLOBAL_READ_LOCK= "HAS GLOBAL READ LOCK";
2055
static const std::string MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT= "HAS GLOBAL READ LOCK WITH BLOCKING COMMIT";
2057
const std::string &type(drizzled::Session::global_read_lock_t type)
2063
case Session::GOT_GLOBAL_READ_LOCK:
2064
return GOT_GLOBAL_READ_LOCK;
2065
case Session::MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT:
2066
return MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT;
2070
size_t max_string_length(drizzled::Session::global_read_lock_t)
2072
return MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT.size();
2075
} /* namespace display */
2026
if ((mysql_handle_derived(lex, &mysql_derived_prepare) ||
2027
(fill_derived_tables() &&
2028
mysql_handle_derived(lex, &mysql_derived_filling))))
2034
bool Session::openTables(TableList *tables, uint32_t flags)
2037
bool ret= fill_derived_tables();
2038
assert(ret == false);
2039
if (open_tables_from_list(&tables, &counter, flags) ||
2040
mysql_handle_derived(lex, &mysql_derived_prepare))
2045
bool Session::rm_temporary_table(plugin::StorageEngine *base, TableIdentifier &identifier)
2051
if (plugin::StorageEngine::deleteDefinitionFromPath(identifier))
2054
if (base->doDropTable(*this, identifier.getPath()))
2057
errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
2058
identifier.getPath(), errno);
2063
bool Session::rm_temporary_table(plugin::StorageEngine *base, const char *path)
2069
if (delete_table_proto_file(path))
2072
if (base->doDropTable(*this, path))
2075
errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
2077
2081
} /* namespace drizzled */