108
197
The following functions form part of the C plugin API
110
200
extern "C" int mysql_tmpfile(const char *prefix)
112
202
char filename[FN_REFLEN];
113
File fd = create_temp_file(filename, drizzle_tmpdir, prefix, MYF(MY_WME));
203
File fd = create_temp_file(filename, mysql_tmpdir, prefix,
204
O_CREAT | O_EXCL | O_RDWR | O_TEMPORARY,
208
This can be removed once the following bug is fixed:
209
Bug #28903 create_temp_file() doesn't honor O_TEMPORARY option
210
(file not removed) (Unix)
115
212
unlink(filename);
122
int session_tablespace_op(const Session *session)
124
return test(session->tablespace_op);
128
Set the process info field of the Session structure.
130
This function is used by plug-ins. Internally, the
131
Session::set_proc_info() function should be used.
133
@see Session::set_proc_info
136
set_session_proc_info(Session *session, const char *info)
138
session->set_proc_info(info);
142
const char *get_session_proc_info(Session *session)
144
return session->get_proc_info();
148
void **session_ha_data(const Session *session, const plugin::StorageEngine *engine)
150
return (void **) &session->ha_data[engine->slot].ha_ptr;
154
int64_t session_test_options(const Session *session, int64_t test_options)
156
return session->options & test_options;
160
int session_sql_command(const Session *session)
162
return (int) session->lex->sql_command;
166
int session_tx_isolation(const Session *session)
168
return (int) session->variables.tx_isolation;
172
void session_inc_row_count(Session *session)
174
session->row_count++;
177
Session::Session(plugin::Client *client_arg)
179
Open_tables_state(refresh_version),
180
mem_root(&main_mem_root),
186
lock_id(&main_lock_id),
188
arg_of_last_insert_id_function(false),
189
first_successful_insert_id_in_prev_stmt(0),
190
first_successful_insert_id_in_cur_stmt(0),
193
some_tables_deleted(false),
196
is_fatal_error(false),
197
transaction_rollback_request(false),
198
is_fatal_sub_stmt_error(0),
199
derived_tables_processing(false),
200
tablespace_op(false),
204
memset(process_list_info, 0, PROCESS_LIST_WIDTH);
205
client->setSession(this);
220
int thd_in_lock_tables(const THD *thd)
222
return test(thd->in_lock_tables);
227
int thd_tablespace_op(const THD *thd)
229
return test(thd->tablespace_op);
234
const char *set_thd_proc_info(THD *thd, const char *info,
235
const char *calling_function __attribute__((unused)),
236
const char *calling_file __attribute__((unused)),
237
const unsigned int calling_line __attribute__((unused)))
239
const char *old_info= thd->get_proc_info();
240
thd->set_proc_info(info);
245
void **thd_ha_data(const THD *thd, const struct handlerton *hton)
247
return (void **) &thd->ha_data[hton->slot].ha_ptr;
251
int64_t thd_test_options(const THD *thd, int64_t test_options)
253
return thd->options & test_options;
257
int thd_sql_command(const THD *thd)
259
return (int) thd->lex->sql_command;
263
int thd_tx_isolation(const THD *thd)
265
return (int) thd->variables.tx_isolation;
269
void thd_inc_row_count(THD *thd)
275
Clear this diagnostics area.
277
Normally called at the end of a statement.
281
Diagnostics_area::reset_diagnostics_area()
283
can_overwrite_status= false;
284
/** Don't take chances in production */
290
m_total_warn_count= 0;
292
/** Tiny reset in debug mode to see garbage right away */
298
Set OK status -- ends commands that do not return a
299
result set, e.g. INSERT/UPDATE/DELETE.
303
Diagnostics_area::set_ok_status(THD *thd, ha_rows affected_rows_arg,
304
uint64_t last_insert_id_arg,
305
const char *message_arg)
309
In production, refuse to overwrite an error or a custom response
312
if (is_error() || is_disabled())
314
/** Only allowed to report success if has not yet reported an error */
316
m_server_status= thd->server_status;
317
m_total_warn_count= thd->total_warn_count;
318
m_affected_rows= affected_rows_arg;
319
m_last_insert_id= last_insert_id_arg;
321
strmake(m_message, message_arg, sizeof(m_message) - 1);
333
Diagnostics_area::set_eof_status(THD *thd)
335
/** Only allowed to report eof if has not yet reported an error */
339
In production, refuse to overwrite an error or a custom response
342
if (is_error() || is_disabled())
345
m_server_status= thd->server_status;
347
If inside a stored procedure, do not return the total
348
number of warnings, since they are not available to the client
351
m_total_warn_count= thd->total_warn_count;
361
Diagnostics_area::set_error_status(THD *thd __attribute__((unused)),
362
uint32_t sql_errno_arg,
363
const char *message_arg)
366
Only allowed to report error if has not yet reported a success
367
The only exception is when we flush the message to the client,
368
an error can happen during the flush.
370
assert(! is_set() || can_overwrite_status);
372
In production, refuse to overwrite a custom response with an
378
m_sql_errno= sql_errno_arg;
379
strmake(m_message, message_arg, sizeof(m_message) - 1);
386
Mark the diagnostics area as 'DISABLED'.
388
This is used in rare cases when the COM_ command at hand sends a response
389
in a custom format. One example is the query cache, another is
394
Diagnostics_area::disable_status()
397
m_status= DA_DISABLED;
402
:Statement(&main_lex, &main_mem_root,
403
/* statement id */ 0),
404
Open_tables_state(refresh_version), rli_fake(0),
405
lock_id(&main_lock_id),
406
user_time(0), in_sub_stmt(0),
407
binlog_table_maps(0), binlog_flags(0UL),
408
arg_of_last_insert_id_function(false),
409
first_successful_insert_id_in_prev_stmt(0),
410
first_successful_insert_id_in_prev_stmt_for_binlog(0),
411
first_successful_insert_id_in_cur_stmt(0),
412
stmt_depends_on_first_successful_insert_id_in_prev_stmt(false),
415
transaction_rollback_request(0),
416
is_fatal_sub_stmt_error(0),
421
derived_tables_processing(false),
208
427
Pass nominal parameters to init_alloc_root only to ensure that
531
841
assert(thread_stack);
533
if (pthread_setspecific(THR_Session, this) ||
534
pthread_setspecific(THR_Mem_root, &mem_root))
843
if (my_pthread_setspecific_ptr(THR_THD, this) ||
844
my_pthread_setspecific_ptr(THR_MALLOC, &mem_root))
537
846
mysys_var=my_thread_var;
540
848
Let mysqld define the thread id (not mysys)
541
This allows us to move Session to different threads if needed.
849
This allows us to move THD to different threads if needed.
543
851
mysys_var->id= thread_id;
544
852
real_id= pthread_self(); // For debugging
547
We have to call thr_lock_info_init() again here as Session may have been
855
We have to call thr_lock_info_init() again here as THD may have been
548
856
created in another thread
550
858
thr_lock_info_init(&lock_info);
555
Init Session for query processing.
556
This has to be called once before we call mysql_parse.
557
See also comments in session.h.
867
THD::cleanup_after_query()
870
This function is used to reset thread data to its default state.
873
This function is not suitable for setting thread data to some
874
non-default values, as there is only one replication thread, so
875
different master threads may overwrite data of each other on
560
void Session::prepareForQueries()
562
if (variables.max_join_size == HA_POS_ERROR)
563
options |= OPTION_BIG_SELECTS;
565
version= refresh_version;
569
ha_enable_transaction(this,true);
571
reset_root_defaults(mem_root, variables.query_alloc_block_size,
572
variables.query_prealloc_size);
573
reset_root_defaults(&transaction.mem_root,
574
variables.trans_alloc_block_size,
575
variables.trans_prealloc_size);
576
transaction.xid_state.xid.null();
577
transaction.xid_state.in_session=1;
580
bool Session::initGlobals()
584
disconnect(ER_OUT_OF_RESOURCES, true);
585
statistic_increment(aborted_connects, &LOCK_status);
593
if (initGlobals() || authenticate())
601
while (! client->haveError() && killed != KILL_CONNECTION)
603
if (! executeStatement())
610
bool Session::schedule()
612
scheduler= plugin::SchedulerFactory::getScheduler();
616
if (connection_count > max_used_connections)
617
max_used_connections= connection_count;
619
thread_id= variables.pseudo_thread_id= global_thread_id++;
621
pthread_mutex_lock(&LOCK_thread_count);
622
session_list.push_back(this);
623
pthread_mutex_unlock(&LOCK_thread_count);
625
if (scheduler->addSession(this))
627
DRIZZLE_CONNECTION_START(thread_id);
628
char error_message_buff[DRIZZLE_ERRMSG_SIZE];
630
killed= Session::KILL_CONNECTION;
632
statistic_increment(aborted_connects, &LOCK_status);
634
/* Can't use my_error() since store_globals has not been called. */
635
/* TODO replace will better error message */
636
snprintf(error_message_buff, sizeof(error_message_buff),
637
ER(ER_CANT_CREATE_THREAD), 1);
638
client->sendError(ER_CANT_CREATE_THREAD, error_message_buff);
645
bool Session::authenticate()
648
if (client->authenticate())
651
statistic_increment(aborted_connects, &LOCK_status);
655
bool Session::checkUser(const char *passwd, uint32_t passwd_len, const char *in_db)
657
LEX_STRING db_str= { (char *) in_db, in_db ? strlen(in_db) : 0 };
658
bool is_authenticated;
661
Clear session->db as it points to something, that will be freed when
662
connection is closed. We don't want to accidentally free a wrong
663
pointer if connect failed. Also in case of 'CHANGE USER' failure,
664
current database will be switched to 'no database selected'.
668
if (passwd_len != 0 && passwd_len != SCRAMBLE_LENGTH)
670
my_error(ER_HANDSHAKE_ERROR, MYF(0), security_ctx.ip.c_str());
674
is_authenticated= plugin::Authentication::isAuthenticated(this, passwd);
676
if (is_authenticated != true)
678
my_error(ER_ACCESS_DENIED_ERROR, MYF(0),
679
security_ctx.user.c_str(),
680
security_ctx.ip.c_str(),
681
passwd_len ? ER(ER_YES) : ER(ER_NO));
686
security_ctx.skip_grants();
688
/* Change database if necessary */
689
if (in_db && in_db[0])
691
if (mysql_change_db(this, &db_str, false))
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
/* We must allocate some extra memory for the cached query string */
751
query_length= 0; /* Extra safety: Avoid races */
752
query= (char*) memdup_w_gap((unsigned char*) in_packet, in_packet_length, db_length + 1);
756
query[in_packet_length]=0;
757
query_length= in_packet_length;
759
/* Reclaim some memory */
760
packet.shrink(variables.net_buffer_length);
761
convert_buffer.shrink(variables.net_buffer_length);
766
bool Session::endTransaction(enum enum_mysql_completiontype completion)
771
if (transaction.xid_state.xa_state != XA_NOTR)
773
my_error(ER_XAER_RMFAIL, MYF(0), xa_state_names[transaction.xid_state.xa_state]);
780
* We don't use endActiveTransaction() here to ensure that this works
781
* even if there is a problem with the OPTION_AUTO_COMMIT flag
782
* (Which of course should never happen...)
784
server_status&= ~SERVER_STATUS_IN_TRANS;
787
options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
788
transaction.all.modified_non_trans_table= false;
791
do_release= 1; /* fall through */
792
case COMMIT_AND_CHAIN:
793
result= endActiveTransaction();
794
if (result == true && completion == COMMIT_AND_CHAIN)
795
result= startTransaction();
797
case ROLLBACK_RELEASE:
798
do_release= 1; /* fall through */
800
case ROLLBACK_AND_CHAIN:
802
server_status&= ~SERVER_STATUS_IN_TRANS;
803
if (ha_rollback(this))
805
options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
806
transaction.all.modified_non_trans_table= false;
807
if (result == true && (completion == ROLLBACK_AND_CHAIN))
808
result= startTransaction();
812
my_error(ER_UNKNOWN_COM_ERROR, MYF(0));
817
my_error(killed_errno(), MYF(0));
818
else if ((result == true) && do_release)
819
killed= Session::KILL_CONNECTION;
824
bool Session::endActiveTransaction()
828
if (transaction.xid_state.xa_state != XA_NOTR)
830
my_error(ER_XAER_RMFAIL, MYF(0), xa_state_names[transaction.xid_state.xa_state]);
833
if (options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
835
server_status&= ~SERVER_STATUS_IN_TRANS;
839
options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
840
transaction.all.modified_non_trans_table= false;
844
bool Session::startTransaction()
848
if (! endActiveTransaction())
852
options|= OPTION_BEGIN;
853
server_status|= SERVER_STATUS_IN_TRANS;
854
if (lex->start_transaction_opt & DRIZZLE_START_TRANS_OPT_WITH_CONS_SNAPSHOT)
855
if (ha_start_consistent_snapshot(this))
861
void Session::cleanup_after_query()
864
Reset rand_used so that detection of calls to rand() will save random
879
void THD::cleanup_after_query()
882
Reset rand_used so that detection of calls to rand() will save random
865
883
seeds if needed by the slave.
885
Do not reset rand_used if inside a stored function or trigger because
886
only the call to these operations is logged. Thus only the calling
887
statement needs to detect rand() calls made by its substatements. These
888
substatements must not set rand_used to 0 because it would remove the
889
detection of rand() by the calling statement.
891
if (!in_sub_stmt) /* stored functions and triggers are a special case */
868
893
/* Forget those values, for next binlogger: */
894
stmt_depends_on_first_successful_insert_id_in_prev_stmt= 0;
869
895
auto_inc_intervals_in_cur_stmt_for_binlog.empty();
871
898
if (first_successful_insert_id_in_cur_stmt > 0)
873
900
/* set what LAST_INSERT_ID() will return */
874
first_successful_insert_id_in_prev_stmt= first_successful_insert_id_in_cur_stmt;
901
first_successful_insert_id_in_prev_stmt=
902
first_successful_insert_id_in_cur_stmt;
875
903
first_successful_insert_id_in_cur_stmt= 0;
876
904
substitute_null_with_insert_id= true;
878
arg_of_last_insert_id_function= false;
906
arg_of_last_insert_id_function= 0;
879
907
/* Free Items that were created during this execution */
881
909
/* Reset where. */
882
where= Session::DEFAULT_WHERE;
910
where= THD::DEFAULT_WHERE;
886
915
Create a LEX_STRING in this connection.
1681
2149
access to mysql.proc table to find definitions of stored routines.
1682
2150
****************************************************************************/
1684
void Session::reset_n_backup_open_tables_state(Open_tables_state *backup)
2152
void THD::reset_n_backup_open_tables_state(Open_tables_state *backup)
1686
2154
backup->set_open_tables_state(this);
1687
2155
reset_open_tables_state();
1688
backups_available= false;
2156
state_flags|= Open_tables_state::BACKUPS_AVAIL;
1692
void Session::restore_backup_open_tables_state(Open_tables_state *backup)
2161
void THD::restore_backup_open_tables_state(Open_tables_state *backup)
1695
2164
Before we will throw away current open tables state we want
1696
2165
to be sure that it was properly cleaned up.
1698
2167
assert(open_tables == 0 && temporary_tables == 0 &&
1699
derived_tables == 0 &&
2168
handler_tables == 0 && derived_tables == 0 &&
2169
lock == 0 && locked_tables == 0);
1701
2170
set_open_tables_state(backup);
1705
bool Session::set_db(const char *new_db, size_t new_db_len)
1707
/* Do not reallocate memory if current chunk is big enough. */
1708
if (db && new_db && db_length >= new_db_len)
1709
memcpy(db, new_db, new_db_len+1);
1716
db= (char *)malloc(new_db_len + 1);
1719
memcpy(db, new_db, new_db_len);
1726
db_length= db ? new_db_len : 0;
1727
return new_db && !db;
1732
2175
Check the killed state of a user thread
1733
@param session user thread
2176
@param thd user thread
1734
2177
@retval 0 the user thread is active
1735
2178
@retval 1 the user thread has been killed
1737
extern "C" int session_killed(const Session *session)
2180
extern "C" int thd_killed(const DRIZZLE_THD thd)
1739
return(session->killed);
2182
return(thd->killed);
1743
Return the session id of a user session
1744
@param pointer to Session object
1745
@return session's id
2186
Return the thread id of a user thread
2187
@param thd user thread
1747
extern "C" unsigned long session_get_thread_id(const Session *session)
1749
return (unsigned long) session->getSessionId();
1754
LEX_STRING *session_make_lex_string(Session *session, LEX_STRING *lex_str,
1755
const char *str, unsigned int size,
1756
int allocate_lex_string)
1758
return session->make_lex_string(lex_str, str, size,
1759
(bool) allocate_lex_string);
1762
const struct charset_info_st *session_charset(Session *session)
1764
return(session->charset());
1767
char **session_query(Session *session)
1769
return(&session->query);
1772
int session_non_transactional_update(const Session *session)
1774
return(session->transaction.all.modified_non_trans_table);
1777
void session_mark_transaction_to_rollback(Session *session, bool all)
1779
mark_transaction_to_rollback(session, all);
2190
extern "C" unsigned long thd_get_thread_id(const DRIZZLE_THD thd)
2192
return((unsigned long)thd->thread_id);
2196
#ifdef INNODB_COMPATIBILITY_HOOKS
2197
extern "C" const struct charset_info_st *thd_charset(DRIZZLE_THD thd)
2199
return(thd->charset());
2202
extern "C" char **thd_query(DRIZZLE_THD thd)
2204
return(&thd->query);
2207
extern "C" int thd_slave_thread(const DRIZZLE_THD thd)
2209
return(thd->slave_thread);
2212
extern "C" int thd_non_transactional_update(const DRIZZLE_THD thd)
2214
return(thd->transaction.all.modified_non_trans_table);
2217
extern "C" int thd_binlog_format(const DRIZZLE_THD thd)
2219
return (int) thd->variables.binlog_format;
2222
extern "C" void thd_mark_transaction_to_rollback(DRIZZLE_THD thd, bool all)
2224
mark_transaction_to_rollback(thd, all);
2226
#endif // INNODB_COMPATIBILITY_HOOKS */
1783
2230
Mark transaction to rollback and mark error as fatal to a sub-statement.
1785
@param session Thread handle
2232
@param thd Thread handle
1786
2233
@param all true <=> rollback main transaction.
1788
void mark_transaction_to_rollback(Session *session, bool all)
1792
session->is_fatal_sub_stmt_error= true;
1793
session->transaction_rollback_request= all;
1797
void Session::disconnect(uint32_t errcode, bool should_lock)
1799
/* Allow any plugins to cleanup their session variables */
1800
plugin_sessionvar_cleanup(this);
1802
/* If necessary, log any aborted or unauthorized connections */
1803
if (killed || client->wasAborted())
1804
statistic_increment(aborted_threads, &LOCK_status);
1806
if (client->wasAborted())
1808
if (! killed && variables.log_warnings > 1)
1810
Security_context *sctx= &security_ctx;
1812
errmsg_printf(ERRMSG_LVL_WARN, ER(ER_NEW_ABORTING_CONNECTION)
1814
, (db ? db : "unconnected")
1815
, sctx->user.empty() == false ? sctx->user.c_str() : "unauthenticated"
1817
, (main_da.is_error() ? main_da.message() : ER(ER_UNKNOWN_ERROR)));
1821
/* Close out our connection to the client */
1823
(void) pthread_mutex_lock(&LOCK_thread_count);
1824
killed= Session::KILL_CONNECTION;
1825
if (client->isConnected())
1829
/*my_error(errcode, ER(errcode));*/
1830
client->sendError(errcode, ER(errcode));
1835
(void) pthread_mutex_unlock(&LOCK_thread_count);
1838
void Session::reset_for_next_command()
1843
Those two lines below are theoretically unneeded as
1844
Session::cleanup_after_query() should take care of this already.
1846
auto_inc_intervals_in_cur_stmt_for_binlog.empty();
1848
is_fatal_error= false;
1849
server_status&= ~ (SERVER_MORE_RESULTS_EXISTS |
1850
SERVER_QUERY_NO_INDEX_USED |
1851
SERVER_QUERY_NO_GOOD_INDEX_USED);
1853
If in autocommit mode and not in a transaction, reset
1854
OPTION_STATUS_NO_TRANS_UPDATE | OPTION_KEEP_LOG to not get warnings
1855
in ha_rollback_trans() about some tables couldn't be rolled back.
1857
if (!(options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
1859
options&= ~OPTION_KEEP_LOG;
1860
transaction.all.modified_non_trans_table= false;
1864
main_da.reset_diagnostics_area();
1865
total_warn_count=0; // Warnings for this query
1866
sent_row_count= examined_row_count= 0;
1870
Close all temporary tables created by 'CREATE TEMPORARY TABLE' for thread
1871
creates one DROP TEMPORARY Table binlog event for each pseudo-thread
1874
void Session::close_temporary_tables()
1879
if (!temporary_tables)
1882
for (table= temporary_tables; table; table= tmp_next)
1884
tmp_next= table->next;
1885
close_temporary(table, true, true);
1887
temporary_tables= NULL;
1891
unlink from session->temporary tables and close temporary table
1894
void Session::close_temporary_table(Table *table,
1895
bool free_share, bool delete_table)
1899
table->prev->next= table->next;
1900
if (table->prev->next)
1901
table->next->prev= table->prev;
2236
void mark_transaction_to_rollback(THD *thd, bool all)
2240
thd->is_fatal_sub_stmt_error= true;
2241
thd->transaction_rollback_request= all;
2244
/***************************************************************************
2245
Handling of XA id cacheing
2246
***************************************************************************/
2248
pthread_mutex_t LOCK_xid_cache;
2251
extern "C" unsigned char *xid_get_hash_key(const unsigned char *, size_t *, bool);
2252
extern "C" void xid_free_hash(void *);
2254
unsigned char *xid_get_hash_key(const unsigned char *ptr, size_t *length,
2255
bool not_used __attribute__((unused)))
2257
*length=((XID_STATE*)ptr)->xid.key_length();
2258
return ((XID_STATE*)ptr)->xid.key();
2261
void xid_free_hash(void *ptr)
2263
if (!((XID_STATE*)ptr)->in_thd)
2264
free((unsigned char*)ptr);
2267
bool xid_cache_init()
2269
pthread_mutex_init(&LOCK_xid_cache, MY_MUTEX_INIT_FAST);
2270
return hash_init(&xid_cache, &my_charset_bin, 100, 0, 0,
2271
xid_get_hash_key, xid_free_hash, 0) != 0;
2274
void xid_cache_free()
2276
if (hash_inited(&xid_cache))
2278
hash_free(&xid_cache);
2279
pthread_mutex_destroy(&LOCK_xid_cache);
2283
XID_STATE *xid_cache_search(XID *xid)
2285
pthread_mutex_lock(&LOCK_xid_cache);
2286
XID_STATE *res=(XID_STATE *)hash_search(&xid_cache, xid->key(), xid->key_length());
2287
pthread_mutex_unlock(&LOCK_xid_cache);
2292
bool xid_cache_insert(XID *xid, enum xa_states xa_state)
2296
pthread_mutex_lock(&LOCK_xid_cache);
2297
if (hash_search(&xid_cache, xid->key(), xid->key_length()))
2299
else if (!(xs=(XID_STATE *)my_malloc(sizeof(*xs), MYF(MY_WME))))
1905
/* removing the item from the list */
1906
assert(table == temporary_tables);
1908
slave must reset its temporary list pointer to zero to exclude
1909
passing non-zero value to end_slave via rli->save_temporary_tables
1910
when no temp tables opened, see an invariant below.
1912
temporary_tables= table->next;
1913
if (temporary_tables)
1914
table->next->prev= NULL;
1916
close_temporary(table, free_share, delete_table);
1920
Close and delete a temporary table
1923
This dosn't unlink table from session->temporary
1924
If this is needed, use close_temporary_table()
1927
void Session::close_temporary(Table *table, bool free_share, bool delete_table)
1929
plugin::StorageEngine *table_type= table->s->db_type();
1931
table->free_io_cache();
1932
table->closefrm(false);
1935
rm_temporary_table(table_type, table->s->path.str);
1939
table->s->free_table_share();
1940
/* This makes me sad, but we're allocating it via malloc */
1945
/** Clear most status variables. */
1946
extern time_t flush_status_time;
1947
extern uint32_t max_used_connections;
1949
void Session::refresh_status()
1951
pthread_mutex_lock(&LOCK_status);
1953
/* Add thread's status variabes to global status */
1954
add_to_status(&global_status_var, &status_var);
1956
/* Reset thread's status variables */
1957
memset(&status_var, 0, sizeof(status_var));
1959
/* Reset some global variables */
1960
reset_status_vars();
1962
/* Reset the counters of all key caches (default and named). */
1963
reset_key_cache_counters();
1964
flush_status_time= time((time_t*) 0);
1965
max_used_connections= 1; /* We set it to one, because we know we exist */
1966
pthread_mutex_unlock(&LOCK_status);
1969
#define extra_size sizeof(double)
1971
user_var_entry *Session::getVariable(LEX_STRING &name, bool create_if_not_exists)
1973
user_var_entry *entry= NULL;
1975
entry= (user_var_entry*) hash_search(&user_vars, (unsigned char*) name.str, name.length);
1977
if ((entry == NULL) && create_if_not_exists)
1979
if (!hash_inited(&user_vars))
1981
entry= new (nothrow) user_var_entry(name.str, query_id);
1986
if (my_hash_insert(&user_vars, (unsigned char*) entry))
1989
free((char*) entry);
1998
void Session::mark_temp_tables_as_free_for_reuse()
2000
for (Table *table= temporary_tables ; table ; table= table->next)
2002
if (table->query_id == query_id)
2005
table->file->ha_reset();
2010
void Session::mark_used_tables_as_free_for_reuse(Table *table)
2012
for (; table ; table= table->next)
2014
if (table->query_id == query_id)
2017
table->file->ha_reset();
2023
Unlocks tables and frees derived tables.
2024
Put all normal tables used by thread in free list.
2026
It will only close/mark as free for reuse tables opened by this
2027
substatement, it will also check if we are closing tables after
2028
execution of complete query (i.e. we are on upper level) and will
2029
leave prelocked mode if needed.
2031
void Session::close_thread_tables()
2036
We are assuming here that session->derived_tables contains ONLY derived
2037
tables for this substatement. i.e. instead of approach which uses
2038
query_id matching for determining which of the derived tables belong
2039
to this substatement we rely on the ability of substatements to
2040
save/restore session->derived_tables during their execution.
2042
TODO: Probably even better approach is to simply associate list of
2043
derived tables with (sub-)statement instead of thread and destroy
2044
them at the end of its execution.
2050
Close all derived tables generated in queries like
2051
SELECT * FROM (SELECT * FROM t1)
2053
for (table= derived_tables ; table ; table= next)
2056
table->free_tmp_table(this);
2062
Mark all temporary tables used by this statement as free for reuse.
2064
mark_temp_tables_as_free_for_reuse();
2066
Let us commit transaction for statement. Since in 5.0 we only have
2067
one statement transaction and don't allow several nested statement
2068
transactions this call will do nothing if we are inside of stored
2069
function or trigger (i.e. statement transaction is already active and
2070
does not belong to statement for which we do close_thread_tables()).
2071
TODO: This should be fixed in later releases.
2073
if (backups_available == false)
2075
main_da.can_overwrite_status= true;
2076
ha_autocommit_or_rollback(this, is_error());
2077
main_da.can_overwrite_status= false;
2078
transaction.stmt.reset();
2084
For RBR we flush the pending event just before we unlock all the
2085
tables. This means that we are at the end of a topmost
2086
statement, so we ensure that the STMT_END_F flag is set on the
2087
pending event. For statements that are *inside* stored
2088
functions, the pending event will not be flushed: that will be
2089
handled either before writing a query log event (inside
2090
binlog_query()) or when preparing a pending event.
2092
mysql_unlock_tables(this, lock);
2096
Note that we need to hold LOCK_open while changing the
2097
open_tables list. Another thread may work on it.
2098
(See: remove_table_from_cache(), mysql_wait_completed_table())
2099
Closing a MERGE child before the parent would be fatal if the
2100
other thread tries to abort the MERGE lock in between.
2103
close_open_tables();
2106
void Session::close_tables_for_reopen(TableList **tables)
2109
If table list consists only from tables from prelocking set, table list
2110
for new attempt should be empty, so we have to update list's root pointer.
2112
if (lex->first_not_own_table() == *tables)
2114
lex->chop_off_not_own_tables();
2115
for (TableList *tmp= *tables; tmp; tmp= tmp->next_global)
2117
close_thread_tables();
2120
bool Session::openTablesLock(TableList *tables)
2127
if (open_tables_from_list(&tables, &counter))
2130
if (!lock_tables(tables, counter, &need_reopen))
2134
close_tables_for_reopen(&tables);
2136
if ((mysql_handle_derived(lex, &mysql_derived_prepare) ||
2137
(fill_derived_tables() &&
2138
mysql_handle_derived(lex, &mysql_derived_filling))))
2144
bool Session::openTables(TableList *tables, uint32_t flags)
2147
bool ret= fill_derived_tables();
2148
assert(ret == false);
2149
if (open_tables_from_list(&tables, &counter, flags) ||
2150
mysql_handle_derived(lex, &mysql_derived_prepare))
2155
bool Session::rm_temporary_table(plugin::StorageEngine *base, char *path)
2161
if (delete_table_proto_file(path))
2164
if (base->deleteTable(this, path))
2167
errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
2303
xs->xa_state=xa_state;
2306
res=my_hash_insert(&xid_cache, (unsigned char*)xs);
2308
pthread_mutex_unlock(&LOCK_xid_cache);
2313
bool xid_cache_insert(XID_STATE *xid_state)
2315
pthread_mutex_lock(&LOCK_xid_cache);
2316
assert(hash_search(&xid_cache, xid_state->xid.key(),
2317
xid_state->xid.key_length())==0);
2318
bool res=my_hash_insert(&xid_cache, (unsigned char*)xid_state);
2319
pthread_mutex_unlock(&LOCK_xid_cache);
2324
void xid_cache_delete(XID_STATE *xid_state)
2326
pthread_mutex_lock(&LOCK_xid_cache);
2327
hash_delete(&xid_cache, (unsigned char *)xid_state);
2328
pthread_mutex_unlock(&LOCK_xid_cache);
2332
Implementation of interface to write rows to the binary log through the
2333
thread. The thread is responsible for writing the rows it has
2334
inserted/updated/deleted.
2339
Template member function for ensuring that there is an rows log
2340
event of the apropriate type before proceeding.
2343
- Events of type 'RowEventT' have the type code 'type_code'.
2346
If a non-NULL pointer is returned, the pending event for thread 'thd' will
2347
be an event of type 'RowEventT' (which have the type code 'type_code')
2348
will either empty or have enough space to hold 'needed' bytes. In
2349
addition, the columns bitmap will be correct for the row, meaning that
2350
the pending event will be flushed if the columns in the event differ from
2351
the columns suppled to the function.
2354
If no error, a non-NULL pending event (either one which already existed or
2355
the newly created one).
2359
template <class RowsEventT> Rows_log_event*
2360
THD::binlog_prepare_pending_rows_event(Table* table, uint32_t serv_id,
2362
bool is_transactional,
2363
RowsEventT *hint __attribute__((unused)))
2365
/* Pre-conditions */
2366
assert(table->s->table_map_id != UINT32_MAX);
2368
/* Fetch the type code for the RowsEventT template parameter */
2369
int const type_code= RowsEventT::TYPE_CODE;
2372
There is no good place to set up the transactional data, so we
2375
if (binlog_setup_trx_data())
2378
Rows_log_event* pending= binlog_get_pending_rows_event();
2380
if (unlikely(pending && !pending->is_valid()))
2384
Check if the current event is non-NULL and a write-rows
2385
event. Also check if the table provided is mapped: if it is not,
2386
then we have switched to writing to a new table.
2387
If there is no pending event, we need to create one. If there is a pending
2388
event, but it's not about the same table id, or not of the same type
2389
(between Write, Update and Delete), or not the same affected columns, or
2390
going to be too big, flush this event to disk and create a new pending
2393
The last test is necessary for the Cluster injector to work
2394
correctly. The reason is that the Cluster can inject two write
2395
rows with different column bitmaps if there is an insert followed
2396
by an update in the same transaction, and these are grouped into a
2397
single epoch/transaction when fed to the injector.
2399
TODO: Fix the code so that the last test can be removed.
2402
pending->server_id != serv_id ||
2403
pending->get_table_id() != table->s->table_map_id ||
2404
pending->get_type_code() != type_code ||
2405
pending->get_data_size() + needed > opt_binlog_rows_event_max_size ||
2406
!bitmap_cmp(pending->get_cols(), table->write_set))
2408
/* Create a new RowsEventT... */
2409
Rows_log_event* const
2410
ev= new RowsEventT(this, table, table->s->table_map_id,
2414
ev->server_id= serv_id; // I don't like this, it's too easy to forget.
2416
flush the pending event and replace it with the newly created
2419
if (unlikely(mysql_bin_log.flush_and_set_pending_rows_event(this, ev)))
2425
return(ev); /* This is the new pending event */
2427
return(pending); /* This is the current pending event */
2430
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
2432
Instantiate the versions we need, we have -fno-implicit-template as
2435
template Rows_log_event*
2436
THD::binlog_prepare_pending_rows_event(Table*, uint32_t, size_t, bool,
2437
Write_rows_log_event*);
2439
template Rows_log_event*
2440
THD::binlog_prepare_pending_rows_event(Table*, uint32_t, size_t, bool,
2441
Delete_rows_log_event *);
2443
template Rows_log_event*
2444
THD::binlog_prepare_pending_rows_event(Table*, uint32_t, size_t, bool,
2445
Update_rows_log_event *);
2450
Class to handle temporary allocation of memory for row data.
2452
The responsibilities of the class is to provide memory for
2453
packing one or two rows of packed data (depending on what
2454
constructor is called).
2456
In order to make the allocation more efficient for "simple" rows,
2457
i.e., rows that do not contain any blobs, a pointer to the
2458
allocated memory is of memory is stored in the table structure
2459
for simple rows. If memory for a table containing a blob field
2460
is requested, only memory for that is allocated, and subsequently
2461
released when the object is destroyed.
2464
class Row_data_memory {
2467
Build an object to keep track of a block-local piece of memory
2468
for storing a row of data.
2471
Table where the pre-allocated memory is stored.
2474
Length of data that is needed, if the record contain blobs.
2476
Row_data_memory(Table *table, size_t const len1)
2479
m_alloc_checked= false;
2480
allocate_memory(table, len1);
2481
m_ptr[0]= has_memory() ? m_memory : 0;
2485
Row_data_memory(Table *table, size_t const len1, size_t const len2)
2488
m_alloc_checked= false;
2489
allocate_memory(table, len1 + len2);
2490
m_ptr[0]= has_memory() ? m_memory : 0;
2491
m_ptr[1]= has_memory() ? m_memory + len1 : 0;
2496
if (m_memory != 0 && m_release_memory_on_destruction)
2497
free((unsigned char*) m_memory);
2501
Is there memory allocated?
2503
@retval true There is memory allocated
2504
@retval false Memory allocation failed
2506
bool has_memory() const {
2507
m_alloc_checked= true;
2508
return m_memory != 0;
2511
unsigned char *slot(uint32_t s)
2513
assert(s < sizeof(m_ptr)/sizeof(*m_ptr));
2514
assert(m_ptr[s] != 0);
2515
assert(m_alloc_checked == true);
2520
void allocate_memory(Table *const table, size_t const total_length)
2522
if (table->s->blob_fields == 0)
2525
The maximum length of a packed record is less than this
2526
length. We use this value instead of the supplied length
2527
when allocating memory for records, since we don't know how
2528
the memory will be used in future allocations.
2530
Since table->s->reclength is for unpacked records, we have
2531
to add two bytes for each field, which can potentially be
2532
added to hold the length of a packed field.
2534
size_t const maxlen= table->s->reclength + 2 * table->s->fields;
2537
Allocate memory for two records if memory hasn't been
2538
allocated. We allocate memory for two records so that it can
2539
be used when processing update rows as well.
2541
if (table->write_row_record == 0)
2542
table->write_row_record=
2543
(unsigned char *) alloc_root(&table->mem_root, 2 * maxlen);
2544
m_memory= table->write_row_record;
2545
m_release_memory_on_destruction= false;
2549
m_memory= (unsigned char *) my_malloc(total_length, MYF(MY_WME));
2550
m_release_memory_on_destruction= true;
2554
mutable bool m_alloc_checked;
2555
bool m_release_memory_on_destruction;
2556
unsigned char *m_memory;
2557
unsigned char *m_ptr[2];
2562
int THD::binlog_write_row(Table* table, bool is_trans,
2563
unsigned char const *record)
2565
assert(current_stmt_binlog_row_based && mysql_bin_log.is_open());
2568
Pack records into format for transfer. We are allocating more
2569
memory than needed, but that doesn't matter.
2571
Row_data_memory memory(table, table->max_row_length(record));
2572
if (!memory.has_memory())
2573
return HA_ERR_OUT_OF_MEM;
2575
unsigned char *row_data= memory.slot(0);
2577
size_t const len= pack_row(table, table->write_set, row_data, record);
2579
Rows_log_event* const ev=
2580
binlog_prepare_pending_rows_event(table, server_id, len, is_trans,
2581
static_cast<Write_rows_log_event*>(0));
2583
if (unlikely(ev == 0))
2584
return HA_ERR_OUT_OF_MEM;
2586
return ev->add_row_data(row_data, len);
2589
int THD::binlog_update_row(Table* table, bool is_trans,
2590
const unsigned char *before_record,
2591
const unsigned char *after_record)
2593
assert(current_stmt_binlog_row_based && mysql_bin_log.is_open());
2595
size_t const before_maxlen = table->max_row_length(before_record);
2596
size_t const after_maxlen = table->max_row_length(after_record);
2598
Row_data_memory row_data(table, before_maxlen, after_maxlen);
2599
if (!row_data.has_memory())
2600
return HA_ERR_OUT_OF_MEM;
2602
unsigned char *before_row= row_data.slot(0);
2603
unsigned char *after_row= row_data.slot(1);
2605
size_t const before_size= pack_row(table, table->read_set, before_row,
2607
size_t const after_size= pack_row(table, table->write_set, after_row,
2610
Rows_log_event* const ev=
2611
binlog_prepare_pending_rows_event(table, server_id,
2612
before_size + after_size, is_trans,
2613
static_cast<Update_rows_log_event*>(0));
2615
if (unlikely(ev == 0))
2616
return HA_ERR_OUT_OF_MEM;
2619
ev->add_row_data(before_row, before_size) ||
2620
ev->add_row_data(after_row, after_size);
2623
int THD::binlog_delete_row(Table* table, bool is_trans,
2624
unsigned char const *record)
2626
assert(current_stmt_binlog_row_based && mysql_bin_log.is_open());
2629
Pack records into format for transfer. We are allocating more
2630
memory than needed, but that doesn't matter.
2632
Row_data_memory memory(table, table->max_row_length(record));
2633
if (unlikely(!memory.has_memory()))
2634
return HA_ERR_OUT_OF_MEM;
2636
unsigned char *row_data= memory.slot(0);
2638
size_t const len= pack_row(table, table->read_set, row_data, record);
2640
Rows_log_event* const ev=
2641
binlog_prepare_pending_rows_event(table, server_id, len, is_trans,
2642
static_cast<Delete_rows_log_event*>(0));
2644
if (unlikely(ev == 0))
2645
return HA_ERR_OUT_OF_MEM;
2647
return ev->add_row_data(row_data, len);
2651
int THD::binlog_flush_pending_rows_event(bool stmt_end)
2654
We shall flush the pending event even if we are not in row-based
2655
mode: it might be the case that we left row-based mode before
2656
flushing anything (e.g., if we have explicitly locked tables).
2658
if (!mysql_bin_log.is_open())
2662
Mark the event as the last event of a statement if the stmt_end
2666
if (Rows_log_event *pending= binlog_get_pending_rows_event())
2670
pending->set_flags(Rows_log_event::STMT_END_F);
2671
pending->flags|= LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F;
2672
binlog_table_maps= 0;
2675
error= mysql_bin_log.flush_and_set_pending_rows_event(this, 0);
2683
Member function that will log query, either row-based or
2684
statement-based depending on the value of the 'current_stmt_binlog_row_based'
2685
the value of the 'qtype' flag.
2687
This function should be called after the all calls to ha_*_row()
2688
functions have been issued, but before tables are unlocked and
2692
There shall be no writes to any system table after calling
2693
binlog_query(), so these writes has to be moved to before the call
2694
of binlog_query() for correct functioning.
2696
This is necessesary not only for RBR, but the master might crash
2697
after binlogging the query but before changing the system tables.
2698
This means that the slave and the master are not in the same state
2699
(after the master has restarted), so therefore we have to
2700
eliminate this problem.
2703
Error code, or 0 if no error.
2705
int THD::binlog_query(THD::enum_binlog_query_type qtype, char const *query_arg,
2706
ulong query_len, bool is_trans, bool suppress_use,
2707
THD::killed_state killed_status_arg)
2709
assert(query_arg && mysql_bin_log.is_open());
2711
if (int error= binlog_flush_pending_rows_event(true))
2715
If we are in statement mode and trying to log an unsafe statement,
2716
we should print a warning.
2718
if (lex->is_stmt_unsafe() &&
2719
variables.binlog_format == BINLOG_FORMAT_STMT)
2721
assert(this->query != NULL);
2722
push_warning(this, DRIZZLE_ERROR::WARN_LEVEL_WARN,
2723
ER_BINLOG_UNSAFE_STATEMENT,
2724
ER(ER_BINLOG_UNSAFE_STATEMENT));
2725
if (!(binlog_flags & BINLOG_FLAG_UNSAFE_STMT_PRINTED))
2727
char warn_buf[DRIZZLE_ERRMSG_SIZE];
2728
snprintf(warn_buf, DRIZZLE_ERRMSG_SIZE, "%s Statement: %s",
2729
ER(ER_BINLOG_UNSAFE_STATEMENT), this->query);
2730
sql_print_warning(warn_buf);
2731
binlog_flags|= BINLOG_FLAG_UNSAFE_STMT_PRINTED;
2736
case THD::ROW_QUERY_TYPE:
2737
if (current_stmt_binlog_row_based)
2739
/* Otherwise, we fall through */
2740
case THD::DRIZZLE_QUERY_TYPE:
2742
Using this query type is a conveniece hack, since we have been
2743
moving back and forth between using RBR for replication of
2744
system tables and not using it.
2746
Make sure to change in check_table_binlog_row_based() according
2747
to how you treat this.
2749
case THD::STMT_QUERY_TYPE:
2751
The DRIZZLE_LOG::write() function will set the STMT_END_F flag and
2752
flush the pending rows event if necessary.
2755
Query_log_event qinfo(this, query_arg, query_len, is_trans, suppress_use,
2757
qinfo.flags|= LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F;
2759
Binlog table maps will be irrelevant after a Query_log_event
2760
(they are just removed on the slave side) so after the query
2761
log event is written to the binary log, we pretend that no
2762
table maps were written.
2764
int error= mysql_bin_log.write(&qinfo);
2765
binlog_table_maps= 0;
2770
case THD::QUERY_TYPE_COUNT:
2772
assert(0 <= qtype && qtype < QUERY_TYPE_COUNT);
2777
bool Discrete_intervals_list::append(uint64_t start, uint64_t val,
2780
/* first, see if this can be merged with previous */
2781
if ((head == NULL) || tail->merge_if_contiguous(start, val, incr))
2783
/* it cannot, so need to add a new interval */
2784
Discrete_interval *new_interval= new Discrete_interval(start, val, incr);
2785
return(append(new_interval));
2790
bool Discrete_intervals_list::append(Discrete_interval *new_interval)
2792
if (unlikely(new_interval == NULL))
2795
head= current= new_interval;
2797
tail->next= new_interval;