24
24
#include "config.h"
25
#include "drizzled/session.h"
26
#include "drizzled/session/cache.h"
25
#include <drizzled/session.h>
26
#include "drizzled/session_list.h"
27
27
#include <sys/stat.h>
28
#include "drizzled/error.h"
29
#include "drizzled/gettext.h"
30
#include "drizzled/query_id.h"
31
#include "drizzled/data_home.h"
32
#include "drizzled/sql_base.h"
33
#include "drizzled/lock.h"
34
#include "drizzled/item/cache.h"
35
#include "drizzled/item/float.h"
36
#include "drizzled/item/return_int.h"
37
#include "drizzled/item/empty_string.h"
38
#include "drizzled/show.h"
39
#include "drizzled/plugin/client.h"
28
#include <drizzled/error.h>
29
#include <drizzled/gettext.h>
30
#include <drizzled/query_id.h>
31
#include <drizzled/data_home.h>
32
#include <drizzled/sql_base.h>
33
#include <drizzled/lock.h>
34
#include <drizzled/item/cache.h>
35
#include <drizzled/item/float.h>
36
#include <drizzled/item/return_int.h>
37
#include <drizzled/item/empty_string.h>
38
#include <drizzled/show.h>
39
#include <drizzled/plugin/client.h>
40
40
#include "drizzled/plugin/scheduler.h"
41
41
#include "drizzled/plugin/authentication.h"
42
42
#include "drizzled/plugin/logging.h"
43
43
#include "drizzled/plugin/transactional_storage_engine.h"
44
#include "drizzled/plugin/query_rewrite.h"
45
44
#include "drizzled/probes.h"
46
45
#include "drizzled/table_proto.h"
47
46
#include "drizzled/db.h"
48
47
#include "drizzled/pthread_globals.h"
49
48
#include "drizzled/transaction_services.h"
50
#include "drizzled/drizzled.h"
52
#include "drizzled/table/instance.h"
54
50
#include "plugin/myisam/myisam.h"
55
51
#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
54
#include <algorithm>
66
#include <boost/filesystem.hpp>
68
#include "drizzled/util/backtrace.h"
70
57
using namespace std;
72
namespace fs=boost::filesystem;
63
unsigned char *get_var_key(user_var_entry *entry, size_t *length, bool );
64
void free_user_var(user_var_entry *entry);
77
68
The following is used to initialise Table_ident with a internal
81
72
char empty_c_string[1]= {0}; /* used for not defined db */
83
74
const char * const Session::DEFAULT_WHERE= "field list";
75
extern pthread_key_t THR_Session;
76
extern pthread_key_t THR_Mem_root;
77
extern uint32_t max_used_connections;
78
extern atomic<uint32_t> connection_count;
81
/****************************************************************************
83
****************************************************************************/
84
unsigned char *get_var_key(user_var_entry *entry, size_t *length, bool )
86
*length= entry->name.length;
87
return (unsigned char*) entry->name.str;
90
void free_user_var(user_var_entry *entry)
85
95
bool Key_part_spec::operator==(const Key_part_spec& other) const
87
97
return length == other.length &&
88
98
field_name.length == other.field_name.length &&
89
!my_strcasecmp(system_charset_info, field_name.str, other.field_name.str);
99
!strcmp(field_name.str, other.field_name.str);
92
Open_tables_state::Open_tables_state(uint64_t version_arg) :
102
Open_tables_state::Open_tables_state(uint64_t version_arg)
103
:version(version_arg), backups_available(false)
95
open_tables= temporary_tables= derived_tables= NULL;
96
extra_lock= lock= NULL;
105
reset_open_tables_state();
100
109
The following functions form part of the C plugin API
102
int mysql_tmpfile(const char *prefix)
111
extern "C" int mysql_tmpfile(const char *prefix)
104
113
char filename[FN_REFLEN];
105
int fd = internal::create_temp_file(filename, drizzle_tmpdir.c_str(), prefix, MYF(MY_WME));
114
int fd = internal::create_temp_file(filename, drizzle_tmpdir, prefix, MYF(MY_WME));
107
116
unlink(filename);
144
156
return &ha_data[monitored->getId()].resource_context[index];
147
160
int64_t session_test_options(const Session *session, int64_t test_options)
149
162
return session->options & test_options;
152
166
int session_sql_command(const Session *session)
154
168
return (int) session->lex->sql_command;
157
enum_tx_isolation session_tx_isolation(const Session *session)
172
int session_tx_isolation(const Session *session)
159
return (enum_tx_isolation)session->variables.tx_isolation;
174
return (int) session->variables.tx_isolation;
162
Session::Session(plugin::Client *client_arg) :
177
Session::Session(plugin::Client *client_arg)
163
179
Open_tables_state(refresh_version),
164
180
mem_root(&main_mem_root),
167
query(new std::string),
168
_schema(new std::string("")),
170
183
client(client_arg),
172
185
scheduler_arg(NULL),
173
186
lock_id(&main_lock_id),
175
188
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),
261
268
/* Initialize sub structures */
262
269
memory::init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
270
hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
271
(hash_get_key) get_var_key,
272
(hash_free_key) free_user_var, 0);
264
274
substitute_null_with_insert_id = false;
265
lock_info.init(); /* safety: will be reset after start */
275
thr_lock_info_init(&lock_info); /* safety: will be reset after start */
266
276
thr_lock_owner_init(&main_lock_id, &lock_info);
268
278
m_internal_handler= NULL;
270
plugin::EventObserver::registerSessionEvents(*this);
273
281
void Session::free_items()
302
310
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
313
void Session::pop_internal_handler()
327
315
assert(m_internal_handler != NULL);
328
316
m_internal_handler= NULL;
331
void Session::get_xid(DRIZZLE_XID *xid)
333
*xid = *(DRIZZLE_XID *) &transaction.xid_state.xid;
319
#if defined(__cplusplus)
323
void *session_alloc(Session *session, unsigned int size)
325
return session->alloc(size);
328
void *session_calloc(Session *session, unsigned int size)
330
return session->calloc(size);
333
char *session_strdup(Session *session, const char *str)
335
return session->strdup(str);
338
char *session_strmake(Session *session, const char *str, unsigned int size)
340
return session->strmake(str, size);
343
void *session_memdup(Session *session, const void* str, unsigned int size)
345
return session->memdup(str, size);
348
void session_get_xid(const Session *session, DRIZZLE_XID *xid)
350
*xid = *(DRIZZLE_XID *) &session->transaction.xid_state.xid;
353
#if defined(__cplusplus)
336
357
/* Do operations that may take a long time */
350
371
TransactionServices &transaction_services= TransactionServices::singleton();
351
transaction_services.rollbackTransaction(this, true);
372
transaction_services.ha_rollback_trans(this, true);
352
373
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;
375
hash_free(&user_vars);
365
376
close_temporary_tables();
367
378
if (global_read_lock)
369
unlockGlobalReadLock();
379
unlock_global_read_lock(this);
372
381
cleanup_done= true;
375
384
Session::~Session()
386
Session_CHECK_SENTRY(this);
387
add_to_status(&global_status_var, &status_var);
379
389
if (client->isConnected())
396
406
plugin::StorageEngine::closeConnection(this);
397
407
plugin_sessionvar_cleanup(this);
399
warn_root.free_root(MYF(0));
409
free_root(&warn_root,MYF(0));
400
410
mysys_var=0; // Safety (shouldn't be needed)
401
411
dbug_sentry= Session_SENTRY_GONE;
403
main_mem_root.free_root(MYF(0));
404
currentMemRoot().release();
405
currentSession().release();
413
free_root(&main_mem_root, MYF(0));
414
pthread_setspecific(THR_Session, 0);
407
416
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);
418
/* Ensure that no one is using Session */
419
pthread_mutex_unlock(&LOCK_delete);
420
pthread_mutex_destroy(&LOCK_delete);
424
Add all status variables to another status variable array
428
to_var add to this array
429
from_var from this array
432
This function assumes that all variables are long/ulong.
433
If this assumption will change, then we have to explictely add
434
the other variables after the while loop
436
void add_to_status(system_status_var *to_var, system_status_var *from_var)
438
ulong *end= (ulong*) ((unsigned char*) to_var +
439
offsetof(system_status_var, last_system_status_var) +
441
ulong *to= (ulong*) to_var, *from= (ulong*) from_var;
448
Add the difference between two status variable arrays to another one.
452
to_var add to this array
453
from_var from this array
454
dec_var minus this array
457
This function assumes that all variables are long/ulong.
459
void add_diff_to_status(system_status_var *to_var, system_status_var *from_var,
460
system_status_var *dec_var)
462
ulong *end= (ulong*) ((unsigned char*) to_var + offsetof(system_status_var,
463
last_system_status_var) +
465
ulong *to= (ulong*) to_var, *from= (ulong*) from_var, *dec= (ulong*) dec_var;
468
*(to++)+= *(from++) - *(dec++);
471
void Session::awake(Session::killed_state state_to_set)
473
Session_CHECK_SENTRY(this);
474
safe_mutex_assert_owner(&LOCK_delete);
476
killed= state_to_set;
433
477
if (state_to_set != Session::KILL_QUERY)
479
scheduler->killSession(this);
435
480
DRIZZLE_CONNECTION_DONE(thread_id);
440
boost_unique_lock_t scopedLock(mysys_var->mutex);
484
pthread_mutex_lock(&mysys_var->mutex);
443
486
This broadcast could be up in the air if the victim thread
444
487
exits the cond in the time between read and broadcast, but that is
445
488
ok since all we want to do is to make the victim thread get out
548
588
prepareForQueries();
550
while (not client->haveError() && getKilled() != KILL_CONNECTION)
590
while (! client->haveError() && killed != KILL_CONNECTION)
552
if (not executeStatement())
592
if (! executeStatement())
556
596
disconnect(0, true);
559
bool Session::schedule(Session::shared_ptr &arg)
599
bool Session::schedule()
561
arg->scheduler= plugin::Scheduler::getScheduler();
562
assert(arg->scheduler);
601
scheduler= plugin::Scheduler::getScheduler();
564
604
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());
606
if (connection_count > max_used_connections)
607
max_used_connections= connection_count;
609
thread_id= variables.pseudo_thread_id= global_thread_id++;
611
pthread_mutex_lock(&LOCK_thread_count);
612
getSessionList().push_back(this);
613
pthread_mutex_unlock(&LOCK_thread_count);
615
if (scheduler->addSession(this))
617
DRIZZLE_CONNECTION_START(thread_id);
584
618
char error_message_buff[DRIZZLE_ERRMSG_SIZE];
586
arg->setKilled(Session::KILL_CONNECTION);
620
killed= Session::KILL_CONNECTION;
588
arg->status_var.aborted_connects++;
622
statistic_increment(aborted_connects, &LOCK_status);
590
624
/* Can't use my_error() since store_globals has not been called. */
591
625
/* TODO replace will better error message */
592
626
snprintf(error_message_buff, sizeof(error_message_buff),
593
627
ER(ER_CANT_CREATE_THREAD), 1);
594
arg->client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
628
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)
636
const char* Session::enter_cond(pthread_cond_t *cond,
637
pthread_mutex_t* mutex,
616
640
const char* old_msg = get_proc_info();
617
641
safe_mutex_assert_owner(mutex);
618
mysys_var->current_mutex = &mutex;
619
mysys_var->current_cond = &cond;
642
mysys_var->current_mutex = mutex;
643
mysys_var->current_cond = cond;
620
644
this->set_proc_info(msg);
629
653
locked (if that would not be the case, you'll get a deadlock if someone
630
654
does a Session::awake() on you).
632
mysys_var->current_mutex->unlock();
633
boost_unique_lock_t scopedLock(mysys_var->mutex);
656
pthread_mutex_unlock(mysys_var->current_mutex);
657
pthread_mutex_lock(&mysys_var->mutex);
634
658
mysys_var->current_mutex = 0;
635
659
mysys_var->current_cond = 0;
636
660
this->set_proc_info(old_msg);
661
pthread_mutex_unlock(&mysys_var->mutex);
639
664
bool Session::authenticate()
642
667
if (client->authenticate())
645
status_var.aborted_connects++;
670
statistic_increment(aborted_connects, &LOCK_status);
650
bool Session::checkUser(const std::string &passwd_str,
651
const std::string &in_db)
674
bool Session::checkUser(const char *passwd, uint32_t passwd_len, const char *in_db)
676
const string passwd_str(passwd, passwd_len);
653
677
bool is_authenticated=
654
678
plugin::Authentication::isAuthenticated(getSecurityContext(),
657
681
if (is_authenticated != true)
659
status_var.access_denied++;
660
683
/* isAuthenticated has pushed the error message */
664
687
/* Change database if necessary */
665
if (not in_db.empty())
688
if (in_db && in_db[0])
667
690
SchemaIdentifier identifier(in_db);
668
691
if (mysql_change_db(this, identifier))
694
717
main_da.reset_diagnostics_area();
696
719
if (client->readCommand(&l_packet, &packet_length) == false)
701
if (getKilled() == KILL_CONNECTION)
704
722
if (packet_length == 0)
707
l_command= static_cast<enum_server_command>(l_packet[0]);
725
l_command= (enum enum_server_command) (unsigned char) l_packet[0];
709
727
if (command >= COM_END)
710
728
command= COM_END; // Wrong command
712
730
assert(packet_length);
713
return not dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
731
return ! dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
716
734
bool Session::readAndStoreQuery(const char *in_packet, uint32_t in_packet_length)
722
740
in_packet_length--;
724
742
const char *pos= in_packet + in_packet_length; /* Point at end null */
725
while (in_packet_length > 0 && (pos[-1] == ';' || my_isspace(charset() ,pos[-1])))
743
while (in_packet_length > 0 &&
744
(pos[-1] == ';' || my_isspace(charset() ,pos[-1])))
728
747
in_packet_length--;
731
std::string *new_query= new std::string(in_packet, in_packet + in_packet_length);
732
// We can not be entirely sure _schema has a value
735
plugin::QueryRewriter::rewriteQuery(*_schema, *new_query);
737
query.reset(new_query);
738
_state.reset(new State(in_packet, in_packet_length));
750
query.assign(in_packet, in_packet + in_packet_length);
1038
static int create_file(Session *session,
1039
fs::path &target_path,
1040
file_exchange *exchange,
1041
internal::IO_CACHE *cache)
1040
static int create_file(Session *session, char *path, file_exchange *exchange, internal::IO_CACHE *cache)
1043
fs::path to_file(exchange->file_name);
1046
if (not to_file.has_root_directory())
1043
uint32_t option= MY_UNPACK_FILENAME | MY_RELATIVE_PATH;
1045
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
1046
option|= MY_REPLACE_DIR; // Force use of db directory
1049
if (!internal::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;
1051
strcpy(path, drizzle_real_data_home);
1052
if (! session->db.empty())
1053
strncat(path, session->db.c_str(), FN_REFLEN-strlen(drizzle_real_data_home)-1);
1054
(void) internal::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))
1057
(void) internal::fn_format(path, exchange->file_name, drizzle_real_data_home, "", option);
1059
if (opt_secure_file_priv &&
1060
strncmp(opt_secure_file_priv, path, strlen(opt_secure_file_priv)))
1062
/* Write only allowed to dir or subdir specified by secure_file_priv */
1063
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
1067
if (!access(path, F_OK))
1082
1069
my_error(ER_FILE_EXISTS_ERROR, MYF(0), exchange->file_name);
1085
1072
/* 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)
1073
if ((file= internal::my_create(path, 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
1088
1075
(void) fchmod(file, 0666); // Because of umask()
1089
if (cache->init_io_cache(file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1076
if (init_io_cache(cache, file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1091
1078
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
1079
internal::my_delete(path, MYF(0)); // Delete file on error, it was just created
1319
1309
for (; length > sizeof(space) ; length-=sizeof(space))
1321
1311
if (my_b_write(cache,(unsigned char*) space,sizeof(space)))
1324
1314
if (my_b_write(cache,(unsigned char*) space,length))
1328
1318
if (res && enclosed)
1330
1320
if (my_b_write(cache, (unsigned char*) exchange->enclosed->ptr(),
1331
1321
exchange->enclosed->length()))
1334
1324
if (--items_left)
1336
1326
if (my_b_write(cache, (unsigned char*) exchange->field_term->ptr(),
1337
1327
field_term_length))
1341
1331
if (my_b_write(cache,(unsigned char*) exchange->line_term->ptr(),
1342
1332
exchange->line_term->length()))
1554
1545
void Session::end_statement()
1556
1547
/* Cleanup SQL processing state to reuse this statement in next query. */
1558
query_cache_key= ""; // reset the cache key
1559
resetResultsetMessage();
1562
1551
bool Session::copy_db_to(char **p_db, size_t *p_db_length)
1565
if (_schema and _schema->empty())
1567
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
1570
else if (not _schema)
1572
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
1577
*p_db= strmake(_schema->c_str(), _schema->size());
1578
*p_db_length= _schema->size();
1555
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
1558
*p_db= strmake(db.c_str(), db.length());
1559
*p_db_length= db.length();
1619
void Session::set_db(const std::string &new_db)
1599
/****************************************************************************
1600
Handling of open and locked tables states.
1602
This is used when we want to open/lock (and then close) some tables when
1603
we already have a set of tables open and locked. We use these methods for
1604
access to mysql.proc table to find definitions of stored routines.
1605
****************************************************************************/
1607
void Session::reset_n_backup_open_tables_state(Open_tables_state *backup)
1609
backup->set_open_tables_state(this);
1610
reset_open_tables_state();
1611
backups_available= false;
1615
void Session::restore_backup_open_tables_state(Open_tables_state *backup)
1618
Before we will throw away current open tables state we want
1619
to be sure that it was properly cleaned up.
1621
assert(open_tables == 0 && temporary_tables == 0 &&
1622
derived_tables == 0 &&
1624
set_open_tables_state(backup);
1627
bool Session::set_db(const std::string &new_db)
1621
1629
/* Do not reallocate memory if current chunk is big enough. */
1622
1630
if (new_db.length())
1624
_schema.reset(new std::string(new_db));
1628
_schema.reset(new std::string(""));
1642
Check the killed state of a user thread
1643
@param session user thread
1644
@retval 0 the user thread is active
1645
@retval 1 the user thread has been killed
1647
extern "C" int session_killed(const Session *session)
1649
return(session->killed);
1653
Return the session id of a user session
1654
@param pointer to Session object
1655
@return session's id
1657
extern "C" unsigned long session_get_thread_id(const Session *session)
1659
return (unsigned long) session->getSessionId();
1663
const struct charset_info_st *session_charset(Session *session)
1665
return(session->charset());
1668
int session_non_transactional_update(const Session *session)
1670
return(session->transaction.all.hasModifiedNonTransData());
1673
void session_mark_transaction_to_rollback(Session *session, bool all)
1675
mark_transaction_to_rollback(session, all);
1634
1679
Mark transaction to rollback and mark error as fatal to a sub-statement.
1651
1696
plugin_sessionvar_cleanup(this);
1653
1698
/* If necessary, log any aborted or unauthorized connections */
1654
if (getKilled() || client->wasAborted())
1656
status_var.aborted_threads++;
1699
if (killed || client->wasAborted())
1700
statistic_increment(aborted_threads, &LOCK_status);
1659
1702
if (client->wasAborted())
1661
if (not getKilled() && variables.log_warnings > 1)
1704
if (! killed && variables.log_warnings > 1)
1663
1706
SecurityContext *sctx= &security_ctx;
1665
1708
errmsg_printf(ERRMSG_LVL_WARN, ER(ER_NEW_ABORTING_CONNECTION)
1667
, (_schema->empty() ? "unconnected" : _schema->c_str())
1710
, (db.empty() ? "unconnected" : db.c_str())
1668
1711
, sctx->getUser().empty() == false ? sctx->getUser().c_str() : "unauthenticated"
1669
1712
, sctx->getIp().c_str()
1670
1713
, (main_da.is_error() ? main_da.message() : ER(ER_UNKNOWN_ERROR)));
1774
1808
If this is needed, use close_temporary_table()
1777
void Open_tables_state::nukeTable(Table *table)
1811
void Session::nukeTable(Table *table)
1779
plugin::StorageEngine *table_type= table->getShare()->db_type();
1813
plugin::StorageEngine *table_type= table->s->db_type();
1781
1815
table->free_io_cache();
1782
table->delete_table();
1816
table->closefrm(false);
1784
TableIdentifier identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName(), table->getShare()->getPath());
1818
TableIdentifier identifier(table->s->getSchemaName(), table->s->table_name.str, table->s->path.str);
1785
1819
rm_temporary_table(table_type, identifier);
1787
delete table->getMutableShare();
1821
table->s->free_table_share();
1789
1823
/* This makes me sad, but we're allocating it via malloc */
1793
1827
/** Clear most status variables. */
1794
1828
extern time_t flush_status_time;
1829
extern uint32_t max_used_connections;
1796
1831
void Session::refresh_status()
1833
pthread_mutex_lock(&LOCK_status);
1835
/* Add thread's status variabes to global status */
1836
add_to_status(&global_status_var, &status_var);
1798
1838
/* Reset thread's status variables */
1799
1839
memset(&status_var, 0, sizeof(status_var));
1841
/* Reset some global variables */
1842
reset_status_vars();
1844
/* Reset the counters of all key caches (default and named). */
1845
reset_key_cache_counters();
1801
1846
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;
1847
max_used_connections= 1; /* We set it to one, because we know we exist */
1848
pthread_mutex_unlock(&LOCK_status);
1806
1851
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
1853
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)
1855
entry= (user_var_entry*) hash_search(&user_vars, (unsigned char*) name.str, name.length);
1857
if ((entry == NULL) && create_if_not_exists)
1859
if (!hash_inited(&user_vars))
1861
entry= new (nothrow) user_var_entry(name.str, query_id);
1866
if (my_hash_insert(&user_vars, (unsigned char*) entry))
1869
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())
1878
void Session::mark_temp_tables_as_free_for_reuse()
1880
for (Table *table= temporary_tables ; table ; table= table->next)
1855
if (table->query_id == getQueryId())
1882
if (table->query_id == query_id)
1857
1884
table->query_id= 0;
1858
1885
table->cursor->ha_reset();
1884
1911
void Session::close_thread_tables()
1886
clearDerivedTables();
1916
We are assuming here that session->derived_tables contains ONLY derived
1917
tables for this substatement. i.e. instead of approach which uses
1918
query_id matching for determining which of the derived tables belong
1919
to this substatement we rely on the ability of substatements to
1920
save/restore session->derived_tables during their execution.
1922
TODO: Probably even better approach is to simply associate list of
1923
derived tables with (sub-)statement instead of thread and destroy
1924
them at the end of its execution.
1930
Close all derived tables generated in queries like
1931
SELECT * FROM (SELECT * FROM t1)
1933
for (table= derived_tables ; table ; table= next)
1936
table->free_tmp_table(this);
1889
1942
Mark all temporary tables used by this statement as free for reuse.
1916
1970
handled either before writing a query log event (inside
1917
1971
binlog_query()) or when preparing a pending event.
1973
mysql_unlock_tables(this, lock);
1923
Note that we need to hold table::Cache::singleton().mutex() while changing the
1977
Note that we need to hold LOCK_open while changing the
1924
1978
open_tables list. Another thread may work on it.
1925
(See: table::Cache::singleton().removeTable(), mysql_wait_completed_table())
1979
(See: remove_table_from_cache(), mysql_wait_completed_table())
1926
1980
Closing a MERGE child before the parent would be fatal if the
1927
1981
other thread tries to abort the MERGE lock in between.
1961
2015
close_tables_for_reopen(&tables);
1963
2017
if ((mysql_handle_derived(lex, &mysql_derived_prepare) ||
2018
(fill_derived_tables() &&
1965
2019
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).
2025
bool Session::openTables(TableList *tables, uint32_t flags)
2028
bool ret= fill_derived_tables();
2029
assert(ret == false);
2030
if (open_tables_from_list(&tables, &counter, flags) ||
2031
mysql_handle_derived(lex, &mysql_derived_prepare))
1977
bool Open_tables_state::rm_temporary_table(const TableIdentifier &identifier, bool best_effort)
2036
bool Session::rm_temporary_table(TableIdentifier &identifier)
1979
if (plugin::StorageEngine::dropTable(*static_cast<Session *>(this), identifier))
2038
if (plugin::StorageEngine::dropTable(*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);
2040
errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
2041
identifier.getSQLPath().c_str(), errno);
2042
dumpTemporaryTableNames("rm_temporary_table()");
1995
bool Open_tables_state::rm_temporary_table(plugin::StorageEngine *base, const TableIdentifier &identifier)
2050
bool Session::rm_temporary_table(plugin::StorageEngine *base, TableIdentifier &identifier)
1999
if (plugin::StorageEngine::dropTable(*static_cast<Session *>(this), *base, identifier))
2054
if (plugin::StorageEngine::dropTable(*this, *base, identifier))
2002
identifier.getSQLPath(path);
2003
2056
errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
2004
path.c_str(), errno);
2057
identifier.getSQLPath().c_str(), errno);
2058
dumpTemporaryTableNames("rm_temporary_table()");
2023
2077
cerr << "Begin Run: " << foo << "\n";
2024
for (table= temporary_tables; table; table= table->getNext())
2078
for (table= temporary_tables; table; table= table->next)
2026
2080
bool have_proto= false;
2028
message::Table *proto= table->getShare()->getTableProto();
2029
if (table->getShare()->getTableProto())
2082
message::Table *proto= table->s->getTableProto();
2083
if (table->s->getTableProto())
2030
2084
have_proto= true;
2032
2086
const char *answer= have_proto ? "true" : "false";
2034
2088
if (have_proto)
2036
cerr << "\tTable Name " << table->getShare()->getSchemaName() << "." << table->getShare()->getTableName() << " : " << answer << "\n";
2090
cerr << "\tTable Name " << table->s->getSchemaName() << "." << table->s->table_name.str << " : " << answer << "\n";
2037
2091
cerr << "\t\t Proto " << proto->schema() << " " << proto->name() << "\n";
2041
cerr << "\tTabl;e Name " << table->getShare()->getSchemaName() << "." << table->getShare()->getTableName() << " : " << answer << "\n";
2094
cerr << "\tTabl;e Name " << table->s->getSchemaName() << "." << table->s->table_name.str << " : " << answer << "\n";
2046
bool Session::TableMessages::storeTableMessage(const TableIdentifier &identifier, message::Table &table_message)
2098
bool Session::storeTableMessage(TableIdentifier &identifier, message::Table &table_message)
2048
2100
table_message_cache.insert(make_pair(identifier.getPath(), table_message));
2053
bool Session::TableMessages::removeTableMessage(const TableIdentifier &identifier)
2105
bool Session::removeTableMessage(TableIdentifier &identifier)
2055
2107
TableMessageCache::iterator iter;
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
2166
} /* namespace drizzled */