17
17
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
* @file Implementation of the Session class and API
26
#include <drizzled/copy_field.h>
20
#include <drizzled/server_includes.h>
21
#include <drizzled/session.h>
23
#include <mysys/mysys_err.h>
24
#include <drizzled/error.h>
25
#include <drizzled/query_id.h>
27
26
#include <drizzled/data_home.h>
28
#include <drizzled/display.h>
29
#include <drizzled/drizzled.h>
30
#include <drizzled/error.h>
31
#include <drizzled/gettext.h>
32
#include <drizzled/identifier.h>
33
#include <drizzled/internal/iocache.h>
34
#include <drizzled/internal/thread_var.h>
35
#include <drizzled/internal_error_handler.h>
27
#include <drizzled/sql_base.h>
28
#include <drizzled/lock.h>
36
29
#include <drizzled/item/cache.h>
37
#include <drizzled/item/empty_string.h>
38
30
#include <drizzled/item/float.h>
39
31
#include <drizzled/item/return_int.h>
40
#include <drizzled/lock.h>
41
#include <drizzled/plugin/authentication.h>
42
#include <drizzled/plugin/client.h>
43
#include <drizzled/plugin/event_observer.h>
44
#include <drizzled/plugin/logging.h>
45
#include <drizzled/plugin/query_rewrite.h>
46
#include <drizzled/plugin/scheduler.h>
47
#include <drizzled/plugin/transactional_storage_engine.h>
48
#include <drizzled/probes.h>
49
#include <drizzled/pthread_globals.h>
50
#include <drizzled/query_id.h>
51
#include <drizzled/refresh_version.h>
52
#include <drizzled/select_dump.h>
53
#include <drizzled/select_exists_subselect.h>
54
#include <drizzled/select_export.h>
55
#include <drizzled/select_max_min_finder_subselect.h>
56
#include <drizzled/select_singlerow_subselect.h>
57
#include <drizzled/select_subselect.h>
58
#include <drizzled/select_to_file.h>
59
#include <drizzled/session.h>
60
#include <drizzled/session/cache.h>
32
#include <drizzled/item/empty_string.h>
61
33
#include <drizzled/show.h>
62
#include <drizzled/sql_base.h>
63
#include <drizzled/table/singular.h>
64
#include <drizzled/table_proto.h>
65
#include <drizzled/tmp_table_param.h>
66
#include <drizzled/transaction_services.h>
67
#include <drizzled/user_var_entry.h>
68
#include <drizzled/util/functors.h>
69
#include <plugin/myisam/myisam.h>
76
#include <boost/filesystem.hpp>
77
#include <boost/checked_delete.hpp>
79
#include <drizzled/util/backtrace.h>
81
#include <drizzled/schema.h>
85
namespace fs=boost::filesystem;
34
#include <drizzled/plugin_scheduling.h>
35
#include <libdrizzleclient/errmsg.h>
37
extern scheduling_st thread_scheduler;
90
39
The following is used to initialise Table_ident with a internal
94
43
char empty_c_string[1]= {0}; /* used for not defined db */
96
45
const char * const Session::DEFAULT_WHERE= "field list";
46
extern pthread_key_t THR_Session;
47
extern pthread_key_t THR_Mem_root;
50
/*****************************************************************************
51
** Instansiate templates
52
*****************************************************************************/
54
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
56
template class List<Key>;
57
template class List_iterator<Key>;
58
template class List<Key_part_spec>;
59
template class List_iterator<Key_part_spec>;
60
template class List<Alter_drop>;
61
template class List_iterator<Alter_drop>;
62
template class List<Alter_column>;
63
template class List_iterator<Alter_column>;
67
/****************************************************************************
69
****************************************************************************/
71
extern "C" unsigned char *get_var_key(user_var_entry *entry, size_t *length,
74
*length= entry->name.length;
75
return (unsigned char*) entry->name.str;
78
extern "C" void free_user_var(user_var_entry *entry)
80
char *pos= (char*) entry+ALIGN_SIZE(sizeof(*entry));
81
if (entry->value && entry->value != pos)
98
86
bool Key_part_spec::operator==(const Key_part_spec& other) const
100
88
return length == other.length &&
101
89
field_name.length == other.field_name.length &&
102
!my_strcasecmp(system_charset_info, field_name.str, other.field_name.str);
105
Open_tables_state::Open_tables_state(uint64_t version_arg) :
108
open_tables= temporary_tables= derived_tables= NULL;
109
extra_lock= lock= NULL;
90
!strcmp(field_name.str, other.field_name.str);
94
Construct an (almost) deep copy of this key. Only those
95
elements that are known to never change are not copied.
96
If out of memory, a partial copy is returned and an error is set
100
Key::Key(const Key &rhs, MEM_ROOT *mem_root)
102
key_create_info(rhs.key_create_info),
103
columns(rhs.columns, mem_root),
105
generated(rhs.generated)
107
list_copy_and_replace_each_value(columns, mem_root);
111
Construct an (almost) deep copy of this foreign key. Only those
112
elements that are known to never change are not copied.
113
If out of memory, a partial copy is returned and an error is set
117
Foreign_key::Foreign_key(const Foreign_key &rhs, MEM_ROOT *mem_root)
119
ref_table(rhs.ref_table),
120
ref_columns(rhs.ref_columns),
121
delete_opt(rhs.delete_opt),
122
update_opt(rhs.update_opt),
123
match_opt(rhs.match_opt)
125
list_copy_and_replace_each_value(ref_columns, mem_root);
129
Test if a foreign key (= generated key) is a prefix of the given key
130
(ignoring key name, key type and order of columns)
133
This is only used to test if an index for a FOREIGN KEY exists
136
We only compare field names
139
0 Generated key is a prefix of other key
143
bool foreign_key_prefix(Key *a, Key *b)
145
/* Ensure that 'a' is the generated key */
148
if (b->generated && a->columns.elements > b->columns.elements)
149
std::swap(a, b); // Put shorter key in 'a'
154
return true; // No foreign key
155
std::swap(a, b); // Put generated key in 'a'
158
/* Test if 'a' is a prefix of 'b' */
159
if (a->columns.elements > b->columns.elements)
160
return true; // Can't be prefix
162
List_iterator<Key_part_spec> col_it1(a->columns);
163
List_iterator<Key_part_spec> col_it2(b->columns);
164
const Key_part_spec *col1, *col2;
166
#ifdef ENABLE_WHEN_INNODB_CAN_HANDLE_SWAPED_FOREIGN_KEY_COLUMNS
167
while ((col1= col_it1++))
171
while ((col2= col_it2++))
180
return true; // Error
182
return false; // Is prefix
184
while ((col1= col_it1++))
187
if (!(*col1 == *col2))
190
return false; // Is prefix
196
Check if the foreign key options are compatible with columns
197
on which the FK is created.
203
bool Foreign_key::validate(List<Create_field> &table_fields)
205
Create_field *sql_field;
206
Key_part_spec *column;
207
List_iterator<Key_part_spec> cols(columns);
208
List_iterator<Create_field> it(table_fields);
209
while ((column= cols++))
212
while ((sql_field= it++) &&
213
my_strcasecmp(system_charset_info,
214
column->field_name.str,
215
sql_field->field_name)) {}
218
my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name.str);
221
if (type == Key::FOREIGN_KEY && sql_field->vcol_info)
223
if (delete_opt == FK_OPTION_SET_NULL)
225
my_error(ER_WRONG_FK_OPTION_FOR_VIRTUAL_COLUMN, MYF(0),
226
"ON DELETE SET NULL");
229
if (update_opt == FK_OPTION_SET_NULL)
231
my_error(ER_WRONG_FK_OPTION_FOR_VIRTUAL_COLUMN, MYF(0),
232
"ON UPDATE SET NULL");
235
if (update_opt == FK_OPTION_CASCADE)
237
my_error(ER_WRONG_FK_OPTION_FOR_VIRTUAL_COLUMN, MYF(0),
238
"ON UPDATE CASCADE");
247
/****************************************************************************
248
** Thread specific functions
249
****************************************************************************/
251
Open_tables_state::Open_tables_state(ulong version_arg)
252
:version(version_arg), state_flags(0U)
254
reset_open_tables_state();
113
258
The following functions form part of the C plugin API
115
int tmpfile(const char *prefix)
261
extern "C" int mysql_tmpfile(const char *prefix)
117
263
char filename[FN_REFLEN];
118
int fd = internal::create_temp_file(filename, drizzle_tmpdir.c_str(), prefix, MYF(MY_WME));
264
File fd = create_temp_file(filename, drizzle_tmpdir, prefix,
265
O_CREAT | O_EXCL | O_RDWR,
120
268
unlink(filename);
126
void **Session::getEngineData(const plugin::MonitoredInTransaction *monitored)
128
return static_cast<void **>(&ha_data[monitored->getId()].ha_ptr);
131
ResourceContext *Session::getResourceContext(const plugin::MonitoredInTransaction *monitored,
134
return &ha_data[monitored->getId()].resource_context[index];
276
int session_in_lock_tables(const Session *session)
278
return test(session->in_lock_tables);
283
int session_tablespace_op(const Session *session)
285
return test(session->tablespace_op);
290
Set the process info field of the Session structure.
292
This function is used by plug-ins. Internally, the
293
Session::set_proc_info() function should be used.
295
@see Session::set_proc_info
298
set_session_proc_info(Session *session, const char *info)
300
session->set_proc_info(info);
304
const char *get_session_proc_info(Session *session)
306
return session->get_proc_info();
310
void **session_ha_data(const Session *session, const struct handlerton *hton)
312
return (void **) &session->ha_data[hton->slot].ha_ptr;
137
316
int64_t session_test_options(const Session *session, int64_t test_options)
139
318
return session->options & test_options;
142
Session::Session(plugin::Client *client_arg, catalog::Instance::shared_ptr catalog_arg) :
143
Open_tables_state(refresh_version),
144
mem_root(&main_mem_root),
147
query(new std::string),
148
_schema(new std::string("")),
152
lock_id(&main_lock_id),
154
security_ctx(identifier::User::make_shared()),
155
_where(Session::DEFAULT_WHERE),
156
dbug_sentry(Session_SENTRY_MAGIC),
158
command(COM_CONNECT),
160
_epoch(boost::gregorian::date(1970,1,1)),
161
_connect_time(boost::posix_time::microsec_clock::universal_time()),
163
ha_data(plugin::num_trx_monitored_objects),
166
concurrent_execute_allowed(true),
167
arg_of_last_insert_id_function(false),
168
first_successful_insert_id_in_prev_stmt(0),
169
first_successful_insert_id_in_cur_stmt(0),
171
options(session_startup_options),
174
examined_row_count(0),
178
statement_id_counter(0),
182
_global_read_lock(NONE),
183
count_cuted_fields(CHECK_FIELD_ERROR_FOR_NULL),
185
some_tables_deleted(false),
188
is_fatal_error(false),
189
transaction_rollback_request(false),
190
is_fatal_sub_stmt_error(0),
191
tablespace_op(false),
192
derived_tables_processing(false),
195
transaction_message(NULL),
196
statement_message(NULL),
197
session_event_observers(NULL),
198
_catalog(catalog_arg),
201
client->setSession(this);
322
int session_sql_command(const Session *session)
324
return (int) session->lex->sql_command;
328
int session_tx_isolation(const Session *session)
330
return (int) session->variables.tx_isolation;
334
void session_inc_row_count(Session *session)
336
session->row_count++;
340
:Statement(&main_lex, &main_mem_root,
341
/* statement id */ 0),
342
Open_tables_state(refresh_version),
343
lock_id(&main_lock_id),
345
arg_of_last_insert_id_function(false),
346
first_successful_insert_id_in_prev_stmt(0),
347
first_successful_insert_id_in_cur_stmt(0),
350
transaction_rollback_request(0),
351
is_fatal_sub_stmt_error(0),
353
derived_tables_processing(false),
204
360
Pass nominal parameters to init_alloc_root only to ensure that
205
361
the destructor works OK in case of an error. The main_mem_root
206
362
will be re-initialized in init_for_queries().
208
memory::init_sql_alloc(&main_mem_root, memory::ROOT_MIN_BLOCK_SIZE, 0);
364
init_sql_alloc(&main_mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
366
catalog= (char*)"std"; // the only catalog we have for now
367
some_tables_deleted=no_errors=password= 0;
368
count_cuted_fields= CHECK_FIELD_IGNORE;
371
thread_specific_used= false;
209
374
cuted_fields= sent_row_count= row_count= 0L;
377
statement_id_counter= 0UL;
210
378
// Must be reset to handle error with Session's created for init of mysqld
211
379
lex->current_select= 0;
380
start_time=(time_t) 0;
382
utime_after_lock= 0L;
212
383
memset(&variables, 0, sizeof(variables));
213
scoreboard_index= -1;
214
cleanup_done= abort_on_warning= no_warnings_for_error= false;
216
/* query_cache init */
388
db_charset= global_system_variables.collation_database;
389
memset(ha_data, 0, sizeof(ha_data));
392
dbug_sentry=Session_SENTRY_MAGIC;
394
client_capabilities= 0; // minimalistic client
395
system_thread= NON_SYSTEM_THREAD;
396
cleanup_done= abort_on_warning= no_warnings_for_error= 0;
397
peer_port= 0; // For SHOW PROCESSLIST
399
pthread_mutex_init(&LOCK_delete, MY_MUTEX_INIT_FAST);
220
401
/* Variables with default values */
221
402
proc_info="login";
223
plugin_sessionvar_init(this);
225
variables= global_system_variables above has reset
226
variables.pseudo_thread_id to 0. We need to correct it here to
227
avoid temporary tables replication failure.
229
variables.pseudo_thread_id= thread_id;
230
server_status= SERVER_STATUS_AUTOCOMMIT;
232
if (variables.max_join_size == HA_POS_ERROR)
233
options |= OPTION_BIG_SELECTS;
235
options &= ~OPTION_BIG_SELECTS;
237
open_options=ha_open_options;
238
update_lock_default= TL_WRITE;
239
session_tx_isolation= (enum_tx_isolation) variables.tx_isolation;
241
memset(warn_count, 0, sizeof(warn_count));
242
memset(&status_var, 0, sizeof(status_var));
403
where= Session::DEFAULT_WHERE;
404
server_id = ::server_id;
244
409
/* Initialize sub structures */
245
memory::init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
410
init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
411
hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
412
(hash_get_key) get_var_key,
413
(hash_free_key) free_user_var, 0);
416
protocol= &protocol_text; // Default protocol
417
protocol_text.init(this);
419
const Query_id& local_query_id= Query_id::get_query_id();
420
tablespace_op= false;
422
drizzleclient_randominit(&rand, tmp + (uint64_t) &rand,
423
tmp + (uint64_t)local_query_id.value());
247
424
substitute_null_with_insert_id = false;
248
lock_info.init(); /* safety: will be reset after start */
425
thr_lock_info_init(&lock_info); /* safety: will be reset after start */
249
426
thr_lock_owner_init(&main_lock_id, &lock_info);
251
428
m_internal_handler= NULL;
253
plugin::EventObserver::registerSessionEvents(*this);
256
void Session::free_items()
259
/* This works because items are allocated with memory::sql_alloc() */
260
for (; free_list; free_list= next)
262
next= free_list->next;
263
free_list->delete_self();
267
432
void Session::push_internal_handler(Internal_error_handler *handler)
311
458
m_internal_handler= NULL;
314
void Session::get_xid(DrizzleXid *xid)
316
*xid = *(DrizzleXid *) &transaction.xid_state.xid;
461
#if defined(__cplusplus)
465
void *session_alloc(Session *session, unsigned int size)
467
return session->alloc(size);
470
void *session_calloc(Session *session, unsigned int size)
472
return session->calloc(size);
475
char *session_strdup(Session *session, const char *str)
477
return session->strdup(str);
480
char *session_strmake(Session *session, const char *str, unsigned int size)
482
return session->strmake(str, size);
485
void *session_memdup(Session *session, const void* str, unsigned int size)
487
return session->memdup(str, size);
490
void session_get_xid(const Session *session, DRIZZLE_XID *xid)
492
*xid = *(DRIZZLE_XID *) &session->transaction.xid_state.xid;
495
#if defined(__cplusplus)
500
Init common variables that has to be reset on start and on change_user
503
void Session::init(void)
505
pthread_mutex_lock(&LOCK_global_system_variables);
506
plugin_sessionvar_init(this);
508
variables= global_system_variables above has reset
509
variables.pseudo_thread_id to 0. We need to correct it here to
510
avoid temporary tables replication failure.
512
variables.pseudo_thread_id= thread_id;
513
pthread_mutex_unlock(&LOCK_global_system_variables);
514
server_status= SERVER_STATUS_AUTOCOMMIT;
515
options= session_startup_options;
517
if (variables.max_join_size == HA_POS_ERROR)
518
options |= OPTION_BIG_SELECTS;
520
options &= ~OPTION_BIG_SELECTS;
522
transaction.all.modified_non_trans_table= transaction.stmt.modified_non_trans_table= false;
523
open_options=ha_open_options;
524
update_lock_default= TL_WRITE;
525
session_tx_isolation= (enum_tx_isolation) variables.tx_isolation;
527
memset(warn_count, 0, sizeof(warn_count));
530
memset(&status_var, 0, sizeof(status_var));
535
Init Session for query processing.
536
This has to be called once before we call mysql_parse.
537
See also comments in session.h.
540
void Session::init_for_queries()
543
ha_enable_transaction(this,true);
545
reset_root_defaults(mem_root, variables.query_alloc_block_size,
546
variables.query_prealloc_size);
547
reset_root_defaults(&transaction.mem_root,
548
variables.trans_alloc_block_size,
549
variables.trans_prealloc_size);
550
transaction.xid_state.xid.null();
551
transaction.xid_state.in_session=1;
319
555
/* Do operations that may take a long time */
321
557
void Session::cleanup(void)
323
assert(cleanup_done == false);
559
assert(cleanup_done == 0);
325
setKilled(KILL_CONNECTION);
561
killed= KILL_CONNECTION;
326
562
#ifdef ENABLE_WHEN_BINLOG_WILL_BE_ABLE_TO_PREPARE
327
563
if (transaction.xid_state.xa_state == XA_PREPARED)
333
TransactionServices &transaction_services= TransactionServices::singleton();
334
transaction_services.rollbackTransaction(*this, true);
335
570
xid_cache_delete(&transaction.xid_state);
338
for (UserVars::iterator iter= user_vars.begin();
339
iter != user_vars.end();
342
user_var_entry *entry= (*iter).second;
343
boost::checked_delete(entry);
574
lock=locked_tables; locked_tables=0;
575
close_thread_tables(this);
577
hash_free(&user_vars);
348
578
close_temporary_tables();
350
580
if (global_read_lock)
352
unlockGlobalReadLock();
581
unlock_global_read_lock(this);
358
587
Session::~Session()
589
Session_CHECK_SENTRY(this);
590
add_to_status(&global_status_var, &status_var);
362
if (client and client->isConnected())
592
if (drizzleclient_vio_ok())
364
assert(security_ctx);
365
594
if (global_system_variables.log_warnings)
367
errmsg_printf(error::WARN, ER(ER_FORCING_CLOSE),
368
internal::my_progname,
370
security_ctx->username().c_str());
595
errmsg_printf(ERRMSG_LVL_WARN, ER(ER_FORCING_CLOSE),my_progname,
597
(security_ctx.user.c_str() ?
598
security_ctx.user.c_str() : ""));
599
disconnect(0, false);
376
602
/* Close connection */
380
boost::checked_delete(client);
605
drizzleclient_net_close(&net);
606
drizzleclient_net_end(&net);
384
if (cleanup_done == false)
387
plugin::StorageEngine::closeConnection(this);
611
ha_close_connection(this);
388
612
plugin_sessionvar_cleanup(this);
390
warn_root.free_root(MYF(0));
619
free_root(&warn_root,MYF(0));
620
free_root(&transaction.mem_root,MYF(0));
391
621
mysys_var=0; // Safety (shouldn't be needed)
392
622
dbug_sentry= Session_SENTRY_GONE;
394
main_mem_root.free_root(MYF(0));
395
currentMemRoot().release();
396
currentSession().release();
398
plugin::Logging::postEndDo(this);
399
plugin::EventObserver::deregisterSessionEvents(*this);
402
void Session::setClient(plugin::Client *client_arg)
405
client->setSession(this);
408
void Session::awake(Session::killed_state_t state_to_set)
410
if ((state_to_set == Session::KILL_QUERY) and (command == COM_SLEEP))
415
setKilled(state_to_set);
416
scheduler->killSession(this);
624
free_root(&main_mem_root, MYF(0));
625
pthread_setspecific(THR_Session, 0);
627
/* Ensure that no one is using Session */
628
pthread_mutex_unlock(&LOCK_delete);
629
pthread_mutex_destroy(&LOCK_delete);
634
Add all status variables to another status variable array
638
to_var add to this array
639
from_var from this array
642
This function assumes that all variables are long/ulong.
643
If this assumption will change, then we have to explictely add
644
the other variables after the while loop
647
void add_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var)
649
ulong *end= (ulong*) ((unsigned char*) to_var +
650
offsetof(STATUS_VAR, last_system_status_var) +
652
ulong *to= (ulong*) to_var, *from= (ulong*) from_var;
659
Add the difference between two status variable arrays to another one.
663
to_var add to this array
664
from_var from this array
665
dec_var minus this array
668
This function assumes that all variables are long/ulong.
671
void add_diff_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var,
674
ulong *end= (ulong*) ((unsigned char*) to_var + offsetof(STATUS_VAR,
675
last_system_status_var) +
677
ulong *to= (ulong*) to_var, *from= (ulong*) from_var, *dec= (ulong*) dec_var;
680
*(to++)+= *(from++) - *(dec++);
684
void Session::awake(Session::killed_state state_to_set)
686
Session_CHECK_SENTRY(this);
687
safe_mutex_assert_owner(&LOCK_delete);
689
killed= state_to_set;
418
690
if (state_to_set != Session::KILL_QUERY)
420
DRIZZLE_CONNECTION_DONE(thread_id);
692
thread_scheduler.post_kill_notification(this);
425
boost_unique_lock_t scopedLock(mysys_var->mutex);
696
pthread_mutex_lock(&mysys_var->mutex);
697
if (!system_thread) // Don't abort locks
428
700
This broadcast could be up in the air if the victim thread
429
701
exits the cond in the time between read and broadcast, but that is
430
702
ok since all we want to do is to make the victim thread get out
465
739
assert(thread_stack);
467
currentSession().release();
468
currentSession().reset(this);
470
currentMemRoot().release();
471
currentMemRoot().reset(&mem_root);
741
if (pthread_setspecific(THR_Session, this) ||
742
pthread_setspecific(THR_Mem_root, &mem_root))
473
744
mysys_var=my_thread_var;
476
746
Let mysqld define the thread id (not mysys)
477
747
This allows us to move Session to different threads if needed.
479
749
mysys_var->id= thread_id;
750
real_id= pthread_self(); // For debugging
482
753
We have to call thr_lock_info_init() again here as Session may have been
483
754
created in another thread
756
thr_lock_info_init(&lock_info);
491
Init Session for query processing.
492
This has to be called once before we call mysql_parse.
493
See also comments in session.h.
496
760
void Session::prepareForQueries()
498
762
if (variables.max_join_size == HA_POS_ERROR)
499
763
options |= OPTION_BIG_SELECTS;
764
if (client_capabilities & CLIENT_COMPRESS)
501
767
version= refresh_version;
503
769
command= COM_SLEEP;
506
mem_root->reset_root_defaults(variables.query_alloc_block_size,
507
variables.query_prealloc_size);
508
transaction.xid_state.xid.null();
509
transaction.xid_state.in_session=1;
773
/* In the past this would only run of the user did not have SUPER_ACL */
774
if (sys_init_connect.value_length)
776
execute_init_command(this, &sys_init_connect, &LOCK_sys_init_connect);
779
Security_context *sctx= &security_ctx;
780
killed= Session::KILL_CONNECTION;
781
errmsg_printf(ERRMSG_LVL_WARN
782
, ER(ER_NEW_ABORTING_CONNECTION)
784
, (db ? db : "unconnected")
785
, sctx->user.empty() == false ? sctx->user.c_str() : "unauthenticated"
786
, sctx->ip.c_str(), "init_connect command failed");
787
errmsg_printf(ERRMSG_LVL_WARN, "%s", main_da.message());
514
795
bool Session::initGlobals()
518
disconnect(ER_OUT_OF_RESOURCES);
519
status_var.aborted_connects++;
527
if (initGlobals() || authenticate())
535
while (not client->haveError() && getKilled() != KILL_CONNECTION)
537
if (not executeStatement())
544
bool Session::schedule(Session::shared_ptr &arg)
546
arg->scheduler= plugin::Scheduler::getScheduler();
547
assert(arg->scheduler);
551
long current_connections= connection_count;
553
if (current_connections > 0 and static_cast<uint64_t>(current_connections) > current_global_counters.max_used_connections)
555
current_global_counters.max_used_connections= static_cast<uint64_t>(connection_count);
558
current_global_counters.connections++;
559
arg->thread_id= arg->variables.pseudo_thread_id= global_thread_id++;
561
session::Cache::singleton().insert(arg);
563
if (unlikely(plugin::EventObserver::connectSession(*arg)))
565
// We should do something about an error...
568
if (plugin::Scheduler::getScheduler()->addSession(arg))
570
DRIZZLE_CONNECTION_START(arg->getSessionId());
571
char error_message_buff[DRIZZLE_ERRMSG_SIZE];
573
arg->setKilled(Session::KILL_CONNECTION);
575
arg->status_var.aborted_connects++;
577
/* Can't use my_error() since store_globals has not been called. */
578
/* TODO replace will better error message */
579
snprintf(error_message_buff, sizeof(error_message_buff),
580
ER(ER_CANT_CREATE_THREAD), 1);
581
arg->client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
591
Is this session viewable by the current user?
593
bool Session::isViewable(identifier::User::const_reference user_arg) const
595
return plugin::Authorization::isAuthorized(user_arg, *this, false);
599
const char* Session::enter_cond(boost::condition_variable_any &cond, boost::mutex &mutex, const char* msg)
601
const char* old_msg = get_proc_info();
602
safe_mutex_assert_owner(mutex);
603
mysys_var->current_mutex = &mutex;
604
mysys_var->current_cond = &cond;
605
this->set_proc_info(msg);
609
void Session::exit_cond(const char* old_msg)
612
Putting the mutex unlock in exit_cond() ensures that
613
mysys_var->current_mutex is always unlocked _before_ mysys_var->mutex is
614
locked (if that would not be the case, you'll get a deadlock if someone
615
does a Session::awake() on you).
617
mysys_var->current_mutex->unlock();
618
boost_unique_lock_t scopedLock(mysys_var->mutex);
619
mysys_var->current_mutex = 0;
620
mysys_var->current_cond = 0;
621
this->set_proc_info(old_msg);
799
disconnect(ER_OUT_OF_RESOURCES, true);
800
statistic_increment(aborted_connects, &LOCK_status);
801
thread_scheduler.end_thread(this, 0);
624
807
bool Session::authenticate()
626
if (client->authenticate())
809
/* Use "connect_timeout" value during connection phase */
810
drizzleclient_net_set_read_timeout(&net, connect_timeout);
811
drizzleclient_net_set_write_timeout(&net, connect_timeout);
815
bool connection_is_valid= check_connection();
816
drizzleclient_net_end_statement(this);
818
if (! connection_is_valid)
820
/* We got wrong permissions from check_connection() */
821
statistic_increment(aborted_connects, &LOCK_status);
629
status_var.aborted_connects++;
825
/* Connect completed, set read/write timeouts back to default */
826
drizzleclient_net_set_read_timeout(&net, variables.net_read_timeout);
827
drizzleclient_net_set_write_timeout(&net, variables.net_write_timeout);
634
bool Session::checkUser(const std::string &passwd_str,
635
const std::string &in_db)
637
bool is_authenticated=
638
plugin::Authentication::isAuthenticated(*user(), passwd_str);
831
bool Session::check_connection()
840
if (drizzleclient_net_peer_addr(&net, ip, &peer_port, NI_MAXHOST))
842
my_error(ER_BAD_HOST_ERROR, MYF(0), security_ctx.ip.c_str());
846
security_ctx.ip.assign(ip);
848
drizzleclient_net_keepalive(&net, true);
850
uint32_t server_capabilites;
852
/* buff[] needs to big enough to hold the server_version variable */
853
char buff[SERVER_VERSION_LENGTH + SCRAMBLE_LENGTH + 64];
855
server_capabilites= CLIENT_BASIC_FLAGS;
857
if (opt_using_transactions)
858
server_capabilites|= CLIENT_TRANSACTIONS;
860
server_capabilites|= CLIENT_COMPRESS;
861
#endif /* HAVE_COMPRESS */
863
end= buff + strlen(server_version);
864
if ((end - buff) >= SERVER_VERSION_LENGTH)
865
end= buff + (SERVER_VERSION_LENGTH - 1);
866
memcpy(buff, server_version, end - buff);
870
int4store((unsigned char*) end, thread_id);
873
So as check_connection is the only entry point to authorization
874
procedure, scramble is set here. This gives us new scramble for
877
drizzleclient_create_random_string(scramble, SCRAMBLE_LENGTH, &rand);
879
Old clients does not understand long scrambles, but can ignore packet
880
tail: that's why first part of the scramble is placed here, and second
881
part at the end of packet.
883
end= strncpy(end, scramble, SCRAMBLE_LENGTH_323);
884
end+= SCRAMBLE_LENGTH_323;
886
*end++= 0; /* an empty byte for some reason */
888
int2store(end, server_capabilites);
889
/* write server characteristics: up to 16 bytes allowed */
890
end[2]=(char) default_charset_info->number;
891
int2store(end+3, server_status);
892
memset(end+5, 0, 13);
894
/* write scramble tail */
895
size_t scramble_len= SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323;
896
end= strncpy(end, scramble + SCRAMBLE_LENGTH_323, scramble_len);
899
*end++= 0; /* an empty byte for some reason */
901
/* At this point we write connection message and read reply */
902
if (drizzleclient_net_write_command(&net
903
, (unsigned char) protocol_version
904
, (unsigned char*) ""
906
, (unsigned char*) buff
907
, (size_t) (end-buff))
908
|| (pkt_len= drizzleclient_net_read(&net)) == packet_error
909
|| pkt_len < MIN_HANDSHAKE_SIZE)
911
my_error(ER_HANDSHAKE_ERROR, MYF(0), security_ctx.ip.c_str());
915
if (packet.alloc(variables.net_buffer_length))
916
return false; /* The error is set by alloc(). */
918
client_capabilities= uint2korr(net.read_pos);
921
client_capabilities|= ((uint32_t) uint2korr(net.read_pos + 2)) << 16;
922
max_client_packet_length= uint4korr(net.read_pos + 4);
924
end= (char*) net.read_pos + 32;
927
Disable those bits which are not supported by the server.
928
This is a precautionary measure, if the client lies. See Bug#27944.
930
client_capabilities&= server_capabilites;
932
if (end >= (char*) net.read_pos + pkt_len + 2)
934
my_error(ER_HANDSHAKE_ERROR, MYF(0), security_ctx.ip.c_str());
938
if (client_capabilities & CLIENT_INTERACTIVE)
939
variables.net_wait_timeout= variables.net_interactive_timeout;
940
if ((client_capabilities & CLIENT_TRANSACTIONS) && opt_using_transactions)
941
net.return_status= &server_status;
944
char *passwd= strchr(user, '\0')+1;
945
uint32_t user_len= passwd - user - 1;
947
char db_buff[NAME_LEN + 1]; // buffer to store db in utf8
948
char user_buff[USERNAME_LENGTH + 1]; // buffer to store user in utf8
949
uint32_t dummy_errors;
952
Old clients send null-terminated string as password; new clients send
953
the size (1 byte) + string (not null-terminated). Hence in case of empty
954
password both send '\0'.
956
This strlen() can't be easily deleted without changing protocol.
958
Cast *passwd to an unsigned char, so that it doesn't extend the sign for
959
*passwd > 127 and become 2**32-127+ after casting to uint.
961
uint32_t passwd_len= client_capabilities & CLIENT_SECURE_CONNECTION ?
962
(unsigned char)(*passwd++) : strlen(passwd);
963
l_db= client_capabilities & CLIENT_CONNECT_WITH_DB ? l_db + passwd_len + 1 : 0;
965
/* strlen() can't be easily deleted without changing protocol */
966
uint32_t db_len= l_db ? strlen(l_db) : 0;
968
if (passwd + passwd_len + db_len > (char *) net.read_pos + pkt_len)
970
my_error(ER_HANDSHAKE_ERROR, MYF(0), security_ctx.ip.c_str());
974
/* Since 4.1 all database names are stored in utf8 */
977
db_buff[copy_and_convert(db_buff, sizeof(db_buff)-1,
980
charset(), &dummy_errors)]= 0;
984
user_buff[user_len= copy_and_convert(user_buff, sizeof(user_buff)-1,
985
system_charset_info, user, user_len,
986
charset(), &dummy_errors)]= '\0';
989
/* If username starts and ends in "'", chop them off */
990
if (user_len > 1 && user[0] == '\'' && user[user_len - 1] == '\'')
997
security_ctx.user.assign(user);
999
return check_user(passwd, passwd_len, l_db);
1002
bool Session::check_user(const char *passwd, uint32_t passwd_len, const char *in_db)
1004
LEX_STRING db_str= { (char *) in_db, in_db ? strlen(in_db) : 0 };
1005
bool is_authenticated;
1008
Clear session->db as it points to something, that will be freed when
1009
connection is closed. We don't want to accidentally free a wrong
1010
pointer if connect failed. Also in case of 'CHANGE USER' failure,
1011
current database will be switched to 'no database selected'.
1015
if (passwd_len != 0 && passwd_len != SCRAMBLE_LENGTH)
1017
my_error(ER_HANDSHAKE_ERROR, MYF(0), security_ctx.ip.c_str());
1021
is_authenticated= authenticate_user(this, passwd);
640
1023
if (is_authenticated != true)
642
status_var.access_denied++;
643
/* isAuthenticated has pushed the error message */
1025
my_error(ER_ACCESS_DENIED_ERROR, MYF(0),
1026
security_ctx.user.c_str(),
1027
security_ctx.ip.c_str(),
1028
passwd_len ? ER(ER_YES) : ER(ER_NO));
1033
security_ctx.skip_grants();
647
1035
/* Change database if necessary */
648
if (not in_db.empty())
1036
if (in_db && in_db[0])
650
identifier::Schema identifier(in_db);
651
if (schema::change(*this, identifier))
1038
if (mysql_change_db(this, &db_str, false))
653
/* change_db() has pushed the error message. */
1040
/* mysql_change_db() has pushed the error message. */
658
password= not passwd_str.empty();
1045
password= test(passwd_len); // remember for error messages
660
1047
/* Ready to handle queries */
673
1061
(see my_message_sql)
675
1063
lex->current_select= 0;
1066
This thread will do a blocking read from the client which
1067
will be interrupted when the next command is received from
1068
the client, the connection is closed or "net_wait_timeout"
1069
number of seconds has passed
1071
drizzleclient_net_set_read_timeout(&net, variables.net_wait_timeout);
1074
XXX: this code is here only to clear possible errors of init_connect.
1075
Consider moving to init_connect() instead.
1077
clear_error(); // Clear error message
677
1078
main_da.reset_diagnostics_area();
679
if (client->readCommand(&l_packet, &packet_length) == false)
684
if (getKilled() == KILL_CONNECTION)
687
if (packet_length == 0)
690
l_command= static_cast<enum_server_command>(l_packet[0]);
1080
net_new_transaction(&net);
1082
packet_length= drizzleclient_net_read(&net);
1083
if (packet_length == packet_error)
1085
/* Check if we can continue without closing the connection */
1087
if(net.last_errno== CR_NET_PACKET_TOO_LARGE)
1088
my_error(ER_NET_PACKET_TOO_LARGE, MYF(0));
1089
/* Assert is invalid for dirty connection shutdown
1090
* assert(session->is_error());
1092
drizzleclient_net_end_statement(this);
1096
return_value= false; // We have to close it.
1105
l_packet= (char*) net.read_pos;
1107
'packet_length' contains length of data, as it was stored in packet
1108
header. In case of malformed header, drizzleclient_net_read returns zero.
1109
If packet_length is not zero, drizzleclient_net_read ensures that the returned
1110
number of bytes was actually read from network.
1111
There is also an extra safety measure in drizzleclient_net_read:
1112
it sets packet[packet_length]= 0, but only for non-zero packets.
1114
if (packet_length == 0) /* safety */
1116
/* Initialize with COM_SLEEP packet */
1117
l_packet[0]= (unsigned char) COM_SLEEP;
1120
/* Do not rely on drizzleclient_net_read, extra safety against programming errors. */
1121
l_packet[packet_length]= '\0'; /* safety */
1123
l_command= (enum enum_server_command) (unsigned char) l_packet[0];
692
1125
if (command >= COM_END)
693
1126
command= COM_END; // Wrong command
1128
/* Restore read timeout value */
1129
drizzleclient_net_set_read_timeout(&net, variables.net_read_timeout);
695
1131
assert(packet_length);
696
return not dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
1132
return_value= ! dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
1135
return return_value;
699
1138
bool Session::readAndStoreQuery(const char *in_packet, uint32_t in_packet_length)
865
1323
@return NULL on failure, or pointer to the LEX_STRING object
867
1325
LEX_STRING *Session::make_lex_string(LEX_STRING *lex_str,
868
const std::string &str,
869
bool allocate_lex_string)
871
return make_lex_string(lex_str, str.c_str(), str.length(), allocate_lex_string);
874
LEX_STRING *Session::make_lex_string(LEX_STRING *lex_str,
875
const char* str, uint32_t length,
876
bool allocate_lex_string)
1326
const char* str, uint32_t length,
1327
bool allocate_lex_string)
878
1329
if (allocate_lex_string)
879
if (!(lex_str= (LEX_STRING *)getMemRoot()->allocate(sizeof(LEX_STRING))))
1330
if (!(lex_str= (LEX_STRING *)alloc(sizeof(LEX_STRING))))
881
if (!(lex_str->str= mem_root->strmake_root(str, length)))
1332
if (!(lex_str->str= strmake_root(mem_root, str, length)))
883
1334
lex_str->length= length;
1340
Convert a string to another character set
1344
to Store new allocated string here
1345
to_cs New character set for allocated string
1346
from String to convert
1347
from_length Length of string to convert
1348
from_cs Original character set
1351
to will be 0-terminated to make it easy to pass to system funcs
1356
In this case to->str will point to 0 and to->length will be 0.
1359
bool Session::convert_string(LEX_STRING *to, const CHARSET_INFO * const to_cs,
1360
const char *from, uint32_t from_length,
1361
const CHARSET_INFO * const from_cs)
1363
size_t new_length= to_cs->mbmaxlen * from_length;
1364
uint32_t dummy_errors;
1365
if (!(to->str= (char*) alloc(new_length+1)))
1367
to->length= 0; // Safety fix
1370
to->length= copy_and_convert((char*) to->str, new_length, to_cs,
1371
from, from_length, from_cs, &dummy_errors);
1372
to->str[to->length]=0; // Safety
1378
Convert string from source character set to target character set inplace.
1381
Session::convert_string
1384
Convert string using convert_buffer - buffer for character set
1385
conversion shared between all protocols.
1392
bool Session::convert_string(String *s, const CHARSET_INFO * const from_cs,
1393
const CHARSET_INFO * const to_cs)
1395
uint32_t dummy_errors;
1396
if (convert_buffer.copy(s->ptr(), s->length(), from_cs, to_cs, &dummy_errors))
1398
/* If convert_buffer >> s copying is more efficient long term */
1399
if (convert_buffer.alloced_length() >= convert_buffer.length() * 2 ||
1402
return s->copy(convert_buffer);
1404
s->swap(convert_buffer);
1410
Update some cache variables when character set changes
1413
void Session::update_charset()
1416
charset_is_system_charset= !String::needs_conversion(0,charset(),
1417
system_charset_info,
1419
charset_is_collation_connection=
1420
!String::needs_conversion(0,charset(),variables.getCollation(),
1422
charset_is_character_set_filesystem=
1423
!String::needs_conversion(0, charset(),
1424
variables.character_set_filesystem, ¬_used);
1428
/* routings to adding tables to list of changed in transaction tables */
1430
inline static void list_include(CHANGED_TableList** prev,
1431
CHANGED_TableList* curr,
1432
CHANGED_TableList* new_table)
1437
(*prev)->next = curr;
1441
/* add table to list of changed in transaction tables */
1443
void Session::add_changed_table(Table *table)
1445
assert((options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) &&
1446
table->file->has_transactions());
1447
add_changed_table(table->s->table_cache_key.str,
1448
(long) table->s->table_cache_key.length);
1453
void Session::add_changed_table(const char *key, long key_length)
1455
CHANGED_TableList **prev_changed = &transaction.changed_tables;
1456
CHANGED_TableList *curr = transaction.changed_tables;
1458
for (; curr; prev_changed = &(curr->next), curr = curr->next)
1460
int cmp = (long)curr->key_length - (long)key_length;
1463
list_include(prev_changed, curr, changed_table_dup(key, key_length));
1468
cmp = memcmp(curr->key, key, curr->key_length);
1471
list_include(prev_changed, curr, changed_table_dup(key, key_length));
1480
*prev_changed = changed_table_dup(key, key_length);
1485
CHANGED_TableList* Session::changed_table_dup(const char *key, long key_length)
1487
CHANGED_TableList* new_table =
1488
(CHANGED_TableList*) trans_alloc(ALIGN_SIZE(sizeof(CHANGED_TableList))+
1492
my_error(EE_OUTOFMEMORY, MYF(ME_BELL),
1493
ALIGN_SIZE(sizeof(TableList)) + key_length + 1);
1494
killed= KILL_CONNECTION;
1498
new_table->key= ((char*)new_table)+ ALIGN_SIZE(sizeof(CHANGED_TableList));
1499
new_table->next = 0;
1500
new_table->key_length = key_length;
1501
::memcpy(new_table->key, key, key_length);
887
1506
int Session::send_explain_fields(select_result *result)
889
1508
List<Item> field_list;
920
1539
item->maybe_null= 1;
921
1540
field_list.push_back(new Item_empty_string("Extra", 255, cs));
922
return (result->send_fields(field_list));
925
void select_result::send_error(drizzled::error_t errcode, const char *err)
927
my_message(errcode, err, MYF(0));
1541
return (result->send_fields(field_list,
1542
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF));
1546
struct Item_change_record: public ilink
1550
/* Placement new was hidden by `new' in ilink (TODO: check): */
1551
static void *operator new(size_t ,
1554
static void operator delete(void *,
1557
static void operator delete(void *,
1559
{ /* never called */ }
1564
Register an item tree tree transformation, performed by the query
1565
optimizer. We need a pointer to runtime_memroot because it may be !=
1566
session->mem_root (this may no longer be a true statement)
1569
void Session::nocheck_register_item_tree_change(Item **place, Item *old_value,
1570
MEM_ROOT *runtime_memroot)
1572
Item_change_record *change;
1574
Now we use one node per change, which adds some memory overhead,
1575
but still is rather fast as we use alloc_root for allocations.
1576
A list of item tree changes of an average query should be short.
1578
void *change_mem= alloc_root(runtime_memroot, sizeof(*change));
1579
if (change_mem == 0)
1582
OOM, session->fatal_error() is called by the error handler of the
1583
memroot. Just return.
1587
change= new (change_mem) Item_change_record;
1588
change->place= place;
1589
change->old_value= old_value;
1590
change_list.append(change);
1594
void Session::rollback_item_tree_changes()
1596
I_List_iterator<Item_change_record> it(change_list);
1597
Item_change_record *change;
1599
while ((change= it++))
1600
*change->place= change->old_value;
1601
/* We can forget about changes memory: it's allocated in runtime memroot */
1602
change_list.empty();
930
1607
/************************************************************************
931
1608
Handling writing to file
932
1609
************************************************************************/
934
void select_to_file::send_error(drizzled::error_t errcode,const char *err)
1611
void select_to_file::send_error(uint32_t errcode,const char *err)
936
1613
my_message(errcode, err, MYF(0));
939
(void) cache->end_io_cache();
940
(void) internal::my_close(file, MYF(0));
941
(void) internal::my_delete(path.file_string().c_str(), MYF(0)); // Delete file on error
1616
(void) end_io_cache(&cache);
1617
(void) my_close(file,MYF(0));
1618
(void) my_delete(path,MYF(0)); // Delete file on error
1019
static int create_file(Session *session,
1020
fs::path &target_path,
1021
file_exchange *exchange,
1022
internal::IO_CACHE *cache)
1693
static File create_file(Session *session, char *path, file_exchange *exchange, IO_CACHE *cache)
1024
fs::path to_file(exchange->file_name);
1027
if (not to_file.has_root_directory())
1696
uint32_t option= MY_UNPACK_FILENAME | MY_RELATIVE_PATH;
1698
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
1699
option|= MY_REPLACE_DIR; // Force use of db directory
1702
if (!dirname_length(exchange->file_name))
1029
target_path= fs::system_complete(getDataHomeCatalog());
1030
util::string::const_shared_ptr schema(session->schema());
1031
if (schema and not schema->empty())
1033
int count_elements= 0;
1034
for (fs::path::iterator iter= to_file.begin();
1035
iter != to_file.end();
1036
++iter, ++count_elements)
1039
if (count_elements == 1)
1041
target_path /= *schema;
1044
target_path /= to_file;
1704
strcpy(path, drizzle_real_data_home);
1706
strncat(path, session->db, FN_REFLEN-strlen(drizzle_real_data_home)-1);
1707
(void) fn_format(path, exchange->file_name, path, "", option);
1048
target_path = exchange->file_name;
1051
if (not secure_file_priv.string().empty())
1053
if (target_path.file_string().substr(0, secure_file_priv.file_string().size()) != secure_file_priv.file_string())
1055
/* Write only allowed to dir or subdir specified by secure_file_priv */
1056
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
1061
if (!access(target_path.file_string().c_str(), F_OK))
1710
(void) fn_format(path, exchange->file_name, drizzle_real_data_home, "", option);
1712
if (opt_secure_file_priv &&
1713
strncmp(opt_secure_file_priv, path, strlen(opt_secure_file_priv)))
1715
/* Write only allowed to dir or subdir specified by secure_file_priv */
1716
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
1720
if (!access(path, F_OK))
1063
1722
my_error(ER_FILE_EXISTS_ERROR, MYF(0), exchange->file_name);
1066
1725
/* Create the file world readable */
1067
if ((file= internal::my_create(target_path.file_string().c_str(), 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
1726
if ((file= my_create(path, 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
1069
1729
(void) fchmod(file, 0666); // Because of umask()
1070
if (cache->init_io_cache(file, 0L, internal::WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1731
(void) chmod(path, 0666);
1733
if (init_io_cache(cache, file, 0L, WRITE_CACHE, 0L, 1, MYF(MY_WME)))
1072
internal::my_close(file, MYF(0));
1073
internal::my_delete(target_path.file_string().c_str(), MYF(0)); // Delete file on error, it was just created
1735
my_close(file, MYF(0));
1736
my_delete(path, MYF(0)); // Delete file on error, it was just created
1257
1924
assert before the loop makes that sure.
1260
if ((needs_escaping(*pos, enclosed) ||
1927
if ((NEED_ESCAPING(*pos) ||
1261
1928
(check_second_byte &&
1262
1929
my_mbcharlen(character_set_client, (unsigned char) *pos) == 2 &&
1263
1930
pos + 1 < end &&
1264
needs_escaping(pos[1], enclosed))) &&
1931
NEED_ESCAPING(pos[1]))) &&
1266
Don't escape field_term_char by doubling - doubling is only
1267
valid for ENCLOSED BY characters:
1933
Don't escape field_term_char by doubling - doubling is only
1934
valid for ENCLOSED BY characters:
1269
1936
(enclosed || !is_ambiguous_field_term ||
1270
1937
(int) (unsigned char) *pos != field_term_char))
1273
1940
tmp_buff[0]= ((int) (unsigned char) *pos == field_sep_char &&
1274
1941
is_ambiguous_field_sep) ?
1275
field_sep_char : escape_char;
1276
tmp_buff[1]= *pos ? *pos : '0';
1277
if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)) ||
1278
my_b_write(cache,(unsigned char*) tmp_buff,2))
1283
if (my_b_write(cache,(unsigned char*) start,(uint32_t) (pos-start)))
1942
field_sep_char : escape_char;
1943
tmp_buff[1]= *pos ? *pos : '0';
1944
if (my_b_write(&cache,(unsigned char*) start,(uint32_t) (pos-start)) ||
1945
my_b_write(&cache,(unsigned char*) tmp_buff,2))
1950
if (my_b_write(&cache,(unsigned char*) start,(uint32_t) (pos-start)))
1286
else if (my_b_write(cache,(unsigned char*) res->ptr(),used_length))
1953
else if (my_b_write(&cache,(unsigned char*) res->ptr(),used_length))
1289
1956
if (fixed_row_size)
1290
1957
{ // Fill with space
1291
1958
if (item->max_length > used_length)
1293
/* QQ: Fix by adding a my_b_fill() function */
1297
memset(space, ' ', sizeof(space));
1299
uint32_t length=item->max_length-used_length;
1300
for (; length > sizeof(space) ; length-=sizeof(space))
1302
if (my_b_write(cache,(unsigned char*) space,sizeof(space)))
1305
if (my_b_write(cache,(unsigned char*) space,length))
1960
/* QQ: Fix by adding a my_b_fill() function */
1964
memset(space, ' ', sizeof(space));
1966
uint32_t length=item->max_length-used_length;
1967
for (; length > sizeof(space) ; length-=sizeof(space))
1969
if (my_b_write(&cache,(unsigned char*) space,sizeof(space)))
1972
if (my_b_write(&cache,(unsigned char*) space,length))
1309
1976
if (res && enclosed)
1311
if (my_b_write(cache, (unsigned char*) exchange->enclosed->ptr(),
1978
if (my_b_write(&cache, (unsigned char*) exchange->enclosed->ptr(),
1312
1979
exchange->enclosed->length()))
1315
1982
if (--items_left)
1317
if (my_b_write(cache, (unsigned char*) exchange->field_term->ptr(),
1984
if (my_b_write(&cache, (unsigned char*) exchange->field_term->ptr(),
1318
1985
field_term_length))
1322
if (my_b_write(cache,(unsigned char*) exchange->line_term->ptr(),
1323
exchange->line_term->length()))
1989
if (my_b_write(&cache,(unsigned char*) exchange->line_term->ptr(),
1990
exchange->line_term->length()))
1596
2298
memset(&status_var, 0, sizeof(status_var));
1600
void Session::set_db(const std::string &new_db)
2301
void Security_context::skip_grants()
2303
/* privileges for the user are unknown everything is allowed */
2307
/****************************************************************************
2308
Handling of open and locked tables states.
2310
This is used when we want to open/lock (and then close) some tables when
2311
we already have a set of tables open and locked. We use these methods for
2312
access to mysql.proc table to find definitions of stored routines.
2313
****************************************************************************/
2315
void Session::reset_n_backup_open_tables_state(Open_tables_state *backup)
2317
backup->set_open_tables_state(this);
2318
reset_open_tables_state();
2319
state_flags|= Open_tables_state::BACKUPS_AVAIL;
2324
void Session::restore_backup_open_tables_state(Open_tables_state *backup)
2327
Before we will throw away current open tables state we want
2328
to be sure that it was properly cleaned up.
2330
assert(open_tables == 0 && temporary_tables == 0 &&
2331
handler_tables == 0 && derived_tables == 0 &&
2332
lock == 0 && locked_tables == 0);
2333
set_open_tables_state(backup);
2338
bool Session::set_db(const char *new_db, size_t new_db_len)
1602
2340
/* Do not reallocate memory if current chunk is big enough. */
1603
if (new_db.length())
1605
_schema.reset(new std::string(new_db));
2341
if (db && new_db && db_length >= new_db_len)
2342
memcpy(db, new_db, new_db_len+1);
1609
_schema.reset(new std::string(""));
2349
db= (char *)malloc(new_db_len + 1);
2352
memcpy(db, new_db, new_db_len);
2359
db_length= db ? new_db_len : 0;
2360
return new_db && !db;
2365
Check the killed state of a user thread
2366
@param session user thread
2367
@retval 0 the user thread is active
2368
@retval 1 the user thread has been killed
2370
extern "C" int session_killed(const Session *session)
2372
return(session->killed);
2376
Return the thread id of a user thread
2377
@param session user thread
2380
extern "C" unsigned long session_get_thread_id(const Session *session)
2382
return((unsigned long)session->thread_id);
2387
LEX_STRING *session_make_lex_string(Session *session, LEX_STRING *lex_str,
2388
const char *str, unsigned int size,
2389
int allocate_lex_string)
2391
return session->make_lex_string(lex_str, str, size,
2392
(bool) allocate_lex_string);
2395
extern "C" const struct charset_info_st *session_charset(Session *session)
2397
return(session->charset());
2400
extern "C" char **session_query(Session *session)
2402
return(&session->query);
2405
extern "C" int session_non_transactional_update(const Session *session)
2407
return(session->transaction.all.modified_non_trans_table);
2410
extern "C" void session_mark_transaction_to_rollback(Session *session, bool all)
2412
mark_transaction_to_rollback(session, all);
1617
2419
@param session Thread handle
1618
2420
@param all true <=> rollback main transaction.
1620
void Session::markTransactionForRollback(bool all)
2423
void mark_transaction_to_rollback(Session *session, bool all)
1622
is_fatal_sub_stmt_error= true;
1623
transaction_rollback_request= all;
2427
session->is_fatal_sub_stmt_error= true;
2428
session->transaction_rollback_request= all;
1626
void Session::disconnect(enum error_t errcode)
2432
void Session::disconnect(uint32_t errcode, bool should_lock)
1628
2434
/* Allow any plugins to cleanup their session variables */
1629
2435
plugin_sessionvar_cleanup(this);
1631
2437
/* If necessary, log any aborted or unauthorized connections */
1632
if (getKilled() || client->wasAborted())
1634
status_var.aborted_threads++;
2438
if (killed || (net.error && net.vio != 0))
2439
statistic_increment(aborted_threads, &LOCK_status);
1637
if (client->wasAborted())
2441
if (net.error && net.vio != 0)
1639
if (not getKilled() && variables.log_warnings > 1)
2443
if (! killed && variables.log_warnings > 1)
1641
errmsg_printf(error::WARN, ER(ER_NEW_ABORTING_CONNECTION)
2445
Security_context *sctx= &security_ctx;
2447
errmsg_printf(ERRMSG_LVL_WARN, ER(ER_NEW_ABORTING_CONNECTION)
1643
, (_schema->empty() ? "unconnected" : _schema->c_str())
1644
, security_ctx->username().empty() == false ? security_ctx->username().c_str() : "unauthenticated"
1645
, security_ctx->address().c_str()
2449
, (db ? db : "unconnected")
2450
, sctx->user.empty() == false ? sctx->user.c_str() : "unauthenticated"
1646
2452
, (main_da.is_error() ? main_da.message() : ER(ER_UNKNOWN_ERROR)));
1650
setKilled(Session::KILL_CONNECTION);
1652
if (client->isConnected())
2456
/* Close out our connection to the client */
2459
(void) pthread_mutex_lock(&LOCK_thread_count);
2460
killed= Session::KILL_CONNECTION;
2461
if ((vio= net.vio) != 0)
1654
if (errcode != EE_OK)
1656
/*my_error(errcode, ER(errcode));*/
1657
client->sendError(errcode, ER(errcode));
2464
net_send_error(this, errcode, ER(errcode)); /* purecov: inspected */
2465
drizzleclient_net_close(&net); /* vio is freed in delete session */
2468
(void) pthread_mutex_unlock(&LOCK_thread_count);
2472
Reset Session part responsible for command processing state.
2474
This needs to be called before execution of every statement
2475
(prepared or conventional).
2476
It is not called by substatements of routines.
2479
Make it a method of Session and align its name with the rest of
2480
reset/end/start/init methods.
2482
Call it after we use Session for queries, not before.
1663
2485
void Session::reset_for_next_command()
1671
2493
auto_inc_intervals_in_cur_stmt_for_binlog.empty();
1673
is_fatal_error= false;
1674
2496
server_status&= ~ (SERVER_MORE_RESULTS_EXISTS |
1675
2497
SERVER_QUERY_NO_INDEX_USED |
1676
2498
SERVER_QUERY_NO_GOOD_INDEX_USED);
2500
If in autocommit mode and not in a transaction, reset
2501
OPTION_STATUS_NO_TRANS_UPDATE | OPTION_KEEP_LOG to not get warnings
2502
in ha_rollback_trans() about some tables couldn't be rolled back.
2504
if (!(options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
2506
options&= ~OPTION_KEEP_LOG;
2507
transaction.all.modified_non_trans_table= false;
2509
thread_specific_used= false;
1679
2512
main_da.reset_diagnostics_area();
1680
2513
total_warn_count=0; // Warnings for this query
1681
2514
sent_row_count= examined_row_count= 0;
1685
2520
Close all temporary tables created by 'CREATE TEMPORARY TABLE' for thread
2521
creates one DROP TEMPORARY Table binlog event for each pseudo-thread
1688
void Open_tables_state::close_temporary_tables()
2524
void Session::close_temporary_tables()
1691
2527
Table *tmp_next;
1693
if (not temporary_tables)
2529
if (!temporary_tables)
1696
2532
for (table= temporary_tables; table; table= tmp_next)
1698
tmp_next= table->getNext();
1701
temporary_tables= NULL;
1705
unlink from session->temporary tables and close temporary table
1708
void Open_tables_state::close_temporary_table(Table *table)
1710
if (table->getPrev())
1712
table->getPrev()->setNext(table->getNext());
1713
if (table->getPrev()->getNext())
1715
table->getNext()->setPrev(table->getPrev());
1720
/* removing the item from the list */
1721
assert(table == temporary_tables);
1723
slave must reset its temporary list pointer to zero to exclude
1724
passing non-zero value to end_slave via rli->save_temporary_tables
1725
when no temp tables opened, see an invariant below.
1727
temporary_tables= table->getNext();
1728
if (temporary_tables)
1730
table->getNext()->setPrev(NULL);
1737
Close and drop a temporary table
1740
This dosn't unlink table from session->temporary
1741
If this is needed, use close_temporary_table()
1744
void Open_tables_state::nukeTable(Table *table)
1746
plugin::StorageEngine *table_type= table->getShare()->db_type();
1748
table->free_io_cache();
1749
table->delete_table();
1751
identifier::Table identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName(), table->getShare()->getPath());
1752
rm_temporary_table(table_type, identifier);
1754
boost::checked_delete(table->getMutableShare());
1756
boost::checked_delete(table);
2534
tmp_next= table->next;
2535
close_temporary(table, 1, 1);
2537
temporary_tables= 0;
1759
2543
/** Clear most status variables. */
1760
2544
extern time_t flush_status_time;
2545
extern uint32_t max_used_connections;
1762
2547
void Session::refresh_status()
2549
pthread_mutex_lock(&LOCK_status);
2551
/* Add thread's status variabes to global status */
2552
add_to_status(&global_status_var, &status_var);
1764
2554
/* Reset thread's status variables */
1765
2555
memset(&status_var, 0, sizeof(status_var));
2557
/* Reset some global variables */
2558
reset_status_vars();
2560
/* Reset the counters of all key caches (default and named). */
2561
process_key_caches(reset_key_cache_counters);
1767
2562
flush_status_time= time((time_t*) 0);
1768
current_global_counters.max_used_connections= 1; /* We set it to one, because we know we exist */
1769
current_global_counters.connections= 0;
1772
user_var_entry *Session::getVariable(LEX_STRING &name, bool create_if_not_exists)
1774
return getVariable(std::string(name.str, name.length), create_if_not_exists);
1777
user_var_entry *Session::getVariable(const std::string &name, bool create_if_not_exists)
1782
UserVars::iterator iter= user_vars.find(name);
1783
if (iter != user_vars.end())
1784
return (*iter).second;
1786
if (not create_if_not_exists)
1789
user_var_entry *entry= NULL;
1790
entry= new (nothrow) user_var_entry(name.c_str(), query_id);
1795
std::pair<UserVars::iterator, bool> returnable= user_vars.insert(make_pair(name, entry));
1797
if (not returnable.second)
1799
boost::checked_delete(entry);
1805
void Session::setVariable(const std::string &name, const std::string &value)
1807
user_var_entry *updateable_var= getVariable(name.c_str(), true);
1810
updateable_var->update_hash(false,
1811
(void*)value.c_str(),
1812
static_cast<uint32_t>(value.length()), STRING_RESULT,
1814
DERIVATION_IMPLICIT, false);
1818
void Open_tables_state::mark_temp_tables_as_free_for_reuse()
1820
for (Table *table= temporary_tables ; table ; table= table->getNext())
1822
if (table->query_id == getQueryId())
1825
table->cursor->ha_reset();
1830
void Session::mark_used_tables_as_free_for_reuse(Table *table)
1832
for (; table ; table= table->getNext())
1834
if (table->query_id == getQueryId())
1837
table->cursor->ha_reset();
1843
Unlocks tables and frees derived tables.
1844
Put all normal tables used by thread in free list.
1846
It will only close/mark as free for reuse tables opened by this
1847
substatement, it will also check if we are closing tables after
1848
execution of complete query (i.e. we are on upper level) and will
1849
leave prelocked mode if needed.
1851
void Session::close_thread_tables()
1853
clearDerivedTables();
1856
Mark all temporary tables used by this statement as free for reuse.
1858
mark_temp_tables_as_free_for_reuse();
1860
Let us commit transaction for statement. Since in 5.0 we only have
1861
one statement transaction and don't allow several nested statement
1862
transactions this call will do nothing if we are inside of stored
1863
function or trigger (i.e. statement transaction is already active and
1864
does not belong to statement for which we do close_thread_tables()).
1865
TODO: This should be fixed in later releases.
1868
TransactionServices &transaction_services= TransactionServices::singleton();
1869
main_da.can_overwrite_status= true;
1870
transaction_services.autocommitOrRollback(*this, is_error());
1871
main_da.can_overwrite_status= false;
1872
transaction.stmt.reset();
1878
For RBR we flush the pending event just before we unlock all the
1879
tables. This means that we are at the end of a topmost
1880
statement, so we ensure that the STMT_END_F flag is set on the
1881
pending event. For statements that are *inside* stored
1882
functions, the pending event will not be flushed: that will be
1883
handled either before writing a query log event (inside
1884
binlog_query()) or when preparing a pending event.
1890
Note that we need to hold table::Cache::singleton().mutex() while changing the
1891
open_tables list. Another thread may work on it.
1892
(See: table::Cache::singleton().removeTable(), wait_completed_table())
1893
Closing a MERGE child before the parent would be fatal if the
1894
other thread tries to abort the MERGE lock in between.
1897
close_open_tables();
1900
void Session::close_tables_for_reopen(TableList **tables)
1903
If table list consists only from tables from prelocking set, table list
1904
for new attempt should be empty, so we have to update list's root pointer.
1906
if (lex->first_not_own_table() == *tables)
1908
lex->chop_off_not_own_tables();
1909
for (TableList *tmp= *tables; tmp; tmp= tmp->next_global)
1911
close_thread_tables();
1914
bool Session::openTablesLock(TableList *tables)
1921
if (open_tables_from_list(&tables, &counter))
1924
if (not lock_tables(tables, counter, &need_reopen))
1927
if (not need_reopen)
1930
close_tables_for_reopen(&tables);
1933
if ((handle_derived(lex, &derived_prepare) || (handle_derived(lex, &derived_filling))))
1940
@note "best_effort" is used in cases were if a failure occurred on this
1941
operation it would not be surprising because we are only removing because there
1942
might be an issue (lame engines).
1945
bool Open_tables_state::rm_temporary_table(const identifier::Table &identifier, bool best_effort)
1947
if (not plugin::StorageEngine::dropTable(*static_cast<Session *>(this), identifier))
1949
if (not best_effort)
1952
identifier.getSQLPath(path);
1953
errmsg_printf(error::WARN, _("Could not remove temporary table: '%s', error: %d"),
1954
path.c_str(), errno);
1963
bool Open_tables_state::rm_temporary_table(plugin::StorageEngine *base, const identifier::Table &identifier)
1965
drizzled::error_t error;
1968
if (not plugin::StorageEngine::dropTable(*static_cast<Session *>(this), *base, identifier, error))
1971
identifier.getSQLPath(path);
1972
errmsg_printf(error::WARN, _("Could not remove temporary table: '%s', error: %d"),
1973
path.c_str(), error);
1982
@note this will be removed, I am looking through Hudson to see if it is finding
1983
any tables that are missed during cleanup.
1985
void Open_tables_state::dumpTemporaryTableNames(const char *foo)
1989
if (not temporary_tables)
1992
cerr << "Begin Run: " << foo << "\n";
1993
for (table= temporary_tables; table; table= table->getNext())
1995
bool have_proto= false;
1997
message::Table *proto= table->getShare()->getTableMessage();
1998
if (table->getShare()->getTableMessage())
2001
const char *answer= have_proto ? "true" : "false";
2005
cerr << "\tTable Name " << table->getShare()->getSchemaName() << "." << table->getShare()->getTableName() << " : " << answer << "\n";
2006
cerr << "\t\t Proto " << proto->schema() << " " << proto->name() << "\n";
2010
cerr << "\tTabl;e Name " << table->getShare()->getSchemaName() << "." << table->getShare()->getTableName() << " : " << answer << "\n";
2015
table::Singular *Session::getInstanceTable()
2017
temporary_shares.push_back(new table::Singular()); // This will not go into the tableshare cache, so no key is used.
2019
table::Singular *tmp_share= temporary_shares.back();
2028
Create a reduced Table object with properly set up Field list from a
2029
list of field definitions.
2031
The created table doesn't have a table Cursor associated with
2032
it, has no keys, no group/distinct, no copy_funcs array.
2033
The sole purpose of this Table object is to use the power of Field
2034
class to read/write data to/from table->getInsertRecord(). Then one can store
2035
the record in any container (RB tree, hash, etc).
2036
The table is created in Session mem_root, so are the table's fields.
2037
Consequently, if you don't BLOB fields, you don't need to free it.
2039
@param session connection handle
2040
@param field_list list of column definitions
2043
0 if out of memory, Table object in case of success
2045
table::Singular *Session::getInstanceTable(List<CreateField> &field_list)
2047
temporary_shares.push_back(new table::Singular(this, field_list)); // This will not go into the tableshare cache, so no key is used.
2049
table::Singular *tmp_share= temporary_shares.back();
2058
static const std::string NONE= "NONE";
2059
static const std::string GOT_GLOBAL_READ_LOCK= "HAS GLOBAL READ LOCK";
2060
static const std::string MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT= "HAS GLOBAL READ LOCK WITH BLOCKING COMMIT";
2062
const std::string &type(drizzled::Session::global_read_lock_t type)
2068
case Session::GOT_GLOBAL_READ_LOCK:
2069
return GOT_GLOBAL_READ_LOCK;
2070
case Session::MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT:
2071
return MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT;
2075
size_t max_string_length(drizzled::Session::global_read_lock_t)
2077
return MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT.size();
2080
} /* namespace display */
2082
} /* namespace drizzled */
2563
max_used_connections= 1; /* We set it to one, because we know we exist */
2564
pthread_mutex_unlock(&LOCK_status);