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"
50
#include "plugin/myisam/myisam.h"
51
#include "drizzled/internal/iocache.h"
71
54
#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
57
using namespace std;
85
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);
90
68
The following is used to initialise Table_ident with a internal
94
72
char empty_c_string[1]= {0}; /* used for not defined db */
96
74
const char * const Session::DEFAULT_WHERE= "field list";
75
extern pthread_key_t THR_Session;
76
extern pthread_key_t THR_Mem_root;
77
extern uint32_t max_used_connections;
78
extern atomic<uint32_t> connection_count;
81
/****************************************************************************
83
****************************************************************************/
84
unsigned char *get_var_key(user_var_entry *entry, size_t *length, bool )
86
*length= entry->name.length;
87
return (unsigned char*) entry->name.str;
90
void free_user_var(user_var_entry *entry)
98
95
bool Key_part_spec::operator==(const Key_part_spec& other) const
100
97
return length == other.length &&
101
98
field_name.length == other.field_name.length &&
102
!my_strcasecmp(system_charset_info, field_name.str, other.field_name.str);
99
!strcmp(field_name.str, other.field_name.str);
105
Open_tables_state::Open_tables_state(uint64_t version_arg) :
102
Open_tables_state::Open_tables_state(uint64_t version_arg)
103
:version(version_arg), backups_available(false)
108
open_tables= temporary_tables= derived_tables= NULL;
109
extra_lock= lock= NULL;
105
reset_open_tables_state();
113
109
The following functions form part of the C plugin API
115
int tmpfile(const char *prefix)
111
extern "C" int mysql_tmpfile(const char *prefix)
117
113
char filename[FN_REFLEN];
118
int fd = internal::create_temp_file(filename, drizzle_tmpdir.c_str(), prefix, MYF(MY_WME));
114
int fd = internal::create_temp_file(filename, drizzle_tmpdir, prefix, MYF(MY_WME));
120
116
unlink(filename);
123
int session_tablespace_op(const Session *session)
125
return test(session->tablespace_op);
129
Set the process info field of the Session structure.
131
This function is used by plug-ins. Internally, the
132
Session::set_proc_info() function should be used.
134
@see Session::set_proc_info
137
set_session_proc_info(Session *session, const char *info)
139
session->set_proc_info(info);
143
const char *get_session_proc_info(Session *session)
145
return session->get_proc_info();
126
148
void **Session::getEngineData(const plugin::MonitoredInTransaction *monitored)
128
150
return static_cast<void **>(&ha_data[monitored->getId()].ha_ptr);
134
156
return &ha_data[monitored->getId()].resource_context[index];
137
160
int64_t session_test_options(const Session *session, int64_t test_options)
139
162
return session->options & test_options;
142
Session::Session(plugin::Client *client_arg, catalog::Instance::shared_ptr catalog_arg) :
166
int session_sql_command(const Session *session)
168
return (int) session->lex->sql_command;
172
int session_tx_isolation(const Session *session)
174
return (int) session->variables.tx_isolation;
177
Session::Session(plugin::Client *client_arg)
143
179
Open_tables_state(refresh_version),
144
180
mem_root(&main_mem_root),
147
query(new std::string),
148
_schema(new std::string("")),
149
183
client(client_arg),
151
185
scheduler_arg(NULL),
152
186
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
188
ha_data(plugin::num_trx_monitored_objects),
166
concurrent_execute_allowed(true),
167
189
arg_of_last_insert_id_function(false),
168
190
first_successful_insert_id_in_prev_stmt(0),
169
191
first_successful_insert_id_in_cur_stmt(0),
170
192
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
194
some_tables_deleted(false),
186
195
no_errors(false),
188
197
is_fatal_error(false),
189
198
transaction_rollback_request(false),
190
199
is_fatal_sub_stmt_error(0),
200
derived_tables_processing(false),
191
201
tablespace_op(false),
192
derived_tables_processing(false),
195
204
transaction_message(NULL),
196
statement_message(NULL),
197
session_event_observers(NULL),
198
_catalog(catalog_arg),
205
statement_message(NULL)
207
memset(process_list_info, 0, PROCESS_LIST_WIDTH);
201
208
client->setSession(this);
206
213
will be re-initialized in init_for_queries().
208
215
memory::init_sql_alloc(&main_mem_root, memory::ROOT_MIN_BLOCK_SIZE, 0);
217
count_cuted_fields= CHECK_FIELD_IGNORE;
209
222
cuted_fields= sent_row_count= row_count= 0L;
224
statement_id_counter= 0UL;
210
225
// Must be reset to handle error with Session's created for init of mysqld
211
226
lex->current_select= 0;
227
start_time=(time_t) 0;
229
utime_after_lock= 0L;
212
230
memset(&variables, 0, sizeof(variables));
213
scoreboard_index= -1;
214
cleanup_done= abort_on_warning= no_warnings_for_error= false;
216
/* query_cache init */
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);
220
240
/* Variables with default values */
221
241
proc_info="login";
242
where= Session::DEFAULT_WHERE;
243
command= COM_CONNECT;
223
245
plugin_sessionvar_init(this);
237
260
open_options=ha_open_options;
238
261
update_lock_default= TL_WRITE;
239
262
session_tx_isolation= (enum_tx_isolation) variables.tx_isolation;
241
264
memset(warn_count, 0, sizeof(warn_count));
242
266
memset(&status_var, 0, sizeof(status_var));
244
268
/* Initialize sub structures */
245
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);
247
274
substitute_null_with_insert_id = false;
248
lock_info.init(); /* safety: will be reset after start */
275
thr_lock_info_init(&lock_info); /* safety: will be reset after start */
249
276
thr_lock_owner_init(&main_lock_id, &lock_info);
251
278
m_internal_handler= NULL;
253
plugin::EventObserver::registerSessionEvents(*this);
256
281
void Session::free_items()
285
310
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
313
void Session::pop_internal_handler()
310
315
assert(m_internal_handler != NULL);
311
316
m_internal_handler= NULL;
314
void Session::get_xid(DrizzleXid *xid)
316
*xid = *(DrizzleXid *) &transaction.xid_state.xid;
319
#if defined(__cplusplus)
323
void *session_alloc(Session *session, unsigned int size)
325
return session->alloc(size);
328
void *session_calloc(Session *session, unsigned int size)
330
return session->calloc(size);
333
char *session_strdup(Session *session, const char *str)
335
return session->strdup(str);
338
char *session_strmake(Session *session, const char *str, unsigned int size)
340
return session->strmake(str, size);
343
void *session_memdup(Session *session, const void* str, unsigned int size)
345
return session->memdup(str, size);
348
void session_get_xid(const Session *session, DRIZZLE_XID *xid)
350
*xid = *(DRIZZLE_XID *) &session->transaction.xid_state.xid;
353
#if defined(__cplusplus)
319
357
/* Do operations that may take a long time */
358
384
Session::~Session()
360
386
this->checkSentry();
387
add_to_status(&global_status_var, &status_var);
362
if (client and client->isConnected())
389
if (client->isConnected())
364
assert(security_ctx);
365
391
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());
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);
376
399
/* Close connection */
380
boost::checked_delete(client);
384
403
if (cleanup_done == false)
387
406
plugin::StorageEngine::closeConnection(this);
388
407
plugin_sessionvar_cleanup(this);
390
warn_root.free_root(MYF(0));
409
free_root(&warn_root,MYF(0));
391
410
mysys_var=0; // Safety (shouldn't be needed)
392
411
dbug_sentry= Session_SENTRY_GONE;
394
main_mem_root.free_root(MYF(0));
395
currentMemRoot().release();
396
currentSession().release();
413
free_root(&main_mem_root, MYF(0));
414
pthread_setspecific(THR_Session, 0);
398
416
plugin::Logging::postEndDo(this);
399
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))
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)
413
473
this->checkSentry();
415
setKilled(state_to_set);
416
scheduler->killSession(this);
474
safe_mutex_assert_owner(&LOCK_delete);
476
killed= state_to_set;
418
477
if (state_to_set != Session::KILL_QUERY)
479
scheduler->killSession(this);
420
480
DRIZZLE_CONNECTION_DONE(thread_id);
425
boost_unique_lock_t scopedLock(mysys_var->mutex);
484
pthread_mutex_lock(&mysys_var->mutex);
428
486
This broadcast could be up in the air if the victim thread
429
487
exits the cond in the time between read and broadcast, but that is
430
488
ok since all we want to do is to make the victim thread get out
503
560
command= COM_SLEEP;
506
mem_root->reset_root_defaults(variables.query_alloc_block_size,
507
variables.query_prealloc_size);
563
reset_root_defaults(mem_root, variables.query_alloc_block_size,
564
variables.query_prealloc_size);
508
565
transaction.xid_state.xid.null();
509
566
transaction.xid_state.in_session=1;
514
569
bool Session::initGlobals()
516
571
if (storeGlobals())
518
disconnect(ER_OUT_OF_RESOURCES);
519
status_var.aborted_connects++;
573
disconnect(ER_OUT_OF_RESOURCES, true);
574
statistic_increment(aborted_connects, &LOCK_status);
527
582
if (initGlobals() || authenticate())
533
588
prepareForQueries();
535
while (not client->haveError() && getKilled() != KILL_CONNECTION)
590
while (! client->haveError() && killed != KILL_CONNECTION)
537
if (not executeStatement())
592
if (! executeStatement())
544
bool Session::schedule(Session::shared_ptr &arg)
599
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());
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);
571
618
char error_message_buff[DRIZZLE_ERRMSG_SIZE];
573
arg->setKilled(Session::KILL_CONNECTION);
620
killed= Session::KILL_CONNECTION;
575
arg->status_var.aborted_connects++;
622
statistic_increment(aborted_connects, &LOCK_status);
577
624
/* Can't use my_error() since store_globals has not been called. */
578
625
/* TODO replace will better error message */
579
626
snprintf(error_message_buff, sizeof(error_message_buff),
580
627
ER(ER_CANT_CREATE_THREAD), 1);
581
arg->client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
628
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)
636
const char* Session::enter_cond(pthread_cond_t *cond,
637
pthread_mutex_t* mutex,
601
640
const char* old_msg = get_proc_info();
602
641
safe_mutex_assert_owner(mutex);
603
mysys_var->current_mutex = &mutex;
604
mysys_var->current_cond = &cond;
642
mysys_var->current_mutex = mutex;
643
mysys_var->current_cond = cond;
605
644
this->set_proc_info(msg);
614
653
locked (if that would not be the case, you'll get a deadlock if someone
615
654
does a Session::awake() on you).
617
mysys_var->current_mutex->unlock();
618
boost_unique_lock_t scopedLock(mysys_var->mutex);
656
pthread_mutex_unlock(mysys_var->current_mutex);
657
pthread_mutex_lock(&mysys_var->mutex);
619
658
mysys_var->current_mutex = 0;
620
659
mysys_var->current_cond = 0;
621
660
this->set_proc_info(old_msg);
661
pthread_mutex_unlock(&mysys_var->mutex);
624
664
bool Session::authenticate()
626
667
if (client->authenticate())
629
status_var.aborted_connects++;
670
statistic_increment(aborted_connects, &LOCK_status);
634
bool Session::checkUser(const std::string &passwd_str,
635
const std::string &in_db)
674
bool Session::checkUser(const char *passwd, uint32_t passwd_len, const char *in_db)
676
const string passwd_str(passwd, passwd_len);
637
677
bool is_authenticated=
638
plugin::Authentication::isAuthenticated(*user(), passwd_str);
678
plugin::Authentication::isAuthenticated(getSecurityContext(),
640
681
if (is_authenticated != true)
642
status_var.access_denied++;
643
683
/* isAuthenticated has pushed the error message */
647
687
/* Change database if necessary */
648
if (not in_db.empty())
688
if (in_db && in_db[0])
650
identifier::Schema identifier(in_db);
651
if (schema::change(*this, identifier))
690
SchemaIdentifier identifier(in_db);
691
if (mysql_change_db(this, identifier))
653
/* change_db() has pushed the error message. */
693
/* mysql_change_db() has pushed the error message. */
658
password= not passwd_str.empty();
698
password= test(passwd_len); // remember for error messages
660
700
/* Ready to handle queries */
677
717
main_da.reset_diagnostics_area();
679
719
if (client->readCommand(&l_packet, &packet_length) == false)
684
if (getKilled() == KILL_CONNECTION)
687
722
if (packet_length == 0)
690
l_command= static_cast<enum_server_command>(l_packet[0]);
725
l_command= (enum enum_server_command) (unsigned char) l_packet[0];
692
727
if (command >= COM_END)
693
728
command= COM_END; // Wrong command
695
730
assert(packet_length);
696
return not dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
731
return ! dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
699
734
bool Session::readAndStoreQuery(const char *in_packet, uint32_t in_packet_length)
705
740
in_packet_length--;
707
742
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])))
743
while (in_packet_length > 0 &&
744
(pos[-1] == ';' || my_isspace(charset() ,pos[-1])))
711
747
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));
750
query.assign(in_packet, in_packet + in_packet_length);
931
952
Handling writing to file
932
953
************************************************************************/
934
void select_to_file::send_error(drizzled::error_t errcode,const char *err)
955
void select_to_file::send_error(uint32_t errcode,const char *err)
936
957
my_message(errcode, err, MYF(0));
939
(void) cache->end_io_cache();
960
(void) end_io_cache(cache);
940
961
(void) internal::my_close(file, MYF(0));
941
(void) internal::my_delete(path.file_string().c_str(), MYF(0)); // Delete file on error
962
(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)
1040
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())
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))
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;
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);
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))
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))
1063
1069
my_error(ER_FILE_EXISTS_ERROR, MYF(0), exchange->file_name);
1066
1072
/* 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)
1073
if ((file= internal::my_create(path, 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
1069
1075
(void) fchmod(file, 0666); // Because of umask()
1070
if (cache->init_io_cache(file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1076
if (init_io_cache(cache, file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1072
1078
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
1079
internal::my_delete(path, MYF(0)); // Delete file on error, it was just created
1300
1302
for (; length > sizeof(space) ; length-=sizeof(space))
1302
1304
if (my_b_write(cache,(unsigned char*) space,sizeof(space)))
1305
1307
if (my_b_write(cache,(unsigned char*) space,length))
1309
1311
if (res && enclosed)
1311
1313
if (my_b_write(cache, (unsigned char*) exchange->enclosed->ptr(),
1312
1314
exchange->enclosed->length()))
1315
1317
if (--items_left)
1317
1319
if (my_b_write(cache, (unsigned char*) exchange->field_term->ptr(),
1318
1320
field_term_length))
1322
1324
if (my_b_write(cache,(unsigned char*) exchange->line_term->ptr(),
1323
1325
exchange->line_term->length()))
1485
1488
bool select_max_min_finder_subselect::cmp_decimal()
1487
1490
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);
1491
my_decimal cval, *cvalue= cache->val_decimal(&cval);
1492
my_decimal mval, *mvalue= maxmin->val_decimal(&mval);
1491
1494
return (cache->null_value && !maxmin->null_value) ||
1492
1495
(!cache->null_value && !maxmin->null_value &&
1493
class_decimal_cmp(cvalue, mvalue) > 0) ;
1496
my_decimal_cmp(cvalue, mvalue) > 0) ;
1494
1497
return (maxmin->null_value && !cache->null_value) ||
1495
1498
(!cache->null_value && !maxmin->null_value &&
1496
class_decimal_cmp(cvalue,mvalue) < 0);
1499
my_decimal_cmp(cvalue,mvalue) < 0);
1499
1502
bool select_max_min_finder_subselect::cmp_str()
1535
1538
void Session::end_statement()
1537
1540
/* Cleanup SQL processing state to reuse this statement in next query. */
1539
query_cache_key= ""; // reset the cache key
1540
resetResultsetMessage();
1543
1544
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();
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();
1600
void Session::set_db(const std::string &new_db)
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)
1602
1622
/* Do not reallocate memory if current chunk is big enough. */
1603
1623
if (new_db.length())
1605
_schema.reset(new std::string(new_db));
1609
_schema.reset(new std::string(""));
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);
1615
1672
Mark transaction to rollback and mark error as fatal to a sub-statement.
1617
1674
@param session Thread handle
1618
1675
@param all true <=> rollback main transaction.
1620
void Session::markTransactionForRollback(bool all)
1677
void mark_transaction_to_rollback(Session *session, bool all)
1622
is_fatal_sub_stmt_error= true;
1623
transaction_rollback_request= all;
1681
session->is_fatal_sub_stmt_error= true;
1682
session->transaction_rollback_request= all;
1626
void Session::disconnect(enum error_t errcode)
1686
void Session::disconnect(uint32_t errcode, bool should_lock)
1628
1688
/* Allow any plugins to cleanup their session variables */
1629
1689
plugin_sessionvar_cleanup(this);
1631
1691
/* If necessary, log any aborted or unauthorized connections */
1632
if (getKilled() || client->wasAborted())
1634
status_var.aborted_threads++;
1692
if (killed || client->wasAborted())
1693
statistic_increment(aborted_threads, &LOCK_status);
1637
1695
if (client->wasAborted())
1639
if (not getKilled() && variables.log_warnings > 1)
1697
if (! killed && variables.log_warnings > 1)
1641
errmsg_printf(error::WARN, ER(ER_NEW_ABORTING_CONNECTION)
1699
SecurityContext *sctx= &security_ctx;
1701
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()
1703
, (db.empty() ? "unconnected" : db.c_str())
1704
, sctx->getUser().empty() == false ? sctx->getUser().c_str() : "unauthenticated"
1705
, sctx->getIp().c_str()
1646
1706
, (main_da.is_error() ? main_da.message() : ER(ER_UNKNOWN_ERROR)));
1650
setKilled(Session::KILL_CONNECTION);
1710
/* Close out our connection to the client */
1712
(void) pthread_mutex_lock(&LOCK_thread_count);
1713
killed= Session::KILL_CONNECTION;
1652
1714
if (client->isConnected())
1654
if (errcode != EE_OK)
1656
1718
/*my_error(errcode, ER(errcode));*/
1657
1719
client->sendError(errcode, ER(errcode));
1659
1721
client->close();
1724
(void) pthread_mutex_unlock(&LOCK_thread_count);
1663
1727
void Session::reset_for_next_command()
1741
1801
If this is needed, use close_temporary_table()
1744
void Open_tables_state::nukeTable(Table *table)
1804
void Session::nukeTable(Table *table)
1746
plugin::StorageEngine *table_type= table->getShare()->db_type();
1806
plugin::StorageEngine *table_type= table->s->db_type();
1748
1808
table->free_io_cache();
1749
table->delete_table();
1809
table->closefrm(false);
1751
identifier::Table identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName(), table->getShare()->getPath());
1811
TableIdentifier identifier(table->s->getSchemaName(), table->s->table_name.str, table->s->path.str);
1752
1812
rm_temporary_table(table_type, identifier);
1754
boost::checked_delete(table->getMutableShare());
1814
table->s->free_table_share();
1756
boost::checked_delete(table);
1816
/* This makes me sad, but we're allocating it via malloc */
1759
1820
/** Clear most status variables. */
1760
1821
extern time_t flush_status_time;
1822
extern uint32_t max_used_connections;
1762
1824
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);
1764
1831
/* Reset thread's status variables */
1765
1832
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();
1767
1839
flush_status_time= time((time_t*) 0);
1768
current_global_counters.max_used_connections= 1; /* We set it to one, because we know we exist */
1769
current_global_counters.connections= 0;
1840
max_used_connections= 1; /* We set it to one, because we know we exist */
1841
pthread_mutex_unlock(&LOCK_status);
1772
1844
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
1846
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)
1848
entry= (user_var_entry*) hash_search(&user_vars, (unsigned char*) name.str, name.length);
1850
if ((entry == NULL) && create_if_not_exists)
1799
boost::checked_delete(entry);
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);
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()
1820
for (Table *table= temporary_tables ; table ; table= table->getNext())
1822
if (table->query_id == getQueryId())
1871
void Session::mark_temp_tables_as_free_for_reuse()
1873
for (Table *table= temporary_tables ; table ; table= table->next)
1875
if (table->query_id == query_id)
1824
1877
table->query_id= 0;
1825
1878
table->cursor->ha_reset();
1851
1904
void Session::close_thread_tables()
1853
clearDerivedTables();
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);
1856
1935
Mark all temporary tables used by this statement as free for reuse.
1924
2004
if (not lock_tables(tables, counter, &need_reopen))
1927
2006
if (not need_reopen)
1930
2008
close_tables_for_reopen(&tables);
1933
if ((handle_derived(lex, &derived_prepare) || (handle_derived(lex, &derived_filling))))
1940
@note "best_effort" is used in cases were if a failure occurred on this
1941
operation it would not be surprising because we are only removing because there
1942
might be an issue (lame engines).
1945
bool Open_tables_state::rm_temporary_table(const identifier::Table &identifier, bool best_effort)
1947
if (not plugin::StorageEngine::dropTable(*static_cast<Session *>(this), identifier))
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))
1949
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);
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()");
1963
bool Open_tables_state::rm_temporary_table(plugin::StorageEngine *base, const identifier::Table &identifier)
2043
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))
2047
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);
2049
errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
2050
identifier.getSQLPath().c_str(), errno);
2051
dumpTemporaryTableNames("rm_temporary_table()");
1992
2070
cerr << "Begin Run: " << foo << "\n";
1993
for (table= temporary_tables; table; table= table->getNext())
2071
for (table= temporary_tables; table; table= table->next)
1995
2073
bool have_proto= false;
1997
message::Table *proto= table->getShare()->getTableMessage();
1998
if (table->getShare()->getTableMessage())
2075
message::Table *proto= table->s->getTableProto();
2076
if (table->s->getTableProto())
1999
2077
have_proto= true;
2001
2079
const char *answer= have_proto ? "true" : "false";
2003
2081
if (have_proto)
2005
cerr << "\tTable Name " << table->getShare()->getSchemaName() << "." << table->getShare()->getTableName() << " : " << answer << "\n";
2083
cerr << "\tTable Name " << table->s->getSchemaName() << "." << table->s->table_name.str << " : " << answer << "\n";
2006
2084
cerr << "\t\t Proto " << proto->schema() << " " << proto->name() << "\n";
2010
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 */
2087
cerr << "\tTabl;e Name " << table->s->getSchemaName() << "." << table->s->table_name.str << " : " << answer << "\n";
2091
bool Session::storeTableMessage(TableIdentifier &identifier, message::Table &table_message)
2093
table_message_cache.insert(make_pair(identifier.getPath(), table_message));
2098
bool Session::removeTableMessage(TableIdentifier &identifier)
2100
TableMessageCache::iterator iter;
2102
iter= table_message_cache.find(identifier.getPath());
2104
if (iter == table_message_cache.end())
2107
table_message_cache.erase(iter);
2112
bool Session::getTableMessage(TableIdentifier &identifier, message::Table &table_message)
2114
TableMessageCache::iterator iter;
2116
iter= table_message_cache.find(identifier.getPath());
2118
if (iter == table_message_cache.end())
2121
table_message.CopyFrom(((*iter).second));
2126
bool Session::doesTableMessageExist(TableIdentifier &identifier)
2128
TableMessageCache::iterator iter;
2130
iter= table_message_cache.find(identifier.getPath());
2132
if (iter == table_message_cache.end())
2140
bool Session::renameTableMessage(TableIdentifier &from, TableIdentifier &to)
2142
TableMessageCache::iterator iter;
2144
table_message_cache[to.getPath()]= table_message_cache[from.getPath()];
2146
iter= table_message_cache.find(to.getPath());
2148
if (iter == table_message_cache.end())
2153
(*iter).second.set_schema(to.getSchemaName());
2154
(*iter).second.set_name(to.getTableName());
2082
2159
} /* namespace drizzled */