24
24
#include "config.h"
25
#include <drizzled/session.h>
26
#include "drizzled/session_list.h"
25
#include "drizzled/session.h"
26
#include "drizzled/session/cache.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"
44
45
#include "drizzled/probes.h"
45
46
#include "drizzled/table_proto.h"
46
47
#include "drizzled/db.h"
47
48
#include "drizzled/pthread_globals.h"
48
49
#include "drizzled/transaction_services.h"
50
#include "drizzled/drizzled.h"
52
#include "drizzled/identifier.h"
54
#include "drizzled/table/singular.h"
50
56
#include "plugin/myisam/myisam.h"
51
57
#include "drizzled/internal/iocache.h"
58
#include "drizzled/internal/thread_var.h"
59
#include "drizzled/plugin/event_observer.h"
61
#include "drizzled/util/functors.h"
63
#include "drizzled/display.h"
54
66
#include <algorithm>
69
#include <boost/filesystem.hpp>
70
#include <boost/checked_delete.hpp>
72
#include "drizzled/util/backtrace.h"
57
74
using namespace std;
76
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);
68
81
The following is used to initialise Table_ident with a internal
72
85
char empty_c_string[1]= {0}; /* used for not defined db */
74
87
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)
95
89
bool Key_part_spec::operator==(const Key_part_spec& other) const
97
91
return length == other.length &&
98
92
field_name.length == other.field_name.length &&
99
!strcmp(field_name.str, other.field_name.str);
93
!my_strcasecmp(system_charset_info, field_name.str, other.field_name.str);
102
Open_tables_state::Open_tables_state(uint64_t version_arg)
103
:version(version_arg), backups_available(false)
96
Open_tables_state::Open_tables_state(uint64_t version_arg) :
105
reset_open_tables_state();
99
open_tables= temporary_tables= derived_tables= NULL;
100
extra_lock= lock= NULL;
109
104
The following functions form part of the C plugin API
111
extern "C" int mysql_tmpfile(const char *prefix)
106
int tmpfile(const char *prefix)
113
108
char filename[FN_REFLEN];
114
int fd = internal::create_temp_file(filename, drizzle_tmpdir, prefix, MYF(MY_WME));
109
int fd = internal::create_temp_file(filename, drizzle_tmpdir.c_str(), prefix, MYF(MY_WME));
116
111
unlink(filename);
156
148
return &ha_data[monitored->getId()].resource_context[index];
160
151
int64_t session_test_options(const Session *session, int64_t test_options)
162
153
return session->options & test_options;
166
156
int session_sql_command(const Session *session)
168
158
return (int) session->lex->sql_command;
172
int session_tx_isolation(const Session *session)
161
enum_tx_isolation session_tx_isolation(const Session *session)
174
return (int) session->variables.tx_isolation;
163
return (enum_tx_isolation)session->variables.tx_isolation;
177
Session::Session(plugin::Client *client_arg)
166
Session::Session(plugin::Client *client_arg, catalog::Instance::shared_ptr catalog_arg) :
179
167
Open_tables_state(refresh_version),
180
168
mem_root(&main_mem_root),
171
query(new std::string),
172
_schema(new std::string("")),
183
173
client(client_arg),
185
175
scheduler_arg(NULL),
186
176
lock_id(&main_lock_id),
178
security_ctx(identifier::User::make_shared()),
179
where(Session::DEFAULT_WHERE),
180
dbug_sentry(Session_SENTRY_MAGIC),
182
command(COM_CONNECT),
184
_epoch(boost::gregorian::date(1970,1,1)),
185
_connect_time(boost::posix_time::microsec_clock::universal_time()),
188
187
ha_data(plugin::num_trx_monitored_objects),
190
concurrent_execute_allowed(true),
189
191
arg_of_last_insert_id_function(false),
190
192
first_successful_insert_id_in_prev_stmt(0),
191
193
first_successful_insert_id_in_cur_stmt(0),
192
194
limit_found_rows(0),
195
options(session_startup_options),
198
examined_row_count(0),
202
statement_id_counter(0),
206
_global_read_lock(NONE),
207
count_cuted_fields(CHECK_FIELD_ERROR_FOR_NULL),
194
209
some_tables_deleted(false),
195
210
no_errors(false),
213
230
will be re-initialized in init_for_queries().
215
232
memory::init_sql_alloc(&main_mem_root, memory::ROOT_MIN_BLOCK_SIZE, 0);
217
count_cuted_fields= CHECK_FIELD_IGNORE;
222
233
cuted_fields= sent_row_count= row_count= 0L;
224
statement_id_counter= 0UL;
225
234
// Must be reset to handle error with Session's created for init of mysqld
226
235
lex->current_select= 0;
227
start_time=(time_t) 0;
229
utime_after_lock= 0L;
230
236
memset(&variables, 0, sizeof(variables));
236
dbug_sentry=Session_SENTRY_MAGIC;
237
cleanup_done= abort_on_warning= no_warnings_for_error= false;
238
pthread_mutex_init(&LOCK_delete, MY_MUTEX_INIT_FAST);
237
scoreboard_index= -1;
238
cleanup_done= abort_on_warning= no_warnings_for_error= false;
240
/* query_cache init */
240
244
/* Variables with default values */
241
245
proc_info="login";
242
where= Session::DEFAULT_WHERE;
243
command= COM_CONNECT;
245
247
plugin_sessionvar_init(this);
262
263
session_tx_isolation= (enum_tx_isolation) variables.tx_isolation;
263
264
warn_list.empty();
264
265
memset(warn_count, 0, sizeof(warn_count));
266
266
memset(&status_var, 0, sizeof(status_var));
268
268
/* Initialize sub structures */
269
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);
274
271
substitute_null_with_insert_id = false;
275
thr_lock_info_init(&lock_info); /* safety: will be reset after start */
272
lock_info.init(); /* safety: will be reset after start */
276
273
thr_lock_owner_init(&main_lock_id, &lock_info);
278
275
m_internal_handler= NULL;
277
plugin::EventObserver::registerSessionEvents(*this);
281
280
void Session::free_items()
310
309
return false; // 'false', as per coding style
312
void Session::setAbort(bool arg)
314
mysys_var->abort= arg;
317
void Session::lockOnSys()
323
boost_unique_lock_t scopedLock(mysys_var->mutex);
324
if (mysys_var->current_cond)
326
mysys_var->current_mutex->lock();
327
mysys_var->current_cond->notify_all();
328
mysys_var->current_mutex->unlock();
313
332
void Session::pop_internal_handler()
315
334
assert(m_internal_handler != NULL);
316
335
m_internal_handler= NULL;
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)
338
void Session::get_xid(DRIZZLE_XID *xid)
340
*xid = *(DRIZZLE_XID *) &transaction.xid_state.xid;
357
343
/* Do operations that may take a long time */
384
382
Session::~Session()
386
384
this->checkSentry();
387
add_to_status(&global_status_var, &status_var);
389
if (client->isConnected())
386
if (client and client->isConnected())
388
assert(security_ctx);
391
389
if (global_system_variables.log_warnings)
392
errmsg_printf(ERRMSG_LVL_WARN, ER(ER_FORCING_CLOSE),internal::my_progname,
394
(getSecurityContext().getUser().c_str() ?
395
getSecurityContext().getUser().c_str() : ""));
396
disconnect(0, false);
391
errmsg_printf(ERRMSG_LVL_WARN, ER(ER_FORCING_CLOSE),
392
internal::my_progname,
394
security_ctx->username().c_str());
399
400
/* Close connection */
404
boost::checked_delete(client);
403
408
if (cleanup_done == false)
406
411
plugin::StorageEngine::closeConnection(this);
407
412
plugin_sessionvar_cleanup(this);
409
free_root(&warn_root,MYF(0));
414
warn_root.free_root(MYF(0));
410
415
mysys_var=0; // Safety (shouldn't be needed)
411
416
dbug_sentry= Session_SENTRY_GONE;
413
free_root(&main_mem_root, MYF(0));
414
pthread_setspecific(THR_Session, 0);
418
main_mem_root.free_root(MYF(0));
419
currentMemRoot().release();
420
currentSession().release();
416
422
plugin::Logging::postEndDo(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)
423
plugin::EventObserver::deregisterSessionEvents(*this);
425
for (PropertyMap::iterator iter= life_properties.begin(); iter != life_properties.end(); iter++)
427
boost::checked_delete((*iter).second);
429
life_properties.clear();
432
void Session::setClient(plugin::Client *client_arg)
435
client->setSession(this);
438
void Session::awake(Session::killed_state_t state_to_set)
440
if ((state_to_set == Session::KILL_QUERY) and (command == COM_SLEEP))
473
443
this->checkSentry();
474
safe_mutex_assert_owner(&LOCK_delete);
476
killed= state_to_set;
445
setKilled(state_to_set);
446
scheduler->killSession(this);
477
448
if (state_to_set != Session::KILL_QUERY)
479
scheduler->killSession(this);
480
450
DRIZZLE_CONNECTION_DONE(thread_id);
484
pthread_mutex_lock(&mysys_var->mutex);
455
boost_unique_lock_t scopedLock(mysys_var->mutex);
486
458
This broadcast could be up in the air if the victim thread
487
459
exits the cond in the time between read and broadcast, but that is
488
460
ok since all we want to do is to make the victim thread get out
560
533
command= COM_SLEEP;
563
reset_root_defaults(mem_root, variables.query_alloc_block_size,
564
variables.query_prealloc_size);
536
mem_root->reset_root_defaults(variables.query_alloc_block_size,
537
variables.query_prealloc_size);
565
538
transaction.xid_state.xid.null();
566
539
transaction.xid_state.in_session=1;
569
544
bool Session::initGlobals()
571
546
if (storeGlobals())
573
disconnect(ER_OUT_OF_RESOURCES, true);
574
statistic_increment(aborted_connects, &LOCK_status);
548
disconnect(ER_OUT_OF_RESOURCES);
549
status_var.aborted_connects++;
582
557
if (initGlobals() || authenticate())
588
563
prepareForQueries();
590
while (! client->haveError() && killed != KILL_CONNECTION)
565
while (not client->haveError() && getKilled() != KILL_CONNECTION)
592
if (! executeStatement())
567
if (not executeStatement())
599
bool Session::schedule()
574
bool Session::schedule(Session::shared_ptr &arg)
601
scheduler= plugin::Scheduler::getScheduler();
604
connection_count.increment();
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);
576
arg->scheduler= plugin::Scheduler::getScheduler();
577
assert(arg->scheduler);
581
long current_connections= connection_count;
583
if (current_connections > 0 and static_cast<uint64_t>(current_connections) > current_global_counters.max_used_connections)
585
current_global_counters.max_used_connections= static_cast<uint64_t>(connection_count);
588
current_global_counters.connections++;
589
arg->thread_id= arg->variables.pseudo_thread_id= global_thread_id++;
591
session::Cache::singleton().insert(arg);
593
if (unlikely(plugin::EventObserver::connectSession(*arg)))
595
// We should do something about an error...
598
if (plugin::Scheduler::getScheduler()->addSession(arg))
600
DRIZZLE_CONNECTION_START(arg->getSessionId());
618
601
char error_message_buff[DRIZZLE_ERRMSG_SIZE];
620
killed= Session::KILL_CONNECTION;
603
arg->setKilled(Session::KILL_CONNECTION);
622
statistic_increment(aborted_connects, &LOCK_status);
605
arg->status_var.aborted_connects++;
624
607
/* Can't use my_error() since store_globals has not been called. */
625
608
/* TODO replace will better error message */
626
609
snprintf(error_message_buff, sizeof(error_message_buff),
627
610
ER(ER_CANT_CREATE_THREAD), 1);
628
client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
611
arg->client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
636
const char* Session::enter_cond(pthread_cond_t *cond,
637
pthread_mutex_t* mutex,
621
Is this session viewable by the current user?
623
bool Session::isViewable(identifier::User::const_reference user_arg) const
625
return plugin::Authorization::isAuthorized(user_arg, this, false);
629
const char* Session::enter_cond(boost::condition_variable_any &cond, boost::mutex &mutex, const char* msg)
640
631
const char* old_msg = get_proc_info();
641
632
safe_mutex_assert_owner(mutex);
642
mysys_var->current_mutex = mutex;
643
mysys_var->current_cond = cond;
633
mysys_var->current_mutex = &mutex;
634
mysys_var->current_cond = &cond;
644
635
this->set_proc_info(msg);
653
644
locked (if that would not be the case, you'll get a deadlock if someone
654
645
does a Session::awake() on you).
656
pthread_mutex_unlock(mysys_var->current_mutex);
657
pthread_mutex_lock(&mysys_var->mutex);
647
mysys_var->current_mutex->unlock();
648
boost_unique_lock_t scopedLock(mysys_var->mutex);
658
649
mysys_var->current_mutex = 0;
659
650
mysys_var->current_cond = 0;
660
651
this->set_proc_info(old_msg);
661
pthread_mutex_unlock(&mysys_var->mutex);
664
654
bool Session::authenticate()
667
656
if (client->authenticate())
670
statistic_increment(aborted_connects, &LOCK_status);
659
status_var.aborted_connects++;
674
bool Session::checkUser(const char *passwd, uint32_t passwd_len, const char *in_db)
664
bool Session::checkUser(const std::string &passwd_str,
665
const std::string &in_db)
676
const string passwd_str(passwd, passwd_len);
677
667
bool is_authenticated=
678
plugin::Authentication::isAuthenticated(getSecurityContext(),
668
plugin::Authentication::isAuthenticated(user(), passwd_str);
681
670
if (is_authenticated != true)
672
status_var.access_denied++;
683
673
/* isAuthenticated has pushed the error message */
687
677
/* Change database if necessary */
688
if (in_db && in_db[0])
678
if (not in_db.empty())
690
SchemaIdentifier identifier(in_db);
691
if (mysql_change_db(this, identifier))
680
identifier::Schema identifier(in_db);
681
if (change_db(this, identifier))
693
/* mysql_change_db() has pushed the error message. */
683
/* change_db() has pushed the error message. */
698
password= test(passwd_len); // remember for error messages
688
password= not passwd_str.empty();
700
690
/* Ready to handle queries */
717
707
main_da.reset_diagnostics_area();
719
709
if (client->readCommand(&l_packet, &packet_length) == false)
714
if (getKilled() == KILL_CONNECTION)
722
717
if (packet_length == 0)
725
l_command= (enum enum_server_command) (unsigned char) l_packet[0];
720
l_command= static_cast<enum_server_command>(l_packet[0]);
727
722
if (command >= COM_END)
728
723
command= COM_END; // Wrong command
730
725
assert(packet_length);
731
return ! dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
726
return not dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
734
729
bool Session::readAndStoreQuery(const char *in_packet, uint32_t in_packet_length)
740
735
in_packet_length--;
742
737
const char *pos= in_packet + in_packet_length; /* Point at end null */
743
while (in_packet_length > 0 &&
744
(pos[-1] == ';' || my_isspace(charset() ,pos[-1])))
738
while (in_packet_length > 0 && (pos[-1] == ';' || my_isspace(charset() ,pos[-1])))
747
741
in_packet_length--;
750
query.assign(in_packet, in_packet + in_packet_length);
744
std::string *new_query= new std::string(in_packet, in_packet + in_packet_length);
745
// We can not be entirely sure _schema has a value
748
plugin::QueryRewriter::rewriteQuery(*_schema, *new_query);
750
query.reset(new_query);
751
_state.reset(new State(in_packet, in_packet_length));
952
963
Handling writing to file
953
964
************************************************************************/
955
void select_to_file::send_error(uint32_t errcode,const char *err)
966
void select_to_file::send_error(drizzled::error_t errcode,const char *err)
957
968
my_message(errcode, err, MYF(0));
960
(void) end_io_cache(cache);
971
(void) cache->end_io_cache();
961
972
(void) internal::my_close(file, MYF(0));
962
(void) internal::my_delete(path, MYF(0)); // Delete file on error
973
(void) internal::my_delete(path.file_string().c_str(), MYF(0)); // Delete file on error
1040
static int create_file(Session *session, char *path, file_exchange *exchange, internal::IO_CACHE *cache)
1051
static int create_file(Session *session,
1052
fs::path &target_path,
1053
file_exchange *exchange,
1054
internal::IO_CACHE *cache)
1056
fs::path to_file(exchange->file_name);
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))
1059
if (not to_file.has_root_directory())
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);
1061
target_path= fs::system_complete(getDataHomeCatalog());
1062
util::string::const_shared_ptr schema(session->schema());
1063
if (schema and not schema->empty())
1065
int count_elements= 0;
1066
for (fs::path::iterator iter= to_file.begin();
1067
iter != to_file.end();
1068
++iter, ++count_elements)
1071
if (count_elements == 1)
1073
target_path /= *schema;
1076
target_path /= to_file;
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))
1080
target_path = exchange->file_name;
1083
if (not secure_file_priv.string().empty())
1085
if (target_path.file_string().substr(0, secure_file_priv.file_string().size()) != secure_file_priv.file_string())
1087
/* Write only allowed to dir or subdir specified by secure_file_priv */
1088
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
1093
if (!access(target_path.file_string().c_str(), F_OK))
1069
1095
my_error(ER_FILE_EXISTS_ERROR, MYF(0), exchange->file_name);
1072
1098
/* Create the file world readable */
1073
if ((file= internal::my_create(path, 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
1099
if ((file= internal::my_create(target_path.file_string().c_str(), 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
1075
1101
(void) fchmod(file, 0666); // Because of umask()
1076
if (init_io_cache(cache, file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1102
if (cache->init_io_cache(file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1078
1104
internal::my_close(file, MYF(0));
1079
internal::my_delete(path, MYF(0)); // Delete file on error, it was just created
1105
internal::my_delete(target_path.file_string().c_str(), MYF(0)); // Delete file on error, it was just created
1302
1332
for (; length > sizeof(space) ; length-=sizeof(space))
1304
1334
if (my_b_write(cache,(unsigned char*) space,sizeof(space)))
1307
1337
if (my_b_write(cache,(unsigned char*) space,length))
1311
1341
if (res && enclosed)
1313
1343
if (my_b_write(cache, (unsigned char*) exchange->enclosed->ptr(),
1314
1344
exchange->enclosed->length()))
1317
1347
if (--items_left)
1319
1349
if (my_b_write(cache, (unsigned char*) exchange->field_term->ptr(),
1320
1350
field_term_length))
1324
1354
if (my_b_write(cache,(unsigned char*) exchange->line_term->ptr(),
1325
1355
exchange->line_term->length()))
1488
1517
bool select_max_min_finder_subselect::cmp_decimal()
1490
1519
Item *maxmin= ((Item_singlerow_subselect *)item)->element_index(0);
1491
my_decimal cval, *cvalue= cache->val_decimal(&cval);
1492
my_decimal mval, *mvalue= maxmin->val_decimal(&mval);
1520
type::Decimal cval, *cvalue= cache->val_decimal(&cval);
1521
type::Decimal mval, *mvalue= maxmin->val_decimal(&mval);
1494
1523
return (cache->null_value && !maxmin->null_value) ||
1495
1524
(!cache->null_value && !maxmin->null_value &&
1496
my_decimal_cmp(cvalue, mvalue) > 0) ;
1525
class_decimal_cmp(cvalue, mvalue) > 0) ;
1497
1526
return (maxmin->null_value && !cache->null_value) ||
1498
1527
(!cache->null_value && !maxmin->null_value &&
1499
my_decimal_cmp(cvalue,mvalue) < 0);
1528
class_decimal_cmp(cvalue,mvalue) < 0);
1502
1531
bool select_max_min_finder_subselect::cmp_str()
1538
1567
void Session::end_statement()
1540
1569
/* Cleanup SQL processing state to reuse this statement in next query. */
1571
query_cache_key= ""; // reset the cache key
1572
resetResultsetMessage();
1544
1575
bool Session::copy_db_to(char **p_db, size_t *p_db_length)
1548
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
1551
*p_db= strmake(db.c_str(), db.length());
1552
*p_db_length= db.length();
1578
if (_schema and _schema->empty())
1580
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
1583
else if (not _schema)
1585
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
1590
*p_db= strmake(_schema->c_str(), _schema->size());
1591
*p_db_length= _schema->size();
1592
/****************************************************************************
1593
Handling of open and locked tables states.
1595
This is used when we want to open/lock (and then close) some tables when
1596
we already have a set of tables open and locked. We use these methods for
1597
access to mysql.proc table to find definitions of stored routines.
1598
****************************************************************************/
1600
void Session::reset_n_backup_open_tables_state(Open_tables_state *backup)
1602
backup->set_open_tables_state(this);
1603
reset_open_tables_state();
1604
backups_available= false;
1608
void Session::restore_backup_open_tables_state(Open_tables_state *backup)
1611
Before we will throw away current open tables state we want
1612
to be sure that it was properly cleaned up.
1614
assert(open_tables == 0 && temporary_tables == 0 &&
1615
derived_tables == 0 &&
1617
set_open_tables_state(backup);
1620
bool Session::set_db(const std::string &new_db)
1632
void Session::set_db(const std::string &new_db)
1622
1634
/* Do not reallocate memory if current chunk is big enough. */
1623
1635
if (new_db.length())
1637
_schema.reset(new std::string(new_db));
1635
Check the killed state of a user thread
1636
@param session user thread
1637
@retval 0 the user thread is active
1638
@retval 1 the user thread has been killed
1640
extern "C" int session_killed(const Session *session)
1642
return(session->killed);
1646
Return the session id of a user session
1647
@param pointer to Session object
1648
@return session's id
1650
extern "C" unsigned long session_get_thread_id(const Session *session)
1652
return (unsigned long) session->getSessionId();
1656
const struct charset_info_st *session_charset(Session *session)
1658
return(session->charset());
1661
int session_non_transactional_update(const Session *session)
1663
return(session->transaction.all.hasModifiedNonTransData());
1666
void session_mark_transaction_to_rollback(Session *session, bool all)
1668
mark_transaction_to_rollback(session, all);
1641
_schema.reset(new std::string(""));
1672
1647
Mark transaction to rollback and mark error as fatal to a sub-statement.
1686
void Session::disconnect(uint32_t errcode, bool should_lock)
1661
void Session::disconnect(enum error_t errcode)
1688
1663
/* Allow any plugins to cleanup their session variables */
1689
1664
plugin_sessionvar_cleanup(this);
1691
1666
/* If necessary, log any aborted or unauthorized connections */
1692
if (killed || client->wasAborted())
1693
statistic_increment(aborted_threads, &LOCK_status);
1667
if (getKilled() || client->wasAborted())
1669
status_var.aborted_threads++;
1695
1672
if (client->wasAborted())
1697
if (! killed && variables.log_warnings > 1)
1674
if (not getKilled() && variables.log_warnings > 1)
1699
SecurityContext *sctx= &security_ctx;
1701
1676
errmsg_printf(ERRMSG_LVL_WARN, ER(ER_NEW_ABORTING_CONNECTION)
1703
, (db.empty() ? "unconnected" : db.c_str())
1704
, sctx->getUser().empty() == false ? sctx->getUser().c_str() : "unauthenticated"
1705
, sctx->getIp().c_str()
1678
, (_schema->empty() ? "unconnected" : _schema->c_str())
1679
, security_ctx->username().empty() == false ? security_ctx->username().c_str() : "unauthenticated"
1680
, security_ctx->address().c_str()
1706
1681
, (main_da.is_error() ? main_da.message() : ER(ER_UNKNOWN_ERROR)));
1710
/* Close out our connection to the client */
1712
(void) pthread_mutex_lock(&LOCK_thread_count);
1713
killed= Session::KILL_CONNECTION;
1685
setKilled(Session::KILL_CONNECTION);
1714
1687
if (client->isConnected())
1689
if (errcode != EE_OK)
1718
1691
/*my_error(errcode, ER(errcode));*/
1719
1692
client->sendError(errcode, ER(errcode));
1721
1694
client->close();
1724
(void) pthread_mutex_unlock(&LOCK_thread_count);
1727
1698
void Session::reset_for_next_command()
1801
1776
If this is needed, use close_temporary_table()
1804
void Session::nukeTable(Table *table)
1779
void Open_tables_state::nukeTable(Table *table)
1806
plugin::StorageEngine *table_type= table->s->db_type();
1781
plugin::StorageEngine *table_type= table->getShare()->db_type();
1808
1783
table->free_io_cache();
1809
table->closefrm(false);
1784
table->delete_table();
1811
TableIdentifier identifier(table->s->getSchemaName(), table->s->table_name.str, table->s->path.str);
1786
identifier::Table identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName(), table->getShare()->getPath());
1812
1787
rm_temporary_table(table_type, identifier);
1814
table->s->free_table_share();
1789
boost::checked_delete(table->getMutableShare());
1816
/* This makes me sad, but we're allocating it via malloc */
1791
boost::checked_delete(table);
1820
1794
/** Clear most status variables. */
1821
1795
extern time_t flush_status_time;
1822
extern uint32_t max_used_connections;
1824
1797
void Session::refresh_status()
1826
pthread_mutex_lock(&LOCK_status);
1828
/* Add thread's status variabes to global status */
1829
add_to_status(&global_status_var, &status_var);
1831
1799
/* Reset thread's status variables */
1832
1800
memset(&status_var, 0, sizeof(status_var));
1834
/* Reset some global variables */
1835
reset_status_vars();
1837
/* Reset the counters of all key caches (default and named). */
1838
reset_key_cache_counters();
1839
1802
flush_status_time= time((time_t*) 0);
1840
max_used_connections= 1; /* We set it to one, because we know we exist */
1841
pthread_mutex_unlock(&LOCK_status);
1803
current_global_counters.max_used_connections= 1; /* We set it to one, because we know we exist */
1804
current_global_counters.connections= 0;
1844
1807
user_var_entry *Session::getVariable(LEX_STRING &name, bool create_if_not_exists)
1809
return getVariable(std::string(name.str, name.length), create_if_not_exists);
1812
user_var_entry *Session::getVariable(const std::string &name, bool create_if_not_exists)
1814
UserVarsRange ppp= user_vars.equal_range(name);
1816
for (UserVars::iterator iter= ppp.first;
1817
iter != ppp.second; ++iter)
1819
return (*iter).second;
1822
if (not create_if_not_exists)
1846
1825
user_var_entry *entry= NULL;
1848
entry= (user_var_entry*) hash_search(&user_vars, (unsigned char*) name.str, name.length);
1850
if ((entry == NULL) && create_if_not_exists)
1826
entry= new (nothrow) user_var_entry(name.c_str(), query_id);
1831
std::pair<UserVars::iterator, bool> returnable= user_vars.insert(make_pair(name, entry));
1833
if (not returnable.second)
1852
if (!hash_inited(&user_vars))
1854
entry= new (nothrow) user_var_entry(name.str, query_id);
1859
if (my_hash_insert(&user_vars, (unsigned char*) entry))
1862
free((char*) entry);
1835
boost::checked_delete(entry);
1871
void Session::mark_temp_tables_as_free_for_reuse()
1873
for (Table *table= temporary_tables ; table ; table= table->next)
1841
void Session::setVariable(const std::string &name, const std::string &value)
1843
user_var_entry *updateable_var= getVariable(name.c_str(), true);
1845
updateable_var->update_hash(false,
1846
(void*)value.c_str(),
1847
static_cast<uint32_t>(value.length()), STRING_RESULT,
1849
DERIVATION_IMPLICIT, false);
1852
void Open_tables_state::mark_temp_tables_as_free_for_reuse()
1854
for (Table *table= temporary_tables ; table ; table= table->getNext())
1875
if (table->query_id == query_id)
1856
if (table->query_id == getQueryId())
1877
1858
table->query_id= 0;
1878
1859
table->cursor->ha_reset();
1904
1885
void Session::close_thread_tables()
1909
We are assuming here that session->derived_tables contains ONLY derived
1910
tables for this substatement. i.e. instead of approach which uses
1911
query_id matching for determining which of the derived tables belong
1912
to this substatement we rely on the ability of substatements to
1913
save/restore session->derived_tables during their execution.
1915
TODO: Probably even better approach is to simply associate list of
1916
derived tables with (sub-)statement instead of thread and destroy
1917
them at the end of its execution.
1923
Close all derived tables generated in queries like
1924
SELECT * FROM (SELECT * FROM t1)
1926
for (table= derived_tables ; table ; table= next)
1929
table->free_tmp_table(this);
1887
clearDerivedTables();
1935
1890
Mark all temporary tables used by this statement as free for reuse.
1963
1917
handled either before writing a query log event (inside
1964
1918
binlog_query()) or when preparing a pending event.
1966
mysql_unlock_tables(this, lock);
1970
Note that we need to hold LOCK_open while changing the
1924
Note that we need to hold table::Cache::singleton().mutex() while changing the
1971
1925
open_tables list. Another thread may work on it.
1972
(See: remove_table_from_cache(), mysql_wait_completed_table())
1926
(See: table::Cache::singleton().removeTable(), wait_completed_table())
1973
1927
Closing a MERGE child before the parent would be fatal if the
1974
1928
other thread tries to abort the MERGE lock in between.
2004
1958
if (not lock_tables(tables, counter, &need_reopen))
2006
1961
if (not need_reopen)
2008
1964
close_tables_for_reopen(&tables);
2010
if ((mysql_handle_derived(lex, &mysql_derived_prepare) ||
2011
(fill_derived_tables() &&
2012
mysql_handle_derived(lex, &mysql_derived_filling))))
2018
bool Session::openTables(TableList *tables, uint32_t flags)
2021
bool ret= fill_derived_tables();
2022
assert(ret == false);
2023
if (open_tables_from_list(&tables, &counter, flags) ||
2024
mysql_handle_derived(lex, &mysql_derived_prepare))
2029
bool Session::rm_temporary_table(TableIdentifier &identifier)
2031
if (plugin::StorageEngine::dropTable(*this, identifier))
1967
if ((handle_derived(lex, &derived_prepare) || (handle_derived(lex, &derived_filling))))
1974
@note "best_effort" is used in cases were if a failure occurred on this
1975
operation it would not be surprising because we are only removing because there
1976
might be an issue (lame engines).
1979
bool Open_tables_state::rm_temporary_table(const identifier::Table &identifier, bool best_effort)
1981
if (not plugin::StorageEngine::dropTable(*static_cast<Session *>(this), identifier))
2033
errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
2034
identifier.getSQLPath().c_str(), errno);
2035
dumpTemporaryTableNames("rm_temporary_table()");
1983
if (not best_effort)
1986
identifier.getSQLPath(path);
1987
errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
1988
path.c_str(), errno);
2043
bool Session::rm_temporary_table(plugin::StorageEngine *base, TableIdentifier &identifier)
1997
bool Open_tables_state::rm_temporary_table(plugin::StorageEngine *base, const identifier::Table &identifier)
1999
drizzled::error_t error;
2047
if (plugin::StorageEngine::dropTable(*this, *base, identifier))
2002
if (not plugin::StorageEngine::dropTable(*static_cast<Session *>(this), *base, identifier, error))
2005
identifier.getSQLPath(path);
2049
2006
errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
2050
identifier.getSQLPath().c_str(), errno);
2051
dumpTemporaryTableNames("rm_temporary_table()");
2007
path.c_str(), error);
2070
2026
cerr << "Begin Run: " << foo << "\n";
2071
for (table= temporary_tables; table; table= table->next)
2027
for (table= temporary_tables; table; table= table->getNext())
2073
2029
bool have_proto= false;
2075
message::Table *proto= table->s->getTableProto();
2076
if (table->s->getTableProto())
2031
message::Table *proto= table->getShare()->getTableProto();
2032
if (table->getShare()->getTableProto())
2077
2033
have_proto= true;
2079
2035
const char *answer= have_proto ? "true" : "false";
2081
2037
if (have_proto)
2083
cerr << "\tTable Name " << table->s->getSchemaName() << "." << table->s->table_name.str << " : " << answer << "\n";
2039
cerr << "\tTable Name " << table->getShare()->getSchemaName() << "." << table->getShare()->getTableName() << " : " << answer << "\n";
2084
2040
cerr << "\t\t Proto " << proto->schema() << " " << proto->name() << "\n";
2087
cerr << "\tTabl;e Name " << table->s->getSchemaName() << "." << table->s->table_name.str << " : " << answer << "\n";
2044
cerr << "\tTabl;e Name " << table->getShare()->getSchemaName() << "." << table->getShare()->getTableName() << " : " << answer << "\n";
2091
bool Session::storeTableMessage(TableIdentifier &identifier, message::Table &table_message)
2049
bool Session::TableMessages::storeTableMessage(const identifier::Table &identifier, message::Table &table_message)
2093
2051
table_message_cache.insert(make_pair(identifier.getPath(), table_message));
2098
bool Session::removeTableMessage(TableIdentifier &identifier)
2056
bool Session::TableMessages::removeTableMessage(const identifier::Table &identifier)
2100
2058
TableMessageCache::iterator iter;
2117
table::Singular *Session::getInstanceTable()
2119
temporary_shares.push_back(new table::Singular()); // This will not go into the tableshare cache, so no key is used.
2121
table::Singular *tmp_share= temporary_shares.back();
2130
Create a reduced Table object with properly set up Field list from a
2131
list of field definitions.
2133
The created table doesn't have a table Cursor associated with
2134
it, has no keys, no group/distinct, no copy_funcs array.
2135
The sole purpose of this Table object is to use the power of Field
2136
class to read/write data to/from table->getInsertRecord(). Then one can store
2137
the record in any container (RB tree, hash, etc).
2138
The table is created in Session mem_root, so are the table's fields.
2139
Consequently, if you don't BLOB fields, you don't need to free it.
2141
@param session connection handle
2142
@param field_list list of column definitions
2145
0 if out of memory, Table object in case of success
2147
table::Singular *Session::getInstanceTable(List<CreateField> &field_list)
2149
temporary_shares.push_back(new table::Singular(this, field_list)); // This will not go into the tableshare cache, so no key is used.
2151
table::Singular *tmp_share= temporary_shares.back();
2160
static const std::string NONE= "NONE";
2161
static const std::string GOT_GLOBAL_READ_LOCK= "HAS GLOBAL READ LOCK";
2162
static const std::string MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT= "HAS GLOBAL READ LOCK WITH BLOCKING COMMIT";
2164
const std::string &type(drizzled::Session::global_read_lock_t type)
2170
case Session::GOT_GLOBAL_READ_LOCK:
2171
return GOT_GLOBAL_READ_LOCK;
2172
case Session::MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT:
2173
return MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT;
2177
size_t max_string_length(drizzled::Session::global_read_lock_t)
2179
return MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT.size();
2182
} /* namespace display */
2159
2184
} /* namespace drizzled */