109
198
The following functions form part of the C plugin API
111
201
extern "C" int mysql_tmpfile(const char *prefix)
113
203
char filename[FN_REFLEN];
114
int fd = internal::create_temp_file(filename, drizzle_tmpdir, prefix, MYF(MY_WME));
204
File fd = create_temp_file(filename, mysql_tmpdir, prefix,
205
O_CREAT | O_EXCL | O_RDWR | O_TEMPORARY,
209
This can be removed once the following bug is fixed:
210
Bug #28903 create_temp_file() doesn't honor O_TEMPORARY option
211
(file not removed) (Unix)
116
213
unlink(filename);
123
int session_tablespace_op(const Session *session)
125
return test(session->tablespace_op);
221
int thd_in_lock_tables(const THD *thd)
223
return test(thd->in_lock_tables);
228
int thd_tablespace_op(const THD *thd)
230
return test(thd->tablespace_op);
129
Set the process info field of the Session structure.
235
Set the process info field of the THD structure.
131
237
This function is used by plug-ins. Internally, the
132
Session::set_proc_info() function should be used.
238
THD::set_proc_info() function should be used.
134
@see Session::set_proc_info
240
@see THD::set_proc_info
137
set_session_proc_info(Session *session, const char *info)
139
session->set_proc_info(info);
143
const char *get_session_proc_info(Session *session)
145
return session->get_proc_info();
148
void **Session::getEngineData(const plugin::MonitoredInTransaction *monitored)
150
return static_cast<void **>(&ha_data[monitored->getId()].ha_ptr);
153
ResourceContext *Session::getResourceContext(const plugin::MonitoredInTransaction *monitored,
156
return &ha_data[monitored->getId()].resource_context[index];
160
int64_t session_test_options(const Session *session, int64_t test_options)
162
return session->options & test_options;
166
int session_sql_command(const Session *session)
168
return (int) session->lex->sql_command;
172
int session_tx_isolation(const Session *session)
174
return (int) session->variables.tx_isolation;
177
Session::Session(plugin::Client *client_arg)
179
Open_tables_state(refresh_version),
180
mem_root(&main_mem_root),
186
lock_id(&main_lock_id),
188
ha_data(plugin::num_trx_monitored_objects),
189
arg_of_last_insert_id_function(false),
190
first_successful_insert_id_in_prev_stmt(0),
191
first_successful_insert_id_in_cur_stmt(0),
194
some_tables_deleted(false),
197
is_fatal_error(false),
198
transaction_rollback_request(false),
199
is_fatal_sub_stmt_error(0),
200
derived_tables_processing(false),
201
tablespace_op(false),
204
transaction_message(NULL),
205
statement_message(NULL)
207
memset(process_list_info, 0, PROCESS_LIST_WIDTH);
208
client->setSession(this);
243
set_thd_proc_info(THD *thd, const char *info)
245
thd->set_proc_info(info);
249
const char *get_thd_proc_info(THD *thd)
251
return thd->get_proc_info();
255
void **thd_ha_data(const THD *thd, const struct handlerton *hton)
257
return (void **) &thd->ha_data[hton->slot].ha_ptr;
261
int64_t thd_test_options(const THD *thd, int64_t test_options)
263
return thd->options & test_options;
267
int thd_sql_command(const THD *thd)
269
return (int) thd->lex->sql_command;
273
int thd_tx_isolation(const THD *thd)
275
return (int) thd->variables.tx_isolation;
279
void thd_inc_row_count(THD *thd)
285
Clear this diagnostics area.
287
Normally called at the end of a statement.
291
Diagnostics_area::reset_diagnostics_area()
293
can_overwrite_status= false;
294
/** Don't take chances in production */
300
m_total_warn_count= 0;
302
/** Tiny reset in debug mode to see garbage right away */
308
Set OK status -- ends commands that do not return a
309
result set, e.g. INSERT/UPDATE/DELETE.
313
Diagnostics_area::set_ok_status(THD *thd, ha_rows affected_rows_arg,
314
uint64_t last_insert_id_arg,
315
const char *message_arg)
319
In production, refuse to overwrite an error or a custom response
322
if (is_error() || is_disabled())
324
/** Only allowed to report success if has not yet reported an error */
326
m_server_status= thd->server_status;
327
m_total_warn_count= thd->total_warn_count;
328
m_affected_rows= affected_rows_arg;
329
m_last_insert_id= last_insert_id_arg;
331
strmake(m_message, message_arg, sizeof(m_message) - 1);
343
Diagnostics_area::set_eof_status(THD *thd)
345
/** Only allowed to report eof if has not yet reported an error */
349
In production, refuse to overwrite an error or a custom response
352
if (is_error() || is_disabled())
355
m_server_status= thd->server_status;
357
If inside a stored procedure, do not return the total
358
number of warnings, since they are not available to the client
361
m_total_warn_count= thd->total_warn_count;
371
Diagnostics_area::set_error_status(THD *thd __attribute__((unused)),
372
uint32_t sql_errno_arg,
373
const char *message_arg)
376
Only allowed to report error if has not yet reported a success
377
The only exception is when we flush the message to the client,
378
an error can happen during the flush.
380
assert(! is_set() || can_overwrite_status);
382
In production, refuse to overwrite a custom response with an
388
m_sql_errno= sql_errno_arg;
389
strmake(m_message, message_arg, sizeof(m_message) - 1);
396
Mark the diagnostics area as 'DISABLED'.
398
This is used in rare cases when the COM_ command at hand sends a response
399
in a custom format. One example is the query cache, another is
404
Diagnostics_area::disable_status()
407
m_status= DA_DISABLED;
412
:Statement(&main_lex, &main_mem_root,
413
/* statement id */ 0),
414
Open_tables_state(refresh_version), rli_fake(0),
415
lock_id(&main_lock_id),
417
binlog_table_maps(0), binlog_flags(0UL),
418
arg_of_last_insert_id_function(false),
419
first_successful_insert_id_in_prev_stmt(0),
420
first_successful_insert_id_in_prev_stmt_for_binlog(0),
421
first_successful_insert_id_in_cur_stmt(0),
422
stmt_depends_on_first_successful_insert_id_in_prev_stmt(false),
425
transaction_rollback_request(0),
426
is_fatal_sub_stmt_error(0),
431
derived_tables_processing(false),
211
437
Pass nominal parameters to init_alloc_root only to ensure that
212
438
the destructor works OK in case of an error. The main_mem_root
213
439
will be re-initialized in init_for_queries().
215
memory::init_sql_alloc(&main_mem_root, memory::ROOT_MIN_BLOCK_SIZE, 0);
441
init_sql_alloc(&main_mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
443
catalog= (char*)"std"; // the only catalog we have for now
444
main_security_ctx.init();
445
security_ctx= &main_security_ctx;
446
some_tables_deleted=no_errors=password= 0;
217
448
count_cuted_fields= CHECK_FIELD_IGNORE;
218
449
killed= NOT_KILLED;
451
is_slave_error= thread_specific_used= false;
452
hash_clear(&handler_tables_hash);
222
455
cuted_fields= sent_row_count= row_count= 0L;
223
457
row_count_func= -1;
224
458
statement_id_counter= 0UL;
225
// Must be reset to handle error with Session's created for init of mysqld
459
// Must be reset to handle error with THD's created for init of mysqld
226
460
lex->current_select= 0;
227
461
start_time=(time_t) 0;
229
463
utime_after_lock= 0L;
230
466
memset(&variables, 0, sizeof(variables));
236
dbug_sentry=Session_SENTRY_MAGIC;
237
cleanup_done= abort_on_warning= no_warnings_for_error= false;
472
db_charset= global_system_variables.collation_database;
473
memset(ha_data, 0, sizeof(ha_data));
475
binlog_evt_union.do_union= false;
476
dbug_sentry=THD_SENTRY_MAGIC;
478
client_capabilities= 0; // minimalistic client
479
system_thread= NON_SYSTEM_THREAD;
480
cleanup_done= abort_on_warning= no_warnings_for_error= 0;
481
peer_port= 0; // For SHOW PROCESSLIST
482
transaction.m_pending_rows_event= 0;
238
484
pthread_mutex_init(&LOCK_delete, MY_MUTEX_INIT_FAST);
240
486
/* Variables with default values */
241
487
proc_info="login";
242
where= Session::DEFAULT_WHERE;
243
command= COM_CONNECT;
245
plugin_sessionvar_init(this);
247
variables= global_system_variables above has reset
248
variables.pseudo_thread_id to 0. We need to correct it here to
249
avoid temporary tables replication failure.
251
variables.pseudo_thread_id= thread_id;
252
server_status= SERVER_STATUS_AUTOCOMMIT;
253
options= session_startup_options;
255
if (variables.max_join_size == HA_POS_ERROR)
256
options |= OPTION_BIG_SELECTS;
258
options &= ~OPTION_BIG_SELECTS;
260
open_options=ha_open_options;
261
update_lock_default= TL_WRITE;
262
session_tx_isolation= (enum_tx_isolation) variables.tx_isolation;
264
memset(warn_count, 0, sizeof(warn_count));
266
memset(&status_var, 0, sizeof(status_var));
488
where= THD::DEFAULT_WHERE;
489
server_id = ::server_id;
268
495
/* Initialize sub structures */
269
memory::init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
496
init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
497
user_connect=(USER_CONN *)0;
270
498
hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
271
499
(hash_get_key) get_var_key,
272
500
(hash_free_key) free_user_var, 0);
502
/* For user vars replication*/
504
my_init_dynamic_array(&user_var_events,
505
sizeof(BINLOG_USER_VAR_EVENT *), 16, 16);
507
memset(&user_var_events, 0, sizeof(user_var_events));
510
protocol= &protocol_text; // Default protocol
511
protocol_text.init(this);
513
tablespace_op= false;
515
randominit(&rand, tmp + (ulong) &rand, tmp + (ulong) ::global_query_id);
274
516
substitute_null_with_insert_id = false;
275
517
thr_lock_info_init(&lock_info); /* safety: will be reset after start */
276
518
thr_lock_owner_init(&main_lock_id, &lock_info);
524
851
assert(thread_stack);
526
if (pthread_setspecific(THR_Session, this) ||
527
pthread_setspecific(THR_Mem_root, &mem_root))
853
if (my_pthread_setspecific_ptr(THR_THD, this) ||
854
my_pthread_setspecific_ptr(THR_MALLOC, &mem_root))
530
856
mysys_var=my_thread_var;
533
858
Let mysqld define the thread id (not mysys)
534
This allows us to move Session to different threads if needed.
859
This allows us to move THD to different threads if needed.
536
861
mysys_var->id= thread_id;
537
862
real_id= pthread_self(); // For debugging
540
We have to call thr_lock_info_init() again here as Session may have been
865
We have to call thr_lock_info_init() again here as THD may have been
541
866
created in another thread
543
868
thr_lock_info_init(&lock_info);
548
Init Session for query processing.
549
This has to be called once before we call mysql_parse.
550
See also comments in session.h.
877
THD::cleanup_after_query()
880
This function is used to reset thread data to its default state.
883
This function is not suitable for setting thread data to some
884
non-default values, as there is only one replication thread, so
885
different master threads may overwrite data of each other on
553
void Session::prepareForQueries()
555
if (variables.max_join_size == HA_POS_ERROR)
556
options |= OPTION_BIG_SELECTS;
558
version= refresh_version;
563
reset_root_defaults(mem_root, variables.query_alloc_block_size,
564
variables.query_prealloc_size);
565
transaction.xid_state.xid.null();
566
transaction.xid_state.in_session=1;
569
bool Session::initGlobals()
573
disconnect(ER_OUT_OF_RESOURCES, true);
574
statistic_increment(aborted_connects, &LOCK_status);
582
if (initGlobals() || authenticate())
590
while (! client->haveError() && killed != KILL_CONNECTION)
592
if (! executeStatement())
599
bool Session::schedule()
601
scheduler= plugin::Scheduler::getScheduler();
604
connection_count.increment();
606
if (connection_count > max_used_connections)
607
max_used_connections= connection_count;
609
thread_id= variables.pseudo_thread_id= global_thread_id++;
611
pthread_mutex_lock(&LOCK_thread_count);
612
getSessionList().push_back(this);
613
pthread_mutex_unlock(&LOCK_thread_count);
615
if (scheduler->addSession(this))
617
DRIZZLE_CONNECTION_START(thread_id);
618
char error_message_buff[DRIZZLE_ERRMSG_SIZE];
620
killed= Session::KILL_CONNECTION;
622
statistic_increment(aborted_connects, &LOCK_status);
624
/* Can't use my_error() since store_globals has not been called. */
625
/* TODO replace will better error message */
626
snprintf(error_message_buff, sizeof(error_message_buff),
627
ER(ER_CANT_CREATE_THREAD), 1);
628
client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
636
const char* Session::enter_cond(pthread_cond_t *cond,
637
pthread_mutex_t* mutex,
640
const char* old_msg = get_proc_info();
641
safe_mutex_assert_owner(mutex);
642
mysys_var->current_mutex = mutex;
643
mysys_var->current_cond = cond;
644
this->set_proc_info(msg);
648
void Session::exit_cond(const char* old_msg)
651
Putting the mutex unlock in exit_cond() ensures that
652
mysys_var->current_mutex is always unlocked _before_ mysys_var->mutex is
653
locked (if that would not be the case, you'll get a deadlock if someone
654
does a Session::awake() on you).
656
pthread_mutex_unlock(mysys_var->current_mutex);
657
pthread_mutex_lock(&mysys_var->mutex);
658
mysys_var->current_mutex = 0;
659
mysys_var->current_cond = 0;
660
this->set_proc_info(old_msg);
661
pthread_mutex_unlock(&mysys_var->mutex);
664
bool Session::authenticate()
667
if (client->authenticate())
670
statistic_increment(aborted_connects, &LOCK_status);
674
bool Session::checkUser(const char *passwd, uint32_t passwd_len, const char *in_db)
676
const string passwd_str(passwd, passwd_len);
677
bool is_authenticated=
678
plugin::Authentication::isAuthenticated(getSecurityContext(),
681
if (is_authenticated != true)
683
/* isAuthenticated has pushed the error message */
687
/* Change database if necessary */
688
if (in_db && in_db[0])
690
SchemaIdentifier identifier(in_db);
691
if (mysql_change_db(this, identifier))
693
/* mysql_change_db() has pushed the error message. */
698
password= test(passwd_len); // remember for error messages
700
/* Ready to handle queries */
704
bool Session::executeStatement()
707
uint32_t packet_length;
709
enum enum_server_command l_command;
712
indicator of uninitialized lex => normal flow of errors handling
715
lex->current_select= 0;
717
main_da.reset_diagnostics_area();
719
if (client->readCommand(&l_packet, &packet_length) == false)
722
if (packet_length == 0)
725
l_command= (enum enum_server_command) (unsigned char) l_packet[0];
727
if (command >= COM_END)
728
command= COM_END; // Wrong command
730
assert(packet_length);
731
return ! dispatch_command(l_command, this, l_packet+1, (uint32_t) (packet_length-1));
734
bool Session::readAndStoreQuery(const char *in_packet, uint32_t in_packet_length)
736
/* Remove garbage at start and end of query */
737
while (in_packet_length > 0 && my_isspace(charset(), in_packet[0]))
742
const char *pos= in_packet + in_packet_length; /* Point at end null */
743
while (in_packet_length > 0 &&
744
(pos[-1] == ';' || my_isspace(charset() ,pos[-1])))
750
query.assign(in_packet, in_packet + in_packet_length);
755
bool Session::endTransaction(enum enum_mysql_completiontype completion)
759
TransactionServices &transaction_services= TransactionServices::singleton();
761
if (transaction.xid_state.xa_state != XA_NOTR)
763
my_error(ER_XAER_RMFAIL, MYF(0), xa_state_names[transaction.xid_state.xa_state]);
770
* We don't use endActiveTransaction() here to ensure that this works
771
* even if there is a problem with the OPTION_AUTO_COMMIT flag
772
* (Which of course should never happen...)
774
server_status&= ~SERVER_STATUS_IN_TRANS;
775
if (transaction_services.ha_commit_trans(this, true))
777
options&= ~(OPTION_BEGIN);
780
do_release= 1; /* fall through */
781
case COMMIT_AND_CHAIN:
782
result= endActiveTransaction();
783
if (result == true && completion == COMMIT_AND_CHAIN)
784
result= startTransaction();
786
case ROLLBACK_RELEASE:
787
do_release= 1; /* fall through */
789
case ROLLBACK_AND_CHAIN:
791
server_status&= ~SERVER_STATUS_IN_TRANS;
792
if (transaction_services.ha_rollback_trans(this, true))
794
options&= ~(OPTION_BEGIN);
795
if (result == true && (completion == ROLLBACK_AND_CHAIN))
796
result= startTransaction();
800
my_error(ER_UNKNOWN_COM_ERROR, MYF(0));
805
my_error(killed_errno(), MYF(0));
806
else if ((result == true) && do_release)
807
killed= Session::KILL_CONNECTION;
812
bool Session::endActiveTransaction()
815
TransactionServices &transaction_services= TransactionServices::singleton();
817
if (transaction.xid_state.xa_state != XA_NOTR)
819
my_error(ER_XAER_RMFAIL, MYF(0), xa_state_names[transaction.xid_state.xa_state]);
822
if (options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
824
server_status&= ~SERVER_STATUS_IN_TRANS;
825
if (transaction_services.ha_commit_trans(this, true))
828
options&= ~(OPTION_BEGIN);
832
bool Session::startTransaction(start_transaction_option_t opt)
836
if (! endActiveTransaction())
842
options|= OPTION_BEGIN;
843
server_status|= SERVER_STATUS_IN_TRANS;
845
if (plugin::TransactionalStorageEngine::notifyStartTransaction(this, opt))
854
void Session::cleanup_after_query()
857
Reset rand_used so that detection of calls to rand() will save random
889
void THD::cleanup_after_query()
892
Reset rand_used so that detection of calls to rand() will save random
858
893
seeds if needed by the slave.
861
896
/* Forget those values, for next binlogger: */
897
stmt_depends_on_first_successful_insert_id_in_prev_stmt= 0;
862
898
auto_inc_intervals_in_cur_stmt_for_binlog.empty();
864
901
if (first_successful_insert_id_in_cur_stmt > 0)
866
903
/* set what LAST_INSERT_ID() will return */
867
first_successful_insert_id_in_prev_stmt= first_successful_insert_id_in_cur_stmt;
904
first_successful_insert_id_in_prev_stmt=
905
first_successful_insert_id_in_cur_stmt;
868
906
first_successful_insert_id_in_cur_stmt= 0;
869
907
substitute_null_with_insert_id= true;
871
arg_of_last_insert_id_function= false;
909
arg_of_last_insert_id_function= 0;
872
910
/* Free Items that were created during this execution */
874
912
/* Reset where. */
875
where= Session::DEFAULT_WHERE;
913
where= THD::DEFAULT_WHERE;
879
918
Create a LEX_STRING in this connection.
1597
2152
access to mysql.proc table to find definitions of stored routines.
1598
2153
****************************************************************************/
1600
void Session::reset_n_backup_open_tables_state(Open_tables_state *backup)
2155
void THD::reset_n_backup_open_tables_state(Open_tables_state *backup)
1602
2157
backup->set_open_tables_state(this);
1603
2158
reset_open_tables_state();
1604
backups_available= false;
2159
state_flags|= Open_tables_state::BACKUPS_AVAIL;
1608
void Session::restore_backup_open_tables_state(Open_tables_state *backup)
2164
void THD::restore_backup_open_tables_state(Open_tables_state *backup)
1611
2167
Before we will throw away current open tables state we want
1612
2168
to be sure that it was properly cleaned up.
1614
2170
assert(open_tables == 0 && temporary_tables == 0 &&
1615
derived_tables == 0 &&
2171
handler_tables == 0 && derived_tables == 0 &&
2172
lock == 0 && locked_tables == 0);
1617
2173
set_open_tables_state(backup);
1620
bool Session::set_db(const std::string &new_db)
1622
/* Do not reallocate memory if current chunk is big enough. */
1623
if (new_db.length())
1635
2178
Check the killed state of a user thread
1636
@param session user thread
2179
@param thd user thread
1637
2180
@retval 0 the user thread is active
1638
2181
@retval 1 the user thread has been killed
1640
extern "C" int session_killed(const Session *session)
2183
extern "C" int thd_killed(const DRIZZLE_THD thd)
1642
return(session->killed);
2185
return(thd->killed);
1646
Return the session id of a user session
1647
@param pointer to Session object
1648
@return session's id
2189
Return the thread id of a user thread
2190
@param thd user thread
1650
extern "C" unsigned long session_get_thread_id(const Session *session)
1652
return (unsigned long) session->getSessionId();
1656
const struct charset_info_st *session_charset(Session *session)
1658
return(session->charset());
1661
int session_non_transactional_update(const Session *session)
1663
return(session->transaction.all.hasModifiedNonTransData());
1666
void session_mark_transaction_to_rollback(Session *session, bool all)
1668
mark_transaction_to_rollback(session, all);
2193
extern "C" unsigned long thd_get_thread_id(const DRIZZLE_THD thd)
2195
return((unsigned long)thd->thread_id);
2199
#ifdef INNODB_COMPATIBILITY_HOOKS
2200
extern "C" const struct charset_info_st *thd_charset(DRIZZLE_THD thd)
2202
return(thd->charset());
2205
extern "C" char **thd_query(DRIZZLE_THD thd)
2207
return(&thd->query);
2210
extern "C" int thd_slave_thread(const DRIZZLE_THD thd)
2212
return(thd->slave_thread);
2215
extern "C" int thd_non_transactional_update(const DRIZZLE_THD thd)
2217
return(thd->transaction.all.modified_non_trans_table);
2220
extern "C" int thd_binlog_format(const DRIZZLE_THD thd)
2222
return (int) thd->variables.binlog_format;
2225
extern "C" void thd_mark_transaction_to_rollback(DRIZZLE_THD thd, bool all)
2227
mark_transaction_to_rollback(thd, all);
2229
#endif // INNODB_COMPATIBILITY_HOOKS */
1672
2233
Mark transaction to rollback and mark error as fatal to a sub-statement.
1674
@param session Thread handle
2235
@param thd Thread handle
1675
2236
@param all true <=> rollback main transaction.
1677
void mark_transaction_to_rollback(Session *session, bool all)
1681
session->is_fatal_sub_stmt_error= true;
1682
session->transaction_rollback_request= all;
1686
void Session::disconnect(uint32_t errcode, bool should_lock)
1688
/* Allow any plugins to cleanup their session variables */
1689
plugin_sessionvar_cleanup(this);
1691
/* If necessary, log any aborted or unauthorized connections */
1692
if (killed || client->wasAborted())
1693
statistic_increment(aborted_threads, &LOCK_status);
1695
if (client->wasAborted())
1697
if (! killed && variables.log_warnings > 1)
1699
SecurityContext *sctx= &security_ctx;
1701
errmsg_printf(ERRMSG_LVL_WARN, ER(ER_NEW_ABORTING_CONNECTION)
1703
, (db.empty() ? "unconnected" : db.c_str())
1704
, sctx->getUser().empty() == false ? sctx->getUser().c_str() : "unauthenticated"
1705
, sctx->getIp().c_str()
1706
, (main_da.is_error() ? main_da.message() : ER(ER_UNKNOWN_ERROR)));
1710
/* Close out our connection to the client */
1712
(void) pthread_mutex_lock(&LOCK_thread_count);
1713
killed= Session::KILL_CONNECTION;
1714
if (client->isConnected())
1718
/*my_error(errcode, ER(errcode));*/
1719
client->sendError(errcode, ER(errcode));
1724
(void) pthread_mutex_unlock(&LOCK_thread_count);
1727
void Session::reset_for_next_command()
1732
Those two lines below are theoretically unneeded as
1733
Session::cleanup_after_query() should take care of this already.
1735
auto_inc_intervals_in_cur_stmt_for_binlog.empty();
1737
is_fatal_error= false;
1738
server_status&= ~ (SERVER_MORE_RESULTS_EXISTS |
1739
SERVER_QUERY_NO_INDEX_USED |
1740
SERVER_QUERY_NO_GOOD_INDEX_USED);
1743
main_da.reset_diagnostics_area();
1744
total_warn_count=0; // Warnings for this query
1745
sent_row_count= examined_row_count= 0;
1749
Close all temporary tables created by 'CREATE TEMPORARY TABLE' for thread
1752
void Session::close_temporary_tables()
1757
if (not temporary_tables)
1760
for (table= temporary_tables; table; table= tmp_next)
1762
tmp_next= table->next;
1765
temporary_tables= NULL;
1769
unlink from session->temporary tables and close temporary table
1772
void Session::close_temporary_table(Table *table)
1776
table->prev->next= table->next;
1777
if (table->prev->next)
1778
table->next->prev= table->prev;
1782
/* removing the item from the list */
1783
assert(table == temporary_tables);
1785
slave must reset its temporary list pointer to zero to exclude
1786
passing non-zero value to end_slave via rli->save_temporary_tables
1787
when no temp tables opened, see an invariant below.
1789
temporary_tables= table->next;
1790
if (temporary_tables)
1791
table->next->prev= NULL;
1797
Close and drop a temporary table
1800
This dosn't unlink table from session->temporary
1801
If this is needed, use close_temporary_table()
1804
void Session::nukeTable(Table *table)
1806
plugin::StorageEngine *table_type= table->s->db_type();
1808
table->free_io_cache();
1809
table->closefrm(false);
1811
TableIdentifier identifier(table->s->getSchemaName(), table->s->table_name.str, table->s->path.str);
1812
rm_temporary_table(table_type, identifier);
1814
table->s->free_table_share();
1816
/* This makes me sad, but we're allocating it via malloc */
1820
/** Clear most status variables. */
1821
extern time_t flush_status_time;
1822
extern uint32_t max_used_connections;
1824
void Session::refresh_status()
1826
pthread_mutex_lock(&LOCK_status);
1828
/* Add thread's status variabes to global status */
1829
add_to_status(&global_status_var, &status_var);
1831
/* Reset thread's status variables */
1832
memset(&status_var, 0, sizeof(status_var));
1834
/* Reset some global variables */
1835
reset_status_vars();
1837
/* Reset the counters of all key caches (default and named). */
1838
reset_key_cache_counters();
1839
flush_status_time= time((time_t*) 0);
1840
max_used_connections= 1; /* We set it to one, because we know we exist */
1841
pthread_mutex_unlock(&LOCK_status);
1844
user_var_entry *Session::getVariable(LEX_STRING &name, bool create_if_not_exists)
1846
user_var_entry *entry= NULL;
1848
entry= (user_var_entry*) hash_search(&user_vars, (unsigned char*) name.str, name.length);
1850
if ((entry == NULL) && create_if_not_exists)
1852
if (!hash_inited(&user_vars))
1854
entry= new (nothrow) user_var_entry(name.str, query_id);
1859
if (my_hash_insert(&user_vars, (unsigned char*) entry))
1862
free((char*) entry);
1871
void Session::mark_temp_tables_as_free_for_reuse()
1873
for (Table *table= temporary_tables ; table ; table= table->next)
1875
if (table->query_id == query_id)
1878
table->cursor->ha_reset();
1883
void Session::mark_used_tables_as_free_for_reuse(Table *table)
1885
for (; table ; table= table->next)
1887
if (table->query_id == query_id)
1890
table->cursor->ha_reset();
1896
Unlocks tables and frees derived tables.
1897
Put all normal tables used by thread in free list.
1899
It will only close/mark as free for reuse tables opened by this
1900
substatement, it will also check if we are closing tables after
1901
execution of complete query (i.e. we are on upper level) and will
1902
leave prelocked mode if needed.
1904
void Session::close_thread_tables()
1909
We are assuming here that session->derived_tables contains ONLY derived
1910
tables for this substatement. i.e. instead of approach which uses
1911
query_id matching for determining which of the derived tables belong
1912
to this substatement we rely on the ability of substatements to
1913
save/restore session->derived_tables during their execution.
1915
TODO: Probably even better approach is to simply associate list of
1916
derived tables with (sub-)statement instead of thread and destroy
1917
them at the end of its execution.
1923
Close all derived tables generated in queries like
1924
SELECT * FROM (SELECT * FROM t1)
1926
for (table= derived_tables ; table ; table= next)
1929
table->free_tmp_table(this);
1935
Mark all temporary tables used by this statement as free for reuse.
1937
mark_temp_tables_as_free_for_reuse();
1939
Let us commit transaction for statement. Since in 5.0 we only have
1940
one statement transaction and don't allow several nested statement
1941
transactions this call will do nothing if we are inside of stored
1942
function or trigger (i.e. statement transaction is already active and
1943
does not belong to statement for which we do close_thread_tables()).
1944
TODO: This should be fixed in later releases.
1946
if (backups_available == false)
1948
TransactionServices &transaction_services= TransactionServices::singleton();
1949
main_da.can_overwrite_status= true;
1950
transaction_services.ha_autocommit_or_rollback(this, is_error());
1951
main_da.can_overwrite_status= false;
1952
transaction.stmt.reset();
1958
For RBR we flush the pending event just before we unlock all the
1959
tables. This means that we are at the end of a topmost
1960
statement, so we ensure that the STMT_END_F flag is set on the
1961
pending event. For statements that are *inside* stored
1962
functions, the pending event will not be flushed: that will be
1963
handled either before writing a query log event (inside
1964
binlog_query()) or when preparing a pending event.
1966
mysql_unlock_tables(this, lock);
1970
Note that we need to hold LOCK_open while changing the
1971
open_tables list. Another thread may work on it.
1972
(See: remove_table_from_cache(), mysql_wait_completed_table())
1973
Closing a MERGE child before the parent would be fatal if the
1974
other thread tries to abort the MERGE lock in between.
1977
close_open_tables();
1980
void Session::close_tables_for_reopen(TableList **tables)
1983
If table list consists only from tables from prelocking set, table list
1984
for new attempt should be empty, so we have to update list's root pointer.
1986
if (lex->first_not_own_table() == *tables)
1988
lex->chop_off_not_own_tables();
1989
for (TableList *tmp= *tables; tmp; tmp= tmp->next_global)
1991
close_thread_tables();
1994
bool Session::openTablesLock(TableList *tables)
2001
if (open_tables_from_list(&tables, &counter))
2004
if (not lock_tables(tables, counter, &need_reopen))
2006
if (not need_reopen)
2008
close_tables_for_reopen(&tables);
2010
if ((mysql_handle_derived(lex, &mysql_derived_prepare) ||
2011
(fill_derived_tables() &&
2012
mysql_handle_derived(lex, &mysql_derived_filling))))
2018
bool Session::openTables(TableList *tables, uint32_t flags)
2021
bool ret= fill_derived_tables();
2022
assert(ret == false);
2023
if (open_tables_from_list(&tables, &counter, flags) ||
2024
mysql_handle_derived(lex, &mysql_derived_prepare))
2029
bool Session::rm_temporary_table(TableIdentifier &identifier)
2031
if (plugin::StorageEngine::dropTable(*this, identifier))
2033
errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
2034
identifier.getSQLPath().c_str(), errno);
2035
dumpTemporaryTableNames("rm_temporary_table()");
2043
bool Session::rm_temporary_table(plugin::StorageEngine *base, TableIdentifier &identifier)
2047
if (plugin::StorageEngine::dropTable(*this, *base, identifier))
2049
errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
2050
identifier.getSQLPath().c_str(), errno);
2051
dumpTemporaryTableNames("rm_temporary_table()");
2060
@note this will be removed, I am looking through Hudson to see if it is finding
2061
any tables that are missed during cleanup.
2063
void Session::dumpTemporaryTableNames(const char *foo)
2067
if (not temporary_tables)
2070
cerr << "Begin Run: " << foo << "\n";
2071
for (table= temporary_tables; table; table= table->next)
2073
bool have_proto= false;
2075
message::Table *proto= table->s->getTableProto();
2076
if (table->s->getTableProto())
2079
const char *answer= have_proto ? "true" : "false";
2083
cerr << "\tTable Name " << table->s->getSchemaName() << "." << table->s->table_name.str << " : " << answer << "\n";
2084
cerr << "\t\t Proto " << proto->schema() << " " << proto->name() << "\n";
2087
cerr << "\tTabl;e Name " << table->s->getSchemaName() << "." << table->s->table_name.str << " : " << answer << "\n";
2091
bool Session::storeTableMessage(TableIdentifier &identifier, message::Table &table_message)
2093
table_message_cache.insert(make_pair(identifier.getPath(), table_message));
2098
bool Session::removeTableMessage(TableIdentifier &identifier)
2100
TableMessageCache::iterator iter;
2102
iter= table_message_cache.find(identifier.getPath());
2104
if (iter == table_message_cache.end())
2107
table_message_cache.erase(iter);
2112
bool Session::getTableMessage(TableIdentifier &identifier, message::Table &table_message)
2114
TableMessageCache::iterator iter;
2116
iter= table_message_cache.find(identifier.getPath());
2118
if (iter == table_message_cache.end())
2121
table_message.CopyFrom(((*iter).second));
2126
bool Session::doesTableMessageExist(TableIdentifier &identifier)
2128
TableMessageCache::iterator iter;
2130
iter= table_message_cache.find(identifier.getPath());
2132
if (iter == table_message_cache.end())
2140
bool Session::renameTableMessage(TableIdentifier &from, TableIdentifier &to)
2142
TableMessageCache::iterator iter;
2144
table_message_cache[to.getPath()]= table_message_cache[from.getPath()];
2146
iter= table_message_cache.find(to.getPath());
2148
if (iter == table_message_cache.end())
2153
(*iter).second.set_schema(to.getSchemaName());
2154
(*iter).second.set_name(to.getTableName());
2159
} /* namespace drizzled */
2239
void mark_transaction_to_rollback(THD *thd, bool all)
2243
thd->is_fatal_sub_stmt_error= true;
2244
thd->transaction_rollback_request= all;
2247
/***************************************************************************
2248
Handling of XA id cacheing
2249
***************************************************************************/
2251
pthread_mutex_t LOCK_xid_cache;
2254
extern "C" unsigned char *xid_get_hash_key(const unsigned char *, size_t *, bool);
2255
extern "C" void xid_free_hash(void *);
2257
unsigned char *xid_get_hash_key(const unsigned char *ptr, size_t *length,
2258
bool not_used __attribute__((unused)))
2260
*length=((XID_STATE*)ptr)->xid.key_length();
2261
return ((XID_STATE*)ptr)->xid.key();
2264
void xid_free_hash(void *ptr)
2266
if (!((XID_STATE*)ptr)->in_thd)
2267
free((unsigned char*)ptr);
2270
bool xid_cache_init()
2272
pthread_mutex_init(&LOCK_xid_cache, MY_MUTEX_INIT_FAST);
2273
return hash_init(&xid_cache, &my_charset_bin, 100, 0, 0,
2274
xid_get_hash_key, xid_free_hash, 0) != 0;
2277
void xid_cache_free()
2279
if (hash_inited(&xid_cache))
2281
hash_free(&xid_cache);
2282
pthread_mutex_destroy(&LOCK_xid_cache);
2286
XID_STATE *xid_cache_search(XID *xid)
2288
pthread_mutex_lock(&LOCK_xid_cache);
2289
XID_STATE *res=(XID_STATE *)hash_search(&xid_cache, xid->key(), xid->key_length());
2290
pthread_mutex_unlock(&LOCK_xid_cache);
2295
bool xid_cache_insert(XID *xid, enum xa_states xa_state)
2299
pthread_mutex_lock(&LOCK_xid_cache);
2300
if (hash_search(&xid_cache, xid->key(), xid->key_length()))
2302
else if (!(xs=(XID_STATE *)my_malloc(sizeof(*xs), MYF(MY_WME))))
2306
xs->xa_state=xa_state;
2309
res=my_hash_insert(&xid_cache, (unsigned char*)xs);
2311
pthread_mutex_unlock(&LOCK_xid_cache);
2316
bool xid_cache_insert(XID_STATE *xid_state)
2318
pthread_mutex_lock(&LOCK_xid_cache);
2319
assert(hash_search(&xid_cache, xid_state->xid.key(),
2320
xid_state->xid.key_length())==0);
2321
bool res=my_hash_insert(&xid_cache, (unsigned char*)xid_state);
2322
pthread_mutex_unlock(&LOCK_xid_cache);
2327
void xid_cache_delete(XID_STATE *xid_state)
2329
pthread_mutex_lock(&LOCK_xid_cache);
2330
hash_delete(&xid_cache, (unsigned char *)xid_state);
2331
pthread_mutex_unlock(&LOCK_xid_cache);
2335
Implementation of interface to write rows to the binary log through the
2336
thread. The thread is responsible for writing the rows it has
2337
inserted/updated/deleted.
2342
Template member function for ensuring that there is an rows log
2343
event of the apropriate type before proceeding.
2346
- Events of type 'RowEventT' have the type code 'type_code'.
2349
If a non-NULL pointer is returned, the pending event for thread 'thd' will
2350
be an event of type 'RowEventT' (which have the type code 'type_code')
2351
will either empty or have enough space to hold 'needed' bytes. In
2352
addition, the columns bitmap will be correct for the row, meaning that
2353
the pending event will be flushed if the columns in the event differ from
2354
the columns suppled to the function.
2357
If no error, a non-NULL pending event (either one which already existed or
2358
the newly created one).
2362
template <class RowsEventT> Rows_log_event*
2363
THD::binlog_prepare_pending_rows_event(Table* table, uint32_t serv_id,
2365
bool is_transactional,
2366
RowsEventT *hint __attribute__((unused)))
2368
/* Pre-conditions */
2369
assert(table->s->table_map_id != UINT32_MAX);
2371
/* Fetch the type code for the RowsEventT template parameter */
2372
int const type_code= RowsEventT::TYPE_CODE;
2375
There is no good place to set up the transactional data, so we
2378
if (binlog_setup_trx_data())
2381
Rows_log_event* pending= binlog_get_pending_rows_event();
2383
if (unlikely(pending && !pending->is_valid()))
2387
Check if the current event is non-NULL and a write-rows
2388
event. Also check if the table provided is mapped: if it is not,
2389
then we have switched to writing to a new table.
2390
If there is no pending event, we need to create one. If there is a pending
2391
event, but it's not about the same table id, or not of the same type
2392
(between Write, Update and Delete), or not the same affected columns, or
2393
going to be too big, flush this event to disk and create a new pending
2396
The last test is necessary for the Cluster injector to work
2397
correctly. The reason is that the Cluster can inject two write
2398
rows with different column bitmaps if there is an insert followed
2399
by an update in the same transaction, and these are grouped into a
2400
single epoch/transaction when fed to the injector.
2402
TODO: Fix the code so that the last test can be removed.
2405
pending->server_id != serv_id ||
2406
pending->get_table_id() != table->s->table_map_id ||
2407
pending->get_type_code() != type_code ||
2408
pending->get_data_size() + needed > opt_binlog_rows_event_max_size ||
2409
!bitmap_cmp(pending->get_cols(), table->write_set))
2411
/* Create a new RowsEventT... */
2412
Rows_log_event* const
2413
ev= new RowsEventT(this, table, table->s->table_map_id,
2417
ev->server_id= serv_id; // I don't like this, it's too easy to forget.
2419
flush the pending event and replace it with the newly created
2422
if (unlikely(mysql_bin_log.flush_and_set_pending_rows_event(this, ev)))
2428
return(ev); /* This is the new pending event */
2430
return(pending); /* This is the current pending event */
2433
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
2435
Instantiate the versions we need, we have -fno-implicit-template as
2438
template Rows_log_event*
2439
THD::binlog_prepare_pending_rows_event(Table*, uint32_t, size_t, bool,
2440
Write_rows_log_event*);
2442
template Rows_log_event*
2443
THD::binlog_prepare_pending_rows_event(Table*, uint32_t, size_t, bool,
2444
Delete_rows_log_event *);
2446
template Rows_log_event*
2447
THD::binlog_prepare_pending_rows_event(Table*, uint32_t, size_t, bool,
2448
Update_rows_log_event *);
2453
Class to handle temporary allocation of memory for row data.
2455
The responsibilities of the class is to provide memory for
2456
packing one or two rows of packed data (depending on what
2457
constructor is called).
2459
In order to make the allocation more efficient for "simple" rows,
2460
i.e., rows that do not contain any blobs, a pointer to the
2461
allocated memory is of memory is stored in the table structure
2462
for simple rows. If memory for a table containing a blob field
2463
is requested, only memory for that is allocated, and subsequently
2464
released when the object is destroyed.
2467
class Row_data_memory {
2470
Build an object to keep track of a block-local piece of memory
2471
for storing a row of data.
2474
Table where the pre-allocated memory is stored.
2477
Length of data that is needed, if the record contain blobs.
2479
Row_data_memory(Table *table, size_t const len1)
2482
m_alloc_checked= false;
2483
allocate_memory(table, len1);
2484
m_ptr[0]= has_memory() ? m_memory : 0;
2488
Row_data_memory(Table *table, size_t const len1, size_t const len2)
2491
m_alloc_checked= false;
2492
allocate_memory(table, len1 + len2);
2493
m_ptr[0]= has_memory() ? m_memory : 0;
2494
m_ptr[1]= has_memory() ? m_memory + len1 : 0;
2499
if (m_memory != 0 && m_release_memory_on_destruction)
2500
free((unsigned char*) m_memory);
2504
Is there memory allocated?
2506
@retval true There is memory allocated
2507
@retval false Memory allocation failed
2509
bool has_memory() const {
2510
m_alloc_checked= true;
2511
return m_memory != 0;
2514
unsigned char *slot(uint32_t s)
2516
assert(s < sizeof(m_ptr)/sizeof(*m_ptr));
2517
assert(m_ptr[s] != 0);
2518
assert(m_alloc_checked == true);
2523
void allocate_memory(Table *const table, size_t const total_length)
2525
if (table->s->blob_fields == 0)
2528
The maximum length of a packed record is less than this
2529
length. We use this value instead of the supplied length
2530
when allocating memory for records, since we don't know how
2531
the memory will be used in future allocations.
2533
Since table->s->reclength is for unpacked records, we have
2534
to add two bytes for each field, which can potentially be
2535
added to hold the length of a packed field.
2537
size_t const maxlen= table->s->reclength + 2 * table->s->fields;
2540
Allocate memory for two records if memory hasn't been
2541
allocated. We allocate memory for two records so that it can
2542
be used when processing update rows as well.
2544
if (table->write_row_record == 0)
2545
table->write_row_record=
2546
(unsigned char *) alloc_root(&table->mem_root, 2 * maxlen);
2547
m_memory= table->write_row_record;
2548
m_release_memory_on_destruction= false;
2552
m_memory= (unsigned char *) my_malloc(total_length, MYF(MY_WME));
2553
m_release_memory_on_destruction= true;
2557
mutable bool m_alloc_checked;
2558
bool m_release_memory_on_destruction;
2559
unsigned char *m_memory;
2560
unsigned char *m_ptr[2];
2565
int THD::binlog_write_row(Table* table, bool is_trans,
2566
unsigned char const *record)
2568
assert(current_stmt_binlog_row_based && mysql_bin_log.is_open());
2571
Pack records into format for transfer. We are allocating more
2572
memory than needed, but that doesn't matter.
2574
Row_data_memory memory(table, table->max_row_length(record));
2575
if (!memory.has_memory())
2576
return HA_ERR_OUT_OF_MEM;
2578
unsigned char *row_data= memory.slot(0);
2580
size_t const len= pack_row(table, table->write_set, row_data, record);
2582
Rows_log_event* const ev=
2583
binlog_prepare_pending_rows_event(table, server_id, len, is_trans,
2584
static_cast<Write_rows_log_event*>(0));
2586
if (unlikely(ev == 0))
2587
return HA_ERR_OUT_OF_MEM;
2589
return ev->add_row_data(row_data, len);
2592
int THD::binlog_update_row(Table* table, bool is_trans,
2593
const unsigned char *before_record,
2594
const unsigned char *after_record)
2596
assert(current_stmt_binlog_row_based && mysql_bin_log.is_open());
2598
size_t const before_maxlen = table->max_row_length(before_record);
2599
size_t const after_maxlen = table->max_row_length(after_record);
2601
Row_data_memory row_data(table, before_maxlen, after_maxlen);
2602
if (!row_data.has_memory())
2603
return HA_ERR_OUT_OF_MEM;
2605
unsigned char *before_row= row_data.slot(0);
2606
unsigned char *after_row= row_data.slot(1);
2608
size_t const before_size= pack_row(table, table->read_set, before_row,
2610
size_t const after_size= pack_row(table, table->write_set, after_row,
2613
Rows_log_event* const ev=
2614
binlog_prepare_pending_rows_event(table, server_id,
2615
before_size + after_size, is_trans,
2616
static_cast<Update_rows_log_event*>(0));
2618
if (unlikely(ev == 0))
2619
return HA_ERR_OUT_OF_MEM;
2622
ev->add_row_data(before_row, before_size) ||
2623
ev->add_row_data(after_row, after_size);
2626
int THD::binlog_delete_row(Table* table, bool is_trans,
2627
unsigned char const *record)
2629
assert(current_stmt_binlog_row_based && mysql_bin_log.is_open());
2632
Pack records into format for transfer. We are allocating more
2633
memory than needed, but that doesn't matter.
2635
Row_data_memory memory(table, table->max_row_length(record));
2636
if (unlikely(!memory.has_memory()))
2637
return HA_ERR_OUT_OF_MEM;
2639
unsigned char *row_data= memory.slot(0);
2641
size_t const len= pack_row(table, table->read_set, row_data, record);
2643
Rows_log_event* const ev=
2644
binlog_prepare_pending_rows_event(table, server_id, len, is_trans,
2645
static_cast<Delete_rows_log_event*>(0));
2647
if (unlikely(ev == 0))
2648
return HA_ERR_OUT_OF_MEM;
2650
return ev->add_row_data(row_data, len);
2654
int THD::binlog_flush_pending_rows_event(bool stmt_end)
2657
We shall flush the pending event even if we are not in row-based
2658
mode: it might be the case that we left row-based mode before
2659
flushing anything (e.g., if we have explicitly locked tables).
2661
if (!mysql_bin_log.is_open())
2665
Mark the event as the last event of a statement if the stmt_end
2669
if (Rows_log_event *pending= binlog_get_pending_rows_event())
2673
pending->set_flags(Rows_log_event::STMT_END_F);
2674
pending->flags|= LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F;
2675
binlog_table_maps= 0;
2678
error= mysql_bin_log.flush_and_set_pending_rows_event(this, 0);
2686
Member function that will log query, either row-based or
2687
statement-based depending on the value of the 'current_stmt_binlog_row_based'
2688
the value of the 'qtype' flag.
2690
This function should be called after the all calls to ha_*_row()
2691
functions have been issued, but before tables are unlocked and
2695
There shall be no writes to any system table after calling
2696
binlog_query(), so these writes has to be moved to before the call
2697
of binlog_query() for correct functioning.
2699
This is necessesary not only for RBR, but the master might crash
2700
after binlogging the query but before changing the system tables.
2701
This means that the slave and the master are not in the same state
2702
(after the master has restarted), so therefore we have to
2703
eliminate this problem.
2706
Error code, or 0 if no error.
2708
int THD::binlog_query(THD::enum_binlog_query_type qtype, char const *query_arg,
2709
ulong query_len, bool is_trans, bool suppress_use,
2710
THD::killed_state killed_status_arg)
2712
assert(query_arg && mysql_bin_log.is_open());
2714
if (int error= binlog_flush_pending_rows_event(true))
2718
If we are in statement mode and trying to log an unsafe statement,
2719
we should print a warning.
2721
if (lex->is_stmt_unsafe() &&
2722
variables.binlog_format == BINLOG_FORMAT_STMT)
2724
assert(this->query != NULL);
2725
push_warning(this, DRIZZLE_ERROR::WARN_LEVEL_WARN,
2726
ER_BINLOG_UNSAFE_STATEMENT,
2727
ER(ER_BINLOG_UNSAFE_STATEMENT));
2728
if (!(binlog_flags & BINLOG_FLAG_UNSAFE_STMT_PRINTED))
2730
char warn_buf[DRIZZLE_ERRMSG_SIZE];
2731
snprintf(warn_buf, DRIZZLE_ERRMSG_SIZE, "%s Statement: %s",
2732
ER(ER_BINLOG_UNSAFE_STATEMENT), this->query);
2733
sql_print_warning(warn_buf);
2734
binlog_flags|= BINLOG_FLAG_UNSAFE_STMT_PRINTED;
2739
case THD::ROW_QUERY_TYPE:
2740
if (current_stmt_binlog_row_based)
2742
/* Otherwise, we fall through */
2743
case THD::DRIZZLE_QUERY_TYPE:
2745
Using this query type is a conveniece hack, since we have been
2746
moving back and forth between using RBR for replication of
2747
system tables and not using it.
2749
Make sure to change in check_table_binlog_row_based() according
2750
to how you treat this.
2752
case THD::STMT_QUERY_TYPE:
2754
The DRIZZLE_LOG::write() function will set the STMT_END_F flag and
2755
flush the pending rows event if necessary.
2758
Query_log_event qinfo(this, query_arg, query_len, is_trans, suppress_use,
2760
qinfo.flags|= LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F;
2762
Binlog table maps will be irrelevant after a Query_log_event
2763
(they are just removed on the slave side) so after the query
2764
log event is written to the binary log, we pretend that no
2765
table maps were written.
2767
int error= mysql_bin_log.write(&qinfo);
2768
binlog_table_maps= 0;
2773
case THD::QUERY_TYPE_COUNT:
2775
assert(0 <= qtype && qtype < QUERY_TYPE_COUNT);
2780
bool Discrete_intervals_list::append(uint64_t start, uint64_t val,
2783
/* first, see if this can be merged with previous */
2784
if ((head == NULL) || tail->merge_if_contiguous(start, val, incr))
2786
/* it cannot, so need to add a new interval */
2787
Discrete_interval *new_interval= new Discrete_interval(start, val, incr);
2788
return(append(new_interval));
2793
bool Discrete_intervals_list::append(Discrete_interval *new_interval)
2795
if (unlikely(new_interval == NULL))
2798
head= current= new_interval;
2800
tail->next= new_interval;