17
17
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
* @file Implementation of the Session class and API
25
#include "drizzled/session.h"
26
#include "drizzled/session/cache.h"
20
#include <drizzled/server_includes.h>
21
#include <drizzled/session.h>
27
22
#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"
40
#include "drizzled/plugin/scheduler.h"
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
#include "drizzled/probes.h"
46
#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"
66
#include <boost/filesystem.hpp>
68
#include "drizzled/util/backtrace.h"
72
namespace fs=boost::filesystem;
23
#include <mysys/mysys_err.h>
24
#include <drizzled/error.h>
25
#include <drizzled/query_id.h>
26
#include <drizzled/data_home.h>
27
#include <drizzled/sql_base.h>
28
#include <drizzled/lock.h>
29
#include <drizzled/item/cache.h>
30
#include <drizzled/item/float.h>
31
#include <drizzled/item/return_int.h>
32
#include <drizzled/item/empty_string.h>
33
#include <drizzled/show.h>
34
#include <drizzled/scheduling.h>
77
37
The following is used to initialise Table_ident with a internal
81
41
char empty_c_string[1]= {0}; /* used for not defined db */
83
43
const char * const Session::DEFAULT_WHERE= "field list";
44
extern pthread_key_t THR_Session;
45
extern pthread_key_t THR_Mem_root;
47
/*****************************************************************************
48
** Instansiate templates
49
*****************************************************************************/
51
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
53
template class List<Key>;
54
template class List_iterator<Key>;
55
template class List<Key_part_spec>;
56
template class List_iterator<Key_part_spec>;
57
template class List<Alter_drop>;
58
template class List_iterator<Alter_drop>;
59
template class List<Alter_column>;
60
template class List_iterator<Alter_column>;
63
/****************************************************************************
65
****************************************************************************/
66
extern "C" unsigned char *get_var_key(user_var_entry *entry, size_t *length,
69
*length= entry->name.length;
70
return (unsigned char*) entry->name.str;
73
extern "C" void free_user_var(user_var_entry *entry)
75
char *pos= (char*) entry+ALIGN_SIZE(sizeof(*entry));
76
if (entry->value && entry->value != pos)
85
81
bool Key_part_spec::operator==(const Key_part_spec& other) const
87
83
return length == other.length &&
88
84
field_name.length == other.field_name.length &&
89
!my_strcasecmp(system_charset_info, field_name.str, other.field_name.str);
85
!strcmp(field_name.str, other.field_name.str);
92
Open_tables_state::Open_tables_state(uint64_t version_arg) :
88
/****************************************************************************
89
** Thread specific functions
90
****************************************************************************/
92
Open_tables_state::Open_tables_state(ulong version_arg)
93
:version(version_arg), state_flags(0U)
95
open_tables= temporary_tables= derived_tables= NULL;
96
extra_lock= lock= NULL;
95
reset_open_tables_state();
100
99
The following functions form part of the C plugin API
102
int mysql_tmpfile(const char *prefix)
102
extern "C" int mysql_tmpfile(const char *prefix)
104
104
char filename[FN_REFLEN];
105
int fd = internal::create_temp_file(filename, drizzle_tmpdir.c_str(), prefix, MYF(MY_WME));
105
File fd = create_temp_file(filename, drizzle_tmpdir, prefix, MYF(MY_WME));
107
107
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 struct 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) :
163
Open_tables_state(refresh_version),
164
mem_root(&main_mem_root),
167
query(new std::string),
168
_schema(new std::string("")),
173
lock_id(&main_lock_id),
175
ha_data(plugin::num_trx_monitored_objects),
176
concurrent_execute_allowed(true),
177
arg_of_last_insert_id_function(false),
178
first_successful_insert_id_in_prev_stmt(0),
179
first_successful_insert_id_in_cur_stmt(0),
181
_global_read_lock(NONE),
183
some_tables_deleted(false),
186
is_fatal_error(false),
187
transaction_rollback_request(false),
188
is_fatal_sub_stmt_error(0),
189
derived_tables_processing(false),
190
tablespace_op(false),
193
transaction_message(NULL),
194
statement_message(NULL),
195
session_event_observers(NULL),
198
client->setSession(this);
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(Protocol *protocol_arg)
179
:Statement(&main_lex, &main_mem_root,
180
/* statement id */ 0),
181
Open_tables_state(refresh_version),
182
lock_id(&main_lock_id),
184
arg_of_last_insert_id_function(false),
185
first_successful_insert_id_in_prev_stmt(0),
186
first_successful_insert_id_in_cur_stmt(0),
189
transaction_rollback_request(0),
190
is_fatal_sub_stmt_error(0),
192
derived_tables_processing(false),
199
memset(process_list_info, 0, PROCESS_LIST_WIDTH);
201
202
Pass nominal parameters to init_alloc_root only to ensure that
202
203
the destructor works OK in case of an error. The main_mem_root
203
204
will be re-initialized in init_for_queries().
205
memory::init_sql_alloc(&main_mem_root, memory::ROOT_MIN_BLOCK_SIZE, 0);
207
count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
206
init_sql_alloc(&main_mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
208
catalog= (char*)"std"; // the only catalog we have for now
209
some_tables_deleted=no_errors=password= 0;
210
count_cuted_fields= CHECK_FIELD_IGNORE;
211
215
cuted_fields= sent_row_count= row_count= 0L;
212
217
row_count_func= -1;
213
218
statement_id_counter= 0UL;
214
219
// Must be reset to handle error with Session's created for init of mysqld
251
258
options &= ~OPTION_BIG_SELECTS;
260
transaction.all.modified_non_trans_table= transaction.stmt.modified_non_trans_table= false;
253
261
open_options=ha_open_options;
254
262
update_lock_default= TL_WRITE;
255
263
session_tx_isolation= (enum_tx_isolation) variables.tx_isolation;
256
264
warn_list.empty();
257
265
memset(warn_count, 0, sizeof(warn_count));
258
266
total_warn_count= 0;
259
268
memset(&status_var, 0, sizeof(status_var));
261
272
/* Initialize sub structures */
262
memory::init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
273
init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
274
hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
275
(hash_get_key) get_var_key,
276
(hash_free_key) free_user_var, 0);
279
protocol= protocol_arg;
280
protocol->setSession(this);
282
const Query_id& local_query_id= Query_id::get_query_id();
283
tablespace_op= false;
285
protocol->setRandom(tmp + (uint64_t) &protocol,
286
tmp + (uint64_t)local_query_id.value());
264
287
substitute_null_with_insert_id = false;
265
lock_info.init(); /* safety: will be reset after start */
288
thr_lock_info_init(&lock_info); /* safety: will be reset after start */
266
289
thr_lock_owner_init(&main_lock_id, &lock_info);
268
291
m_internal_handler= NULL;
270
plugin::EventObserver::registerSessionEvents(*this);
273
void Session::free_items()
276
/* This works because items are allocated with memory::sql_alloc() */
277
for (; free_list; free_list= next)
279
next= free_list->next;
280
free_list->delete_self();
284
295
void Session::push_internal_handler(Internal_error_handler *handler)
328
321
m_internal_handler= NULL;
331
void Session::get_xid(DRIZZLE_XID *xid)
333
*xid = *(DRIZZLE_XID *) &transaction.xid_state.xid;
324
#if defined(__cplusplus)
328
void *session_alloc(Session *session, unsigned int size)
330
return session->alloc(size);
333
void *session_calloc(Session *session, unsigned int size)
335
return session->calloc(size);
338
char *session_strdup(Session *session, const char *str)
340
return session->strdup(str);
343
char *session_strmake(Session *session, const char *str, unsigned int size)
345
return session->strmake(str, size);
348
void *session_memdup(Session *session, const void* str, unsigned int size)
350
return session->memdup(str, size);
353
void session_get_xid(const Session *session, DRIZZLE_XID *xid)
355
*xid = *(DRIZZLE_XID *) &session->transaction.xid_state.xid;
358
#if defined(__cplusplus)
363
Init Session for query processing.
364
This has to be called once before we call mysql_parse.
365
See also comments in session.h.
368
void Session::init_for_queries()
371
ha_enable_transaction(this,true);
373
reset_root_defaults(mem_root, variables.query_alloc_block_size,
374
variables.query_prealloc_size);
375
reset_root_defaults(&transaction.mem_root,
376
variables.trans_alloc_block_size,
377
variables.trans_prealloc_size);
378
transaction.xid_state.xid.null();
379
transaction.xid_state.in_session=1;
336
383
/* Do operations that may take a long time */
350
TransactionServices &transaction_services= TransactionServices::singleton();
351
transaction_services.rollbackTransaction(this, true);
352
398
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;
402
lock=locked_tables; locked_tables=0;
403
close_thread_tables();
405
hash_free(&user_vars);
365
406
close_temporary_tables();
367
408
if (global_read_lock)
369
unlockGlobalReadLock();
409
unlock_global_read_lock(this);
372
411
cleanup_done= true;
375
414
Session::~Session()
416
Session_CHECK_SENTRY(this);
417
add_to_status(&global_status_var, &status_var);
379
if (client->isConnected())
419
if (protocol->isConnected())
381
421
if (global_system_variables.log_warnings)
382
errmsg_printf(ERRMSG_LVL_WARN, ER(ER_FORCING_CLOSE),internal::my_progname,
422
errmsg_printf(ERRMSG_LVL_WARN, ER(ER_FORCING_CLOSE),my_progname,
384
(getSecurityContext().getUser().c_str() ?
385
getSecurityContext().getUser().c_str() : ""));
424
(security_ctx.user.c_str() ?
425
security_ctx.user.c_str() : ""));
386
426
disconnect(0, false);
389
429
/* Close connection */
393
433
if (cleanup_done == false)
396
plugin::StorageEngine::closeConnection(this);
436
ha_close_connection(this);
397
437
plugin_sessionvar_cleanup(this);
399
warn_root.free_root(MYF(0));
444
free_root(&warn_root,MYF(0));
445
free_root(&transaction.mem_root,MYF(0));
400
446
mysys_var=0; // Safety (shouldn't be needed)
401
447
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);
449
free_root(&main_mem_root, MYF(0));
450
pthread_setspecific(THR_Session, 0);
453
/* Ensure that no one is using Session */
454
pthread_mutex_unlock(&LOCK_delete);
455
pthread_mutex_destroy(&LOCK_delete);
460
Add all status variables to another status variable array
464
to_var add to this array
465
from_var from this array
468
This function assumes that all variables are long/ulong.
469
If this assumption will change, then we have to explictely add
470
the other variables after the while loop
473
void add_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var)
475
ulong *end= (ulong*) ((unsigned char*) to_var +
476
offsetof(STATUS_VAR, last_system_status_var) +
478
ulong *to= (ulong*) to_var, *from= (ulong*) from_var;
485
Add the difference between two status variable arrays to another one.
489
to_var add to this array
490
from_var from this array
491
dec_var minus this array
494
This function assumes that all variables are long/ulong.
497
void add_diff_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var,
500
ulong *end= (ulong*) ((unsigned char*) to_var + offsetof(STATUS_VAR,
501
last_system_status_var) +
503
ulong *to= (ulong*) to_var, *from= (ulong*) from_var, *dec= (ulong*) dec_var;
506
*(to++)+= *(from++) - *(dec++);
510
void Session::awake(Session::killed_state state_to_set)
512
Session_CHECK_SENTRY(this);
513
safe_mutex_assert_owner(&LOCK_delete);
514
Scheduler &thread_scheduler= get_thread_scheduler();
516
killed= state_to_set;
433
517
if (state_to_set != Session::KILL_QUERY)
435
DRIZZLE_CONNECTION_DONE(thread_id);
519
thread_scheduler.post_kill_notification(this);
440
boost_unique_lock_t scopedLock(mysys_var->mutex);
523
pthread_mutex_lock(&mysys_var->mutex);
443
525
This broadcast could be up in the air if the victim thread
444
526
exits the cond in the time between read and broadcast, but that is
445
527
ok since all we want to do is to make the victim thread get out
492
572
This allows us to move Session to different threads if needed.
494
574
mysys_var->id= thread_id;
575
real_id= pthread_self(); // For debugging
497
578
We have to call thr_lock_info_init() again here as Session may have been
498
579
created in another thread
581
thr_lock_info_init(&lock_info);
506
Init Session for query processing.
507
This has to be called once before we call mysql_parse.
508
See also comments in session.h.
511
585
void Session::prepareForQueries()
513
587
if (variables.max_join_size == HA_POS_ERROR)
514
588
options |= OPTION_BIG_SELECTS;
589
if (client_capabilities & CLIENT_COMPRESS)
592
protocol->enableCompression();
516
595
version= refresh_version;
517
596
set_proc_info(NULL);
518
597
command= COM_SLEEP;
521
mem_root->reset_root_defaults(variables.query_alloc_block_size,
522
variables.query_prealloc_size);
523
transaction.xid_state.xid.null();
524
transaction.xid_state.in_session=1;
529
602
bool Session::initGlobals()
533
606
disconnect(ER_OUT_OF_RESOURCES, true);
534
status_var.aborted_connects++;
542
if (initGlobals() || authenticate())
550
while (not client->haveError() && getKilled() != KILL_CONNECTION)
552
if (not executeStatement())
559
bool Session::schedule(Session::shared_ptr &arg)
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());
584
char error_message_buff[DRIZZLE_ERRMSG_SIZE];
586
arg->setKilled(Session::KILL_CONNECTION);
588
arg->status_var.aborted_connects++;
590
/* Can't use my_error() since store_globals has not been called. */
591
/* TODO replace will better error message */
592
snprintf(error_message_buff, sizeof(error_message_buff),
593
ER(ER_CANT_CREATE_THREAD), 1);
594
arg->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);
607
statistic_increment(aborted_connects, &LOCK_status);
608
Scheduler &thread_scheduler= get_thread_scheduler();
609
thread_scheduler.end_thread(this, 0);
639
615
bool Session::authenticate()
642
if (client->authenticate())
618
if (protocol->authenticate())
621
statistic_increment(aborted_connects, &LOCK_status);
625
bool Session::checkUser(const char *passwd, uint32_t passwd_len, const char *in_db)
627
LEX_STRING db_str= { (char *) in_db, in_db ? strlen(in_db) : 0 };
628
bool is_authenticated;
631
Clear session->db as it points to something, that will be freed when
632
connection is closed. We don't want to accidentally free a wrong
633
pointer if connect failed. Also in case of 'CHANGE USER' failure,
634
current database will be switched to 'no database selected'.
638
if (passwd_len != 0 && passwd_len != SCRAMBLE_LENGTH)
640
my_error(ER_HANDSHAKE_ERROR, MYF(0), security_ctx.ip.c_str());
645
status_var.aborted_connects++;
650
bool Session::checkUser(const std::string &passwd_str,
651
const std::string &in_db)
653
bool is_authenticated=
654
plugin::Authentication::isAuthenticated(getSecurityContext(),
644
is_authenticated= authenticate_user(this, passwd);
657
646
if (is_authenticated != true)
659
status_var.access_denied++;
660
/* isAuthenticated has pushed the error message */
648
my_error(ER_ACCESS_DENIED_ERROR, MYF(0),
649
security_ctx.user.c_str(),
650
security_ctx.ip.c_str(),
651
passwd_len ? ER(ER_YES) : ER(ER_NO));
656
security_ctx.skip_grants();
664
658
/* Change database if necessary */
665
if (not in_db.empty())
659
if (in_db && in_db[0])
667
SchemaIdentifier identifier(in_db);
668
if (mysql_change_db(this, identifier))
661
if (mysql_change_db(this, &db_str, false))
670
663
/* mysql_change_db() has pushed the error message. */
675
password= not passwd_str.empty();
668
password= test(passwd_len); // remember for error messages
677
670
/* Ready to handle queries */
804
792
bool Session::endActiveTransaction()
806
794
bool result= true;
807
TransactionServices &transaction_services= TransactionServices::singleton();
809
796
if (transaction.xid_state.xa_state != XA_NOTR)
811
798
my_error(ER_XAER_RMFAIL, MYF(0), xa_state_names[transaction.xid_state.xa_state]);
814
if (options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
801
if (options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN | OPTION_TABLE_LOCK))
803
/* Safety if one did "drop table" on locked tables */
805
options&= ~OPTION_TABLE_LOCK;
816
806
server_status&= ~SERVER_STATUS_IN_TRANS;
817
if (transaction_services.commitTransaction(this, true))
820
options&= ~(OPTION_BEGIN);
810
options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
811
transaction.all.modified_non_trans_table= false;
824
bool Session::startTransaction(start_transaction_option_t opt)
815
bool Session::startTransaction()
826
817
bool result= true;
822
locked_tables= 0; // Will be automatically closed
823
close_thread_tables(); // Free tables
828
825
if (! endActiveTransaction())
834
829
options|= OPTION_BEGIN;
835
830
server_status|= SERVER_STATUS_IN_TRANS;
837
if (plugin::TransactionalStorageEngine::notifyStartTransaction(this, opt))
831
if (lex->start_transaction_opt & DRIZZLE_START_TRANS_OPT_WITH_CONS_SNAPSHOT)
832
if (ha_start_consistent_snapshot(this))
842
Session::cleanup_after_query()
845
This function is used to reset thread data to its default state.
848
This function is not suitable for setting thread data to some
849
non-default values, as there is only one replication thread, so
850
different master threads may overwrite data of each other on
846
853
void Session::cleanup_after_query()
884
887
@return NULL on failure, or pointer to the LEX_STRING object
886
889
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)
890
const char* str, uint32_t length,
891
bool allocate_lex_string)
897
893
if (allocate_lex_string)
898
894
if (!(lex_str= (LEX_STRING *)alloc(sizeof(LEX_STRING))))
900
if (!(lex_str->str= mem_root->strmake_root(str, length)))
896
if (!(lex_str->str= strmake_root(mem_root, str, length)))
902
898
lex_str->length= length;
904
Convert a string to another character set
908
to Store new allocated string here
909
to_cs New character set for allocated string
910
from String to convert
911
from_length Length of string to convert
912
from_cs Original character set
915
to will be 0-terminated to make it easy to pass to system funcs
920
In this case to->str will point to 0 and to->length will be 0.
923
bool Session::convert_string(LEX_STRING *to, const CHARSET_INFO * const to_cs,
924
const char *from, uint32_t from_length,
925
const CHARSET_INFO * const from_cs)
927
size_t new_length= to_cs->mbmaxlen * from_length;
928
uint32_t dummy_errors;
929
if (!(to->str= (char*) alloc(new_length+1)))
931
to->length= 0; // Safety fix
934
to->length= copy_and_convert((char*) to->str, new_length, to_cs,
935
from, from_length, from_cs, &dummy_errors);
936
to->str[to->length]=0; // Safety
942
Convert string from source character set to target character set inplace.
945
Session::convert_string
948
Convert string using convert_buffer - buffer for character set
949
conversion shared between all protocols.
956
bool Session::convert_string(String *s, const CHARSET_INFO * const from_cs,
957
const CHARSET_INFO * const to_cs)
959
uint32_t dummy_errors;
960
if (convert_buffer.copy(s->ptr(), s->length(), from_cs, to_cs, &dummy_errors))
962
/* If convert_buffer >> s copying is more efficient long term */
963
if (convert_buffer.alloced_length() >= convert_buffer.length() * 2 ||
966
return s->copy(convert_buffer);
968
s->swap(convert_buffer);
974
Update some cache variables when character set changes
977
void Session::update_charset()
980
charset_is_system_charset= !String::needs_conversion(0,charset(),
983
charset_is_collation_connection=
984
!String::needs_conversion(0,charset(),variables.getCollation(),
986
charset_is_character_set_filesystem=
987
!String::needs_conversion(0, charset(),
988
variables.character_set_filesystem, ¬_used);
992
/* routings to adding tables to list of changed in transaction tables */
994
inline static void list_include(CHANGED_TableList** prev,
995
CHANGED_TableList* curr,
996
CHANGED_TableList* new_table)
1001
(*prev)->next = curr;
1005
/* add table to list of changed in transaction tables */
1007
void Session::add_changed_table(Table *table)
1009
assert((options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) &&
1010
table->file->has_transactions());
1011
add_changed_table(table->s->table_cache_key.str,
1012
(long) table->s->table_cache_key.length);
1016
void Session::add_changed_table(const char *key, long key_length)
1018
CHANGED_TableList **prev_changed = &transaction.changed_tables;
1019
CHANGED_TableList *curr = transaction.changed_tables;
1021
for (; curr; prev_changed = &(curr->next), curr = curr->next)
1023
int cmp = (long)curr->key_length - (long)key_length;
1026
list_include(prev_changed, curr, changed_table_dup(key, key_length));
1031
cmp = memcmp(curr->key, key, curr->key_length);
1034
list_include(prev_changed, curr, changed_table_dup(key, key_length));
1043
*prev_changed = changed_table_dup(key, key_length);
1047
CHANGED_TableList* Session::changed_table_dup(const char *key, long key_length)
1049
CHANGED_TableList* new_table =
1050
(CHANGED_TableList*) trans_alloc(ALIGN_SIZE(sizeof(CHANGED_TableList))+
1054
my_error(EE_OUTOFMEMORY, MYF(ME_BELL),
1055
ALIGN_SIZE(sizeof(TableList)) + key_length + 1);
1056
killed= KILL_CONNECTION;
1060
new_table->key= ((char*)new_table)+ ALIGN_SIZE(sizeof(CHANGED_TableList));
1061
new_table->next = 0;
1062
new_table->key_length = key_length;
1063
::memcpy(new_table->key, key, key_length);
906
1068
int Session::send_explain_fields(select_result *result)
908
1070
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)
1193
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())
1196
uint32_t option= MY_UNPACK_FILENAME | MY_RELATIVE_PATH;
1198
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
1199
option|= MY_REPLACE_DIR; // Force use of db directory
1202
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;
1204
strcpy(path, drizzle_real_data_home);
1206
strncat(path, session->db, FN_REFLEN-strlen(drizzle_real_data_home)-1);
1207
(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))
1210
(void) fn_format(path, exchange->file_name, drizzle_real_data_home, "", option);
1212
if (opt_secure_file_priv &&
1213
strncmp(opt_secure_file_priv, path, strlen(opt_secure_file_priv)))
1215
/* Write only allowed to dir or subdir specified by secure_file_priv */
1216
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
1220
if (!access(path, F_OK))
1082
1222
my_error(ER_FILE_EXISTS_ERROR, MYF(0), exchange->file_name);
1085
1225
/* 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)
1226
if ((file= my_create(path, 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
1088
1229
(void) fchmod(file, 0666); // Because of umask()
1089
if (cache->init_io_cache(file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1231
(void) chmod(path, 0666);
1233
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
1235
my_close(file, MYF(0));
1236
my_delete(path, MYF(0)); // Delete file on error, it was just created
1188
1335
res=item->str_result(&tmp);
1189
1336
if (res && enclosed)
1191
if (my_b_write(cache,(unsigned char*) exchange->enclosed->ptr(),
1192
exchange->enclosed->length()))
1338
if (my_b_write(&cache,(unsigned char*) exchange->enclosed->ptr(),
1339
exchange->enclosed->length()))
1197
1344
if (!fixed_row_size)
1199
if (escape_char != -1) // Use \N syntax
1201
null_buff[0]=escape_char;
1203
if (my_b_write(cache,(unsigned char*) null_buff,2))
1206
else if (my_b_write(cache,(unsigned char*) "NULL",4))
1346
if (escape_char != -1) // Use \N syntax
1348
null_buff[0]=escape_char;
1350
if (my_b_write(&cache,(unsigned char*) null_buff,2))
1353
else if (my_b_write(&cache,(unsigned char*) "NULL",4))
1211
used_length=0; // Fill with space
1358
used_length=0; // Fill with space
1216
1363
if (fixed_row_size)
1217
used_length= min(res->length(), static_cast<size_t>(item->max_length));
1364
used_length=cmin(res->length(),item->max_length);
1219
used_length= res->length();
1366
used_length=res->length();
1221
1367
if ((result_type == STRING_RESULT || is_unsafe_field_sep) &&
1224
1370
char *pos, *start, *end;
1225
1371
const CHARSET_INFO * const res_charset= res->charset();
1226
1372
const CHARSET_INFO * const character_set_client= default_charset_info;
1228
1374
bool check_second_byte= (res_charset == &my_charset_bin) &&
1229
character_set_client->
1230
escape_with_backslash_is_dangerous;
1375
character_set_client->
1376
escape_with_backslash_is_dangerous;
1231
1377
assert(character_set_client->mbmaxlen == 2 ||
1232
1378
!character_set_client->escape_with_backslash_is_dangerous);
1233
for (start=pos=(char*) res->ptr(),end=pos+used_length ;
1237
if (use_mb(res_charset))
1240
if ((l=my_ismbchar(res_charset, pos, end)))
1379
for (start=pos=(char*) res->ptr(),end=pos+used_length ;
1384
if (use_mb(res_charset))
1387
if ((l=my_ismbchar(res_charset, pos, end)))
1248
1396
Special case when dumping BINARY/VARBINARY/BLOB values
1276
1424
assert before the loop makes that sure.
1279
if ((needs_escaping(*pos, enclosed) ||
1427
if ((NEED_ESCAPING(*pos) ||
1280
1428
(check_second_byte &&
1281
1429
my_mbcharlen(character_set_client, (unsigned char) *pos) == 2 &&
1282
1430
pos + 1 < end &&
1283
needs_escaping(pos[1], enclosed))) &&
1431
NEED_ESCAPING(pos[1]))) &&
1285
Don't escape field_term_char by doubling - doubling is only
1286
valid for ENCLOSED BY characters:
1433
Don't escape field_term_char by doubling - doubling is only
1434
valid for ENCLOSED BY characters:
1288
1436
(enclosed || !is_ambiguous_field_term ||
1289
1437
(int) (unsigned char) *pos != field_term_char))
1292
1440
tmp_buff[0]= ((int) (unsigned char) *pos == field_sep_char &&
1293
1441
is_ambiguous_field_sep) ?
1294
field_sep_char : escape_char;
1295
tmp_buff[1]= *pos ? *pos : '0';
1296
if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)) ||
1297
my_b_write(cache,(unsigned char*) tmp_buff,2))
1302
if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)))
1442
field_sep_char : escape_char;
1443
tmp_buff[1]= *pos ? *pos : '0';
1444
if (my_b_write(&cache,(unsigned char*) start,(uint32_t) (pos-start)) ||
1445
my_b_write(&cache,(unsigned char*) tmp_buff,2))
1450
if (my_b_write(&cache,(unsigned char*) start,(uint32_t) (pos-start)))
1305
else if (my_b_write(cache,(unsigned char*) res->ptr(),used_length))
1453
else if (my_b_write(&cache,(unsigned char*) res->ptr(),used_length))
1308
1456
if (fixed_row_size)
1309
1457
{ // Fill with space
1310
1458
if (item->max_length > used_length)
1312
/* QQ: Fix by adding a my_b_fill() function */
1316
memset(space, ' ', sizeof(space));
1318
uint32_t length=item->max_length-used_length;
1319
for (; length > sizeof(space) ; length-=sizeof(space))
1321
if (my_b_write(cache,(unsigned char*) space,sizeof(space)))
1324
if (my_b_write(cache,(unsigned char*) space,length))
1460
/* QQ: Fix by adding a my_b_fill() function */
1464
memset(space, ' ', sizeof(space));
1466
uint32_t length=item->max_length-used_length;
1467
for (; length > sizeof(space) ; length-=sizeof(space))
1469
if (my_b_write(&cache,(unsigned char*) space,sizeof(space)))
1472
if (my_b_write(&cache,(unsigned char*) space,length))
1328
1476
if (res && enclosed)
1330
if (my_b_write(cache, (unsigned char*) exchange->enclosed->ptr(),
1478
if (my_b_write(&cache, (unsigned char*) exchange->enclosed->ptr(),
1331
1479
exchange->enclosed->length()))
1334
1482
if (--items_left)
1336
if (my_b_write(cache, (unsigned char*) exchange->field_term->ptr(),
1484
if (my_b_write(&cache, (unsigned char*) exchange->field_term->ptr(),
1337
1485
field_term_length))
1341
if (my_b_write(cache,(unsigned char*) exchange->line_term->ptr(),
1342
exchange->line_term->length()))
1489
if (my_b_write(&cache,(unsigned char*) exchange->line_term->ptr(),
1490
exchange->line_term->length()))
1615
1796
memset(&status_var, 0, sizeof(status_var));
1619
void Session::set_db(const std::string &new_db)
1799
void Security_context::skip_grants()
1801
/* privileges for the user are unknown everything is allowed */
1805
/****************************************************************************
1806
Handling of open and locked tables states.
1808
This is used when we want to open/lock (and then close) some tables when
1809
we already have a set of tables open and locked. We use these methods for
1810
access to mysql.proc table to find definitions of stored routines.
1811
****************************************************************************/
1813
void Session::reset_n_backup_open_tables_state(Open_tables_state *backup)
1815
backup->set_open_tables_state(this);
1816
reset_open_tables_state();
1817
state_flags|= Open_tables_state::BACKUPS_AVAIL;
1821
void Session::restore_backup_open_tables_state(Open_tables_state *backup)
1824
Before we will throw away current open tables state we want
1825
to be sure that it was properly cleaned up.
1827
assert(open_tables == 0 && temporary_tables == 0 &&
1828
derived_tables == 0 &&
1829
lock == 0 && locked_tables == 0);
1830
set_open_tables_state(backup);
1834
bool Session::set_db(const char *new_db, size_t new_db_len)
1621
1836
/* Do not reallocate memory if current chunk is big enough. */
1622
if (new_db.length())
1624
_schema.reset(new std::string(new_db));
1837
if (db && new_db && db_length >= new_db_len)
1838
memcpy(db, new_db, new_db_len+1);
1628
_schema.reset(new std::string(""));
1845
db= (char *)malloc(new_db_len + 1);
1848
memcpy(db, new_db, new_db_len);
1855
db_length= db ? new_db_len : 0;
1856
return new_db && !db;
1861
Check the killed state of a user thread
1862
@param session user thread
1863
@retval 0 the user thread is active
1864
@retval 1 the user thread has been killed
1866
extern "C" int session_killed(const Session *session)
1868
return(session->killed);
1872
Return the thread id of a user thread
1873
@param session user thread
1876
extern "C" unsigned long session_get_thread_id(const Session *session)
1878
return((unsigned long)session->thread_id);
1883
LEX_STRING *session_make_lex_string(Session *session, LEX_STRING *lex_str,
1884
const char *str, unsigned int size,
1885
int allocate_lex_string)
1887
return session->make_lex_string(lex_str, str, size,
1888
(bool) allocate_lex_string);
1891
extern "C" const struct charset_info_st *session_charset(Session *session)
1893
return(session->charset());
1896
extern "C" char **session_query(Session *session)
1898
return(&session->query);
1901
extern "C" int session_non_transactional_update(const Session *session)
1903
return(session->transaction.all.modified_non_trans_table);
1906
extern "C" void session_mark_transaction_to_rollback(Session *session, bool all)
1908
mark_transaction_to_rollback(session, all);
1651
1931
plugin_sessionvar_cleanup(this);
1653
1933
/* If necessary, log any aborted or unauthorized connections */
1654
if (getKilled() || client->wasAborted())
1656
status_var.aborted_threads++;
1934
if (killed || protocol->wasAborted())
1935
statistic_increment(aborted_threads, &LOCK_status);
1659
if (client->wasAborted())
1937
if (protocol->wasAborted())
1661
if (not getKilled() && variables.log_warnings > 1)
1939
if (! killed && variables.log_warnings > 1)
1663
SecurityContext *sctx= &security_ctx;
1941
Security_context *sctx= &security_ctx;
1665
1943
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()
1945
, (db ? db : "unconnected")
1946
, sctx->user.empty() == false ? sctx->user.c_str() : "unauthenticated"
1670
1948
, (main_da.is_error() ? main_da.message() : ER(ER_UNKNOWN_ERROR)));
1674
1952
/* Close out our connection to the client */
1675
1953
if (should_lock)
1676
session::Cache::singleton().mutex().lock();
1678
setKilled(Session::KILL_CONNECTION);
1680
if (client->isConnected())
1954
(void) pthread_mutex_lock(&LOCK_thread_count);
1955
killed= Session::KILL_CONNECTION;
1956
if (protocol->isConnected())
1684
1960
/*my_error(errcode, ER(errcode));*/
1685
client->sendError(errcode, ER(errcode));
1961
protocol->sendError(errcode, ER(errcode)); /* purecov: inspected */
1690
1965
if (should_lock)
1692
session::Cache::singleton().mutex().unlock();
1966
(void) pthread_mutex_unlock(&LOCK_thread_count);
1970
Reset Session part responsible for command processing state.
1972
This needs to be called before execution of every statement
1973
(prepared or conventional).
1974
It is not called by substatements of routines.
1977
Make it a method of Session and align its name with the rest of
1978
reset/end/start/init methods.
1980
Call it after we use Session for queries, not before.
1696
1983
void Session::reset_for_next_command()
1718
2015
Close all temporary tables created by 'CREATE TEMPORARY TABLE' for thread
2016
creates one DROP TEMPORARY Table binlog event for each pseudo-thread
1721
void Open_tables_state::close_temporary_tables()
2019
void Session::close_temporary_tables()
1724
2022
Table *tmp_next;
1726
if (not temporary_tables)
2024
if (!temporary_tables)
1729
2027
for (table= temporary_tables; table; table= tmp_next)
1731
tmp_next= table->getNext();
2029
tmp_next= table->next;
2030
close_temporary(table, 1, 1);
1734
2032
temporary_tables= NULL;
1738
unlink from session->temporary tables and close temporary table
1741
void Open_tables_state::close_temporary_table(Table *table)
1743
if (table->getPrev())
1745
table->getPrev()->setNext(table->getNext());
1746
if (table->getPrev()->getNext())
1748
table->getNext()->setPrev(table->getPrev());
1753
/* removing the item from the list */
1754
assert(table == temporary_tables);
1756
slave must reset its temporary list pointer to zero to exclude
1757
passing non-zero value to end_slave via rli->save_temporary_tables
1758
when no temp tables opened, see an invariant below.
1760
temporary_tables= table->getNext();
1761
if (temporary_tables)
1763
table->getNext()->setPrev(NULL);
1770
Close and drop a temporary table
1773
This dosn't unlink table from session->temporary
1774
If this is needed, use close_temporary_table()
1777
void Open_tables_state::nukeTable(Table *table)
1779
plugin::StorageEngine *table_type= table->getShare()->db_type();
1781
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 */
1793
2036
/** Clear most status variables. */
1794
2037
extern time_t flush_status_time;
2038
extern uint32_t max_used_connections;
1796
2040
void Session::refresh_status()
2042
pthread_mutex_lock(&LOCK_status);
2044
/* Add thread's status variabes to global status */
2045
add_to_status(&global_status_var, &status_var);
1798
2047
/* Reset thread's status variables */
1799
2048
memset(&status_var, 0, sizeof(status_var));
2050
/* Reset some global variables */
2051
reset_status_vars();
2053
/* Reset the counters of all key caches (default and named). */
2054
process_key_caches(reset_key_cache_counters);
1801
2055
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;
2056
max_used_connections= 1; /* We set it to one, because we know we exist */
2057
pthread_mutex_unlock(&LOCK_status);
2060
#define extra_size sizeof(double)
1806
2062
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
2064
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)
2066
assert(name.length == strlen (name.str));
2067
entry= (user_var_entry*) hash_search(&user_vars, (unsigned char*) name.str, name.length);
2069
if ((entry == NULL) && create_if_not_exists)
2071
uint32_t size=ALIGN_SIZE(sizeof(user_var_entry))+name.length+1+extra_size;
2072
if (!hash_inited(&user_vars))
2074
if (!(entry = (user_var_entry*) malloc(size)))
2076
entry->name.str=(char*) entry+ ALIGN_SIZE(sizeof(user_var_entry))+
2078
entry->name.length=name.length;
2081
entry->update_query_id=0;
2082
entry->collation.set(NULL, DERIVATION_IMPLICIT);
2083
entry->unsigned_flag= 0;
2085
If we are here, we were called from a SET or a query which sets a
2086
variable. Imagine it is this:
2087
INSERT INTO t SELECT @a:=10, @a:=@a+1.
2088
Then when we have a Item_func_get_user_var (because of the @a+1) so we
2089
think we have to write the value of @a to the binlog. But before that,
2090
we have a Item_func_set_user_var to create @a (@a:=10), in this we mark
2091
the variable as "already logged" (line below) so that it won't be logged
2092
by Item_func_get_user_var (because that's not necessary).
2094
entry->used_query_id= query_id;
2095
entry->type=STRING_RESULT;
2096
memcpy(entry->name.str, name.str, name.length+1);
2097
if (my_hash_insert(&user_vars, (unsigned char*) entry))
2100
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())
2110
Mark all temporary tables which were used by the current statement or
2111
substatement as free for reuse, but only if the query_id can be cleared.
2113
@param session thread context
2115
@remark For temp tables associated with a open SQL HANDLER the query_id
2116
is not reset until the HANDLER is closed.
2119
void Session::mark_temp_tables_as_free_for_reuse()
2121
for (Table *table= temporary_tables ; table ; table= table->next)
1855
if (table->query_id == getQueryId())
2123
if (table->query_id == query_id)
1857
2125
table->query_id= 0;
1858
table->cursor->ha_reset();
2126
table->file->ha_reset();
2133
Mark all tables in the list which were used by current substatement
2137
mark_used_tables_as_free_for_reuse()
2138
session - thread context
2139
table - head of the list of tables
2142
Marks all tables in the list which were used by current substatement
2143
(they are marked by its query_id) as free for reuse.
2146
The reason we reset query_id is that it's not enough to just test
2147
if table->query_id != session->query_id to know if a table is in use.
2150
SELECT f1_that_uses_t1() FROM t1;
2151
In f1_that_uses_t1() we will see one instance of t1 where query_id is
2152
set to query_id of original query.
1863
2155
void Session::mark_used_tables_as_free_for_reuse(Table *table)
1865
for (; table ; table= table->getNext())
2157
for (; table ; table= table->next)
1867
if (table->query_id == getQueryId())
2159
if (table->query_id == query_id)
1869
2161
table->query_id= 0;
1870
table->cursor->ha_reset();
2162
table->file->ha_reset();
1876
Unlocks tables and frees derived tables.
1877
Put all normal tables used by thread in free list.
1879
It will only close/mark as free for reuse tables opened by this
1880
substatement, it will also check if we are closing tables after
1881
execution of complete query (i.e. we are on upper level) and will
1882
leave prelocked mode if needed.
2169
Close all tables used by the current substatement, or all tables
2170
used by this thread if we are on the upper level.
2173
close_thread_tables()
2174
session Thread handler
2177
Unlocks tables and frees derived tables.
2178
Put all normal tables used by thread in free list.
2180
It will only close/mark as free for reuse tables opened by this
2181
substatement, it will also check if we are closing tables after
2182
execution of complete query (i.e. we are on upper level) and will
2183
leave prelocked mode if needed.
1884
2186
void Session::close_thread_tables()
1886
clearDerivedTables();
2191
We are assuming here that session->derived_tables contains ONLY derived
2192
tables for this substatement. i.e. instead of approach which uses
2193
query_id matching for determining which of the derived tables belong
2194
to this substatement we rely on the ability of substatements to
2195
save/restore session->derived_tables during their execution.
2197
TODO: Probably even better approach is to simply associate list of
2198
derived tables with (sub-)statement instead of thread and destroy
2199
them at the end of its execution.
2205
Close all derived tables generated in queries like
2206
SELECT * FROM (SELECT * FROM t1)
2208
for (table= derived_tables ; table ; table= next)
2211
table->free_tmp_table(this);
1889
2217
Mark all temporary tables used by this statement as free for reuse.
1916
2256
handled either before writing a query log event (inside
1917
2257
binlog_query()) or when preparing a pending event.
2259
mysql_unlock_tables(this, lock);
1923
Note that we need to hold table::Cache::singleton().mutex() while changing the
2263
Note that we need to hold LOCK_open while changing the
1924
2264
open_tables list. Another thread may work on it.
1925
(See: table::Cache::singleton().removeTable(), mysql_wait_completed_table())
2265
(See: remove_table_from_cache(), mysql_wait_completed_table())
1926
2266
Closing a MERGE child before the parent would be fatal if the
1927
2267
other thread tries to abort the MERGE lock in between.
1929
2269
if (open_tables)
1930
2270
close_open_tables();
1933
void Session::close_tables_for_reopen(TableList **tables)
1936
If table list consists only from tables from prelocking set, table list
1937
for new attempt should be empty, so we have to update list's root pointer.
1939
if (lex->first_not_own_table() == *tables)
1941
lex->chop_off_not_own_tables();
1942
for (TableList *tmp= *tables; tmp; tmp= tmp->next_global)
1944
close_thread_tables();
1947
bool Session::openTablesLock(TableList *tables)
1954
if (open_tables_from_list(&tables, &counter))
1957
if (not lock_tables(tables, counter, &need_reopen))
1959
if (not need_reopen)
1961
close_tables_for_reopen(&tables);
1963
if ((mysql_handle_derived(lex, &mysql_derived_prepare) ||
1965
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 */