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"
49
48
#include "drizzled/transaction_services.h"
50
49
#include "drizzled/drizzled.h"
52
#include "drizzled/table/instance.h"
54
51
#include "plugin/myisam/myisam.h"
55
52
#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
55
#include <algorithm>
66
#include <boost/filesystem.hpp>
68
#include "drizzled/util/backtrace.h"
70
58
using namespace std;
72
namespace fs=boost::filesystem;
81
67
char empty_c_string[1]= {0}; /* used for not defined db */
83
69
const char * const Session::DEFAULT_WHERE= "field list";
70
extern pthread_key_t THR_Session;
71
extern pthread_key_t THR_Mem_root;
74
/****************************************************************************
76
****************************************************************************/
77
static unsigned char *get_var_key(user_var_entry *entry, size_t *length, bool)
79
*length= entry->name.length;
80
return (unsigned char*) entry->name.str;
83
static void free_user_var(user_var_entry *entry)
85
88
bool Key_part_spec::operator==(const Key_part_spec& other) const
87
90
return length == other.length &&
88
91
field_name.length == other.field_name.length &&
89
!my_strcasecmp(system_charset_info, field_name.str, other.field_name.str);
92
!strcmp(field_name.str, other.field_name.str);
92
Open_tables_state::Open_tables_state(uint64_t version_arg) :
95
Open_tables_state::Open_tables_state(uint64_t version_arg)
96
:version(version_arg), backups_available(false)
95
open_tables= temporary_tables= derived_tables= NULL;
96
extra_lock= lock= NULL;
98
reset_open_tables_state();
154
156
return (int) session->lex->sql_command;
157
enum_tx_isolation session_tx_isolation(const Session *session)
159
int session_tx_isolation(const Session *session)
159
return (enum_tx_isolation)session->variables.tx_isolation;
161
return (int) session->variables.tx_isolation;
162
Session::Session(plugin::Client *client_arg) :
164
Session::Session(plugin::Client *client_arg)
163
166
Open_tables_state(refresh_version),
164
167
mem_root(&main_mem_root),
167
query(new std::string),
168
_schema(new std::string("")),
170
170
client(client_arg),
172
172
scheduler_arg(NULL),
173
173
lock_id(&main_lock_id),
175
175
ha_data(plugin::num_trx_monitored_objects),
176
concurrent_execute_allowed(true),
177
176
arg_of_last_insert_id_function(false),
178
177
first_successful_insert_id_in_prev_stmt(0),
179
178
first_successful_insert_id_in_cur_stmt(0),
180
179
limit_found_rows(0),
181
_global_read_lock(NONE),
183
181
some_tables_deleted(false),
184
182
no_errors(false),
261
255
/* Initialize sub structures */
262
256
memory::init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
257
hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
258
(hash_get_key) get_var_key,
259
(hash_free_key) free_user_var, 0);
264
261
substitute_null_with_insert_id = false;
265
lock_info.init(); /* safety: will be reset after start */
262
thr_lock_info_init(&lock_info); /* safety: will be reset after start */
266
263
thr_lock_owner_init(&main_lock_id, &lock_info);
268
265
m_internal_handler= NULL;
270
plugin::EventObserver::registerSessionEvents(*this);
273
268
void Session::free_items()
401
365
dbug_sentry= Session_SENTRY_GONE;
403
367
main_mem_root.free_root(MYF(0));
404
currentMemRoot().release();
405
currentSession().release();
368
pthread_setspecific(THR_Session, 0);
407
370
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))
372
/* Ensure that no one is using Session */
373
pthread_mutex_unlock(&LOCK_delete);
374
pthread_mutex_destroy(&LOCK_delete);
378
Add all status variables to another status variable array
382
to_var add to this array
383
from_var from this array
386
This function assumes that all variables are long/ulong.
387
If this assumption will change, then we have to explictely add
388
the other variables after the while loop
390
void add_to_status(system_status_var *to_var, system_status_var *from_var)
392
ulong *end= (ulong*) ((unsigned char*) to_var +
393
offsetof(system_status_var, last_system_status_var) +
395
ulong *to= (ulong*) to_var, *from= (ulong*) from_var;
402
Add the difference between two status variable arrays to another one.
406
to_var add to this array
407
from_var from this array
408
dec_var minus this array
411
This function assumes that all variables are long/ulong.
413
void add_diff_to_status(system_status_var *to_var, system_status_var *from_var,
414
system_status_var *dec_var)
416
ulong *end= (ulong*) ((unsigned char*) to_var + offsetof(system_status_var,
417
last_system_status_var) +
419
ulong *to= (ulong*) to_var, *from= (ulong*) from_var, *dec= (ulong*) dec_var;
422
*(to++)+= *(from++) - *(dec++);
425
void Session::awake(Session::killed_state state_to_set)
428
427
this->checkSentry();
430
setKilled(state_to_set);
431
scheduler->killSession(this);
428
safe_mutex_assert_owner(&LOCK_delete);
430
killed= state_to_set;
433
431
if (state_to_set != Session::KILL_QUERY)
433
scheduler->killSession(this);
435
434
DRIZZLE_CONNECTION_DONE(thread_id);
440
boost_unique_lock_t scopedLock(mysys_var->mutex);
438
pthread_mutex_lock(&mysys_var->mutex);
443
440
This broadcast could be up in the air if the victim thread
444
441
exits the cond in the time between read and broadcast, but that is
445
442
ok since all we want to do is to make the victim thread get out
548
542
prepareForQueries();
550
while (not client->haveError() && getKilled() != KILL_CONNECTION)
544
while (! client->haveError() && killed != KILL_CONNECTION)
552
if (not executeStatement())
546
if (! executeStatement())
556
550
disconnect(0, true);
559
bool Session::schedule(Session::shared_ptr &arg)
553
bool Session::schedule()
561
arg->scheduler= plugin::Scheduler::getScheduler();
562
assert(arg->scheduler);
555
scheduler= plugin::Scheduler::getScheduler();
564
558
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());
560
if (connection_count > max_used_connections)
561
max_used_connections= connection_count;
563
thread_id= variables.pseudo_thread_id= global_thread_id++;
565
pthread_mutex_lock(&LOCK_thread_count);
566
getSessionList().push_back(this);
567
pthread_mutex_unlock(&LOCK_thread_count);
569
if (scheduler->addSession(this))
571
DRIZZLE_CONNECTION_START(thread_id);
584
572
char error_message_buff[DRIZZLE_ERRMSG_SIZE];
586
arg->setKilled(Session::KILL_CONNECTION);
574
killed= Session::KILL_CONNECTION;
588
arg->status_var.aborted_connects++;
576
statistic_increment(aborted_connects, &LOCK_status);
590
578
/* Can't use my_error() since store_globals has not been called. */
591
579
/* TODO replace will better error message */
592
580
snprintf(error_message_buff, sizeof(error_message_buff),
593
581
ER(ER_CANT_CREATE_THREAD), 1);
594
arg->client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
582
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)
590
const char* Session::enter_cond(pthread_cond_t *cond,
591
pthread_mutex_t* mutex,
616
594
const char* old_msg = get_proc_info();
617
595
safe_mutex_assert_owner(mutex);
618
mysys_var->current_mutex = &mutex;
619
mysys_var->current_cond = &cond;
596
mysys_var->current_mutex = mutex;
597
mysys_var->current_cond = cond;
620
598
this->set_proc_info(msg);
629
607
locked (if that would not be the case, you'll get a deadlock if someone
630
608
does a Session::awake() on you).
632
mysys_var->current_mutex->unlock();
633
boost_unique_lock_t scopedLock(mysys_var->mutex);
610
pthread_mutex_unlock(mysys_var->current_mutex);
611
pthread_mutex_lock(&mysys_var->mutex);
634
612
mysys_var->current_mutex = 0;
635
613
mysys_var->current_cond = 0;
636
614
this->set_proc_info(old_msg);
615
pthread_mutex_unlock(&mysys_var->mutex);
639
618
bool Session::authenticate()
642
621
if (client->authenticate())
645
status_var.aborted_connects++;
624
statistic_increment(aborted_connects, &LOCK_status);
650
bool Session::checkUser(const std::string &passwd_str,
651
const std::string &in_db)
628
bool Session::checkUser(const char *passwd, uint32_t passwd_len, const char *in_db)
630
const string passwd_str(passwd, passwd_len);
653
631
bool is_authenticated=
654
632
plugin::Authentication::isAuthenticated(getSecurityContext(),
657
635
if (is_authenticated != true)
659
status_var.access_denied++;
660
637
/* isAuthenticated has pushed the error message */
664
641
/* Change database if necessary */
665
if (not in_db.empty())
642
if (in_db && in_db[0])
667
644
SchemaIdentifier identifier(in_db);
668
645
if (mysql_change_db(this, identifier))
694
671
main_da.reset_diagnostics_area();
696
673
if (client->readCommand(&l_packet, &packet_length) == false)
701
if (getKilled() == KILL_CONNECTION)
704
676
if (packet_length == 0)
707
l_command= static_cast<enum_server_command>(l_packet[0]);
679
l_command= (enum enum_server_command) (unsigned char) l_packet[0];
709
681
if (command >= COM_END)
710
682
command= COM_END; // Wrong command
712
684
assert(packet_length);
713
return not dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
685
return ! dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
716
688
bool Session::readAndStoreQuery(const char *in_packet, uint32_t in_packet_length)
722
694
in_packet_length--;
724
696
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])))
697
while (in_packet_length > 0 &&
698
(pos[-1] == ';' || my_isspace(charset() ,pos[-1])))
728
701
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));
704
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)
994
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())
997
uint32_t option= MY_UNPACK_FILENAME | MY_RELATIVE_PATH;
999
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
1000
option|= MY_REPLACE_DIR; // Force use of db directory
1003
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;
1005
strcpy(path, data_home_real);
1006
if (! session->db.empty())
1007
strncat(path, session->db.c_str(), FN_REFLEN-strlen(data_home_real)-1);
1008
(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))
1011
(void) internal::fn_format(path, exchange->file_name, data_home_real, "", option);
1013
if (opt_secure_file_priv &&
1014
strncmp(opt_secure_file_priv, path, strlen(opt_secure_file_priv)))
1016
/* Write only allowed to dir or subdir specified by secure_file_priv */
1017
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
1021
if (!access(path, F_OK))
1082
1023
my_error(ER_FILE_EXISTS_ERROR, MYF(0), exchange->file_name);
1085
1026
/* 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)
1027
if ((file= internal::my_create(path, 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
1088
1029
(void) fchmod(file, 0666); // Because of umask()
1089
if (cache->init_io_cache(file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1030
if (init_io_cache(cache, file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1091
1032
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
1033
internal::my_delete(path, MYF(0)); // Delete file on error, it was just created
1319
1256
for (; length > sizeof(space) ; length-=sizeof(space))
1321
1258
if (my_b_write(cache,(unsigned char*) space,sizeof(space)))
1324
1261
if (my_b_write(cache,(unsigned char*) space,length))
1328
1265
if (res && enclosed)
1330
1267
if (my_b_write(cache, (unsigned char*) exchange->enclosed->ptr(),
1331
1268
exchange->enclosed->length()))
1334
1271
if (--items_left)
1336
1273
if (my_b_write(cache, (unsigned char*) exchange->field_term->ptr(),
1337
1274
field_term_length))
1341
1278
if (my_b_write(cache,(unsigned char*) exchange->line_term->ptr(),
1342
1279
exchange->line_term->length()))
1554
1492
void Session::end_statement()
1556
1494
/* Cleanup SQL processing state to reuse this statement in next query. */
1558
query_cache_key= ""; // reset the cache key
1559
resetResultsetMessage();
1562
1498
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();
1502
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
1505
*p_db= strmake(db.c_str(), db.length());
1506
*p_db_length= db.length();
1619
void Session::set_db(const std::string &new_db)
1546
/****************************************************************************
1547
Handling of open and locked tables states.
1549
This is used when we want to open/lock (and then close) some tables when
1550
we already have a set of tables open and locked. We use these methods for
1551
access to mysql.proc table to find definitions of stored routines.
1552
****************************************************************************/
1554
void Session::reset_n_backup_open_tables_state(Open_tables_state *backup)
1556
backup->set_open_tables_state(this);
1557
reset_open_tables_state();
1558
backups_available= false;
1562
void Session::restore_backup_open_tables_state(Open_tables_state *backup)
1565
Before we will throw away current open tables state we want
1566
to be sure that it was properly cleaned up.
1568
assert(open_tables == 0 && temporary_tables == 0 &&
1569
derived_tables == 0 &&
1571
set_open_tables_state(backup);
1574
bool Session::set_db(const std::string &new_db)
1621
1576
/* Do not reallocate memory if current chunk is big enough. */
1622
1577
if (new_db.length())
1624
_schema.reset(new std::string(new_db));
1628
_schema.reset(new std::string(""));
1589
Check the killed state of a user thread
1590
@param session user thread
1591
@retval 0 the user thread is active
1592
@retval 1 the user thread has been killed
1594
int session_killed(const Session *session)
1596
return(session->killed);
1600
const struct charset_info_st *session_charset(Session *session)
1602
return(session->charset());
1634
1606
Mark transaction to rollback and mark error as fatal to a sub-statement.
1651
1623
plugin_sessionvar_cleanup(this);
1653
1625
/* If necessary, log any aborted or unauthorized connections */
1654
if (getKilled() || client->wasAborted())
1656
status_var.aborted_threads++;
1626
if (killed || client->wasAborted())
1627
statistic_increment(aborted_threads, &LOCK_status);
1659
1629
if (client->wasAborted())
1661
if (not getKilled() && variables.log_warnings > 1)
1631
if (! killed && variables.log_warnings > 1)
1663
1633
SecurityContext *sctx= &security_ctx;
1665
1635
errmsg_printf(ERRMSG_LVL_WARN, ER(ER_NEW_ABORTING_CONNECTION)
1667
, (_schema->empty() ? "unconnected" : _schema->c_str())
1637
, (db.empty() ? "unconnected" : db.c_str())
1668
1638
, sctx->getUser().empty() == false ? sctx->getUser().c_str() : "unauthenticated"
1669
1639
, sctx->getIp().c_str()
1670
1640
, (main_da.is_error() ? main_da.message() : ER(ER_UNKNOWN_ERROR)));
1774
1735
If this is needed, use close_temporary_table()
1777
void Open_tables_state::nukeTable(Table *table)
1738
void Session::nukeTable(Table *table)
1779
plugin::StorageEngine *table_type= table->getShare()->db_type();
1740
plugin::StorageEngine *table_type= table->s->db_type();
1781
1742
table->free_io_cache();
1782
table->delete_table();
1743
table->delete_table(false);
1784
TableIdentifier identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName(), table->getShare()->getPath());
1745
TableIdentifier identifier(table->s->getSchemaName(), table->s->getTableName(), table->s->getPath());
1785
1746
rm_temporary_table(table_type, identifier);
1787
delete table->getMutableShare();
1789
1750
/* This makes me sad, but we're allocating it via malloc */
1793
1754
/** Clear most status variables. */
1794
1755
extern time_t flush_status_time;
1756
extern uint32_t max_used_connections;
1796
1758
void Session::refresh_status()
1760
pthread_mutex_lock(&LOCK_status);
1762
/* Add thread's status variabes to global status */
1763
add_to_status(&global_status_var, &status_var);
1798
1765
/* Reset thread's status variables */
1799
1766
memset(&status_var, 0, sizeof(status_var));
1768
/* Reset some global variables */
1769
reset_status_vars();
1771
/* Reset the counters of all key caches (default and named). */
1772
reset_key_cache_counters();
1801
1773
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;
1774
max_used_connections= 1; /* We set it to one, because we know we exist */
1775
pthread_mutex_unlock(&LOCK_status);
1806
1778
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
1780
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)
1782
entry= (user_var_entry*) hash_search(&user_vars, (unsigned char*) name.str, name.length);
1784
if ((entry == NULL) && create_if_not_exists)
1786
if (!hash_inited(&user_vars))
1788
entry= new (nothrow) user_var_entry(name.str, query_id);
1793
if (my_hash_insert(&user_vars, (unsigned 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())
1805
void Session::mark_temp_tables_as_free_for_reuse()
1807
for (Table *table= temporary_tables ; table ; table= table->next)
1855
if (table->query_id == getQueryId())
1809
if (table->query_id == query_id)
1857
1811
table->query_id= 0;
1858
1812
table->cursor->ha_reset();
1884
1838
void Session::close_thread_tables()
1886
clearDerivedTables();
1843
We are assuming here that session->derived_tables contains ONLY derived
1844
tables for this substatement. i.e. instead of approach which uses
1845
query_id matching for determining which of the derived tables belong
1846
to this substatement we rely on the ability of substatements to
1847
save/restore session->derived_tables during their execution.
1849
TODO: Probably even better approach is to simply associate list of
1850
derived tables with (sub-)statement instead of thread and destroy
1851
them at the end of its execution.
1857
Close all derived tables generated in queries like
1858
SELECT * FROM (SELECT * FROM t1)
1860
for (table= derived_tables ; table ; table= next)
1863
table->free_tmp_table(this);
1889
1869
Mark all temporary tables used by this statement as free for reuse.
1916
1897
handled either before writing a query log event (inside
1917
1898
binlog_query()) or when preparing a pending event.
1900
mysql_unlock_tables(this, lock);
1923
Note that we need to hold table::Cache::singleton().mutex() while changing the
1904
Note that we need to hold LOCK_open while changing the
1924
1905
open_tables list. Another thread may work on it.
1925
(See: table::Cache::singleton().removeTable(), mysql_wait_completed_table())
1906
(See: remove_table_from_cache(), mysql_wait_completed_table())
1926
1907
Closing a MERGE child before the parent would be fatal if the
1927
1908
other thread tries to abort the MERGE lock in between.
1961
1942
close_tables_for_reopen(&tables);
1963
1944
if ((mysql_handle_derived(lex, &mysql_derived_prepare) ||
1945
(fill_derived_tables() &&
1965
1946
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).
1952
bool Session::openTables(TableList *tables, uint32_t flags)
1955
bool ret= fill_derived_tables();
1956
assert(ret == false);
1957
if (open_tables_from_list(&tables, &counter, flags) ||
1958
mysql_handle_derived(lex, &mysql_derived_prepare))
1977
bool Open_tables_state::rm_temporary_table(const TableIdentifier &identifier, bool best_effort)
1963
bool Session::rm_temporary_table(TableIdentifier &identifier)
1979
if (plugin::StorageEngine::dropTable(*static_cast<Session *>(this), identifier))
1965
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);
1967
errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
1968
identifier.getSQLPath().c_str(), errno);
1969
dumpTemporaryTableNames("rm_temporary_table()");
1995
bool Open_tables_state::rm_temporary_table(plugin::StorageEngine *base, const TableIdentifier &identifier)
1977
bool Session::rm_temporary_table(plugin::StorageEngine *base, TableIdentifier &identifier)
1999
if (plugin::StorageEngine::dropTable(*static_cast<Session *>(this), *base, identifier))
1981
if (plugin::StorageEngine::dropTable(*this, *base, identifier))
2002
identifier.getSQLPath(path);
2003
1983
errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
2004
path.c_str(), errno);
1984
identifier.getSQLPath().c_str(), errno);
1985
dumpTemporaryTableNames("rm_temporary_table()");
2023
2004
cerr << "Begin Run: " << foo << "\n";
2024
for (table= temporary_tables; table; table= table->getNext())
2005
for (table= temporary_tables; table; table= table->next)
2026
2007
bool have_proto= false;
2028
message::Table *proto= table->getShare()->getTableProto();
2029
if (table->getShare()->getTableProto())
2009
message::Table *proto= table->s->getTableProto();
2010
if (table->s->getTableProto())
2030
2011
have_proto= true;
2032
2013
const char *answer= have_proto ? "true" : "false";
2034
2015
if (have_proto)
2036
cerr << "\tTable Name " << table->getShare()->getSchemaName() << "." << table->getShare()->getTableName() << " : " << answer << "\n";
2017
cerr << "\tTable Name " << table->s->getSchemaName() << "." << table->s->getTableName() << " : " << answer << "\n";
2037
2018
cerr << "\t\t Proto " << proto->schema() << " " << proto->name() << "\n";
2041
cerr << "\tTabl;e Name " << table->getShare()->getSchemaName() << "." << table->getShare()->getTableName() << " : " << answer << "\n";
2021
cerr << "\tTabl;e Name " << table->s->getSchemaName() << "." << table->s->getTableName() << " : " << answer << "\n";
2046
bool Session::TableMessages::storeTableMessage(const TableIdentifier &identifier, message::Table &table_message)
2025
bool Session::storeTableMessage(TableIdentifier &identifier, message::Table &table_message)
2048
2027
table_message_cache.insert(make_pair(identifier.getPath(), table_message));
2053
bool Session::TableMessages::removeTableMessage(const TableIdentifier &identifier)
2032
bool Session::removeTableMessage(TableIdentifier &identifier)
2055
2034
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
2093
} /* namespace drizzled */