17
17
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
* @file Implementation of the Session class and API
25
#include "drizzled/session.h"
26
#include "drizzled/session/cache.h"
20
#include <drizzled/server_includes.h>
21
#include <drizzled/session.h>
27
22
#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"
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/plugin/query_rewrite.h"
45
#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"
66
#include <boost/filesystem.hpp>
68
#include "drizzled/util/backtrace.h"
72
namespace fs=boost::filesystem;
23
#include <mysys/mysys_err.h>
24
#include <drizzled/error.h>
25
#include <drizzled/query_id.h>
26
#include <drizzled/data_home.h>
27
#include <drizzled/sql_base.h>
28
#include <drizzled/lock.h>
29
#include <drizzled/item/cache.h>
30
#include <drizzled/item/float.h>
31
#include <drizzled/item/return_int.h>
32
#include <drizzled/item/empty_string.h>
33
#include <drizzled/show.h>
34
#include <drizzled/scheduling.h>
35
#include <libdrizzleclient/errmsg.h>
77
38
The following is used to initialise Table_ident with a internal
81
42
char empty_c_string[1]= {0}; /* used for not defined db */
83
44
const char * const Session::DEFAULT_WHERE= "field list";
45
extern pthread_key_t THR_Session;
46
extern pthread_key_t THR_Mem_root;
48
/*****************************************************************************
49
** Instansiate templates
50
*****************************************************************************/
52
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
54
template class List<Key>;
55
template class List_iterator<Key>;
56
template class List<Key_part_spec>;
57
template class List_iterator<Key_part_spec>;
58
template class List<Alter_drop>;
59
template class List_iterator<Alter_drop>;
60
template class List<Alter_column>;
61
template class List_iterator<Alter_column>;
64
/****************************************************************************
66
****************************************************************************/
67
extern "C" unsigned char *get_var_key(user_var_entry *entry, size_t *length,
70
*length= entry->name.length;
71
return (unsigned char*) entry->name.str;
74
extern "C" void free_user_var(user_var_entry *entry)
76
char *pos= (char*) entry+ALIGN_SIZE(sizeof(*entry));
77
if (entry->value && entry->value != pos)
85
82
bool Key_part_spec::operator==(const Key_part_spec& other) const
87
84
return length == other.length &&
88
85
field_name.length == other.field_name.length &&
89
!my_strcasecmp(system_charset_info, field_name.str, other.field_name.str);
86
!strcmp(field_name.str, other.field_name.str);
92
Open_tables_state::Open_tables_state(uint64_t version_arg) :
89
/****************************************************************************
90
** Thread specific functions
91
****************************************************************************/
93
Open_tables_state::Open_tables_state(ulong version_arg)
94
:version(version_arg), state_flags(0U)
95
open_tables= temporary_tables= derived_tables= NULL;
96
extra_lock= lock= NULL;
96
reset_open_tables_state();
100
100
The following functions form part of the C plugin API
102
int mysql_tmpfile(const char *prefix)
103
extern "C" int mysql_tmpfile(const char *prefix)
104
105
char filename[FN_REFLEN];
105
int fd = internal::create_temp_file(filename, drizzle_tmpdir.c_str(), prefix, MYF(MY_WME));
106
File fd = create_temp_file(filename, drizzle_tmpdir, prefix,
107
O_CREAT | O_EXCL | O_RDWR,
107
110
unlink(filename);
124
137
@see Session::set_proc_info
126
void set_session_proc_info(Session *session, const char *info)
140
set_session_proc_info(Session *session, const char *info)
128
142
session->set_proc_info(info);
131
146
const char *get_session_proc_info(Session *session)
133
148
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];
152
void **session_ha_data(const Session *session, const struct handlerton *hton)
154
return (void **) &session->ha_data[hton->slot].ha_ptr;
147
158
int64_t session_test_options(const Session *session, int64_t test_options)
149
160
return session->options & test_options;
152
164
int session_sql_command(const Session *session)
154
166
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) :
163
Open_tables_state(refresh_version),
164
mem_root(&main_mem_root),
167
query(new std::string),
168
_schema(new std::string("")),
173
lock_id(&main_lock_id),
175
ha_data(plugin::num_trx_monitored_objects),
176
concurrent_execute_allowed(true),
177
arg_of_last_insert_id_function(false),
178
first_successful_insert_id_in_prev_stmt(0),
179
first_successful_insert_id_in_cur_stmt(0),
181
_global_read_lock(NONE),
183
some_tables_deleted(false),
186
is_fatal_error(false),
187
transaction_rollback_request(false),
188
is_fatal_sub_stmt_error(0),
189
derived_tables_processing(false),
190
tablespace_op(false),
193
transaction_message(NULL),
194
statement_message(NULL),
195
session_event_observers(NULL),
198
client->setSession(this);
170
int session_tx_isolation(const Session *session)
172
return (int) session->variables.tx_isolation;
176
void session_inc_row_count(Session *session)
178
session->row_count++;
182
:Statement(&main_lex, &main_mem_root,
183
/* statement id */ 0),
184
Open_tables_state(refresh_version),
185
lock_id(&main_lock_id),
187
arg_of_last_insert_id_function(false),
188
first_successful_insert_id_in_prev_stmt(0),
189
first_successful_insert_id_in_cur_stmt(0),
192
transaction_rollback_request(0),
193
is_fatal_sub_stmt_error(0),
195
derived_tables_processing(false),
201
memset(process_list_info, 0, PROCESS_LIST_WIDTH);
201
204
Pass nominal parameters to init_alloc_root only to ensure that
202
205
the destructor works OK in case of an error. The main_mem_root
203
206
will be re-initialized in init_for_queries().
205
memory::init_sql_alloc(&main_mem_root, memory::ROOT_MIN_BLOCK_SIZE, 0);
207
count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
208
init_sql_alloc(&main_mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
210
catalog= (char*)"std"; // the only catalog we have for now
211
some_tables_deleted=no_errors=password= 0;
212
count_cuted_fields= CHECK_FIELD_IGNORE;
215
thread_specific_used= false;
211
218
cuted_fields= sent_row_count= row_count= 0L;
212
220
row_count_func= -1;
213
221
statement_id_counter= 0UL;
214
222
// Must be reset to handle error with Session's created for init of mysqld
225
scoreboard_index= -1;
232
db_charset= global_system_variables.collation_database;
233
memset(ha_data, 0, sizeof(ha_data));
226
236
dbug_sentry=Session_SENTRY_MAGIC;
227
cleanup_done= abort_on_warning= no_warnings_for_error= false;
229
/* query_cache init */
238
client_capabilities= 0; // minimalistic client
239
system_thread= NON_SYSTEM_THREAD;
240
cleanup_done= abort_on_warning= no_warnings_for_error= false;
241
peer_port= 0; // For SHOW PROCESSLIST
243
pthread_mutex_init(&LOCK_delete, MY_MUTEX_INIT_FAST);
233
245
/* Variables with default values */
234
246
proc_info="login";
235
247
where= Session::DEFAULT_WHERE;
236
command= COM_CONNECT;
238
plugin_sessionvar_init(this);
240
variables= global_system_variables above has reset
241
variables.pseudo_thread_id to 0. We need to correct it here to
242
avoid temporary tables replication failure.
244
variables.pseudo_thread_id= thread_id;
245
server_status= SERVER_STATUS_AUTOCOMMIT;
246
options= session_startup_options;
248
if (variables.max_join_size == HA_POS_ERROR)
249
options |= OPTION_BIG_SELECTS;
251
options &= ~OPTION_BIG_SELECTS;
253
open_options=ha_open_options;
254
update_lock_default= TL_WRITE;
255
session_tx_isolation= (enum_tx_isolation) variables.tx_isolation;
257
memset(warn_count, 0, sizeof(warn_count));
259
memset(&status_var, 0, sizeof(status_var));
248
server_id = ::server_id;
261
253
/* Initialize sub structures */
262
memory::init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
254
init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
255
hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
256
(hash_get_key) get_var_key,
257
(hash_free_key) free_user_var, 0);
260
protocol= &protocol_text; // Default protocol
261
protocol_text.init(this);
263
const Query_id& local_query_id= Query_id::get_query_id();
264
tablespace_op= false;
266
drizzleclient_randominit(&rand, tmp + (uint64_t) &rand,
267
tmp + (uint64_t)local_query_id.value());
264
268
substitute_null_with_insert_id = false;
265
lock_info.init(); /* safety: will be reset after start */
269
thr_lock_info_init(&lock_info); /* safety: will be reset after start */
266
270
thr_lock_owner_init(&main_lock_id, &lock_info);
268
272
m_internal_handler= NULL;
270
plugin::EventObserver::registerSessionEvents(*this);
273
void Session::free_items()
276
/* This works because items are allocated with memory::sql_alloc() */
277
for (; free_list; free_list= next)
279
next= free_list->next;
280
free_list->delete_self();
284
276
void Session::push_internal_handler(Internal_error_handler *handler)
328
302
m_internal_handler= NULL;
331
void Session::get_xid(DRIZZLE_XID *xid)
333
*xid = *(DRIZZLE_XID *) &transaction.xid_state.xid;
305
#if defined(__cplusplus)
309
void *session_alloc(Session *session, unsigned int size)
311
return session->alloc(size);
314
void *session_calloc(Session *session, unsigned int size)
316
return session->calloc(size);
319
char *session_strdup(Session *session, const char *str)
321
return session->strdup(str);
324
char *session_strmake(Session *session, const char *str, unsigned int size)
326
return session->strmake(str, size);
329
void *session_memdup(Session *session, const void* str, unsigned int size)
331
return session->memdup(str, size);
334
void session_get_xid(const Session *session, DRIZZLE_XID *xid)
336
*xid = *(DRIZZLE_XID *) &session->transaction.xid_state.xid;
339
#if defined(__cplusplus)
344
Init common variables that has to be reset on start and on change_user
347
void Session::init(void)
349
pthread_mutex_lock(&LOCK_global_system_variables);
350
plugin_sessionvar_init(this);
352
variables= global_system_variables above has reset
353
variables.pseudo_thread_id to 0. We need to correct it here to
354
avoid temporary tables replication failure.
356
variables.pseudo_thread_id= thread_id;
357
pthread_mutex_unlock(&LOCK_global_system_variables);
358
server_status= SERVER_STATUS_AUTOCOMMIT;
359
options= session_startup_options;
361
if (variables.max_join_size == HA_POS_ERROR)
362
options |= OPTION_BIG_SELECTS;
364
options &= ~OPTION_BIG_SELECTS;
366
transaction.all.modified_non_trans_table= transaction.stmt.modified_non_trans_table= false;
367
open_options=ha_open_options;
368
update_lock_default= TL_WRITE;
369
session_tx_isolation= (enum_tx_isolation) variables.tx_isolation;
371
memset(warn_count, 0, sizeof(warn_count));
374
memset(&status_var, 0, sizeof(status_var));
379
Init Session for query processing.
380
This has to be called once before we call mysql_parse.
381
See also comments in session.h.
384
void Session::init_for_queries()
387
ha_enable_transaction(this,true);
389
reset_root_defaults(mem_root, variables.query_alloc_block_size,
390
variables.query_prealloc_size);
391
reset_root_defaults(&transaction.mem_root,
392
variables.trans_alloc_block_size,
393
variables.trans_prealloc_size);
394
transaction.xid_state.xid.null();
395
transaction.xid_state.in_session=1;
336
399
/* Do operations that may take a long time */
350
TransactionServices &transaction_services= TransactionServices::singleton();
351
transaction_services.rollbackTransaction(this, true);
352
414
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;
418
lock=locked_tables; locked_tables=0;
419
close_thread_tables(this);
421
hash_free(&user_vars);
365
422
close_temporary_tables();
367
424
if (global_read_lock)
369
unlockGlobalReadLock();
425
unlock_global_read_lock(this);
372
427
cleanup_done= true;
375
431
Session::~Session()
433
Session_CHECK_SENTRY(this);
434
add_to_status(&global_status_var, &status_var);
379
if (client->isConnected())
436
if (drizzleclient_vio_ok())
381
438
if (global_system_variables.log_warnings)
382
errmsg_printf(ERRMSG_LVL_WARN, ER(ER_FORCING_CLOSE),internal::my_progname,
439
errmsg_printf(ERRMSG_LVL_WARN, ER(ER_FORCING_CLOSE),my_progname,
384
(getSecurityContext().getUser().c_str() ?
385
getSecurityContext().getUser().c_str() : ""));
441
(security_ctx.user.c_str() ?
442
security_ctx.user.c_str() : ""));
386
443
disconnect(0, false);
389
446
/* Close connection */
449
drizzleclient_net_close(&net);
450
drizzleclient_net_end(&net);
393
452
if (cleanup_done == false)
396
plugin::StorageEngine::closeConnection(this);
455
ha_close_connection(this);
397
456
plugin_sessionvar_cleanup(this);
399
warn_root.free_root(MYF(0));
463
free_root(&warn_root,MYF(0));
464
free_root(&transaction.mem_root,MYF(0));
400
465
mysys_var=0; // Safety (shouldn't be needed)
401
466
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);
468
free_root(&main_mem_root, MYF(0));
469
pthread_setspecific(THR_Session, 0);
472
/* Ensure that no one is using Session */
473
pthread_mutex_unlock(&LOCK_delete);
474
pthread_mutex_destroy(&LOCK_delete);
479
Add all status variables to another status variable array
483
to_var add to this array
484
from_var from this array
487
This function assumes that all variables are long/ulong.
488
If this assumption will change, then we have to explictely add
489
the other variables after the while loop
492
void add_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var)
494
ulong *end= (ulong*) ((unsigned char*) to_var +
495
offsetof(STATUS_VAR, last_system_status_var) +
497
ulong *to= (ulong*) to_var, *from= (ulong*) from_var;
504
Add the difference between two status variable arrays to another one.
508
to_var add to this array
509
from_var from this array
510
dec_var minus this array
513
This function assumes that all variables are long/ulong.
516
void add_diff_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var,
519
ulong *end= (ulong*) ((unsigned char*) to_var + offsetof(STATUS_VAR,
520
last_system_status_var) +
522
ulong *to= (ulong*) to_var, *from= (ulong*) from_var, *dec= (ulong*) dec_var;
525
*(to++)+= *(from++) - *(dec++);
529
void Session::awake(Session::killed_state state_to_set)
531
Session_CHECK_SENTRY(this);
532
safe_mutex_assert_owner(&LOCK_delete);
533
Scheduler &thread_scheduler= get_thread_scheduler();
535
killed= state_to_set;
433
536
if (state_to_set != Session::KILL_QUERY)
435
DRIZZLE_CONNECTION_DONE(thread_id);
538
thread_scheduler.post_kill_notification(this);
440
boost_unique_lock_t scopedLock(mysys_var->mutex);
542
pthread_mutex_lock(&mysys_var->mutex);
543
if (!system_thread) // Don't abort locks
443
546
This broadcast could be up in the air if the victim thread
444
547
exits the cond in the time between read and broadcast, but that is
445
548
ok since all we want to do is to make the victim thread get out
492
594
This allows us to move Session to different threads if needed.
494
596
mysys_var->id= thread_id;
597
real_id= pthread_self(); // For debugging
497
600
We have to call thr_lock_info_init() again here as Session may have been
498
601
created in another thread
603
thr_lock_info_init(&lock_info);
506
Init Session for query processing.
507
This has to be called once before we call mysql_parse.
508
See also comments in session.h.
511
607
void Session::prepareForQueries()
513
609
if (variables.max_join_size == HA_POS_ERROR)
514
610
options |= OPTION_BIG_SELECTS;
611
if (client_capabilities & CLIENT_COMPRESS)
516
614
version= refresh_version;
517
615
set_proc_info(NULL);
518
616
command= COM_SLEEP;
521
mem_root->reset_root_defaults(variables.query_alloc_block_size,
522
variables.query_prealloc_size);
523
transaction.xid_state.xid.null();
524
transaction.xid_state.in_session=1;
620
/* In the past this would only run of the user did not have SUPER_ACL */
621
if (sys_init_connect.value_length)
623
execute_init_command(this, &sys_init_connect, &LOCK_sys_init_connect);
626
Security_context *sctx= &security_ctx;
627
killed= Session::KILL_CONNECTION;
628
errmsg_printf(ERRMSG_LVL_WARN
629
, ER(ER_NEW_ABORTING_CONNECTION)
631
, (db ? db : "unconnected")
632
, sctx->user.empty() == false ? sctx->user.c_str() : "unauthenticated"
633
, sctx->ip.c_str(), "init_connect command failed");
634
errmsg_printf(ERRMSG_LVL_WARN, "%s", main_da.message());
529
642
bool Session::initGlobals()
533
646
disconnect(ER_OUT_OF_RESOURCES, true);
534
status_var.aborted_connects++;
542
if (initGlobals() || authenticate())
550
while (not client->haveError() && getKilled() != KILL_CONNECTION)
552
if (not executeStatement())
559
bool Session::schedule(Session::shared_ptr &arg)
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());
584
char error_message_buff[DRIZZLE_ERRMSG_SIZE];
586
arg->setKilled(Session::KILL_CONNECTION);
588
arg->status_var.aborted_connects++;
590
/* Can't use my_error() since store_globals has not been called. */
591
/* TODO replace will better error message */
592
snprintf(error_message_buff, sizeof(error_message_buff),
593
ER(ER_CANT_CREATE_THREAD), 1);
594
arg->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);
647
statistic_increment(aborted_connects, &LOCK_status);
648
Scheduler &thread_scheduler= get_thread_scheduler();
649
thread_scheduler.end_thread(this, 0);
639
655
bool Session::authenticate()
642
if (client->authenticate())
657
/* Use "connect_timeout" value during connection phase */
658
drizzleclient_net_set_read_timeout(&net, connect_timeout);
659
drizzleclient_net_set_write_timeout(&net, connect_timeout);
663
bool connection_is_valid= check_connection();
664
drizzleclient_net_end_statement(this);
666
if (! connection_is_valid)
668
/* We got wrong permissions from check_connection() */
669
statistic_increment(aborted_connects, &LOCK_status);
645
status_var.aborted_connects++;
673
/* Connect completed, set read/write timeouts back to default */
674
drizzleclient_net_set_read_timeout(&net, variables.net_read_timeout);
675
drizzleclient_net_set_write_timeout(&net, variables.net_write_timeout);
650
bool Session::checkUser(const std::string &passwd_str,
651
const std::string &in_db)
653
bool is_authenticated=
654
plugin::Authentication::isAuthenticated(getSecurityContext(),
679
bool Session::check_connection()
688
if (drizzleclient_net_peer_addr(&net, ip, &peer_port, NI_MAXHOST))
690
my_error(ER_BAD_HOST_ERROR, MYF(0), security_ctx.ip.c_str());
694
security_ctx.ip.assign(ip);
696
drizzleclient_net_keepalive(&net, true);
698
uint32_t server_capabilites;
700
/* buff[] needs to big enough to hold the server_version variable */
701
char buff[SERVER_VERSION_LENGTH + SCRAMBLE_LENGTH + 64];
703
server_capabilites= CLIENT_BASIC_FLAGS;
706
server_capabilites|= CLIENT_COMPRESS;
707
#endif /* HAVE_COMPRESS */
709
end= buff + strlen(server_version);
710
if ((end - buff) >= SERVER_VERSION_LENGTH)
711
end= buff + (SERVER_VERSION_LENGTH - 1);
712
memcpy(buff, server_version, end - buff);
716
int4store((unsigned char*) end, thread_id);
719
So as check_connection is the only entry point to authorization
720
procedure, scramble is set here. This gives us new scramble for
723
drizzleclient_create_random_string(scramble, SCRAMBLE_LENGTH, &rand);
725
Old clients does not understand long scrambles, but can ignore packet
726
tail: that's why first part of the scramble is placed here, and second
727
part at the end of packet.
729
end= strncpy(end, scramble, SCRAMBLE_LENGTH_323);
730
end+= SCRAMBLE_LENGTH_323;
732
*end++= 0; /* an empty byte for some reason */
734
int2store(end, server_capabilites);
735
/* write server characteristics: up to 16 bytes allowed */
736
end[2]=(char) default_charset_info->number;
737
int2store(end+3, server_status);
738
memset(end+5, 0, 13);
740
/* write scramble tail */
741
size_t scramble_len= SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323;
742
end= strncpy(end, scramble + SCRAMBLE_LENGTH_323, scramble_len);
745
*end++= 0; /* an empty byte for some reason */
747
/* At this point we write connection message and read reply */
748
if (drizzleclient_net_write_command(&net
749
, (unsigned char) protocol_version
750
, (unsigned char*) ""
752
, (unsigned char*) buff
753
, (size_t) (end-buff))
754
|| (pkt_len= drizzleclient_net_read(&net)) == packet_error
755
|| pkt_len < MIN_HANDSHAKE_SIZE)
757
my_error(ER_HANDSHAKE_ERROR, MYF(0), security_ctx.ip.c_str());
761
if (packet.alloc(variables.net_buffer_length))
762
return false; /* The error is set by alloc(). */
764
client_capabilities= uint2korr(net.read_pos);
767
client_capabilities|= ((uint32_t) uint2korr(net.read_pos + 2)) << 16;
768
max_client_packet_length= uint4korr(net.read_pos + 4);
770
end= (char*) net.read_pos + 32;
773
Disable those bits which are not supported by the server.
774
This is a precautionary measure, if the client lies. See Bug#27944.
776
client_capabilities&= server_capabilites;
778
if (end >= (char*) net.read_pos + pkt_len + 2)
780
my_error(ER_HANDSHAKE_ERROR, MYF(0), security_ctx.ip.c_str());
784
net.return_status= &server_status;
787
char *passwd= strchr(user, '\0')+1;
788
uint32_t user_len= passwd - user - 1;
790
char db_buff[NAME_LEN + 1]; // buffer to store db in utf8
791
char user_buff[USERNAME_LENGTH + 1]; // buffer to store user in utf8
792
uint32_t dummy_errors;
795
Old clients send null-terminated string as password; new clients send
796
the size (1 byte) + string (not null-terminated). Hence in case of empty
797
password both send '\0'.
799
This strlen() can't be easily deleted without changing protocol.
801
Cast *passwd to an unsigned char, so that it doesn't extend the sign for
802
*passwd > 127 and become 2**32-127+ after casting to uint.
804
uint32_t passwd_len= client_capabilities & CLIENT_SECURE_CONNECTION ?
805
(unsigned char)(*passwd++) : strlen(passwd);
806
l_db= client_capabilities & CLIENT_CONNECT_WITH_DB ? l_db + passwd_len + 1 : 0;
808
/* strlen() can't be easily deleted without changing protocol */
809
uint32_t db_len= l_db ? strlen(l_db) : 0;
811
if (passwd + passwd_len + db_len > (char *) net.read_pos + pkt_len)
813
my_error(ER_HANDSHAKE_ERROR, MYF(0), security_ctx.ip.c_str());
817
/* Since 4.1 all database names are stored in utf8 */
820
db_buff[copy_and_convert(db_buff, sizeof(db_buff)-1,
823
charset(), &dummy_errors)]= 0;
827
user_buff[user_len= copy_and_convert(user_buff, sizeof(user_buff)-1,
828
system_charset_info, user, user_len,
829
charset(), &dummy_errors)]= '\0';
832
/* If username starts and ends in "'", chop them off */
833
if (user_len > 1 && user[0] == '\'' && user[user_len - 1] == '\'')
840
security_ctx.user.assign(user);
842
return check_user(passwd, passwd_len, l_db);
845
bool Session::check_user(const char *passwd, uint32_t passwd_len, const char *in_db)
847
LEX_STRING db_str= { (char *) in_db, in_db ? strlen(in_db) : 0 };
848
bool is_authenticated;
851
Clear session->db as it points to something, that will be freed when
852
connection is closed. We don't want to accidentally free a wrong
853
pointer if connect failed. Also in case of 'CHANGE USER' failure,
854
current database will be switched to 'no database selected'.
858
if (passwd_len != 0 && passwd_len != SCRAMBLE_LENGTH)
860
my_error(ER_HANDSHAKE_ERROR, MYF(0), security_ctx.ip.c_str());
864
is_authenticated= authenticate_user(this, passwd);
657
866
if (is_authenticated != true)
659
status_var.access_denied++;
660
/* isAuthenticated has pushed the error message */
868
my_error(ER_ACCESS_DENIED_ERROR, MYF(0),
869
security_ctx.user.c_str(),
870
security_ctx.ip.c_str(),
871
passwd_len ? ER(ER_YES) : ER(ER_NO));
876
security_ctx.skip_grants();
664
878
/* Change database if necessary */
665
if (not in_db.empty())
879
if (in_db && in_db[0])
667
SchemaIdentifier identifier(in_db);
668
if (mysql_change_db(this, identifier))
881
if (mysql_change_db(this, &db_str, false))
670
883
/* mysql_change_db() has pushed the error message. */
675
password= not passwd_str.empty();
888
password= test(passwd_len); // remember for error messages
677
890
/* Ready to handle queries */
690
904
(see my_message_sql)
692
906
lex->current_select= 0;
909
This thread will do a blocking read from the client which
910
will be interrupted when the next command is received from
911
the client, the connection is closed or "net_wait_timeout"
912
number of seconds has passed
914
drizzleclient_net_set_read_timeout(&net, variables.net_wait_timeout);
917
XXX: this code is here only to clear possible errors of init_connect.
918
Consider moving to init_connect() instead.
920
clear_error(); // Clear error message
694
921
main_da.reset_diagnostics_area();
696
if (client->readCommand(&l_packet, &packet_length) == false)
701
if (getKilled() == KILL_CONNECTION)
704
if (packet_length == 0)
707
l_command= static_cast<enum_server_command>(l_packet[0]);
923
net_new_transaction(&net);
925
packet_length= drizzleclient_net_read(&net);
926
if (packet_length == packet_error)
928
/* Check if we can continue without closing the connection */
930
if(net.last_errno== CR_NET_PACKET_TOO_LARGE)
931
my_error(ER_NET_PACKET_TOO_LARGE, MYF(0));
932
/* Assert is invalid for dirty connection shutdown
933
* assert(session->is_error());
935
drizzleclient_net_end_statement(this);
939
return_value= false; // We have to close it.
948
l_packet= (char*) net.read_pos;
950
'packet_length' contains length of data, as it was stored in packet
951
header. In case of malformed header, drizzleclient_net_read returns zero.
952
If packet_length is not zero, drizzleclient_net_read ensures that the returned
953
number of bytes was actually read from network.
954
There is also an extra safety measure in drizzleclient_net_read:
955
it sets packet[packet_length]= 0, but only for non-zero packets.
957
if (packet_length == 0) /* safety */
959
/* Initialize with COM_SLEEP packet */
960
l_packet[0]= (unsigned char) COM_SLEEP;
963
/* Do not rely on drizzleclient_net_read, extra safety against programming errors. */
964
l_packet[packet_length]= '\0'; /* safety */
966
l_command= (enum enum_server_command) (unsigned char) l_packet[0];
709
968
if (command >= COM_END)
710
969
command= COM_END; // Wrong command
971
/* Restore read timeout value */
972
drizzleclient_net_set_read_timeout(&net, variables.net_read_timeout);
712
974
assert(packet_length);
713
return not dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
975
return_value= ! dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
716
981
bool Session::readAndStoreQuery(const char *in_packet, uint32_t in_packet_length)
884
1166
@return NULL on failure, or pointer to the LEX_STRING object
886
1168
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)
1169
const char* str, uint32_t length,
1170
bool allocate_lex_string)
897
1172
if (allocate_lex_string)
898
1173
if (!(lex_str= (LEX_STRING *)alloc(sizeof(LEX_STRING))))
900
if (!(lex_str->str= mem_root->strmake_root(str, length)))
1175
if (!(lex_str->str= strmake_root(mem_root, str, length)))
902
1177
lex_str->length= length;
1183
Convert a string to another character set
1187
to Store new allocated string here
1188
to_cs New character set for allocated string
1189
from String to convert
1190
from_length Length of string to convert
1191
from_cs Original character set
1194
to will be 0-terminated to make it easy to pass to system funcs
1199
In this case to->str will point to 0 and to->length will be 0.
1202
bool Session::convert_string(LEX_STRING *to, const CHARSET_INFO * const to_cs,
1203
const char *from, uint32_t from_length,
1204
const CHARSET_INFO * const from_cs)
1206
size_t new_length= to_cs->mbmaxlen * from_length;
1207
uint32_t dummy_errors;
1208
if (!(to->str= (char*) alloc(new_length+1)))
1210
to->length= 0; // Safety fix
1213
to->length= copy_and_convert((char*) to->str, new_length, to_cs,
1214
from, from_length, from_cs, &dummy_errors);
1215
to->str[to->length]=0; // Safety
1221
Convert string from source character set to target character set inplace.
1224
Session::convert_string
1227
Convert string using convert_buffer - buffer for character set
1228
conversion shared between all protocols.
1235
bool Session::convert_string(String *s, const CHARSET_INFO * const from_cs,
1236
const CHARSET_INFO * const to_cs)
1238
uint32_t dummy_errors;
1239
if (convert_buffer.copy(s->ptr(), s->length(), from_cs, to_cs, &dummy_errors))
1241
/* If convert_buffer >> s copying is more efficient long term */
1242
if (convert_buffer.alloced_length() >= convert_buffer.length() * 2 ||
1245
return s->copy(convert_buffer);
1247
s->swap(convert_buffer);
1253
Update some cache variables when character set changes
1256
void Session::update_charset()
1259
charset_is_system_charset= !String::needs_conversion(0,charset(),
1260
system_charset_info,
1262
charset_is_collation_connection=
1263
!String::needs_conversion(0,charset(),variables.getCollation(),
1265
charset_is_character_set_filesystem=
1266
!String::needs_conversion(0, charset(),
1267
variables.character_set_filesystem, ¬_used);
1271
/* routings to adding tables to list of changed in transaction tables */
1273
inline static void list_include(CHANGED_TableList** prev,
1274
CHANGED_TableList* curr,
1275
CHANGED_TableList* new_table)
1280
(*prev)->next = curr;
1284
/* add table to list of changed in transaction tables */
1286
void Session::add_changed_table(Table *table)
1288
assert((options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) &&
1289
table->file->has_transactions());
1290
add_changed_table(table->s->table_cache_key.str,
1291
(long) table->s->table_cache_key.length);
1296
void Session::add_changed_table(const char *key, long key_length)
1298
CHANGED_TableList **prev_changed = &transaction.changed_tables;
1299
CHANGED_TableList *curr = transaction.changed_tables;
1301
for (; curr; prev_changed = &(curr->next), curr = curr->next)
1303
int cmp = (long)curr->key_length - (long)key_length;
1306
list_include(prev_changed, curr, changed_table_dup(key, key_length));
1311
cmp = memcmp(curr->key, key, curr->key_length);
1314
list_include(prev_changed, curr, changed_table_dup(key, key_length));
1323
*prev_changed = changed_table_dup(key, key_length);
1328
CHANGED_TableList* Session::changed_table_dup(const char *key, long key_length)
1330
CHANGED_TableList* new_table =
1331
(CHANGED_TableList*) trans_alloc(ALIGN_SIZE(sizeof(CHANGED_TableList))+
1335
my_error(EE_OUTOFMEMORY, MYF(ME_BELL),
1336
ALIGN_SIZE(sizeof(TableList)) + key_length + 1);
1337
killed= KILL_CONNECTION;
1341
new_table->key= ((char*)new_table)+ ALIGN_SIZE(sizeof(CHANGED_TableList));
1342
new_table->next = 0;
1343
new_table->key_length = key_length;
1344
::memcpy(new_table->key, key, key_length);
906
1349
int Session::send_explain_fields(select_result *result)
908
1351
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)
1474
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())
1477
uint32_t option= MY_UNPACK_FILENAME | MY_RELATIVE_PATH;
1479
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
1480
option|= MY_REPLACE_DIR; // Force use of db directory
1483
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;
1485
strcpy(path, drizzle_real_data_home);
1487
strncat(path, session->db, FN_REFLEN-strlen(drizzle_real_data_home)-1);
1488
(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))
1491
(void) fn_format(path, exchange->file_name, drizzle_real_data_home, "", option);
1493
if (opt_secure_file_priv &&
1494
strncmp(opt_secure_file_priv, path, strlen(opt_secure_file_priv)))
1496
/* Write only allowed to dir or subdir specified by secure_file_priv */
1497
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
1501
if (!access(path, F_OK))
1082
1503
my_error(ER_FILE_EXISTS_ERROR, MYF(0), exchange->file_name);
1085
1506
/* 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)
1507
if ((file= my_create(path, 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
1088
1510
(void) fchmod(file, 0666); // Because of umask()
1089
if (cache->init_io_cache(file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1512
(void) chmod(path, 0666);
1514
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
1516
my_close(file, MYF(0));
1517
my_delete(path, MYF(0)); // Delete file on error, it was just created
1276
1705
assert before the loop makes that sure.
1279
if ((needs_escaping(*pos, enclosed) ||
1708
if ((NEED_ESCAPING(*pos) ||
1280
1709
(check_second_byte &&
1281
1710
my_mbcharlen(character_set_client, (unsigned char) *pos) == 2 &&
1282
1711
pos + 1 < end &&
1283
needs_escaping(pos[1], enclosed))) &&
1712
NEED_ESCAPING(pos[1]))) &&
1285
Don't escape field_term_char by doubling - doubling is only
1286
valid for ENCLOSED BY characters:
1714
Don't escape field_term_char by doubling - doubling is only
1715
valid for ENCLOSED BY characters:
1288
1717
(enclosed || !is_ambiguous_field_term ||
1289
1718
(int) (unsigned char) *pos != field_term_char))
1292
1721
tmp_buff[0]= ((int) (unsigned char) *pos == field_sep_char &&
1293
1722
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)))
1723
field_sep_char : escape_char;
1724
tmp_buff[1]= *pos ? *pos : '0';
1725
if (my_b_write(&cache,(unsigned char*) start,(uint32_t) (pos-start)) ||
1726
my_b_write(&cache,(unsigned char*) tmp_buff,2))
1731
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))
1734
else if (my_b_write(&cache,(unsigned char*) res->ptr(),used_length))
1308
1737
if (fixed_row_size)
1309
1738
{ // Fill with space
1310
1739
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))
1741
/* QQ: Fix by adding a my_b_fill() function */
1745
memset(space, ' ', sizeof(space));
1747
uint32_t length=item->max_length-used_length;
1748
for (; length > sizeof(space) ; length-=sizeof(space))
1750
if (my_b_write(&cache,(unsigned char*) space,sizeof(space)))
1753
if (my_b_write(&cache,(unsigned char*) space,length))
1328
1757
if (res && enclosed)
1330
if (my_b_write(cache, (unsigned char*) exchange->enclosed->ptr(),
1759
if (my_b_write(&cache, (unsigned char*) exchange->enclosed->ptr(),
1331
1760
exchange->enclosed->length()))
1334
1763
if (--items_left)
1336
if (my_b_write(cache, (unsigned char*) exchange->field_term->ptr(),
1765
if (my_b_write(&cache, (unsigned char*) exchange->field_term->ptr(),
1337
1766
field_term_length))
1341
if (my_b_write(cache,(unsigned char*) exchange->line_term->ptr(),
1342
exchange->line_term->length()))
1770
if (my_b_write(&cache,(unsigned char*) exchange->line_term->ptr(),
1771
exchange->line_term->length()))
1615
2079
memset(&status_var, 0, sizeof(status_var));
1619
void Session::set_db(const std::string &new_db)
2082
void Security_context::skip_grants()
2084
/* privileges for the user are unknown everything is allowed */
2088
/****************************************************************************
2089
Handling of open and locked tables states.
2091
This is used when we want to open/lock (and then close) some tables when
2092
we already have a set of tables open and locked. We use these methods for
2093
access to mysql.proc table to find definitions of stored routines.
2094
****************************************************************************/
2096
void Session::reset_n_backup_open_tables_state(Open_tables_state *backup)
2098
backup->set_open_tables_state(this);
2099
reset_open_tables_state();
2100
state_flags|= Open_tables_state::BACKUPS_AVAIL;
2105
void Session::restore_backup_open_tables_state(Open_tables_state *backup)
2108
Before we will throw away current open tables state we want
2109
to be sure that it was properly cleaned up.
2111
assert(open_tables == 0 && temporary_tables == 0 &&
2112
handler_tables == 0 && derived_tables == 0 &&
2113
lock == 0 && locked_tables == 0);
2114
set_open_tables_state(backup);
2119
bool Session::set_db(const char *new_db, size_t new_db_len)
1621
2121
/* Do not reallocate memory if current chunk is big enough. */
1622
if (new_db.length())
1624
_schema.reset(new std::string(new_db));
2122
if (db && new_db && db_length >= new_db_len)
2123
memcpy(db, new_db, new_db_len+1);
1628
_schema.reset(new std::string(""));
2130
db= (char *)malloc(new_db_len + 1);
2133
memcpy(db, new_db, new_db_len);
2140
db_length= db ? new_db_len : 0;
2141
return new_db && !db;
2146
Check the killed state of a user thread
2147
@param session user thread
2148
@retval 0 the user thread is active
2149
@retval 1 the user thread has been killed
2151
extern "C" int session_killed(const Session *session)
2153
return(session->killed);
2157
Return the thread id of a user thread
2158
@param session user thread
2161
extern "C" unsigned long session_get_thread_id(const Session *session)
2163
return((unsigned long)session->thread_id);
2168
LEX_STRING *session_make_lex_string(Session *session, LEX_STRING *lex_str,
2169
const char *str, unsigned int size,
2170
int allocate_lex_string)
2172
return session->make_lex_string(lex_str, str, size,
2173
(bool) allocate_lex_string);
2176
extern "C" const struct charset_info_st *session_charset(Session *session)
2178
return(session->charset());
2181
extern "C" char **session_query(Session *session)
2183
return(&session->query);
2186
extern "C" int session_non_transactional_update(const Session *session)
2188
return(session->transaction.all.modified_non_trans_table);
2191
extern "C" void session_mark_transaction_to_rollback(Session *session, bool all)
2193
mark_transaction_to_rollback(session, all);
1704
2274
auto_inc_intervals_in_cur_stmt_for_binlog.empty();
1706
is_fatal_error= false;
1707
2277
server_status&= ~ (SERVER_MORE_RESULTS_EXISTS |
1708
2278
SERVER_QUERY_NO_INDEX_USED |
1709
2279
SERVER_QUERY_NO_GOOD_INDEX_USED);
2281
If in autocommit mode and not in a transaction, reset
2282
OPTION_STATUS_NO_TRANS_UPDATE | OPTION_KEEP_LOG to not get warnings
2283
in ha_rollback_trans() about some tables couldn't be rolled back.
2285
if (!(options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
2287
options&= ~OPTION_KEEP_LOG;
2288
transaction.all.modified_non_trans_table= false;
2290
thread_specific_used= false;
1712
2293
main_da.reset_diagnostics_area();
1713
2294
total_warn_count=0; // Warnings for this query
1714
2295
sent_row_count= examined_row_count= 0;
1718
2301
Close all temporary tables created by 'CREATE TEMPORARY TABLE' for thread
2302
creates one DROP TEMPORARY Table binlog event for each pseudo-thread
1721
void Open_tables_state::close_temporary_tables()
2305
void Session::close_temporary_tables()
1724
2308
Table *tmp_next;
1726
if (not temporary_tables)
2310
if (!temporary_tables)
1729
2313
for (table= temporary_tables; table; table= tmp_next)
1731
tmp_next= table->getNext();
1734
temporary_tables= NULL;
1738
unlink from session->temporary tables and close temporary table
1741
void Open_tables_state::close_temporary_table(Table *table)
1743
if (table->getPrev())
1745
table->getPrev()->setNext(table->getNext());
1746
if (table->getPrev()->getNext())
1748
table->getNext()->setPrev(table->getPrev());
1753
/* removing the item from the list */
1754
assert(table == temporary_tables);
1756
slave must reset its temporary list pointer to zero to exclude
1757
passing non-zero value to end_slave via rli->save_temporary_tables
1758
when no temp tables opened, see an invariant below.
1760
temporary_tables= table->getNext();
1761
if (temporary_tables)
1763
table->getNext()->setPrev(NULL);
1770
Close and drop a temporary table
1773
This dosn't unlink table from session->temporary
1774
If this is needed, use close_temporary_table()
1777
void Open_tables_state::nukeTable(Table *table)
1779
plugin::StorageEngine *table_type= table->getShare()->db_type();
1781
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 */
2315
tmp_next= table->next;
2316
close_temporary(table, 1, 1);
2318
temporary_tables= 0;
1793
2324
/** Clear most status variables. */
1794
2325
extern time_t flush_status_time;
2326
extern uint32_t max_used_connections;
1796
2328
void Session::refresh_status()
2330
pthread_mutex_lock(&LOCK_status);
2332
/* Add thread's status variabes to global status */
2333
add_to_status(&global_status_var, &status_var);
1798
2335
/* Reset thread's status variables */
1799
2336
memset(&status_var, 0, sizeof(status_var));
2338
/* Reset some global variables */
2339
reset_status_vars();
2341
/* Reset the counters of all key caches (default and named). */
2342
process_key_caches(reset_key_cache_counters);
1801
2343
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;
1806
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
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)
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())
1855
if (table->query_id == getQueryId())
1858
table->cursor->ha_reset();
1863
void Session::mark_used_tables_as_free_for_reuse(Table *table)
1865
for (; table ; table= table->getNext())
1867
if (table->query_id == getQueryId())
1870
table->cursor->ha_reset();
1876
Unlocks tables and frees derived tables.
1877
Put all normal tables used by thread in free list.
1879
It will only close/mark as free for reuse tables opened by this
1880
substatement, it will also check if we are closing tables after
1881
execution of complete query (i.e. we are on upper level) and will
1882
leave prelocked mode if needed.
1884
void Session::close_thread_tables()
1886
clearDerivedTables();
1889
Mark all temporary tables used by this statement as free for reuse.
1891
mark_temp_tables_as_free_for_reuse();
1893
Let us commit transaction for statement. Since in 5.0 we only have
1894
one statement transaction and don't allow several nested statement
1895
transactions this call will do nothing if we are inside of stored
1896
function or trigger (i.e. statement transaction is already active and
1897
does not belong to statement for which we do close_thread_tables()).
1898
TODO: This should be fixed in later releases.
1901
TransactionServices &transaction_services= TransactionServices::singleton();
1902
main_da.can_overwrite_status= true;
1903
transaction_services.autocommitOrRollback(this, is_error());
1904
main_da.can_overwrite_status= false;
1905
transaction.stmt.reset();
1911
For RBR we flush the pending event just before we unlock all the
1912
tables. This means that we are at the end of a topmost
1913
statement, so we ensure that the STMT_END_F flag is set on the
1914
pending event. For statements that are *inside* stored
1915
functions, the pending event will not be flushed: that will be
1916
handled either before writing a query log event (inside
1917
binlog_query()) or when preparing a pending event.
1923
Note that we need to hold table::Cache::singleton().mutex() while changing the
1924
open_tables list. Another thread may work on it.
1925
(See: table::Cache::singleton().removeTable(), mysql_wait_completed_table())
1926
Closing a MERGE child before the parent would be fatal if the
1927
other thread tries to abort the MERGE lock in between.
1930
close_open_tables();
1933
void Session::close_tables_for_reopen(TableList **tables)
1936
If table list consists only from tables from prelocking set, table list
1937
for new attempt should be empty, so we have to update list's root pointer.
1939
if (lex->first_not_own_table() == *tables)
1941
lex->chop_off_not_own_tables();
1942
for (TableList *tmp= *tables; tmp; tmp= tmp->next_global)
1944
close_thread_tables();
1947
bool Session::openTablesLock(TableList *tables)
1954
if (open_tables_from_list(&tables, &counter))
1957
if (not lock_tables(tables, counter, &need_reopen))
1959
if (not need_reopen)
1961
close_tables_for_reopen(&tables);
1963
if ((mysql_handle_derived(lex, &mysql_derived_prepare) ||
1965
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)
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);
1995
bool Open_tables_state::rm_temporary_table(plugin::StorageEngine *base, const TableIdentifier &identifier)
1999
if (plugin::StorageEngine::dropTable(*static_cast<Session *>(this), *base, identifier))
2002
identifier.getSQLPath(path);
2003
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 */
2344
max_used_connections= 1; /* We set it to one, because we know we exist */
2345
pthread_mutex_unlock(&LOCK_status);