21
21
* @file Implementation of the Session class and API
25
#include "drizzled/session.h"
26
#include "drizzled/session/cache.h"
24
#include <drizzled/server_includes.h>
25
#include <drizzled/session.h>
27
26
#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"
27
#include <mysys/mysys_err.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
#include "drizzled/plugin/logging.h"
43
#include "drizzled/plugin/transactional_storage_engine.h"
44
#include "drizzled/plugin/query_rewrite.h"
45
42
#include "drizzled/probes.h"
46
#include "drizzled/table_proto.h"
47
#include "drizzled/db.h"
48
#include "drizzled/pthread_globals.h"
49
#include "drizzled/transaction_services.h"
50
#include "drizzled/drizzled.h"
52
#include "drizzled/table/instance.h"
54
#include "plugin/myisam/myisam.h"
55
#include "drizzled/internal/iocache.h"
56
#include "drizzled/internal/thread_var.h"
57
#include "drizzled/plugin/event_observer.h"
59
#include "drizzled/util/functors.h"
61
#include "drizzled/display.h"
64
44
#include <algorithm>
66
#include <boost/filesystem.hpp>
68
#include "drizzled/util/backtrace.h"
70
46
using namespace std;
47
using namespace drizzled;
72
namespace fs=boost::filesystem;
51
unsigned char *get_var_key(user_var_entry *entry, size_t *length, bool );
52
void free_user_var(user_var_entry *entry);
77
56
The following is used to initialise Table_ident with a internal
81
60
char empty_c_string[1]= {0}; /* used for not defined db */
83
62
const char * const Session::DEFAULT_WHERE= "field list";
63
extern pthread_key_t THR_Session;
64
extern pthread_key_t THR_Mem_root;
65
extern uint32_t max_used_connections;
66
extern drizzled::atomic<uint32_t> connection_count;
68
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
70
template class List<Key>;
71
template class List_iterator<Key>;
72
template class List<Key_part_spec>;
73
template class List_iterator<Key_part_spec>;
74
template class List<AlterDrop>;
75
template class List_iterator<AlterDrop>;
76
template class List<AlterColumn>;
77
template class List_iterator<AlterColumn>;
80
/****************************************************************************
82
****************************************************************************/
83
unsigned char *get_var_key(user_var_entry *entry, size_t *length, bool )
85
*length= entry->name.length;
86
return (unsigned char*) entry->name.str;
89
void free_user_var(user_var_entry *entry)
85
94
bool Key_part_spec::operator==(const Key_part_spec& other) const
87
96
return length == other.length &&
88
97
field_name.length == other.field_name.length &&
89
!my_strcasecmp(system_charset_info, field_name.str, other.field_name.str);
98
!strcmp(field_name.str, other.field_name.str);
92
Open_tables_state::Open_tables_state(uint64_t version_arg) :
101
Open_tables_state::Open_tables_state(ulong version_arg)
102
:version(version_arg), backups_available(false)
95
open_tables= temporary_tables= derived_tables= NULL;
96
extra_lock= lock= NULL;
104
reset_open_tables_state();
100
108
The following functions form part of the C plugin API
102
int mysql_tmpfile(const char *prefix)
110
extern "C" int mysql_tmpfile(const char *prefix)
104
112
char filename[FN_REFLEN];
105
int fd = internal::create_temp_file(filename, drizzle_tmpdir.c_str(), prefix, MYF(MY_WME));
113
File fd = create_temp_file(filename, drizzle_tmpdir, prefix, MYF(MY_WME));
107
115
unlink(filename);
124
133
@see Session::set_proc_info
126
void set_session_proc_info(Session *session, const char *info)
136
set_session_proc_info(Session *session, const char *info)
128
138
session->set_proc_info(info);
131
142
const char *get_session_proc_info(Session *session)
133
144
return session->get_proc_info();
136
void **Session::getEngineData(const plugin::MonitoredInTransaction *monitored)
138
return static_cast<void **>(&ha_data[monitored->getId()].ha_ptr);
141
ResourceContext *Session::getResourceContext(const plugin::MonitoredInTransaction *monitored,
144
return &ha_data[monitored->getId()].resource_context[index];
148
void **session_ha_data(const Session *session, const plugin::StorageEngine *engine)
150
return (void **) &session->ha_data[engine->slot].ha_ptr;
147
154
int64_t session_test_options(const Session *session, int64_t test_options)
149
156
return session->options & test_options;
152
160
int session_sql_command(const Session *session)
154
162
return (int) session->lex->sql_command;
157
enum_tx_isolation session_tx_isolation(const Session *session)
159
return (enum_tx_isolation)session->variables.tx_isolation;
162
Session::Session(plugin::Client *client_arg) :
166
int session_tx_isolation(const Session *session)
168
return (int) session->variables.tx_isolation;
172
void session_inc_row_count(Session *session)
174
session->row_count++;
177
Session::Session(plugin::Client *client_arg)
163
179
Open_tables_state(refresh_version),
164
180
mem_root(&main_mem_root),
167
query(new std::string),
168
_schema(new std::string("")),
170
183
client(client_arg),
172
185
scheduler_arg(NULL),
173
186
lock_id(&main_lock_id),
175
ha_data(plugin::num_trx_monitored_objects),
176
concurrent_execute_allowed(true),
177
188
arg_of_last_insert_id_function(false),
178
189
first_successful_insert_id_in_prev_stmt(0),
179
190
first_successful_insert_id_in_cur_stmt(0),
180
191
limit_found_rows(0),
181
_global_read_lock(NONE),
183
193
some_tables_deleted(false),
184
194
no_errors(false),
259
269
memset(&status_var, 0, sizeof(status_var));
261
271
/* Initialize sub structures */
262
memory::init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
272
init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
273
hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
274
(hash_get_key) get_var_key,
275
(hash_free_key) free_user_var, 0);
264
277
substitute_null_with_insert_id = false;
265
lock_info.init(); /* safety: will be reset after start */
278
thr_lock_info_init(&lock_info); /* safety: will be reset after start */
266
279
thr_lock_owner_init(&main_lock_id, &lock_info);
268
281
m_internal_handler= NULL;
270
plugin::EventObserver::registerSessionEvents(*this);
273
284
void Session::free_items()
276
/* This works because items are allocated with memory::sql_alloc() */
287
/* This works because items are allocated with sql_alloc() */
277
288
for (; free_list; free_list= next)
279
290
next= free_list->next;
302
313
return false; // 'false', as per coding style
305
void Session::setAbort(bool arg)
307
mysys_var->abort= arg;
310
void Session::lockOnSys()
316
boost_unique_lock_t scopedLock(mysys_var->mutex);
317
if (mysys_var->current_cond)
319
mysys_var->current_mutex->lock();
320
mysys_var->current_cond->notify_all();
321
mysys_var->current_mutex->unlock();
325
316
void Session::pop_internal_handler()
327
318
assert(m_internal_handler != NULL);
328
319
m_internal_handler= NULL;
331
void Session::get_xid(DRIZZLE_XID *xid)
333
*xid = *(DRIZZLE_XID *) &transaction.xid_state.xid;
322
#if defined(__cplusplus)
326
void *session_alloc(Session *session, unsigned int size)
328
return session->alloc(size);
331
void *session_calloc(Session *session, unsigned int size)
333
return session->calloc(size);
336
char *session_strdup(Session *session, const char *str)
338
return session->strdup(str);
341
char *session_strmake(Session *session, const char *str, unsigned int size)
343
return session->strmake(str, size);
346
void *session_memdup(Session *session, const void* str, unsigned int size)
348
return session->memdup(str, size);
351
void session_get_xid(const Session *session, DRIZZLE_XID *xid)
353
*xid = *(DRIZZLE_XID *) &session->transaction.xid_state.xid;
356
#if defined(__cplusplus)
336
360
/* Do operations that may take a long time */
350
TransactionServices &transaction_services= TransactionServices::singleton();
351
transaction_services.rollbackTransaction(this, true);
352
375
xid_cache_delete(&transaction.xid_state);
355
for (UserVars::iterator iter= user_vars.begin();
356
iter != user_vars.end();
359
user_var_entry *entry= (*iter).second;
377
hash_free(&user_vars);
365
378
close_temporary_tables();
367
380
if (global_read_lock)
369
unlockGlobalReadLock();
381
unlock_global_read_lock(this);
372
383
cleanup_done= true;
375
386
Session::~Session()
388
Session_CHECK_SENTRY(this);
389
add_to_status(&global_status_var, &status_var);
379
391
if (client->isConnected())
381
393
if (global_system_variables.log_warnings)
382
errmsg_printf(ERRMSG_LVL_WARN, ER(ER_FORCING_CLOSE),internal::my_progname,
394
errmsg_printf(ERRMSG_LVL_WARN, ER(ER_FORCING_CLOSE),my_progname,
384
(getSecurityContext().getUser().c_str() ?
385
getSecurityContext().getUser().c_str() : ""));
396
(security_ctx.user.c_str() ?
397
security_ctx.user.c_str() : ""));
386
398
disconnect(0, false);
396
408
plugin::StorageEngine::closeConnection(this);
397
409
plugin_sessionvar_cleanup(this);
399
warn_root.free_root(MYF(0));
416
free_root(&warn_root,MYF(0));
417
free_root(&transaction.mem_root,MYF(0));
400
418
mysys_var=0; // Safety (shouldn't be needed)
401
419
dbug_sentry= Session_SENTRY_GONE;
403
main_mem_root.free_root(MYF(0));
404
currentMemRoot().release();
405
currentSession().release();
407
plugin::Logging::postEndDo(this);
408
plugin::EventObserver::deregisterSessionEvents(*this);
410
for (PropertyMap::iterator iter= life_properties.begin(); iter != life_properties.end(); iter++)
412
delete (*iter).second;
414
life_properties.clear();
417
void Session::setClient(plugin::Client *client_arg)
420
client->setSession(this);
423
void Session::awake(Session::killed_state_t state_to_set)
425
if ((state_to_set == Session::KILL_QUERY) and (command == COM_SLEEP))
430
setKilled(state_to_set);
431
scheduler->killSession(this);
421
free_root(&main_mem_root, MYF(0));
422
pthread_setspecific(THR_Session, 0);
425
/* Ensure that no one is using Session */
426
pthread_mutex_unlock(&LOCK_delete);
427
pthread_mutex_destroy(&LOCK_delete);
431
Add all status variables to another status variable array
435
to_var add to this array
436
from_var from this array
439
This function assumes that all variables are long/ulong.
440
If this assumption will change, then we have to explictely add
441
the other variables after the while loop
443
void add_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var)
445
ulong *end= (ulong*) ((unsigned char*) to_var +
446
offsetof(STATUS_VAR, last_system_status_var) +
448
ulong *to= (ulong*) to_var, *from= (ulong*) from_var;
455
Add the difference between two status variable arrays to another one.
459
to_var add to this array
460
from_var from this array
461
dec_var minus this array
464
This function assumes that all variables are long/ulong.
466
void add_diff_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var,
469
ulong *end= (ulong*) ((unsigned char*) to_var + offsetof(STATUS_VAR,
470
last_system_status_var) +
472
ulong *to= (ulong*) to_var, *from= (ulong*) from_var, *dec= (ulong*) dec_var;
475
*(to++)+= *(from++) - *(dec++);
478
void Session::awake(Session::killed_state state_to_set)
480
Session_CHECK_SENTRY(this);
481
safe_mutex_assert_owner(&LOCK_delete);
483
killed= state_to_set;
433
484
if (state_to_set != Session::KILL_QUERY)
486
scheduler->killSession(this);
435
487
DRIZZLE_CONNECTION_DONE(thread_id);
440
boost_unique_lock_t scopedLock(mysys_var->mutex);
491
pthread_mutex_lock(&mysys_var->mutex);
443
493
This broadcast could be up in the air if the victim thread
444
494
exits the cond in the time between read and broadcast, but that is
445
495
ok since all we want to do is to make the victim thread get out
548
599
prepareForQueries();
550
while (not client->haveError() && getKilled() != KILL_CONNECTION)
601
while (! client->haveError() && killed != KILL_CONNECTION)
552
if (not executeStatement())
603
if (! executeStatement())
556
607
disconnect(0, true);
559
bool Session::schedule(Session::shared_ptr &arg)
610
bool Session::schedule()
561
arg->scheduler= plugin::Scheduler::getScheduler();
562
assert(arg->scheduler);
564
connection_count.increment();
566
if (connection_count > current_global_counters.max_used_connections)
568
current_global_counters.max_used_connections= connection_count;
571
current_global_counters.connections++;
572
arg->thread_id= arg->variables.pseudo_thread_id= global_thread_id++;
574
session::Cache::singleton().insert(arg);
576
if (unlikely(plugin::EventObserver::connectSession(*arg)))
578
// We should do something about an error...
581
if (plugin::Scheduler::getScheduler()->addSession(arg))
583
DRIZZLE_CONNECTION_START(arg->getSessionId());
612
scheduler= plugin::Scheduler::getScheduler();
617
if (connection_count > max_used_connections)
618
max_used_connections= connection_count;
620
thread_id= variables.pseudo_thread_id= global_thread_id++;
622
pthread_mutex_lock(&LOCK_thread_count);
623
session_list.push_back(this);
624
pthread_mutex_unlock(&LOCK_thread_count);
626
if (scheduler->addSession(this))
628
DRIZZLE_CONNECTION_START(thread_id);
584
629
char error_message_buff[DRIZZLE_ERRMSG_SIZE];
586
arg->setKilled(Session::KILL_CONNECTION);
631
killed= Session::KILL_CONNECTION;
588
arg->status_var.aborted_connects++;
633
statistic_increment(aborted_connects, &LOCK_status);
590
635
/* Can't use my_error() since store_globals has not been called. */
591
636
/* TODO replace will better error message */
592
637
snprintf(error_message_buff, sizeof(error_message_buff),
593
638
ER(ER_CANT_CREATE_THREAD), 1);
594
arg->client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
639
client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
604
Is this session viewable by the current user?
606
bool Session::isViewable() const
608
return plugin::Authorization::isAuthorized(current_session->getSecurityContext(),
614
const char* Session::enter_cond(boost::condition_variable_any &cond, boost::mutex &mutex, const char* msg)
616
const char* old_msg = get_proc_info();
617
safe_mutex_assert_owner(mutex);
618
mysys_var->current_mutex = &mutex;
619
mysys_var->current_cond = &cond;
620
this->set_proc_info(msg);
624
void Session::exit_cond(const char* old_msg)
627
Putting the mutex unlock in exit_cond() ensures that
628
mysys_var->current_mutex is always unlocked _before_ mysys_var->mutex is
629
locked (if that would not be the case, you'll get a deadlock if someone
630
does a Session::awake() on you).
632
mysys_var->current_mutex->unlock();
633
boost_unique_lock_t scopedLock(mysys_var->mutex);
634
mysys_var->current_mutex = 0;
635
mysys_var->current_cond = 0;
636
this->set_proc_info(old_msg);
639
646
bool Session::authenticate()
642
649
if (client->authenticate())
645
status_var.aborted_connects++;
652
statistic_increment(aborted_connects, &LOCK_status);
650
bool Session::checkUser(const std::string &passwd_str,
651
const std::string &in_db)
656
bool Session::checkUser(const char *passwd, uint32_t passwd_len, const char *in_db)
653
bool is_authenticated=
654
plugin::Authentication::isAuthenticated(getSecurityContext(),
658
LEX_STRING db_str= { (char *) in_db, in_db ? strlen(in_db) : 0 };
659
bool is_authenticated;
662
Clear session->db as it points to something, that will be freed when
663
connection is closed. We don't want to accidentally free a wrong
664
pointer if connect failed. Also in case of 'CHANGE USER' failure,
665
current database will be switched to 'no database selected'.
669
if (passwd_len != 0 && passwd_len != SCRAMBLE_LENGTH)
671
my_error(ER_HANDSHAKE_ERROR, MYF(0), security_ctx.ip.c_str());
675
is_authenticated= plugin::Authentication::isAuthenticated(this, passwd);
657
677
if (is_authenticated != true)
659
status_var.access_denied++;
660
/* isAuthenticated has pushed the error message */
679
my_error(ER_ACCESS_DENIED_ERROR, MYF(0),
680
security_ctx.user.c_str(),
681
security_ctx.ip.c_str(),
682
passwd_len ? ER(ER_YES) : ER(ER_NO));
687
security_ctx.skip_grants();
664
689
/* Change database if necessary */
665
if (not in_db.empty())
690
if (in_db && in_db[0])
667
SchemaIdentifier identifier(in_db);
668
if (mysql_change_db(this, identifier))
692
if (mysql_change_db(this, &db_str, false))
670
694
/* mysql_change_db() has pushed the error message. */
675
password= not passwd_str.empty();
699
password= test(passwd_len); // remember for error messages
677
701
/* Ready to handle queries */
722
741
in_packet_length--;
724
743
const char *pos= in_packet + in_packet_length; /* Point at end null */
725
while (in_packet_length > 0 && (pos[-1] == ';' || my_isspace(charset() ,pos[-1])))
744
while (in_packet_length > 0 &&
745
(pos[-1] == ';' || my_isspace(charset() ,pos[-1])))
728
748
in_packet_length--;
731
std::string *new_query= new std::string(in_packet, in_packet + in_packet_length);
732
// We can not be entirely sure _schema has a value
735
plugin::QueryRewriter::rewriteQuery(*_schema, *new_query);
737
query.reset(new_query);
738
_state.reset(new State(in_packet, in_packet_length));
751
/* We must allocate some extra memory for the cached query string */
752
query_length= 0; /* Extra safety: Avoid races */
753
query= (char*) memdup_w_gap((unsigned char*) in_packet, in_packet_length, db_length + 1);
757
query[in_packet_length]=0;
758
query_length= in_packet_length;
760
/* Reclaim some memory */
761
packet.shrink(variables.net_buffer_length);
762
convert_buffer.shrink(variables.net_buffer_length);
884
894
@return NULL on failure, or pointer to the LEX_STRING object
886
896
LEX_STRING *Session::make_lex_string(LEX_STRING *lex_str,
887
const std::string &str,
888
bool allocate_lex_string)
890
return make_lex_string(lex_str, str.c_str(), str.length(), allocate_lex_string);
893
LEX_STRING *Session::make_lex_string(LEX_STRING *lex_str,
894
const char* str, uint32_t length,
895
bool allocate_lex_string)
897
const char* str, uint32_t length,
898
bool allocate_lex_string)
897
900
if (allocate_lex_string)
898
901
if (!(lex_str= (LEX_STRING *)alloc(sizeof(LEX_STRING))))
900
if (!(lex_str->str= mem_root->strmake_root(str, length)))
903
if (!(lex_str->str= strmake_root(mem_root, str, length)))
902
905
lex_str->length= length;
909
/* routings to adding tables to list of changed in transaction tables */
910
inline static void list_include(CHANGED_TableList** prev,
911
CHANGED_TableList* curr,
912
CHANGED_TableList* new_table)
917
(*prev)->next = curr;
921
/* add table to list of changed in transaction tables */
923
void Session::add_changed_table(Table *table)
925
assert((options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) &&
926
table->file->has_transactions());
927
add_changed_table(table->s->table_cache_key.str,
928
(long) table->s->table_cache_key.length);
932
void Session::add_changed_table(const char *key, long key_length)
934
CHANGED_TableList **prev_changed = &transaction.changed_tables;
935
CHANGED_TableList *curr = transaction.changed_tables;
937
for (; curr; prev_changed = &(curr->next), curr = curr->next)
939
int cmp = (long)curr->key_length - (long)key_length;
942
list_include(prev_changed, curr, changed_table_dup(key, key_length));
947
cmp = memcmp(curr->key, key, curr->key_length);
950
list_include(prev_changed, curr, changed_table_dup(key, key_length));
959
*prev_changed = changed_table_dup(key, key_length);
963
CHANGED_TableList* Session::changed_table_dup(const char *key, long key_length)
965
CHANGED_TableList* new_table =
966
(CHANGED_TableList*) trans_alloc(ALIGN_SIZE(sizeof(CHANGED_TableList))+
970
my_error(EE_OUTOFMEMORY, MYF(ME_BELL),
971
ALIGN_SIZE(sizeof(TableList)) + key_length + 1);
972
killed= KILL_CONNECTION;
976
new_table->key= ((char*)new_table)+ ALIGN_SIZE(sizeof(CHANGED_TableList));
978
new_table->key_length = key_length;
979
::memcpy(new_table->key, key, key_length);
906
984
int Session::send_explain_fields(select_result *result)
908
986
List<Item> field_list;
1038
static int create_file(Session *session,
1039
fs::path &target_path,
1040
file_exchange *exchange,
1041
internal::IO_CACHE *cache)
1108
static File create_file(Session *session, char *path, file_exchange *exchange, IO_CACHE *cache)
1043
fs::path to_file(exchange->file_name);
1046
if (not to_file.has_root_directory())
1111
uint32_t option= MY_UNPACK_FILENAME | MY_RELATIVE_PATH;
1113
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
1114
option|= MY_REPLACE_DIR; // Force use of db directory
1117
if (!dirname_length(exchange->file_name))
1048
target_path= fs::system_complete(getDataHomeCatalog());
1049
util::string::const_shared_ptr schema(session->schema());
1050
if (schema and not schema->empty())
1052
int count_elements= 0;
1053
for (fs::path::iterator iter= to_file.begin();
1054
iter != to_file.end();
1055
++iter, ++count_elements)
1058
if (count_elements == 1)
1060
target_path /= *schema;
1063
target_path /= to_file;
1119
strcpy(path, drizzle_real_data_home);
1121
strncat(path, session->db, FN_REFLEN-strlen(drizzle_real_data_home)-1);
1122
(void) fn_format(path, exchange->file_name, path, "", option);
1067
target_path = exchange->file_name;
1070
if (not secure_file_priv.string().empty())
1072
if (target_path.file_string().substr(0, secure_file_priv.file_string().size()) != secure_file_priv.file_string())
1074
/* Write only allowed to dir or subdir specified by secure_file_priv */
1075
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
1080
if (!access(target_path.file_string().c_str(), F_OK))
1125
(void) fn_format(path, exchange->file_name, drizzle_real_data_home, "", option);
1127
if (opt_secure_file_priv &&
1128
strncmp(opt_secure_file_priv, path, strlen(opt_secure_file_priv)))
1130
/* Write only allowed to dir or subdir specified by secure_file_priv */
1131
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
1135
if (!access(path, F_OK))
1082
1137
my_error(ER_FILE_EXISTS_ERROR, MYF(0), exchange->file_name);
1085
1140
/* Create the file world readable */
1086
if ((file= internal::my_create(target_path.file_string().c_str(), 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
1141
if ((file= my_create(path, 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
1088
1144
(void) fchmod(file, 0666); // Because of umask()
1089
if (cache->init_io_cache(file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1146
(void) chmod(path, 0666);
1148
if (init_io_cache(cache, file, 0L, WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1091
internal::my_close(file, MYF(0));
1092
internal::my_delete(target_path.file_string().c_str(), MYF(0)); // Delete file on error, it was just created
1150
my_close(file, MYF(0));
1151
my_delete(path, MYF(0)); // Delete file on error, it was just created
1188
1250
res=item->str_result(&tmp);
1189
1251
if (res && enclosed)
1191
if (my_b_write(cache,(unsigned char*) exchange->enclosed->ptr(),
1192
exchange->enclosed->length()))
1253
if (my_b_write(&cache,(unsigned char*) exchange->enclosed->ptr(),
1254
exchange->enclosed->length()))
1197
1259
if (!fixed_row_size)
1199
if (escape_char != -1) // Use \N syntax
1201
null_buff[0]=escape_char;
1203
if (my_b_write(cache,(unsigned char*) null_buff,2))
1206
else if (my_b_write(cache,(unsigned char*) "NULL",4))
1261
if (escape_char != -1) // Use \N syntax
1263
null_buff[0]=escape_char;
1265
if (my_b_write(&cache,(unsigned char*) null_buff,2))
1268
else if (my_b_write(&cache,(unsigned char*) "NULL",4))
1211
used_length=0; // Fill with space
1273
used_length=0; // Fill with space
1216
1278
if (fixed_row_size)
1217
used_length= min(res->length(), static_cast<size_t>(item->max_length));
1279
used_length= min(res->length(),item->max_length);
1219
1281
used_length= res->length();
1221
1283
if ((result_type == STRING_RESULT || is_unsafe_field_sep) &&
1224
1286
char *pos, *start, *end;
1225
1287
const CHARSET_INFO * const res_charset= res->charset();
1226
1288
const CHARSET_INFO * const character_set_client= default_charset_info;
1228
1290
bool check_second_byte= (res_charset == &my_charset_bin) &&
1229
character_set_client->
1230
escape_with_backslash_is_dangerous;
1291
character_set_client->
1292
escape_with_backslash_is_dangerous;
1231
1293
assert(character_set_client->mbmaxlen == 2 ||
1232
1294
!character_set_client->escape_with_backslash_is_dangerous);
1233
for (start=pos=(char*) res->ptr(),end=pos+used_length ;
1237
if (use_mb(res_charset))
1240
if ((l=my_ismbchar(res_charset, pos, end)))
1295
for (start=pos=(char*) res->ptr(),end=pos+used_length ;
1299
if (use_mb(res_charset))
1302
if ((l=my_ismbchar(res_charset, pos, end)))
1248
1310
Special case when dumping BINARY/VARBINARY/BLOB values
1276
1338
assert before the loop makes that sure.
1279
if ((needs_escaping(*pos, enclosed) ||
1341
if ((NEED_ESCAPING(*pos) ||
1280
1342
(check_second_byte &&
1281
1343
my_mbcharlen(character_set_client, (unsigned char) *pos) == 2 &&
1282
1344
pos + 1 < end &&
1283
needs_escaping(pos[1], enclosed))) &&
1345
NEED_ESCAPING(pos[1]))) &&
1285
Don't escape field_term_char by doubling - doubling is only
1286
valid for ENCLOSED BY characters:
1347
Don't escape field_term_char by doubling - doubling is only
1348
valid for ENCLOSED BY characters:
1288
1350
(enclosed || !is_ambiguous_field_term ||
1289
1351
(int) (unsigned char) *pos != field_term_char))
1292
1354
tmp_buff[0]= ((int) (unsigned char) *pos == field_sep_char &&
1293
1355
is_ambiguous_field_sep) ?
1294
field_sep_char : escape_char;
1295
tmp_buff[1]= *pos ? *pos : '0';
1296
if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)) ||
1297
my_b_write(cache,(unsigned char*) tmp_buff,2))
1302
if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)))
1356
field_sep_char : escape_char;
1357
tmp_buff[1]= *pos ? *pos : '0';
1358
if (my_b_write(&cache,(unsigned char*) start,(uint32_t) (pos-start)) ||
1359
my_b_write(&cache,(unsigned char*) tmp_buff,2))
1364
if (my_b_write(&cache,(unsigned char*) start,(uint32_t) (pos-start)))
1305
else if (my_b_write(cache,(unsigned char*) res->ptr(),used_length))
1367
else if (my_b_write(&cache,(unsigned char*) res->ptr(),used_length))
1308
1370
if (fixed_row_size)
1309
1371
{ // Fill with space
1310
1372
if (item->max_length > used_length)
1312
/* QQ: Fix by adding a my_b_fill() function */
1316
memset(space, ' ', sizeof(space));
1318
uint32_t length=item->max_length-used_length;
1319
for (; length > sizeof(space) ; length-=sizeof(space))
1321
if (my_b_write(cache,(unsigned char*) space,sizeof(space)))
1324
if (my_b_write(cache,(unsigned char*) space,length))
1374
/* QQ: Fix by adding a my_b_fill() function */
1378
memset(space, ' ', sizeof(space));
1380
uint32_t length=item->max_length-used_length;
1381
for (; length > sizeof(space) ; length-=sizeof(space))
1383
if (my_b_write(&cache,(unsigned char*) space,sizeof(space)))
1386
if (my_b_write(&cache,(unsigned char*) space,length))
1328
1390
if (res && enclosed)
1330
if (my_b_write(cache, (unsigned char*) exchange->enclosed->ptr(),
1392
if (my_b_write(&cache, (unsigned char*) exchange->enclosed->ptr(),
1331
1393
exchange->enclosed->length()))
1334
1396
if (--items_left)
1336
if (my_b_write(cache, (unsigned char*) exchange->field_term->ptr(),
1398
if (my_b_write(&cache, (unsigned char*) exchange->field_term->ptr(),
1337
1399
field_term_length))
1341
if (my_b_write(cache,(unsigned char*) exchange->line_term->ptr(),
1342
exchange->line_term->length()))
1403
if (my_b_write(&cache,(unsigned char*) exchange->line_term->ptr(),
1404
exchange->line_term->length()))
1615
1668
memset(&status_var, 0, sizeof(status_var));
1619
void Session::set_db(const std::string &new_db)
1671
void Security_context::skip_grants()
1673
/* privileges for the user are unknown everything is allowed */
1677
/****************************************************************************
1678
Handling of open and locked tables states.
1680
This is used when we want to open/lock (and then close) some tables when
1681
we already have a set of tables open and locked. We use these methods for
1682
access to mysql.proc table to find definitions of stored routines.
1683
****************************************************************************/
1685
void Session::reset_n_backup_open_tables_state(Open_tables_state *backup)
1687
backup->set_open_tables_state(this);
1688
reset_open_tables_state();
1689
backups_available= false;
1693
void Session::restore_backup_open_tables_state(Open_tables_state *backup)
1696
Before we will throw away current open tables state we want
1697
to be sure that it was properly cleaned up.
1699
assert(open_tables == 0 && temporary_tables == 0 &&
1700
derived_tables == 0 &&
1702
set_open_tables_state(backup);
1706
bool Session::set_db(const char *new_db, size_t new_db_len)
1621
1708
/* Do not reallocate memory if current chunk is big enough. */
1622
if (new_db.length())
1624
_schema.reset(new std::string(new_db));
1709
if (db && new_db && db_length >= new_db_len)
1710
memcpy(db, new_db, new_db_len+1);
1628
_schema.reset(new std::string(""));
1717
db= (char *)malloc(new_db_len + 1);
1720
memcpy(db, new_db, new_db_len);
1727
db_length= db ? new_db_len : 0;
1728
return new_db && !db;
1733
Check the killed state of a user thread
1734
@param session user thread
1735
@retval 0 the user thread is active
1736
@retval 1 the user thread has been killed
1738
extern "C" int session_killed(const Session *session)
1740
return(session->killed);
1744
Return the session id of a user session
1745
@param pointer to Session object
1746
@return session's id
1748
extern "C" unsigned long session_get_thread_id(const Session *session)
1750
return (unsigned long) session->getSessionId();
1755
LEX_STRING *session_make_lex_string(Session *session, LEX_STRING *lex_str,
1756
const char *str, unsigned int size,
1757
int allocate_lex_string)
1759
return session->make_lex_string(lex_str, str, size,
1760
(bool) allocate_lex_string);
1763
const struct charset_info_st *session_charset(Session *session)
1765
return(session->charset());
1768
char **session_query(Session *session)
1770
return(&session->query);
1773
int session_non_transactional_update(const Session *session)
1775
return(session->transaction.all.modified_non_trans_table);
1778
void session_mark_transaction_to_rollback(Session *session, bool all)
1780
mark_transaction_to_rollback(session, all);
1634
1784
Mark transaction to rollback and mark error as fatal to a sub-statement.
1651
1801
plugin_sessionvar_cleanup(this);
1653
1803
/* If necessary, log any aborted or unauthorized connections */
1654
if (getKilled() || client->wasAborted())
1656
status_var.aborted_threads++;
1804
if (killed || client->wasAborted())
1805
statistic_increment(aborted_threads, &LOCK_status);
1659
1807
if (client->wasAborted())
1661
if (not getKilled() && variables.log_warnings > 1)
1809
if (! killed && variables.log_warnings > 1)
1663
SecurityContext *sctx= &security_ctx;
1811
Security_context *sctx= &security_ctx;
1665
1813
errmsg_printf(ERRMSG_LVL_WARN, ER(ER_NEW_ABORTING_CONNECTION)
1667
, (_schema->empty() ? "unconnected" : _schema->c_str())
1668
, sctx->getUser().empty() == false ? sctx->getUser().c_str() : "unauthenticated"
1669
, sctx->getIp().c_str()
1815
, (db ? db : "unconnected")
1816
, sctx->user.empty() == false ? sctx->user.c_str() : "unauthenticated"
1670
1818
, (main_da.is_error() ? main_da.message() : ER(ER_UNKNOWN_ERROR)));
1674
1822
/* Close out our connection to the client */
1675
1823
if (should_lock)
1676
session::Cache::singleton().mutex().lock();
1678
setKilled(Session::KILL_CONNECTION);
1824
(void) pthread_mutex_lock(&LOCK_thread_count);
1825
killed= Session::KILL_CONNECTION;
1680
1826
if (client->isConnected())
1757
1910
passing non-zero value to end_slave via rli->save_temporary_tables
1758
1911
when no temp tables opened, see an invariant below.
1760
temporary_tables= table->getNext();
1913
temporary_tables= table->next;
1761
1914
if (temporary_tables)
1763
table->getNext()->setPrev(NULL);
1915
table->next->prev= NULL;
1917
close_temporary(table, free_share, delete_table);
1770
Close and drop a temporary table
1921
Close and delete a temporary table
1773
1924
This dosn't unlink table from session->temporary
1774
1925
If this is needed, use close_temporary_table()
1777
void Open_tables_state::nukeTable(Table *table)
1928
void Session::close_temporary(Table *table, bool free_share, bool delete_table)
1779
plugin::StorageEngine *table_type= table->getShare()->db_type();
1930
plugin::StorageEngine *table_type= table->s->db_type();
1781
1932
table->free_io_cache();
1782
table->delete_table();
1784
TableIdentifier identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName(), table->getShare()->getPath());
1785
rm_temporary_table(table_type, identifier);
1787
delete table->getMutableShare();
1789
/* This makes me sad, but we're allocating it via malloc */
1933
table->closefrm(false);
1936
rm_temporary_table(table_type, table->s->path.str);
1940
table->s->free_table_share();
1941
/* This makes me sad, but we're allocating it via malloc */
1793
1946
/** Clear most status variables. */
1794
1947
extern time_t flush_status_time;
1948
extern uint32_t max_used_connections;
1796
1950
void Session::refresh_status()
1952
pthread_mutex_lock(&LOCK_status);
1954
/* Add thread's status variabes to global status */
1955
add_to_status(&global_status_var, &status_var);
1798
1957
/* Reset thread's status variables */
1799
1958
memset(&status_var, 0, sizeof(status_var));
1960
/* Reset some global variables */
1961
reset_status_vars();
1963
/* Reset the counters of all key caches (default and named). */
1964
reset_key_cache_counters();
1801
1965
flush_status_time= time((time_t*) 0);
1802
current_global_counters.max_used_connections= 1; /* We set it to one, because we know we exist */
1803
current_global_counters.connections= 0;
1966
max_used_connections= 1; /* We set it to one, because we know we exist */
1967
pthread_mutex_unlock(&LOCK_status);
1970
#define extra_size sizeof(double)
1806
1972
user_var_entry *Session::getVariable(LEX_STRING &name, bool create_if_not_exists)
1808
return getVariable(std::string(name.str, name.length), create_if_not_exists);
1811
user_var_entry *Session::getVariable(const std::string &name, bool create_if_not_exists)
1813
UserVarsRange ppp= user_vars.equal_range(name);
1815
for (UserVars::iterator iter= ppp.first;
1816
iter != ppp.second; ++iter)
1818
return (*iter).second;
1821
if (not create_if_not_exists)
1824
1974
user_var_entry *entry= NULL;
1825
entry= new (nothrow) user_var_entry(name.c_str(), query_id);
1830
std::pair<UserVars::iterator, bool> returnable= user_vars.insert(make_pair(name, entry));
1832
if (not returnable.second)
1976
entry= (user_var_entry*) hash_search(&user_vars, (unsigned char*) name.str, name.length);
1978
if ((entry == NULL) && create_if_not_exists)
1980
if (!hash_inited(&user_vars))
1982
entry= new (nothrow) user_var_entry(name.str, query_id);
1987
if (my_hash_insert(&user_vars, (unsigned char*) entry))
1990
free((char*) entry);
1840
void Session::setVariable(const std::string &name, const std::string &value)
1842
user_var_entry *updateable_var= getVariable(name.c_str(), true);
1844
updateable_var->update_hash(false,
1845
(void*)value.c_str(),
1846
static_cast<uint32_t>(value.length()), STRING_RESULT,
1848
DERIVATION_IMPLICIT, false);
1851
void Open_tables_state::mark_temp_tables_as_free_for_reuse()
1853
for (Table *table= temporary_tables ; table ; table= table->getNext())
1999
void Session::mark_temp_tables_as_free_for_reuse()
2001
for (Table *table= temporary_tables ; table ; table= table->next)
1855
if (table->query_id == getQueryId())
2003
if (table->query_id == query_id)
1857
2005
table->query_id= 0;
1858
table->cursor->ha_reset();
2006
table->file->ha_reset();
1863
2011
void Session::mark_used_tables_as_free_for_reuse(Table *table)
1865
for (; table ; table= table->getNext())
2013
for (; table ; table= table->next)
1867
if (table->query_id == getQueryId())
2015
if (table->query_id == query_id)
1869
2017
table->query_id= 0;
1870
table->cursor->ha_reset();
2018
table->file->ha_reset();
1954
2128
if (open_tables_from_list(&tables, &counter))
1957
if (not lock_tables(tables, counter, &need_reopen))
2131
if (!lock_tables(tables, counter, &need_reopen))
1959
if (not need_reopen)
1961
2135
close_tables_for_reopen(&tables);
1963
2137
if ((mysql_handle_derived(lex, &mysql_derived_prepare) ||
2138
(fill_derived_tables() &&
1965
2139
mysql_handle_derived(lex, &mysql_derived_filling))))
1972
@note "best_effort" is used in cases were if a failure occurred on this
1973
operation it would not be surprising because we are only removing because there
1974
might be an issue (lame engines).
1977
bool Open_tables_state::rm_temporary_table(const TableIdentifier &identifier, bool best_effort)
2145
bool Session::openTables(TableList *tables, uint32_t flags)
1979
if (plugin::StorageEngine::dropTable(*static_cast<Session *>(this), identifier))
1981
if (not best_effort)
1984
identifier.getSQLPath(path);
1985
errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
1986
path.c_str(), errno);
2148
bool ret= fill_derived_tables();
2149
assert(ret == false);
2150
if (open_tables_from_list(&tables, &counter, flags) ||
2151
mysql_handle_derived(lex, &mysql_derived_prepare))
1995
bool Open_tables_state::rm_temporary_table(plugin::StorageEngine *base, const TableIdentifier &identifier)
2156
bool Session::rm_temporary_table(plugin::StorageEngine *base, char *path)
1999
if (plugin::StorageEngine::dropTable(*static_cast<Session *>(this), *base, identifier))
2162
if (delete_table_proto_file(path))
2165
if (base->deleteTable(this, path))
2002
identifier.getSQLPath(path);
2003
2168
errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
2004
path.c_str(), errno);
2013
@note this will be removed, I am looking through Hudson to see if it is finding
2014
any tables that are missed during cleanup.
2016
void Open_tables_state::dumpTemporaryTableNames(const char *foo)
2020
if (not temporary_tables)
2023
cerr << "Begin Run: " << foo << "\n";
2024
for (table= temporary_tables; table; table= table->getNext())
2026
bool have_proto= false;
2028
message::Table *proto= table->getShare()->getTableProto();
2029
if (table->getShare()->getTableProto())
2032
const char *answer= have_proto ? "true" : "false";
2036
cerr << "\tTable Name " << table->getShare()->getSchemaName() << "." << table->getShare()->getTableName() << " : " << answer << "\n";
2037
cerr << "\t\t Proto " << proto->schema() << " " << proto->name() << "\n";
2041
cerr << "\tTabl;e Name " << table->getShare()->getSchemaName() << "." << table->getShare()->getTableName() << " : " << answer << "\n";
2046
bool Session::TableMessages::storeTableMessage(const TableIdentifier &identifier, message::Table &table_message)
2048
table_message_cache.insert(make_pair(identifier.getPath(), table_message));
2053
bool Session::TableMessages::removeTableMessage(const TableIdentifier &identifier)
2055
TableMessageCache::iterator iter;
2057
iter= table_message_cache.find(identifier.getPath());
2059
if (iter == table_message_cache.end())
2062
table_message_cache.erase(iter);
2067
bool Session::TableMessages::getTableMessage(const TableIdentifier &identifier, message::Table &table_message)
2069
TableMessageCache::iterator iter;
2071
iter= table_message_cache.find(identifier.getPath());
2073
if (iter == table_message_cache.end())
2076
table_message.CopyFrom(((*iter).second));
2081
bool Session::TableMessages::doesTableMessageExist(const TableIdentifier &identifier)
2083
TableMessageCache::iterator iter;
2085
iter= table_message_cache.find(identifier.getPath());
2087
if (iter == table_message_cache.end())
2095
bool Session::TableMessages::renameTableMessage(const TableIdentifier &from, const TableIdentifier &to)
2097
TableMessageCache::iterator iter;
2099
table_message_cache[to.getPath()]= table_message_cache[from.getPath()];
2101
iter= table_message_cache.find(to.getPath());
2103
if (iter == table_message_cache.end())
2108
(*iter).second.set_schema(to.getSchemaName());
2109
(*iter).second.set_name(to.getTableName());
2114
table::Instance *Session::getInstanceTable()
2116
temporary_shares.push_back(new table::Instance()); // This will not go into the tableshare cache, so no key is used.
2118
table::Instance *tmp_share= temporary_shares.back();
2127
Create a reduced Table object with properly set up Field list from a
2128
list of field definitions.
2130
The created table doesn't have a table Cursor associated with
2131
it, has no keys, no group/distinct, no copy_funcs array.
2132
The sole purpose of this Table object is to use the power of Field
2133
class to read/write data to/from table->getInsertRecord(). Then one can store
2134
the record in any container (RB tree, hash, etc).
2135
The table is created in Session mem_root, so are the table's fields.
2136
Consequently, if you don't BLOB fields, you don't need to free it.
2138
@param session connection handle
2139
@param field_list list of column definitions
2142
0 if out of memory, Table object in case of success
2144
table::Instance *Session::getInstanceTable(List<CreateField> &field_list)
2146
temporary_shares.push_back(new table::Instance(this, field_list)); // This will not go into the tableshare cache, so no key is used.
2148
table::Instance *tmp_share= temporary_shares.back();
2157
static const std::string NONE= "NONE";
2158
static const std::string GOT_GLOBAL_READ_LOCK= "HAS GLOBAL READ LOCK";
2159
static const std::string MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT= "HAS GLOBAL READ LOCK WITH BLOCKING COMMIT";
2161
const std::string &type(drizzled::Session::global_read_lock_t type)
2167
case Session::GOT_GLOBAL_READ_LOCK:
2168
return GOT_GLOBAL_READ_LOCK;
2169
case Session::MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT:
2170
return MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT;
2174
size_t max_string_length(drizzled::Session::global_read_lock_t)
2176
return MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT.size();
2179
} /* namespace display */
2181
} /* namespace drizzled */