21
21
* @file Implementation of the Session class and API
26
#include <drizzled/copy_field.h>
27
#include <drizzled/data_home.h>
28
#include <drizzled/display.h>
29
#include <drizzled/drizzled.h>
25
#include <drizzled/session.h>
26
#include "drizzled/session_list.h"
30
28
#include <drizzled/error.h>
31
29
#include <drizzled/gettext.h>
32
#include <drizzled/identifier.h>
33
#include <drizzled/internal/iocache.h>
34
#include <drizzled/internal/thread_var.h>
35
#include <drizzled/internal_error_handler.h>
30
#include <drizzled/query_id.h>
31
#include <drizzled/data_home.h>
32
#include <drizzled/sql_base.h>
33
#include <drizzled/lock.h>
36
34
#include <drizzled/item/cache.h>
37
#include <drizzled/item/empty_string.h>
38
35
#include <drizzled/item/float.h>
39
36
#include <drizzled/item/return_int.h>
40
#include <drizzled/lock.h>
41
#include <drizzled/plugin/authentication.h>
37
#include <drizzled/item/empty_string.h>
38
#include <drizzled/show.h>
42
39
#include <drizzled/plugin/client.h>
43
#include <drizzled/plugin/event_observer.h>
44
#include <drizzled/plugin/logging.h>
45
#include <drizzled/plugin/query_rewrite.h>
46
#include <drizzled/plugin/scheduler.h>
47
#include <drizzled/plugin/transactional_storage_engine.h>
48
#include <drizzled/probes.h>
49
#include <drizzled/pthread_globals.h>
50
#include <drizzled/query_id.h>
51
#include <drizzled/refresh_version.h>
52
#include <drizzled/select_dump.h>
53
#include <drizzled/select_exists_subselect.h>
54
#include <drizzled/select_export.h>
55
#include <drizzled/select_max_min_finder_subselect.h>
56
#include <drizzled/select_singlerow_subselect.h>
57
#include <drizzled/select_subselect.h>
58
#include <drizzled/select_to_file.h>
59
#include <drizzled/session.h>
60
#include <drizzled/session/cache.h>
61
#include <drizzled/show.h>
62
#include <drizzled/sql_base.h>
63
#include <drizzled/table/singular.h>
64
#include <drizzled/table_proto.h>
65
#include <drizzled/tmp_table_param.h>
66
#include <drizzled/transaction_services.h>
67
#include <drizzled/user_var_entry.h>
68
#include <drizzled/util/functors.h>
69
#include <plugin/myisam/myisam.h>
40
#include "drizzled/plugin/scheduler.h"
41
#include "drizzled/plugin/authentication.h"
42
#include "drizzled/plugin/logging.h"
43
#include "drizzled/plugin/transactional_storage_engine.h"
44
#include "drizzled/probes.h"
45
#include "drizzled/table_proto.h"
46
#include "drizzled/db.h"
47
#include "drizzled/pthread_globals.h"
48
#include "drizzled/transaction_services.h"
49
#include "drizzled/drizzled.h"
51
#include "drizzled/table_share_instance.h"
53
#include "plugin/myisam/myisam.h"
54
#include "drizzled/internal/iocache.h"
55
#include "drizzled/plugin/event_observer.h"
71
58
#include <algorithm>
76
#include <boost/filesystem.hpp>
77
#include <boost/checked_delete.hpp>
79
#include <drizzled/util/backtrace.h>
81
#include <drizzled/schema.h>
83
61
using namespace std;
85
namespace fs=boost::filesystem;
94
70
char empty_c_string[1]= {0}; /* used for not defined db */
96
72
const char * const Session::DEFAULT_WHERE= "field list";
73
extern pthread_key_t THR_Session;
74
extern pthread_key_t THR_Mem_root;
77
/****************************************************************************
79
****************************************************************************/
80
static unsigned char *get_var_key(user_var_entry *entry, size_t *length, bool)
82
*length= entry->name.length;
83
return (unsigned char*) entry->name.str;
86
static void free_user_var(user_var_entry *entry)
98
91
bool Key_part_spec::operator==(const Key_part_spec& other) const
100
93
return length == other.length &&
101
94
field_name.length == other.field_name.length &&
102
!my_strcasecmp(system_charset_info, field_name.str, other.field_name.str);
95
!strcmp(field_name.str, other.field_name.str);
105
98
Open_tables_state::Open_tables_state(uint64_t version_arg) :
119
int session_tablespace_op(const Session *session)
121
return test(session->tablespace_op);
125
Set the process info field of the Session structure.
127
This function is used by plug-ins. Internally, the
128
Session::set_proc_info() function should be used.
130
@see Session::set_proc_info
132
void set_session_proc_info(Session *session, const char *info)
134
session->set_proc_info(info);
137
const char *get_session_proc_info(Session *session)
139
return session->get_proc_info();
126
142
void **Session::getEngineData(const plugin::MonitoredInTransaction *monitored)
128
144
return static_cast<void **>(&ha_data[monitored->getId()].ha_ptr);
139
155
return session->options & test_options;
142
Session::Session(plugin::Client *client_arg, catalog::Instance::shared_ptr catalog_arg) :
158
int session_sql_command(const Session *session)
160
return (int) session->lex->sql_command;
163
int session_tx_isolation(const Session *session)
165
return (int) session->variables.tx_isolation;
168
Session::Session(plugin::Client *client_arg) :
143
169
Open_tables_state(refresh_version),
144
170
mem_root(&main_mem_root),
147
query(new std::string),
148
_schema(new std::string("")),
149
173
client(client_arg),
151
175
scheduler_arg(NULL),
152
176
lock_id(&main_lock_id),
154
security_ctx(identifier::User::make_shared()),
155
_where(Session::DEFAULT_WHERE),
156
dbug_sentry(Session_SENTRY_MAGIC),
158
command(COM_CONNECT),
160
_epoch(boost::gregorian::date(1970,1,1)),
161
_connect_time(boost::posix_time::microsec_clock::universal_time()),
163
178
ha_data(plugin::num_trx_monitored_objects),
166
concurrent_execute_allowed(true),
167
179
arg_of_last_insert_id_function(false),
168
180
first_successful_insert_id_in_prev_stmt(0),
169
181
first_successful_insert_id_in_cur_stmt(0),
170
182
limit_found_rows(0),
171
options(session_startup_options),
174
examined_row_count(0),
178
statement_id_counter(0),
182
_global_read_lock(NONE),
183
count_cuted_fields(CHECK_FIELD_ERROR_FOR_NULL),
185
184
some_tables_deleted(false),
186
185
no_errors(false),
188
187
is_fatal_error(false),
189
188
transaction_rollback_request(false),
190
189
is_fatal_sub_stmt_error(0),
190
derived_tables_processing(false),
191
191
tablespace_op(false),
192
derived_tables_processing(false),
195
194
transaction_message(NULL),
196
195
statement_message(NULL),
197
session_event_observers(NULL),
198
_catalog(catalog_arg),
196
session_event_observers(NULL)
198
memset(process_list_info, 0, PROCESS_LIST_WIDTH);
201
199
client->setSession(this);
206
204
will be re-initialized in init_for_queries().
208
206
memory::init_sql_alloc(&main_mem_root, memory::ROOT_MIN_BLOCK_SIZE, 0);
208
count_cuted_fields= CHECK_FIELD_IGNORE;
209
213
cuted_fields= sent_row_count= row_count= 0L;
215
statement_id_counter= 0UL;
210
216
// Must be reset to handle error with Session's created for init of mysqld
211
217
lex->current_select= 0;
218
start_time=(time_t) 0;
220
utime_after_lock= 0L;
212
221
memset(&variables, 0, sizeof(variables));
213
227
scoreboard_index= -1;
214
cleanup_done= abort_on_warning= no_warnings_for_error= false;
216
/* query_cache init */
228
dbug_sentry=Session_SENTRY_MAGIC;
229
cleanup_done= abort_on_warning= no_warnings_for_error= false;
230
pthread_mutex_init(&LOCK_delete, MY_MUTEX_INIT_FAST);
220
232
/* Variables with default values */
221
233
proc_info="login";
234
where= Session::DEFAULT_WHERE;
235
command= COM_CONNECT;
223
237
plugin_sessionvar_init(this);
237
252
open_options=ha_open_options;
238
253
update_lock_default= TL_WRITE;
239
254
session_tx_isolation= (enum_tx_isolation) variables.tx_isolation;
241
256
memset(warn_count, 0, sizeof(warn_count));
242
258
memset(&status_var, 0, sizeof(status_var));
244
260
/* Initialize sub structures */
245
261
memory::init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
262
hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
263
(hash_get_key) get_var_key,
264
(hash_free_key) free_user_var, 0);
247
266
substitute_null_with_insert_id = false;
248
lock_info.init(); /* safety: will be reset after start */
267
thr_lock_info_init(&lock_info); /* safety: will be reset after start */
249
268
thr_lock_owner_init(&main_lock_id, &lock_info);
251
270
m_internal_handler= NULL;
285
304
return false; // 'false', as per coding style
288
void Session::setAbort(bool arg)
290
mysys_var->abort= arg;
293
void Session::lockOnSys()
299
boost_unique_lock_t scopedLock(mysys_var->mutex);
300
if (mysys_var->current_cond)
302
mysys_var->current_mutex->lock();
303
mysys_var->current_cond->notify_all();
304
mysys_var->current_mutex->unlock();
308
307
void Session::pop_internal_handler()
310
309
assert(m_internal_handler != NULL);
311
310
m_internal_handler= NULL;
314
void Session::get_xid(DrizzleXid *xid)
313
void Session::get_xid(DRIZZLE_XID *xid)
316
*xid = *(DrizzleXid *) &transaction.xid_state.xid;
315
*xid = *(DRIZZLE_XID *) &transaction.xid_state.xid;
319
318
/* Do operations that may take a long time */
360
347
this->checkSentry();
362
if (client and client->isConnected())
349
if (client->isConnected())
364
assert(security_ctx);
365
351
if (global_system_variables.log_warnings)
367
errmsg_printf(error::WARN, ER(ER_FORCING_CLOSE),
368
internal::my_progname,
370
security_ctx->username().c_str());
352
errmsg_printf(ERRMSG_LVL_WARN, ER(ER_FORCING_CLOSE),internal::my_progname,
354
(getSecurityContext().getUser().c_str() ?
355
getSecurityContext().getUser().c_str() : ""));
356
disconnect(0, false);
376
359
/* Close connection */
380
boost::checked_delete(client);
384
363
if (cleanup_done == false)
392
371
dbug_sentry= Session_SENTRY_GONE;
394
373
main_mem_root.free_root(MYF(0));
395
currentMemRoot().release();
396
currentSession().release();
374
pthread_setspecific(THR_Session, 0);
398
376
plugin::Logging::postEndDo(this);
399
377
plugin::EventObserver::deregisterSessionEvents(*this);
402
void Session::setClient(plugin::Client *client_arg)
405
client->setSession(this);
408
void Session::awake(Session::killed_state_t state_to_set)
410
if ((state_to_set == Session::KILL_QUERY) and (command == COM_SLEEP))
379
/* Ensure that no one is using Session */
380
pthread_mutex_unlock(&LOCK_delete);
381
pthread_mutex_destroy(&LOCK_delete);
384
void Session::awake(Session::killed_state state_to_set)
413
386
this->checkSentry();
415
setKilled(state_to_set);
416
scheduler->killSession(this);
387
safe_mutex_assert_owner(&LOCK_delete);
389
killed= state_to_set;
418
390
if (state_to_set != Session::KILL_QUERY)
392
scheduler->killSession(this);
420
393
DRIZZLE_CONNECTION_DONE(thread_id);
425
boost_unique_lock_t scopedLock(mysys_var->mutex);
397
pthread_mutex_lock(&mysys_var->mutex);
428
399
This broadcast could be up in the air if the victim thread
429
400
exits the cond in the time between read and broadcast, but that is
430
401
ok since all we want to do is to make the victim thread get out
527
495
if (initGlobals() || authenticate())
533
501
prepareForQueries();
535
while (not client->haveError() && getKilled() != KILL_CONNECTION)
503
while (! client->haveError() && killed != KILL_CONNECTION)
537
if (not executeStatement())
505
if (! executeStatement())
544
bool Session::schedule(Session::shared_ptr &arg)
512
bool Session::schedule()
546
arg->scheduler= plugin::Scheduler::getScheduler();
547
assert(arg->scheduler);
551
long current_connections= connection_count;
553
if (current_connections > 0 and static_cast<uint64_t>(current_connections) > current_global_counters.max_used_connections)
555
current_global_counters.max_used_connections= static_cast<uint64_t>(connection_count);
558
current_global_counters.connections++;
559
arg->thread_id= arg->variables.pseudo_thread_id= global_thread_id++;
561
session::Cache::singleton().insert(arg);
563
if (unlikely(plugin::EventObserver::connectSession(*arg)))
565
// We should do something about an error...
568
if (plugin::Scheduler::getScheduler()->addSession(arg))
570
DRIZZLE_CONNECTION_START(arg->getSessionId());
514
scheduler= plugin::Scheduler::getScheduler();
517
connection_count.increment();
519
if (connection_count > current_global_counters.max_used_connections)
521
current_global_counters.max_used_connections= connection_count;
524
thread_id= variables.pseudo_thread_id= global_thread_id++;
526
pthread_mutex_lock(&LOCK_thread_count);
527
getSessionList().push_back(this);
528
pthread_mutex_unlock(&LOCK_thread_count);
530
if (scheduler->addSession(this))
532
DRIZZLE_CONNECTION_START(thread_id);
571
533
char error_message_buff[DRIZZLE_ERRMSG_SIZE];
573
arg->setKilled(Session::KILL_CONNECTION);
535
killed= Session::KILL_CONNECTION;
575
arg->status_var.aborted_connects++;
537
status_var_increment(current_global_counters.aborted_connects);
577
539
/* Can't use my_error() since store_globals has not been called. */
578
540
/* TODO replace will better error message */
579
541
snprintf(error_message_buff, sizeof(error_message_buff),
580
542
ER(ER_CANT_CREATE_THREAD), 1);
581
arg->client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
543
client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
591
Is this session viewable by the current user?
593
bool Session::isViewable(identifier::User::const_reference user_arg) const
595
return plugin::Authorization::isAuthorized(user_arg, *this, false);
599
const char* Session::enter_cond(boost::condition_variable_any &cond, boost::mutex &mutex, const char* msg)
551
const char* Session::enter_cond(pthread_cond_t *cond,
552
pthread_mutex_t* mutex,
601
555
const char* old_msg = get_proc_info();
602
556
safe_mutex_assert_owner(mutex);
603
mysys_var->current_mutex = &mutex;
604
mysys_var->current_cond = &cond;
557
mysys_var->current_mutex = mutex;
558
mysys_var->current_cond = cond;
605
559
this->set_proc_info(msg);
614
568
locked (if that would not be the case, you'll get a deadlock if someone
615
569
does a Session::awake() on you).
617
mysys_var->current_mutex->unlock();
618
boost_unique_lock_t scopedLock(mysys_var->mutex);
571
pthread_mutex_unlock(mysys_var->current_mutex);
572
pthread_mutex_lock(&mysys_var->mutex);
619
573
mysys_var->current_mutex = 0;
620
574
mysys_var->current_cond = 0;
621
575
this->set_proc_info(old_msg);
576
pthread_mutex_unlock(&mysys_var->mutex);
624
579
bool Session::authenticate()
626
582
if (client->authenticate())
629
status_var.aborted_connects++;
585
status_var_increment(current_global_counters.aborted_connects);
634
bool Session::checkUser(const std::string &passwd_str,
635
const std::string &in_db)
589
bool Session::checkUser(const char *passwd, uint32_t passwd_len, const char *in_db)
591
const string passwd_str(passwd, passwd_len);
637
592
bool is_authenticated=
638
plugin::Authentication::isAuthenticated(*user(), passwd_str);
593
plugin::Authentication::isAuthenticated(getSecurityContext(),
640
596
if (is_authenticated != true)
642
status_var.access_denied++;
643
598
/* isAuthenticated has pushed the error message */
647
602
/* Change database if necessary */
648
if (not in_db.empty())
603
if (in_db && in_db[0])
650
identifier::Schema identifier(in_db);
651
if (schema::change(*this, identifier))
605
SchemaIdentifier identifier(in_db);
606
if (mysql_change_db(this, identifier))
653
/* change_db() has pushed the error message. */
608
/* mysql_change_db() has pushed the error message. */
658
password= not passwd_str.empty();
613
password= test(passwd_len); // remember for error messages
660
615
/* Ready to handle queries */
677
632
main_da.reset_diagnostics_area();
679
634
if (client->readCommand(&l_packet, &packet_length) == false)
684
if (getKilled() == KILL_CONNECTION)
687
637
if (packet_length == 0)
690
l_command= static_cast<enum_server_command>(l_packet[0]);
640
l_command= (enum enum_server_command) (unsigned char) l_packet[0];
692
642
if (command >= COM_END)
693
643
command= COM_END; // Wrong command
695
645
assert(packet_length);
696
return not dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
646
return ! dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
699
649
bool Session::readAndStoreQuery(const char *in_packet, uint32_t in_packet_length)
705
655
in_packet_length--;
707
657
const char *pos= in_packet + in_packet_length; /* Point at end null */
708
while (in_packet_length > 0 && (pos[-1] == ';' || my_isspace(charset() ,pos[-1])))
658
while (in_packet_length > 0 &&
659
(pos[-1] == ';' || my_isspace(charset() ,pos[-1])))
711
662
in_packet_length--;
714
std::string *new_query= new std::string(in_packet, in_packet + in_packet_length);
715
// We can not be entirely sure _schema has a value
718
plugin::QueryRewriter::rewriteQuery(*_schema, *new_query);
720
query.reset(new_query);
721
_state.reset(new session::State(in_packet, in_packet_length));
665
query.assign(in_packet, in_packet + in_packet_length);
838
783
first_successful_insert_id_in_cur_stmt= 0;
839
784
substitute_null_with_insert_id= true;
842
786
arg_of_last_insert_id_function= false;
844
787
/* Free Items that were created during this execution */
848
_where= Session::DEFAULT_WHERE;
790
where= Session::DEFAULT_WHERE;
850
792
/* Reset the temporary shares we built */
851
for_each(temporary_shares.begin(),
852
temporary_shares.end(),
793
for (std::vector<TableShareInstance *>::iterator iter= temporary_shares.begin();
794
iter != temporary_shares.end(); iter++)
854
798
temporary_shares.clear();
931
875
Handling writing to file
932
876
************************************************************************/
934
void select_to_file::send_error(drizzled::error_t errcode,const char *err)
878
void select_to_file::send_error(uint32_t errcode,const char *err)
936
880
my_message(errcode, err, MYF(0));
939
(void) cache->end_io_cache();
883
(void) end_io_cache(cache);
940
884
(void) internal::my_close(file, MYF(0));
941
(void) internal::my_delete(path.file_string().c_str(), MYF(0)); // Delete file on error
885
(void) internal::my_delete(path, MYF(0)); // Delete file on error
1019
static int create_file(Session *session,
1020
fs::path &target_path,
1021
file_exchange *exchange,
1022
internal::IO_CACHE *cache)
963
static int create_file(Session *session, char *path, file_exchange *exchange, internal::IO_CACHE *cache)
1024
fs::path to_file(exchange->file_name);
1027
if (not to_file.has_root_directory())
966
uint32_t option= MY_UNPACK_FILENAME | MY_RELATIVE_PATH;
968
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
969
option|= MY_REPLACE_DIR; // Force use of db directory
972
if (!internal::dirname_length(exchange->file_name))
1029
target_path= fs::system_complete(getDataHomeCatalog());
1030
util::string::const_shared_ptr schema(session->schema());
1031
if (schema and not schema->empty())
1033
int count_elements= 0;
1034
for (fs::path::iterator iter= to_file.begin();
1035
iter != to_file.end();
1036
++iter, ++count_elements)
1039
if (count_elements == 1)
1041
target_path /= *schema;
1044
target_path /= to_file;
974
strcpy(path, data_home_real);
975
if (! session->db.empty())
976
strncat(path, session->db.c_str(), FN_REFLEN-strlen(data_home_real)-1);
977
(void) internal::fn_format(path, exchange->file_name, path, "", option);
1048
target_path = exchange->file_name;
1051
if (not secure_file_priv.string().empty())
1053
if (target_path.file_string().substr(0, secure_file_priv.file_string().size()) != secure_file_priv.file_string())
1055
/* Write only allowed to dir or subdir specified by secure_file_priv */
1056
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
1061
if (!access(target_path.file_string().c_str(), F_OK))
980
(void) internal::fn_format(path, exchange->file_name, data_home_real, "", option);
982
if (opt_secure_file_priv &&
983
strncmp(opt_secure_file_priv, path, strlen(opt_secure_file_priv)))
985
/* Write only allowed to dir or subdir specified by secure_file_priv */
986
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
990
if (!access(path, F_OK))
1063
992
my_error(ER_FILE_EXISTS_ERROR, MYF(0), exchange->file_name);
1066
995
/* Create the file world readable */
1067
if ((file= internal::my_create(target_path.file_string().c_str(), 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
996
if ((file= internal::my_create(path, 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
1069
998
(void) fchmod(file, 0666); // Because of umask()
1070
if (cache->init_io_cache(file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
999
if (init_io_cache(cache, file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1072
1001
internal::my_close(file, MYF(0));
1073
internal::my_delete(target_path.file_string().c_str(), MYF(0)); // Delete file on error, it was just created
1002
internal::my_delete(path, MYF(0)); // Delete file on error, it was just created
1300
1225
for (; length > sizeof(space) ; length-=sizeof(space))
1302
1227
if (my_b_write(cache,(unsigned char*) space,sizeof(space)))
1305
1230
if (my_b_write(cache,(unsigned char*) space,length))
1309
1234
if (res && enclosed)
1311
1236
if (my_b_write(cache, (unsigned char*) exchange->enclosed->ptr(),
1312
1237
exchange->enclosed->length()))
1315
1240
if (--items_left)
1317
1242
if (my_b_write(cache, (unsigned char*) exchange->field_term->ptr(),
1318
1243
field_term_length))
1322
1247
if (my_b_write(cache,(unsigned char*) exchange->line_term->ptr(),
1323
1248
exchange->line_term->length()))
1485
1411
bool select_max_min_finder_subselect::cmp_decimal()
1487
1413
Item *maxmin= ((Item_singlerow_subselect *)item)->element_index(0);
1488
type::Decimal cval, *cvalue= cache->val_decimal(&cval);
1489
type::Decimal mval, *mvalue= maxmin->val_decimal(&mval);
1414
my_decimal cval, *cvalue= cache->val_decimal(&cval);
1415
my_decimal mval, *mvalue= maxmin->val_decimal(&mval);
1491
1417
return (cache->null_value && !maxmin->null_value) ||
1492
1418
(!cache->null_value && !maxmin->null_value &&
1493
class_decimal_cmp(cvalue, mvalue) > 0) ;
1419
my_decimal_cmp(cvalue, mvalue) > 0) ;
1494
1420
return (maxmin->null_value && !cache->null_value) ||
1495
1421
(!cache->null_value && !maxmin->null_value &&
1496
class_decimal_cmp(cvalue,mvalue) < 0);
1422
my_decimal_cmp(cvalue,mvalue) < 0);
1499
1425
bool select_max_min_finder_subselect::cmp_str()
1535
1461
void Session::end_statement()
1537
1463
/* Cleanup SQL processing state to reuse this statement in next query. */
1539
query_cache_key= ""; // reset the cache key
1540
resetResultsetMessage();
1543
1467
bool Session::copy_db_to(char **p_db, size_t *p_db_length)
1546
if (_schema and _schema->empty())
1548
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
1551
else if (not _schema)
1553
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
1558
*p_db= strmake(_schema->c_str(), _schema->size());
1559
*p_db_length= _schema->size();
1471
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
1474
*p_db= strmake(db.c_str(), db.length());
1475
*p_db_length= db.length();
1600
void Session::set_db(const std::string &new_db)
1515
bool Session::set_db(const std::string &new_db)
1602
1517
/* Do not reallocate memory if current chunk is big enough. */
1603
1518
if (new_db.length())
1605
_schema.reset(new std::string(new_db));
1609
_schema.reset(new std::string(""));
1530
Check the killed state of a user thread
1531
@param session user thread
1532
@retval 0 the user thread is active
1533
@retval 1 the user thread has been killed
1535
int session_killed(const Session *session)
1537
return(session->killed);
1541
const struct charset_info_st *session_charset(Session *session)
1543
return(session->charset());
1615
1547
Mark transaction to rollback and mark error as fatal to a sub-statement.
1617
1549
@param session Thread handle
1618
1550
@param all true <=> rollback main transaction.
1620
void Session::markTransactionForRollback(bool all)
1552
void mark_transaction_to_rollback(Session *session, bool all)
1622
is_fatal_sub_stmt_error= true;
1623
transaction_rollback_request= all;
1556
session->is_fatal_sub_stmt_error= true;
1557
session->transaction_rollback_request= all;
1626
void Session::disconnect(enum error_t errcode)
1561
void Session::disconnect(uint32_t errcode, bool should_lock)
1628
1563
/* Allow any plugins to cleanup their session variables */
1629
1564
plugin_sessionvar_cleanup(this);
1631
1566
/* If necessary, log any aborted or unauthorized connections */
1632
if (getKilled() || client->wasAborted())
1567
if (killed || client->wasAborted())
1634
status_var.aborted_threads++;
1569
status_var_increment(current_global_counters.aborted_threads);
1637
1572
if (client->wasAborted())
1639
if (not getKilled() && variables.log_warnings > 1)
1574
if (! killed && variables.log_warnings > 1)
1641
errmsg_printf(error::WARN, ER(ER_NEW_ABORTING_CONNECTION)
1576
SecurityContext *sctx= &security_ctx;
1578
errmsg_printf(ERRMSG_LVL_WARN, ER(ER_NEW_ABORTING_CONNECTION)
1643
, (_schema->empty() ? "unconnected" : _schema->c_str())
1644
, security_ctx->username().empty() == false ? security_ctx->username().c_str() : "unauthenticated"
1645
, security_ctx->address().c_str()
1580
, (db.empty() ? "unconnected" : db.c_str())
1581
, sctx->getUser().empty() == false ? sctx->getUser().c_str() : "unauthenticated"
1582
, sctx->getIp().c_str()
1646
1583
, (main_da.is_error() ? main_da.message() : ER(ER_UNKNOWN_ERROR)));
1650
setKilled(Session::KILL_CONNECTION);
1587
/* Close out our connection to the client */
1589
(void) pthread_mutex_lock(&LOCK_thread_count);
1590
killed= Session::KILL_CONNECTION;
1652
1591
if (client->isConnected())
1654
if (errcode != EE_OK)
1656
1595
/*my_error(errcode, ER(errcode));*/
1657
1596
client->sendError(errcode, ER(errcode));
1659
1598
client->close();
1601
(void) pthread_mutex_unlock(&LOCK_thread_count);
1663
1604
void Session::reset_for_next_command()
1741
1682
If this is needed, use close_temporary_table()
1744
void Open_tables_state::nukeTable(Table *table)
1685
void Session::nukeTable(Table *table)
1746
1687
plugin::StorageEngine *table_type= table->getShare()->db_type();
1748
1689
table->free_io_cache();
1749
table->delete_table();
1690
table->delete_table(false);
1751
identifier::Table identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName(), table->getShare()->getPath());
1692
TableIdentifier identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName(), table->getShare()->getPath());
1752
1693
rm_temporary_table(table_type, identifier);
1754
boost::checked_delete(table->getMutableShare());
1695
delete table->getMutableShare();
1756
boost::checked_delete(table);
1697
/* This makes me sad, but we're allocating it via malloc */
1759
1701
/** Clear most status variables. */
1762
1704
void Session::refresh_status()
1706
pthread_mutex_lock(&LOCK_status);
1764
1708
/* Reset thread's status variables */
1765
1709
memset(&status_var, 0, sizeof(status_var));
1711
/* Reset the counters of all key caches (default and named). */
1712
reset_key_cache_counters();
1767
1713
flush_status_time= time((time_t*) 0);
1768
1714
current_global_counters.max_used_connections= 1; /* We set it to one, because we know we exist */
1769
current_global_counters.connections= 0;
1715
pthread_mutex_unlock(&LOCK_status);
1772
1718
user_var_entry *Session::getVariable(LEX_STRING &name, bool create_if_not_exists)
1774
return getVariable(std::string(name.str, name.length), create_if_not_exists);
1777
user_var_entry *Session::getVariable(const std::string &name, bool create_if_not_exists)
1782
UserVars::iterator iter= user_vars.find(name);
1783
if (iter != user_vars.end())
1784
return (*iter).second;
1786
if (not create_if_not_exists)
1789
1720
user_var_entry *entry= NULL;
1790
entry= new (nothrow) user_var_entry(name.c_str(), query_id);
1795
std::pair<UserVars::iterator, bool> returnable= user_vars.insert(make_pair(name, entry));
1797
if (not returnable.second)
1722
entry= (user_var_entry*) hash_search(&user_vars, (unsigned char*) name.str, name.length);
1724
if ((entry == NULL) && create_if_not_exists)
1799
boost::checked_delete(entry);
1726
if (!hash_inited(&user_vars))
1728
entry= new (nothrow) user_var_entry(name.str, query_id);
1733
if (my_hash_insert(&user_vars, (unsigned char*) entry))
1805
void Session::setVariable(const std::string &name, const std::string &value)
1807
user_var_entry *updateable_var= getVariable(name.c_str(), true);
1810
updateable_var->update_hash(false,
1811
(void*)value.c_str(),
1812
static_cast<uint32_t>(value.length()), STRING_RESULT,
1814
DERIVATION_IMPLICIT, false);
1818
void Open_tables_state::mark_temp_tables_as_free_for_reuse()
1745
void Session::mark_temp_tables_as_free_for_reuse()
1820
1747
for (Table *table= temporary_tables ; table ; table= table->getNext())
1822
if (table->query_id == getQueryId())
1749
if (table->query_id == query_id)
1824
1751
table->query_id= 0;
1825
1752
table->cursor->ha_reset();
1883
1811
handled either before writing a query log event (inside
1884
1812
binlog_query()) or when preparing a pending event.
1814
mysql_unlock_tables(this, lock);
1890
Note that we need to hold table::Cache::singleton().mutex() while changing the
1818
Note that we need to hold LOCK_open while changing the
1891
1819
open_tables list. Another thread may work on it.
1892
(See: table::Cache::singleton().removeTable(), wait_completed_table())
1820
(See: remove_table_from_cache(), mysql_wait_completed_table())
1893
1821
Closing a MERGE child before the parent would be fatal if the
1894
1822
other thread tries to abort the MERGE lock in between.
1924
1852
if (not lock_tables(tables, counter, &need_reopen))
1927
1854
if (not need_reopen)
1930
1856
close_tables_for_reopen(&tables);
1933
if ((handle_derived(lex, &derived_prepare) || (handle_derived(lex, &derived_filling))))
1858
if ((mysql_handle_derived(lex, &mysql_derived_prepare) ||
1859
(fill_derived_tables() &&
1860
mysql_handle_derived(lex, &mysql_derived_filling))))
1866
bool Session::openTables(TableList *tables, uint32_t flags)
1869
bool ret= fill_derived_tables();
1870
assert(ret == false);
1871
if (open_tables_from_list(&tables, &counter, flags) ||
1872
mysql_handle_derived(lex, &mysql_derived_prepare))
1942
1882
might be an issue (lame engines).
1945
bool Open_tables_state::rm_temporary_table(const identifier::Table &identifier, bool best_effort)
1885
bool Session::rm_temporary_table(TableIdentifier &identifier, bool best_effort)
1947
if (not plugin::StorageEngine::dropTable(*static_cast<Session *>(this), identifier))
1887
if (plugin::StorageEngine::dropTable(*this, identifier))
1949
1889
if (not best_effort)
1952
identifier.getSQLPath(path);
1953
errmsg_printf(error::WARN, _("Could not remove temporary table: '%s', error: %d"),
1954
path.c_str(), errno);
1891
errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
1892
identifier.getSQLPath().c_str(), errno);
1963
bool Open_tables_state::rm_temporary_table(plugin::StorageEngine *base, const identifier::Table &identifier)
1901
bool Session::rm_temporary_table(plugin::StorageEngine *base, TableIdentifier &identifier)
1965
drizzled::error_t error;
1968
if (not plugin::StorageEngine::dropTable(*static_cast<Session *>(this), *base, identifier, error))
1905
if (plugin::StorageEngine::dropTable(*this, *base, identifier))
1971
identifier.getSQLPath(path);
1972
errmsg_printf(error::WARN, _("Could not remove temporary table: '%s', error: %d"),
1973
path.c_str(), error);
1907
errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
1908
identifier.getSQLPath().c_str(), errno);
2006
1941
cerr << "\t\t Proto " << proto->schema() << " " << proto->name() << "\n";
2010
1944
cerr << "\tTabl;e Name " << table->getShare()->getSchemaName() << "." << table->getShare()->getTableName() << " : " << answer << "\n";
2015
table::Singular *Session::getInstanceTable()
2017
temporary_shares.push_back(new table::Singular()); // This will not go into the tableshare cache, so no key is used.
2019
table::Singular *tmp_share= temporary_shares.back();
2028
Create a reduced Table object with properly set up Field list from a
2029
list of field definitions.
2031
The created table doesn't have a table Cursor associated with
2032
it, has no keys, no group/distinct, no copy_funcs array.
2033
The sole purpose of this Table object is to use the power of Field
2034
class to read/write data to/from table->getInsertRecord(). Then one can store
2035
the record in any container (RB tree, hash, etc).
2036
The table is created in Session mem_root, so are the table's fields.
2037
Consequently, if you don't BLOB fields, you don't need to free it.
2039
@param session connection handle
2040
@param field_list list of column definitions
2043
0 if out of memory, Table object in case of success
2045
table::Singular *Session::getInstanceTable(List<CreateField> &field_list)
2047
temporary_shares.push_back(new table::Singular(this, field_list)); // This will not go into the tableshare cache, so no key is used.
2049
table::Singular *tmp_share= temporary_shares.back();
2058
static const std::string NONE= "NONE";
2059
static const std::string GOT_GLOBAL_READ_LOCK= "HAS GLOBAL READ LOCK";
2060
static const std::string MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT= "HAS GLOBAL READ LOCK WITH BLOCKING COMMIT";
2062
const std::string &type(drizzled::Session::global_read_lock_t type)
2068
case Session::GOT_GLOBAL_READ_LOCK:
2069
return GOT_GLOBAL_READ_LOCK;
2070
case Session::MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT:
2071
return MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT;
2075
size_t max_string_length(drizzled::Session::global_read_lock_t)
2077
return MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT.size();
2080
} /* namespace display */
1948
bool Session::storeTableMessage(TableIdentifier &identifier, message::Table &table_message)
1950
table_message_cache.insert(make_pair(identifier.getPath(), table_message));
1955
bool Session::removeTableMessage(TableIdentifier &identifier)
1957
TableMessageCache::iterator iter;
1959
iter= table_message_cache.find(identifier.getPath());
1961
if (iter == table_message_cache.end())
1964
table_message_cache.erase(iter);
1969
bool Session::getTableMessage(TableIdentifier &identifier, message::Table &table_message)
1971
TableMessageCache::iterator iter;
1973
iter= table_message_cache.find(identifier.getPath());
1975
if (iter == table_message_cache.end())
1978
table_message.CopyFrom(((*iter).second));
1983
bool Session::doesTableMessageExist(TableIdentifier &identifier)
1985
TableMessageCache::iterator iter;
1987
iter= table_message_cache.find(identifier.getPath());
1989
if (iter == table_message_cache.end())
1997
bool Session::renameTableMessage(TableIdentifier &from, TableIdentifier &to)
1999
TableMessageCache::iterator iter;
2001
table_message_cache[to.getPath()]= table_message_cache[from.getPath()];
2003
iter= table_message_cache.find(to.getPath());
2005
if (iter == table_message_cache.end())
2010
(*iter).second.set_schema(to.getSchemaName());
2011
(*iter).second.set_name(to.getTableName());
2016
TableShareInstance *Session::getTemporaryShare(TableIdentifier::Type type_arg)
2018
temporary_shares.push_back(new TableShareInstance(type_arg)); // This will not go into the tableshare cache, so no key is used.
2020
TableShareInstance *tmp_share= temporary_shares.back();
2082
2027
} /* namespace drizzled */