1 /*
2 Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25 #include "sql/sql_class.h"
26
27 #include <assert.h>
28 #include <errno.h>
29 #include <stdarg.h>
30 #include <stdio.h>
31 #include <algorithm>
32 #include <utility>
33
34 #include "field_types.h"
35 #include "m_ctype.h"
36 #include "m_string.h"
37 #include "my_compiler.h"
38 #include "my_dbug.h"
39 #include "my_loglevel.h"
40 #include "my_systime.h"
41 #include "my_thread.h"
42 #include "my_time.h"
43 #include "mysql/components/services/log_builtins.h" // LogErr
44 #include "mysql/components/services/log_shared.h"
45 #include "mysql/components/services/psi_error_bits.h"
46 #include "mysql/plugin_audit.h"
47 #include "mysql/psi/mysql_cond.h"
48 #include "mysql/psi/mysql_error.h"
49 #include "mysql/psi/mysql_ps.h"
50 #include "mysql/psi/mysql_stage.h"
51 #include "mysql/psi/mysql_statement.h"
52 #include "mysql/psi/mysql_table.h"
53 #include "mysql/psi/psi_table.h"
54 #include "mysql/service_mysql_alloc.h"
55 #include "mysys_err.h" // EE_OUTOFMEMORY
56 #include "pfs_statement_provider.h"
57 #include "rpl_master.h" // unregister_slave
58 #include "sql/auth/sql_security_ctx.h"
59 #include "sql/binlog.h"
60 #include "sql/check_stack.h"
61 #include "sql/conn_handler/connection_handler_manager.h" // Connection_handler_manager
62 #include "sql/current_thd.h"
63 #include "sql/dd/cache/dictionary_client.h" // Dictionary_client
64 #include "sql/dd/dd_kill_immunizer.h" // dd:DD_kill_immunizer
65 #include "sql/debug_sync.h" // DEBUG_SYNC
66 #include "sql/derror.h" // ER_THD
67 #include "sql/enum_query_type.h"
68 #include "sql/error_handler.h" // Internal_error_handler
69 #include "sql/field.h"
70 #include "sql/handler.h"
71 #include "sql/item.h"
72 #include "sql/item_func.h" // user_var_entry
73 #include "sql/lock.h" // mysql_lock_abort_for_thread
74 #include "sql/locking_service.h" // release_all_locking_service_locks
75 #include "sql/log_event.h"
76 #include "sql/mdl_context_backup.h" // MDL context backup for XA
77 #include "sql/mysqld.h" // global_system_variables ...
78 #include "sql/mysqld_thd_manager.h" // Global_THD_manager
79 #include "sql/parse_location.h"
80 #include "sql/protocol.h"
81 #include "sql/protocol_classic.h"
82 #include "sql/psi_memory_key.h"
83 #include "sql/query_result.h"
84 #include "sql/rpl_rli.h" // Relay_log_info
85 #include "sql/rpl_slave.h" // rpl_master_erroneous_autoinc
86 #include "sql/rpl_transaction_write_set_ctx.h"
87 #include "sql/sp_cache.h" // sp_cache_clear
88 #include "sql/sp_head.h" // sp_head
89 #include "sql/sql_audit.h" // mysql_audit_free_thd
90 #include "sql/sql_backup_lock.h" // release_backup_lock
91 #include "sql/sql_base.h" // close_temporary_tables
92 #include "sql/sql_callback.h" // MYSQL_CALLBACK
93 #include "sql/sql_cmd.h"
94 #include "sql/sql_handler.h" // mysql_ha_cleanup
95 #include "sql/sql_lex.h"
96 #include "sql/sql_parse.h" // is_update_query
97 #include "sql/sql_plugin.h" // plugin_thdvar_init
98 #include "sql/sql_prepare.h" // Prepared_statement
99 #include "sql/sql_profile.h"
100 #include "sql/sql_timer.h" // thd_timer_destroy
101 #include "sql/table.h"
102 #include "sql/table_cache.h" // table_cache_manager
103 #include "sql/tc_log.h"
104 #include "sql/thr_malloc.h"
105 #include "sql/transaction.h" // trans_rollback
106 #include "sql/transaction_info.h"
107 #include "sql/xa.h"
108 #include "template_utils.h"
109 #include "thr_mutex.h"
110
111 class Parse_tree_root;
112
113 using std::max;
114 using std::min;
115 using std::unique_ptr;
116
117 /*
118 The following is used to initialise Table_ident with a internal
119 table name
120 */
121 char empty_c_string[1] = {0}; /* used for not defined db */
122
123 const char *const THD::DEFAULT_WHERE = "field list";
124 extern PSI_stage_info stage_waiting_for_disk_space;
125
backup(THD * thd)126 void THD::Transaction_state::backup(THD *thd) {
127 this->m_sql_command = thd->lex->sql_command;
128 this->m_trx = thd->get_transaction();
129
130 thd->backup_ha_data(&this->m_ha_data);
131
132 this->m_tx_isolation = thd->tx_isolation;
133 this->m_tx_read_only = thd->tx_read_only;
134 this->m_thd_option_bits = thd->variables.option_bits;
135 this->m_sql_mode = thd->variables.sql_mode;
136 this->m_transaction_psi = thd->m_transaction_psi;
137 this->m_server_status = thd->server_status;
138 this->m_in_lock_tables = thd->in_lock_tables;
139 this->m_time_zone_used = thd->time_zone_used;
140 this->m_transaction_rollback_request = thd->transaction_rollback_request;
141 }
142
restore(THD * thd)143 void THD::Transaction_state::restore(THD *thd) {
144 thd->set_transaction(this->m_trx);
145
146 thd->restore_ha_data(this->m_ha_data);
147
148 thd->tx_isolation = this->m_tx_isolation;
149 thd->variables.sql_mode = this->m_sql_mode;
150 thd->tx_read_only = this->m_tx_read_only;
151 thd->variables.option_bits = this->m_thd_option_bits;
152
153 thd->m_transaction_psi = this->m_transaction_psi;
154 thd->server_status = this->m_server_status;
155 thd->lex->sql_command = this->m_sql_command;
156 thd->in_lock_tables = this->m_in_lock_tables;
157 thd->time_zone_used = this->m_time_zone_used;
158 thd->transaction_rollback_request = this->m_transaction_rollback_request;
159 }
160
Attachable_trx(THD * thd,Attachable_trx * prev_trx)161 THD::Attachable_trx::Attachable_trx(THD *thd, Attachable_trx *prev_trx)
162 : m_thd(thd),
163 m_reset_lex(RESET_LEX),
164 m_prev_attachable_trx(prev_trx),
165 m_trx_state() {
166 // Save the transaction state.
167
168 m_trx_state.backup(m_thd);
169
170 // Save and reset query-tables-list and reset the sql-command.
171 //
172 // NOTE: ha_innobase::store_lock() takes the current sql-command into account.
173 // It must be SQLCOM_SELECT.
174 //
175 // Do NOT reset LEX if we're running tests. LEX is used by SELECT statements.
176
177 bool reset = (m_reset_lex == RESET_LEX ? true : false);
178 if (DBUG_EVALUATE_IF("use_attachable_trx", false, reset)) {
179 m_thd->lex->reset_n_backup_query_tables_list(
180 m_trx_state.m_query_tables_list);
181 m_thd->lex->sql_command = SQLCOM_SELECT;
182 }
183
184 // Save and reset open-tables.
185
186 m_thd->reset_n_backup_open_tables_state(&m_trx_state.m_open_tables_state,
187 Open_tables_state::SYSTEM_TABLES);
188
189 // Reset transaction state.
190
191 m_thd->m_transaction.release(); // it's been backed up.
192 DBUG_EXECUTE_IF("after_delete_wait", {
193 const char act[] = "now SIGNAL leader_reached WAIT_FOR leader_proceed";
194 DBUG_ASSERT(!debug_sync_set_action(m_thd, STRING_WITH_LEN(act)));
195 DBUG_SET("-d,after_delete_wait");
196 DBUG_SET("-d,block_leader_after_delete");
197 };);
198
199 m_thd->m_transaction.reset(new Transaction_ctx());
200
201 // Prepare for a new attachable transaction for read-only DD-transaction.
202
203 // LOCK_thd_data must be locked to prevent e.g. KILL CONNECTION from
204 // reading ha_data after clear() but before resize().
205 mysql_mutex_lock(&m_thd->LOCK_thd_data);
206 m_thd->ha_data.clear();
207 m_thd->ha_data.resize(m_thd->ha_data.capacity());
208 mysql_mutex_unlock(&m_thd->LOCK_thd_data);
209
210 // The attachable transaction must used READ COMMITTED isolation level.
211
212 m_thd->tx_isolation = ISO_READ_COMMITTED;
213
214 // The attachable transaction must be read-only.
215
216 m_thd->tx_read_only = true;
217
218 // The attachable transaction must be AUTOCOMMIT.
219
220 m_thd->variables.option_bits |= OPTION_AUTOCOMMIT;
221 m_thd->variables.option_bits &= ~OPTION_NOT_AUTOCOMMIT;
222 m_thd->variables.option_bits &= ~OPTION_BEGIN;
223
224 // Nothing should be binlogged from attachable transactions and disabling
225 // the binary log allows skipping some code related to figuring out what
226 // log format should be used.
227 m_thd->variables.option_bits &= ~OPTION_BIN_LOG;
228
229 // Possible parent's involvement to multi-statement transaction is masked
230
231 m_thd->server_status &= ~SERVER_STATUS_IN_TRANS;
232 m_thd->server_status &= ~SERVER_STATUS_IN_TRANS_READONLY;
233
234 // Reset SQL_MODE during system operations.
235
236 m_thd->variables.sql_mode = 0;
237
238 // Reset transaction instrumentation.
239
240 m_thd->m_transaction_psi = nullptr;
241
242 // Reset THD::in_lock_tables so InnoDB won't start acquiring table locks.
243 m_thd->in_lock_tables = false;
244
245 // Reset @@session.time_zone usage indicator for consistency.
246 m_thd->time_zone_used = false;
247
248 /*
249 InnoDB can ask to start attachable transaction while rolling back
250 the regular transaction. Reset rollback request flag to avoid it
251 influencing attachable transaction we are initiating.
252 */
253 m_thd->transaction_rollback_request = false;
254 }
255
~Attachable_trx()256 THD::Attachable_trx::~Attachable_trx() {
257 // Ensure that the SE didn't request rollback in the attachable transaction.
258 // Having THD::transaction_rollback_request set most likely means that we've
259 // experienced some sort of deadlock/timeout while processing the attachable
260 // transaction. That is not possible by the definition of an attachable
261 // transaction.
262 DBUG_ASSERT(!m_thd->transaction_rollback_request);
263
264 // Commit the attachable transaction before discarding transaction state.
265 // This is mostly needed to properly reset transaction state in SE.
266 // Note: We can't rely on InnoDB hack which auto-magically commits InnoDB
267 // transaction when the last table for a statement in auto-commit mode is
268 // unlocked. Apparently it doesn't work correctly in some corner cases
269 // (for example, when statement is killed just after tables are locked but
270 // before any other operations on the table happes). We try not to rely on
271 // it in other places on SQL-layer as well.
272 trans_commit_attachable(m_thd);
273
274 // Close all the tables that are open till now.
275
276 close_thread_tables(m_thd);
277
278 // Cleanup connection specific state which was created for attachable
279 // transaction (for InnoDB removes cached transaction object).
280 //
281 // Note that we need to call handlerton::close_connection for all SEs
282 // and not only SEs which participated in attachable transaction since
283 // connection specific state can be created when TABLE object is simply
284 // expelled from the Table Cache (e.g. this happens for MyISAM).
285 ha_close_connection(m_thd);
286
287 // Restore the transaction state.
288
289 m_trx_state.restore(m_thd);
290
291 m_thd->restore_backup_open_tables_state(&m_trx_state.m_open_tables_state);
292
293 bool reset = (m_reset_lex == RESET_LEX ? true : false);
294 if (DBUG_EVALUATE_IF("use_attachable_trx", false, reset)) {
295 m_thd->lex->restore_backup_query_tables_list(
296 m_trx_state.m_query_tables_list);
297 }
298 }
299
Attachable_trx_rw(THD * thd)300 THD::Attachable_trx_rw::Attachable_trx_rw(THD *thd)
301 : Attachable_trx(thd, nullptr) {
302 m_thd->tx_read_only = false;
303 m_thd->lex->sql_command = SQLCOM_END;
304 thd->get_transaction()->xid_state()->set_state(XID_STATE::XA_NOTR);
305 }
306
enter_stage(const PSI_stage_info * new_stage,PSI_stage_info * old_stage,const char * calling_func MY_ATTRIBUTE ((unused)),const char * calling_file,const unsigned int calling_line)307 void THD::enter_stage(const PSI_stage_info *new_stage,
308 PSI_stage_info *old_stage,
309 const char *calling_func MY_ATTRIBUTE((unused)),
310 const char *calling_file,
311 const unsigned int calling_line) {
312 DBUG_PRINT("THD::enter_stage",
313 ("'%s' %s:%d", new_stage ? new_stage->m_name : "", calling_file,
314 calling_line));
315
316 if (old_stage != nullptr) {
317 old_stage->m_key = m_current_stage_key;
318 old_stage->m_name = proc_info;
319 }
320
321 if (new_stage != nullptr) {
322 const char *msg = new_stage->m_name;
323
324 #if defined(ENABLED_PROFILING)
325 profiling->status_change(msg, calling_func, calling_file, calling_line);
326 #endif
327
328 m_current_stage_key = new_stage->m_key;
329 proc_info = msg;
330
331 m_stage_progress_psi =
332 MYSQL_SET_STAGE(m_current_stage_key, calling_file, calling_line);
333 } else {
334 m_stage_progress_psi = nullptr;
335 }
336
337 return;
338 }
339
set_open_tables_state(Open_tables_state * state)340 void Open_tables_state::set_open_tables_state(Open_tables_state *state) {
341 this->open_tables = state->open_tables;
342
343 this->temporary_tables = state->temporary_tables;
344
345 this->lock = state->lock;
346 this->extra_lock = state->extra_lock;
347
348 this->locked_tables_mode = state->locked_tables_mode;
349
350 this->state_flags = state->state_flags;
351
352 this->m_reprepare_observers = state->m_reprepare_observers;
353 }
354
reset_open_tables_state()355 void Open_tables_state::reset_open_tables_state() {
356 open_tables = nullptr;
357 temporary_tables = nullptr;
358 lock = nullptr;
359 extra_lock = nullptr;
360 locked_tables_mode = LTM_NONE;
361 state_flags = 0U;
362 reset_reprepare_observers();
363 }
364
THD(bool enable_plugins)365 THD::THD(bool enable_plugins)
366 : Query_arena(&main_mem_root, STMT_REGULAR_EXECUTION),
367 mark_used_columns(MARK_COLUMNS_READ),
368 want_privilege(0),
369 main_lex(new LEX),
370 lex(main_lex.get()),
371 m_dd_client(new dd::cache::Dictionary_client(this)),
372 m_query_string(NULL_CSTR),
373 m_db(NULL_CSTR),
374 rli_fake(nullptr),
375 rli_slave(nullptr),
376 initial_status_var(nullptr),
377 status_var_aggregated(false),
378 m_connection_attributes(),
379 m_current_query_cost(0),
380 m_current_query_partial_plans(0),
381 m_main_security_ctx(this),
382 m_security_ctx(&m_main_security_ctx),
383 protocol_text(new Protocol_text),
384 protocol_binary(new Protocol_binary),
385 query_plan(this),
386 m_current_stage_key(0),
387 current_mutex(nullptr),
388 current_cond(nullptr),
389 m_is_admin_conn(false),
390 in_sub_stmt(0),
391 fill_status_recursion_level(0),
392 fill_variables_recursion_level(0),
393 ha_data(PSI_NOT_INSTRUMENTED, ha_data.initial_capacity),
394 binlog_row_event_extra_data(nullptr),
395 skip_readonly_check(false),
396 binlog_unsafe_warning_flags(0),
397 binlog_table_maps(0),
398 binlog_accessed_db_names(nullptr),
399 m_trans_log_file(nullptr),
400 m_trans_fixed_log_file(nullptr),
401 m_trans_end_pos(0),
402 m_transaction(new Transaction_ctx()),
403 m_attachable_trx(nullptr),
404 table_map_for_update(0),
405 m_examined_row_count(0),
406 #if defined(ENABLED_PROFILING)
407 profiling(new PROFILING),
408 #endif
409 m_stage_progress_psi(nullptr),
410 m_digest(nullptr),
411 m_statement_psi(nullptr),
412 m_transaction_psi(nullptr),
413 m_idle_psi(nullptr),
414 m_server_idle(false),
415 user_var_events(key_memory_user_var_entry),
416 next_to_commit(nullptr),
417 binlog_need_explicit_defaults_ts(false),
418 kill_immunizer(nullptr),
419 m_is_fatal_error(false),
420 transaction_rollback_request(false),
421 is_fatal_sub_stmt_error(false),
422 rand_used(false),
423 time_zone_used(false),
424 in_lock_tables(false),
425 derived_tables_processing(false),
426 parsing_system_view(false),
427 sp_runtime_ctx(nullptr),
428 m_parser_state(nullptr),
429 work_part_info(nullptr),
430 // No need to instrument, highly unlikely to have that many plugins.
431 audit_class_plugins(PSI_NOT_INSTRUMENTED),
432 audit_class_mask(PSI_NOT_INSTRUMENTED),
433 #if defined(ENABLED_DEBUG_SYNC)
434 debug_sync_control(nullptr),
435 #endif /* defined(ENABLED_DEBUG_SYNC) */
436 m_enable_plugins(enable_plugins),
437 m_audited(true),
438 #ifdef HAVE_GTID_NEXT_LIST
439 owned_gtid_set(global_sid_map),
440 #endif
441 skip_gtid_rollback(false),
442 is_commit_in_middle_of_statement(false),
443 has_gtid_consistency_violation(false),
444 main_da(false),
445 m_parser_da(false),
446 m_query_rewrite_plugin_da(false),
447 m_query_rewrite_plugin_da_ptr(&m_query_rewrite_plugin_da),
448 m_stmt_da(&main_da),
449 duplicate_slave_id(false),
450 is_a_srv_session_thd(false),
451 m_is_plugin_fake_ddl(false) {
452 main_lex->reset();
453 set_psi(nullptr);
454 mdl_context.init(this);
455 init_sql_alloc(key_memory_thd_main_mem_root, &main_mem_root,
456 global_system_variables.query_alloc_block_size,
457 global_system_variables.query_prealloc_size);
458 stmt_arena = this;
459 thread_stack = nullptr;
460 m_catalog.str = "std";
461 m_catalog.length = 3;
462 password = 0;
463 query_start_usec_used = false;
464 check_for_truncated_fields = CHECK_FIELD_IGNORE;
465 killed = NOT_KILLED;
466 col_access = 0;
467 is_slave_error = thread_specific_used = false;
468 tmp_table = 0;
469 num_truncated_fields = 0L;
470 m_sent_row_count = 0L;
471 current_found_rows = 0;
472 previous_found_rows = 0;
473 is_operating_gtid_table_implicitly = false;
474 is_operating_substatement_implicitly = false;
475 m_row_count_func = -1;
476 statement_id_counter = 0UL;
477 // Must be reset to handle error with THD's created for init of mysqld
478 lex->thd = nullptr;
479 lex->set_current_select(nullptr);
480 utime_after_lock = 0L;
481 current_linfo = nullptr;
482 slave_thread = false;
483 memset(&variables, 0, sizeof(variables));
484 m_thread_id = Global_THD_manager::reserved_thread_id;
485 file_id = 0;
486 query_id = 0;
487 query_name_consts = 0;
488 db_charset = global_system_variables.collation_database;
489 is_killable = false;
490 binlog_evt_union.do_union = false;
491 enable_slow_log = false;
492 commit_error = CE_NONE;
493 tx_commit_pending = false;
494 durability_property = HA_REGULAR_DURABILITY;
495 #ifndef DBUG_OFF
496 dbug_sentry = THD_SENTRY_MAGIC;
497 #endif
498 mysql_audit_init_thd(this);
499 net.vio = nullptr;
500 system_thread = NON_SYSTEM_THREAD;
501 cleanup_done = false;
502 m_release_resources_done = false;
503 peer_port = 0; // For SHOW PROCESSLIST
504 get_transaction()->m_flags.enabled = true;
505 m_resource_group_ctx.m_cur_resource_group = nullptr;
506 m_resource_group_ctx.m_switch_resource_group_str[0] = '\0';
507 m_resource_group_ctx.m_warn = 0;
508
509 mysql_mutex_init(key_LOCK_thd_data, &LOCK_thd_data, MY_MUTEX_INIT_FAST);
510 mysql_mutex_init(key_LOCK_thd_query, &LOCK_thd_query, MY_MUTEX_INIT_FAST);
511 mysql_mutex_init(key_LOCK_thd_sysvar, &LOCK_thd_sysvar, MY_MUTEX_INIT_FAST);
512 mysql_mutex_init(key_LOCK_thd_protocol, &LOCK_thd_protocol,
513 MY_MUTEX_INIT_FAST);
514 mysql_mutex_init(key_LOCK_query_plan, &LOCK_query_plan, MY_MUTEX_INIT_FAST);
515 mysql_mutex_init(key_LOCK_current_cond, &LOCK_current_cond,
516 MY_MUTEX_INIT_FAST);
517 mysql_cond_init(key_COND_thr_lock, &COND_thr_lock);
518
519 /* Variables with default values */
520 proc_info = "login";
521 where = THD::DEFAULT_WHERE;
522 server_id = ::server_id;
523 unmasked_server_id = server_id;
524 set_command(COM_CONNECT);
525 *scramble = '\0';
526
527 /* Call to init() below requires fully initialized Open_tables_state. */
528 reset_open_tables_state();
529
530 init();
531 #if defined(ENABLED_PROFILING)
532 profiling->set_thd(this);
533 #endif
534 m_user_connect = nullptr;
535 user_vars.clear();
536
537 sp_proc_cache = nullptr;
538 sp_func_cache = nullptr;
539
540 /* Protocol */
541 m_protocol = protocol_text.get(); // Default protocol
542 protocol_text->init(this);
543 protocol_binary->init(this);
544 protocol_text->set_client_capabilities(0); // minimalistic client
545
546 /*
547 Make sure thr_lock_info_init() is called for threads which do not get
548 assigned a proper thread_id value but keep using reserved_thread_id.
549 */
550 thr_lock_info_init(&lock_info, m_thread_id, &COND_thr_lock);
551
552 m_internal_handler = nullptr;
553 m_binlog_invoker = false;
554 memset(&m_invoker_user, 0, sizeof(m_invoker_user));
555 memset(&m_invoker_host, 0, sizeof(m_invoker_host));
556
557 binlog_next_event_pos.file_name = nullptr;
558 binlog_next_event_pos.pos = 0;
559
560 timer = nullptr;
561 timer_cache = nullptr;
562
563 m_token_array = nullptr;
564 if (max_digest_length > 0) {
565 m_token_array = (unsigned char *)my_malloc(PSI_INSTRUMENT_ME,
566 max_digest_length, MYF(MY_WME));
567 }
568 #ifndef DBUG_OFF
569 debug_binlog_xid_last.reset();
570 #endif
571 set_system_user(false);
572 }
573
set_transaction(Transaction_ctx * transaction_ctx)574 void THD::set_transaction(Transaction_ctx *transaction_ctx) {
575 DBUG_ASSERT(is_attachable_ro_transaction_active());
576
577 delete m_transaction.release();
578 m_transaction.reset(transaction_ctx);
579 }
580
set_db(const LEX_CSTRING & new_db)581 bool THD::set_db(const LEX_CSTRING &new_db) {
582 bool result;
583 /*
584 Acquiring mutex LOCK_thd_data as we either free the memory allocated
585 for the database and reallocating the memory for the new db or memcpy
586 the new_db to the db.
587 */
588 mysql_mutex_lock(&LOCK_thd_data);
589 /* Do not reallocate memory if current chunk is big enough. */
590 if (m_db.str && new_db.str && m_db.length >= new_db.length)
591 memcpy(const_cast<char *>(m_db.str), new_db.str, new_db.length + 1);
592 else {
593 my_free(const_cast<char *>(m_db.str));
594 m_db = NULL_CSTR;
595 if (new_db.str)
596 m_db.str = my_strndup(key_memory_THD_db, new_db.str, new_db.length,
597 MYF(MY_WME | ME_FATALERROR));
598 }
599 m_db.length = m_db.str ? new_db.length : 0;
600 mysql_mutex_unlock(&LOCK_thd_data);
601 result = new_db.str && !m_db.str;
602 #ifdef HAVE_PSI_THREAD_INTERFACE
603 if (!result)
604 PSI_THREAD_CALL(set_thread_db)(new_db.str, static_cast<int>(new_db.length));
605 #endif
606 return result;
607 }
608
push_internal_handler(Internal_error_handler * handler)609 void THD::push_internal_handler(Internal_error_handler *handler) {
610 if (m_internal_handler) {
611 handler->m_prev_internal_handler = m_internal_handler;
612 m_internal_handler = handler;
613 } else
614 m_internal_handler = handler;
615 }
616
handle_condition(uint sql_errno,const char * sqlstate,Sql_condition::enum_severity_level * level,const char * msg)617 bool THD::handle_condition(uint sql_errno, const char *sqlstate,
618 Sql_condition::enum_severity_level *level,
619 const char *msg) {
620 if (!m_internal_handler) return false;
621
622 for (Internal_error_handler *error_handler = m_internal_handler;
623 error_handler; error_handler = error_handler->m_prev_internal_handler) {
624 if (error_handler->handle_condition(this, sql_errno, sqlstate, level, msg))
625 return true;
626 }
627 return false;
628 }
629
pop_internal_handler()630 Internal_error_handler *THD::pop_internal_handler() {
631 DBUG_ASSERT(m_internal_handler != nullptr);
632 Internal_error_handler *popped_handler = m_internal_handler;
633 m_internal_handler = m_internal_handler->m_prev_internal_handler;
634 return popped_handler;
635 }
636
raise_error(uint sql_errno)637 void THD::raise_error(uint sql_errno) {
638 const char *msg = ER_THD_NONCONST(this, sql_errno);
639 (void)raise_condition(sql_errno, nullptr, Sql_condition::SL_ERROR, msg);
640 }
641
raise_error_printf(uint sql_errno,...)642 void THD::raise_error_printf(uint sql_errno, ...) {
643 va_list args;
644 char ebuff[MYSQL_ERRMSG_SIZE];
645 DBUG_TRACE;
646 DBUG_PRINT("my", ("nr: %d errno: %d", sql_errno, errno));
647 const char *format = ER_THD_NONCONST(this, sql_errno);
648 va_start(args, sql_errno);
649 vsnprintf(ebuff, sizeof(ebuff), format, args);
650 va_end(args);
651 (void)raise_condition(sql_errno, nullptr, Sql_condition::SL_ERROR, ebuff);
652 }
653
raise_warning(uint sql_errno)654 void THD::raise_warning(uint sql_errno) {
655 const char *msg = ER_THD_NONCONST(this, sql_errno);
656 (void)raise_condition(sql_errno, nullptr, Sql_condition::SL_WARNING, msg);
657 }
658
raise_warning_printf(uint sql_errno,...)659 void THD::raise_warning_printf(uint sql_errno, ...) {
660 va_list args;
661 char ebuff[MYSQL_ERRMSG_SIZE];
662 DBUG_TRACE;
663 DBUG_PRINT("enter", ("warning: %u", sql_errno));
664 const char *format = ER_THD_NONCONST(this, sql_errno);
665 va_start(args, sql_errno);
666 vsnprintf(ebuff, sizeof(ebuff), format, args);
667 va_end(args);
668 (void)raise_condition(sql_errno, nullptr, Sql_condition::SL_WARNING, ebuff);
669 }
670
raise_note(uint sql_errno)671 void THD::raise_note(uint sql_errno) {
672 DBUG_TRACE;
673 DBUG_PRINT("enter", ("code: %d", sql_errno));
674 if (!(variables.option_bits & OPTION_SQL_NOTES)) return;
675 const char *msg = ER_THD_NONCONST(this, sql_errno);
676 (void)raise_condition(sql_errno, nullptr, Sql_condition::SL_NOTE, msg);
677 }
678
raise_note_printf(uint sql_errno,...)679 void THD::raise_note_printf(uint sql_errno, ...) {
680 va_list args;
681 char ebuff[MYSQL_ERRMSG_SIZE];
682 DBUG_TRACE;
683 DBUG_PRINT("enter", ("code: %u", sql_errno));
684 if (!(variables.option_bits & OPTION_SQL_NOTES)) return;
685 const char *format = ER_THD_NONCONST(this, sql_errno);
686 va_start(args, sql_errno);
687 vsnprintf(ebuff, sizeof(ebuff), format, args);
688 va_end(args);
689 (void)raise_condition(sql_errno, nullptr, Sql_condition::SL_NOTE, ebuff);
690 }
691
query_start_timeval_trunc(uint decimals)692 struct timeval THD::query_start_timeval_trunc(uint decimals) {
693 struct timeval tv;
694 tv.tv_sec = start_time.tv_sec;
695 if (decimals) {
696 tv.tv_usec = start_time.tv_usec;
697 my_timeval_trunc(&tv, decimals);
698 query_start_usec_used = true;
699 } else {
700 tv.tv_usec = 0;
701 }
702 return tv;
703 }
704
raise_condition(uint sql_errno,const char * sqlstate,Sql_condition::enum_severity_level level,const char * msg,bool fatal_error)705 Sql_condition *THD::raise_condition(uint sql_errno, const char *sqlstate,
706 Sql_condition::enum_severity_level level,
707 const char *msg, bool fatal_error) {
708 DBUG_TRACE;
709
710 if (!(variables.option_bits & OPTION_SQL_NOTES) &&
711 (level == Sql_condition::SL_NOTE))
712 return nullptr;
713
714 DBUG_ASSERT(sql_errno != 0);
715 if (sql_errno == 0) /* Safety in release build */
716 sql_errno = ER_UNKNOWN_ERROR;
717 if (msg == nullptr) msg = ER_THD_NONCONST(this, sql_errno);
718 if (sqlstate == nullptr) sqlstate = mysql_errno_to_sqlstate(sql_errno);
719
720 if (fatal_error) {
721 // Only makes sense for errors
722 DBUG_ASSERT(level == Sql_condition::SL_ERROR);
723 this->fatal_error();
724 }
725
726 MYSQL_LOG_ERROR(sql_errno, PSI_ERROR_OPERATION_RAISED);
727 if (handle_condition(sql_errno, sqlstate, &level, msg)) return nullptr;
728
729 Diagnostics_area *da = get_stmt_da();
730 if (level == Sql_condition::SL_ERROR) {
731 /*
732 Reporting an error invokes audit API call that notifies the error
733 to the plugin. Audit API that generate the error adds a protection
734 (condition handler) that prevents entering infinite recursion, when
735 a plugin signals error, when already handling the error.
736
737 mysql_audit_notify() must therefore be called after handle_condition().
738 */
739 mysql_audit_notify(this, AUDIT_EVENT(MYSQL_AUDIT_GENERAL_ERROR), sql_errno,
740 msg, strlen(msg));
741
742 is_slave_error = true; // needed to catch query errors during replication
743
744 if (!da->is_error()) {
745 set_row_count_func(-1);
746 da->set_error_status(sql_errno, msg, sqlstate);
747 }
748 }
749
750 /*
751 Avoid pushing a condition for fatal out of memory errors as this will
752 require memory allocation and therefore might fail. Non fatal out of
753 memory errors can occur if raised by SIGNAL/RESIGNAL statement.
754 */
755 Sql_condition *cond = nullptr;
756 if (!(is_fatal_error() &&
757 (sql_errno == EE_OUTOFMEMORY || sql_errno == ER_OUTOFMEMORY ||
758 sql_errno == ER_STD_BAD_ALLOC_ERROR))) {
759 cond = da->push_warning(this, sql_errno, sqlstate, level, msg);
760 }
761 return cond;
762 }
763
764 /*
765 Init common variables that has to be reset on start and on cleanup_connection
766 */
767
init(void)768 void THD::init(void) {
769 plugin_thdvar_init(this, m_enable_plugins);
770 /*
771 variables= global_system_variables above has reset
772 variables.pseudo_thread_id to 0. We need to correct it here to
773 avoid temporary tables replication failure.
774 */
775 variables.pseudo_thread_id = m_thread_id;
776
777 /*
778 NOTE: reset_connection command will reset the THD to its default state.
779 All system variables whose scope is SESSION ONLY should be set to their
780 default values here.
781 */
782 reset_first_successful_insert_id();
783 user_time.tv_sec = user_time.tv_usec = 0;
784 start_time.tv_sec = start_time.tv_usec = 0;
785 set_time();
786 auto_inc_intervals_forced.empty();
787 {
788 ulong tmp;
789 tmp = sql_rnd_with_mutex();
790 randominit(&rand, tmp + (ulong)&rand,
791 tmp + (ulong)::atomic_global_query_id);
792 }
793
794 server_status = SERVER_STATUS_AUTOCOMMIT;
795 if (variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES)
796 server_status |= SERVER_STATUS_NO_BACKSLASH_ESCAPES;
797
798 get_transaction()->reset_unsafe_rollback_flags(Transaction_ctx::SESSION);
799 get_transaction()->reset_unsafe_rollback_flags(Transaction_ctx::STMT);
800 open_options = ha_open_options;
801 update_lock_default =
802 (variables.low_priority_updates ? TL_WRITE_LOW_PRIORITY : TL_WRITE);
803 insert_lock_default =
804 (variables.low_priority_updates ? TL_WRITE_LOW_PRIORITY
805 : TL_WRITE_CONCURRENT_INSERT);
806 tx_isolation = (enum_tx_isolation)variables.transaction_isolation;
807 tx_read_only = variables.transaction_read_only;
808 tx_priority = 0;
809 thd_tx_priority = 0;
810 update_charset();
811 reset_current_stmt_binlog_format_row();
812 reset_binlog_local_stmt_filter();
813 memset(&status_var, 0, sizeof(status_var));
814 binlog_row_event_extra_data = nullptr;
815
816 if (variables.sql_log_bin)
817 variables.option_bits |= OPTION_BIN_LOG;
818 else
819 variables.option_bits &= ~OPTION_BIN_LOG;
820
821 #if defined(ENABLED_DEBUG_SYNC)
822 /* Initialize the Debug Sync Facility. See debug_sync.cc. */
823 debug_sync_init_thread(this);
824 #endif /* defined(ENABLED_DEBUG_SYNC) */
825
826 /* Initialize session_tracker and create all tracker objects */
827 session_tracker.init(this->charset());
828 session_tracker.enable(this);
829
830 owned_gtid.clear();
831 owned_sid.clear();
832 m_se_gtid_flags.reset();
833 owned_gtid.dbug_print(nullptr, "set owned_gtid (clear) in THD::init");
834
835 // This will clear the writeset session history.
836 rpl_thd_ctx.dependency_tracker_ctx().set_last_session_sequence_number(0);
837
838 /*
839 This variable is used to temporarily disable the password validation plugin
840 when a RANDOM PASSWORD is generated during SET PASSWORD,CREATE USER or
841 ALTER USER statements.
842 */
843 m_disable_password_validation = false;
844 }
845
init_query_mem_roots()846 void THD::init_query_mem_roots() {
847 mem_root->set_block_size(variables.query_alloc_block_size);
848 get_transaction()->init_mem_root_defaults(variables.trans_alloc_block_size,
849 variables.trans_prealloc_size);
850 }
851
set_new_thread_id()852 void THD::set_new_thread_id() {
853 m_thread_id = Global_THD_manager::get_instance()->get_new_thread_id();
854 variables.pseudo_thread_id = m_thread_id;
855 thr_lock_info_init(&lock_info, m_thread_id, &COND_thr_lock);
856 }
857
858 /*
859 Do what's needed when one invokes change user
860
861 SYNOPSIS
862 cleanup_connection()
863
864 IMPLEMENTATION
865 Reset all resources that are connection specific
866 */
867
cleanup_connection(void)868 void THD::cleanup_connection(void) {
869 mysql_mutex_lock(&LOCK_status);
870 add_to_status(&global_status_var, &status_var);
871 reset_system_status_vars(&status_var);
872 mysql_mutex_unlock(&LOCK_status);
873
874 cleanup();
875 #if defined(ENABLED_DEBUG_SYNC)
876 /* End the Debug Sync Facility. See debug_sync.cc. */
877 debug_sync_end_thread(this);
878 #endif /* defined(ENABLED_DEBUG_SYNC) */
879 killed = NOT_KILLED;
880 running_explain_analyze = false;
881 cleanup_done = false;
882 init();
883 stmt_map.reset();
884 user_vars.clear();
885 sp_cache_clear(&sp_proc_cache);
886 sp_cache_clear(&sp_func_cache);
887
888 clear_error();
889 // clear the warnings
890 get_stmt_da()->reset_condition_info(this);
891 // clear profiling information
892 #if defined(ENABLED_PROFILING)
893 profiling->cleanup();
894 #endif
895
896 #ifndef DBUG_OFF
897 /* DEBUG code only (begin) */
898 bool check_cleanup = false;
899 DBUG_EXECUTE_IF("debug_test_cleanup_connection", check_cleanup = true;);
900 if (check_cleanup) {
901 /* isolation level should be default */
902 DBUG_ASSERT(variables.transaction_isolation == ISO_REPEATABLE_READ);
903 /* check autocommit is ON by default */
904 DBUG_ASSERT(server_status == SERVER_STATUS_AUTOCOMMIT);
905 /* check prepared stmts are cleaned up */
906 DBUG_ASSERT(prepared_stmt_count == 0);
907 /* check diagnostic area is cleaned up */
908 DBUG_ASSERT(get_stmt_da()->status() == Diagnostics_area::DA_EMPTY);
909 /* check if temp tables are deleted */
910 DBUG_ASSERT(temporary_tables == nullptr);
911 /* check if tables are unlocked */
912 DBUG_ASSERT(locked_tables_list.locked_tables() == nullptr);
913 }
914 /* DEBUG code only (end) */
915 #endif
916 }
917
918 /*
919 Do what's needed when one invokes change user.
920 Also used during THD::release_resources, i.e. prior to THD destruction.
921 */
cleanup(void)922 void THD::cleanup(void) {
923 Transaction_ctx *trn_ctx = get_transaction();
924 XID_STATE *xs = trn_ctx->xid_state();
925
926 DBUG_TRACE;
927 DBUG_ASSERT(cleanup_done == 0);
928 DEBUG_SYNC(this, "thd_cleanup_start");
929
930 killed = KILL_CONNECTION;
931 if (trn_ctx->xid_state()->has_state(XID_STATE::XA_PREPARED)) {
932 /*
933 Return error is not an option as XA is in prepared state and
934 connection is gone. Log the error and continue.
935 */
936 if (MDL_context_backup_manager::instance().create_backup(
937 &mdl_context, xs->get_xid()->key(), xs->get_xid()->key_length())) {
938 LogErr(ERROR_LEVEL, ER_XA_CANT_CREATE_MDL_BACKUP);
939 }
940 transaction_cache_detach(trn_ctx);
941 } else {
942 xs->set_state(XID_STATE::XA_NOTR);
943 trans_rollback(this);
944 transaction_cache_delete(trn_ctx);
945 }
946
947 locked_tables_list.unlock_locked_tables(this);
948 mysql_ha_cleanup(this);
949
950 DBUG_ASSERT(open_tables == nullptr);
951 /*
952 If the thread was in the middle of an ongoing transaction (rolled
953 back a few lines above) or under LOCK TABLES (unlocked the tables
954 and left the mode a few lines above), there will be outstanding
955 metadata locks. Release them.
956 */
957 mdl_context.release_transactional_locks();
958
959 /* Release the global read lock, if acquired. */
960 if (global_read_lock.is_acquired())
961 global_read_lock.unlock_global_read_lock(this);
962
963 mysql_ull_cleanup(this);
964 /*
965 All locking service locks must be released on disconnect.
966 */
967 release_all_locking_service_locks(this);
968
969 /*
970 If Backup Lock was acquired it must be released on disconnect.
971 */
972 release_backup_lock(this);
973
974 /* All metadata locks must have been released by now. */
975 DBUG_ASSERT(!mdl_context.has_locks());
976
977 /* Protects user_vars. */
978 mysql_mutex_lock(&LOCK_thd_data);
979 user_vars.clear();
980 mysql_mutex_unlock(&LOCK_thd_data);
981
982 /*
983 When we call drop table for temporary tables, the
984 user_var_events container is not cleared this might
985 cause error if the container was filled before the
986 drop table command is called.
987 So call this before calling close_temporary_tables.
988 */
989 user_var_events.clear();
990 close_temporary_tables(this);
991 sp_cache_clear(&sp_proc_cache);
992 sp_cache_clear(&sp_func_cache);
993
994 /*
995 Actions above might generate events for the binary log, so we
996 commit the current transaction coordinator after executing cleanup
997 actions.
998 */
999 if (tc_log && !trn_ctx->xid_state()->has_state(XID_STATE::XA_PREPARED))
1000 tc_log->commit(this, true);
1001
1002 /*
1003 Destroy trackers only after finishing manipulations with transaction
1004 state to avoid issues with Transaction_state_tracker.
1005 */
1006 session_tracker.deinit();
1007
1008 /*
1009 If we have a Security_context, make sure it is "logged out"
1010 */
1011
1012 cleanup_done = true;
1013 }
1014
1015 /**
1016 Release most resources, prior to THD destruction.
1017 */
release_resources()1018 void THD::release_resources() {
1019 DBUG_ASSERT(m_release_resources_done == false);
1020
1021 Global_THD_manager::get_instance()->release_thread_id(m_thread_id);
1022
1023 /* Ensure that no one is using THD */
1024 mysql_mutex_lock(&LOCK_thd_data);
1025 mysql_mutex_lock(&LOCK_query_plan);
1026
1027 /* Close connection */
1028 if (is_classic_protocol() && get_protocol_classic()->get_vio()) {
1029 vio_delete(get_protocol_classic()->get_vio());
1030 get_protocol_classic()->end_net();
1031 }
1032
1033 /* modification plan for UPDATE/DELETE should be freed. */
1034 DBUG_ASSERT(query_plan.get_modification_plan() == nullptr);
1035 mysql_mutex_unlock(&LOCK_query_plan);
1036 mysql_mutex_unlock(&LOCK_thd_data);
1037 mysql_mutex_lock(&LOCK_thd_query);
1038 mysql_mutex_unlock(&LOCK_thd_query);
1039
1040 stmt_map.reset(); /* close all prepared statements */
1041 if (!cleanup_done) cleanup();
1042
1043 mdl_context.destroy();
1044 ha_close_connection(this);
1045
1046 /*
1047 Debug sync system must be closed after ha_close_connection, because
1048 DEBUG_SYNC is used in InnoDB connection handlerton close.
1049 */
1050 #if defined(ENABLED_DEBUG_SYNC)
1051 /* End the Debug Sync Facility. See debug_sync.cc. */
1052 debug_sync_end_thread(this);
1053 #endif /* defined(ENABLED_DEBUG_SYNC) */
1054
1055 plugin_thdvar_cleanup(this, m_enable_plugins);
1056
1057 DBUG_ASSERT(timer == nullptr);
1058
1059 if (timer_cache) thd_timer_destroy(timer_cache);
1060
1061 if (rli_fake) {
1062 rli_fake->end_info();
1063 delete rli_fake;
1064 rli_fake = nullptr;
1065 }
1066 mysql_audit_free_thd(this);
1067
1068 if (current_thd == this) restore_globals();
1069
1070 mysql_mutex_lock(&LOCK_status);
1071 /* Add thread status to the global totals. */
1072 add_to_status(&global_status_var, &status_var);
1073 #ifdef HAVE_PSI_THREAD_INTERFACE
1074 /* Aggregate thread status into the Performance Schema. */
1075 if (m_psi != nullptr) {
1076 PSI_THREAD_CALL(aggregate_thread_status)(m_psi);
1077 }
1078 #endif /* HAVE_PSI_THREAD_INTERFACE */
1079 /* Ensure that the thread status is not re-aggregated to the global totals. */
1080 status_var_aggregated = true;
1081
1082 mysql_mutex_unlock(&LOCK_status);
1083
1084 m_release_resources_done = true;
1085 }
1086
~THD()1087 THD::~THD() {
1088 THD_CHECK_SENTRY(this);
1089 DBUG_TRACE;
1090 DBUG_PRINT("info", ("THD dtor, this %p", this));
1091
1092 if (!m_release_resources_done) release_resources();
1093
1094 clear_next_event_pos();
1095
1096 /* Ensure that no one is using THD */
1097 mysql_mutex_lock(&LOCK_thd_data);
1098 mysql_mutex_unlock(&LOCK_thd_data);
1099 mysql_mutex_lock(&LOCK_thd_query);
1100 mysql_mutex_unlock(&LOCK_thd_query);
1101
1102 DBUG_ASSERT(!m_attachable_trx);
1103
1104 my_free(const_cast<char *>(m_db.str));
1105 m_db = NULL_CSTR;
1106 get_transaction()->free_memory(MYF(0));
1107 mysql_mutex_destroy(&LOCK_query_plan);
1108 mysql_mutex_destroy(&LOCK_thd_data);
1109 mysql_mutex_destroy(&LOCK_thd_query);
1110 mysql_mutex_destroy(&LOCK_thd_sysvar);
1111 mysql_mutex_destroy(&LOCK_thd_protocol);
1112 mysql_mutex_destroy(&LOCK_current_cond);
1113 mysql_cond_destroy(&COND_thr_lock);
1114 #ifndef DBUG_OFF
1115 dbug_sentry = THD_SENTRY_GONE;
1116 #endif
1117
1118 if (variables.gtid_next_list.gtid_set != nullptr) {
1119 #ifdef HAVE_GTID_NEXT_LIST
1120 delete variables.gtid_next_list.gtid_set;
1121 variables.gtid_next_list.gtid_set = NULL;
1122 variables.gtid_next_list.is_non_null = false;
1123 #else
1124 DBUG_ASSERT(0);
1125 #endif
1126 }
1127 if (rli_slave) rli_slave->cleanup_after_session();
1128
1129 /*
1130 As slaves can be added in one mysql command like COM_REGISTER_SLAVE
1131 but then need to be removed on error scenarios, we call this method
1132 here
1133 */
1134 unregister_slave(this, true, true);
1135
1136 free_root(&main_mem_root, MYF(0));
1137
1138 if (m_token_array != nullptr) {
1139 my_free(m_token_array);
1140 }
1141 }
1142
1143 /**
1144 Awake a thread.
1145
1146 @param[in] state_to_set value for THD::killed
1147
1148 This is normally called from another thread's THD object.
1149
1150 @note Do always call this while holding LOCK_thd_data.
1151 */
1152
awake(THD::killed_state state_to_set)1153 void THD::awake(THD::killed_state state_to_set) {
1154 DBUG_TRACE;
1155 DBUG_PRINT("enter", ("this: %p current_thd: %p", this, current_thd));
1156 THD_CHECK_SENTRY(this);
1157 mysql_mutex_assert_owner(&LOCK_thd_data);
1158
1159 /* Shutdown clone vio always, to wake up clone waiting for remote. */
1160 shutdown_clone_vio();
1161
1162 /*
1163 If THD is in kill immune mode (i.e. operation on new DD tables is in
1164 progress) then just save state_to_set with THD::kill_immunizer object.
1165
1166 While exiting kill immune mode, awake() is called again with the killed
1167 state saved in THD::kill_immunizer object.
1168 */
1169 if (kill_immunizer && kill_immunizer->is_active()) {
1170 kill_immunizer->save_killed_state(state_to_set);
1171 return;
1172 }
1173
1174 /*
1175 Set killed flag if the connection is being killed (state_to_set
1176 is KILL_CONNECTION) or the connection is processing a query
1177 (state_to_set is KILL_QUERY and m_server_idle flag is not set).
1178 If the connection is idle and state_to_set is KILL QUERY, the
1179 the killed flag is not set so that it doesn't affect the next
1180 command incorrectly.
1181 */
1182 if (this->m_server_idle && state_to_set == KILL_QUERY) { /* nothing */
1183 } else {
1184 killed = state_to_set;
1185 }
1186
1187 if (state_to_set != THD::KILL_QUERY && state_to_set != THD::KILL_TIMEOUT) {
1188 if (this != current_thd || kill_immunizer) {
1189 DBUG_ASSERT(!kill_immunizer || !kill_immunizer->is_active());
1190
1191 /*
1192 Before sending a signal, let's close the socket of the thread
1193 that is being killed ("this", which is not the current thread).
1194 This is to make sure it does not block if the signal is lost.
1195 This needs to be done only on platforms where signals are not
1196 a reliable interruption mechanism.
1197
1198 Note that the downside of this mechanism is that we could close
1199 the connection while "this" target thread is in the middle of
1200 sending a result to the application, thus violating the client-
1201 server protocol.
1202
1203 On the other hand, without closing the socket we have a race
1204 condition. If "this" target thread passes the check of
1205 thd->killed, and then the current thread runs through
1206 THD::awake(), sets the 'killed' flag and completes the
1207 signaling, and then the target thread runs into read(), it will
1208 block on the socket. As a result of the discussions around
1209 Bug#37780, it has been decided that we accept the race
1210 condition. A second KILL awakes the target from read().
1211
1212 If we are killing ourselves, we know that we are not blocked.
1213 We also know that we will check thd->killed before we go for
1214 reading the next statement.
1215 */
1216
1217 shutdown_active_vio();
1218 }
1219
1220 /* Send an event to the scheduler that a thread should be killed. */
1221 if (!slave_thread)
1222 MYSQL_CALLBACK(Connection_handler_manager::event_functions,
1223 post_kill_notification, (this));
1224 }
1225
1226 /* Interrupt target waiting inside a storage engine. */
1227 if (state_to_set != THD::NOT_KILLED) ha_kill_connection(this);
1228
1229 if (state_to_set == THD::KILL_TIMEOUT) {
1230 DBUG_ASSERT(!status_var_aggregated);
1231 status_var.max_execution_time_exceeded++;
1232 }
1233
1234 /* Broadcast a condition to kick the target if it is waiting on it. */
1235 if (is_killable) {
1236 mysql_mutex_lock(&LOCK_current_cond);
1237 /*
1238 This broadcast could be up in the air if the victim thread
1239 exits the cond in the time between read and broadcast, but that is
1240 ok since all we want to do is to make the victim thread get out
1241 of waiting on current_cond.
1242 If we see a non-zero current_cond: it cannot be an old value (because
1243 then exit_cond() should have run and it can't because we have mutex); so
1244 it is the true value but maybe current_mutex is not yet non-zero (we're
1245 in the middle of enter_cond() and there is a "memory order
1246 inversion"). So we test the mutex too to not lock 0.
1247
1248 Note that there is a small chance we fail to kill. If victim has locked
1249 current_mutex, but hasn't yet entered enter_cond() (which means that
1250 current_cond and current_mutex are 0), then the victim will not get
1251 a signal and it may wait "forever" on the cond (until
1252 we issue a second KILL or the status it's waiting for happens).
1253 It's true that we have set its thd->killed but it may not
1254 see it immediately and so may have time to reach the cond_wait().
1255
1256 However, where possible, we test for killed once again after
1257 enter_cond(). This should make the signaling as safe as possible.
1258 However, there is still a small chance of failure on platforms with
1259 instruction or memory write reordering.
1260 */
1261 if (current_cond.load() && current_mutex.load()) {
1262 DBUG_EXECUTE_IF("before_dump_thread_acquires_current_mutex", {
1263 const char act[] =
1264 "now signal dump_thread_signal wait_for go_dump_thread";
1265 DBUG_ASSERT(!debug_sync_set_action(current_thd, STRING_WITH_LEN(act)));
1266 };);
1267 mysql_mutex_lock(current_mutex);
1268 mysql_cond_broadcast(current_cond);
1269 mysql_mutex_unlock(current_mutex);
1270 }
1271 mysql_mutex_unlock(&LOCK_current_cond);
1272 }
1273 }
1274
1275 /**
1276 Close the Vio associated this session.
1277
1278 @remark LOCK_thd_data is taken due to the fact that
1279 the Vio might be disassociated concurrently.
1280 */
1281
disconnect(bool server_shutdown)1282 void THD::disconnect(bool server_shutdown) {
1283 Vio *vio = nullptr;
1284
1285 mysql_mutex_lock(&LOCK_thd_data);
1286
1287 /* Shutdown clone vio always, to wake up clone waiting for remote. */
1288 shutdown_clone_vio();
1289
1290 /*
1291 If thread is in kill immune mode (i.e. operation on new DD tables
1292 is in progress) then just save state_to_set with THD::kill_immunizer
1293 object.
1294
1295 While exiting kill immune mode, awake() is called again with the killed
1296 state saved in THD::kill_immunizer object.
1297
1298 active_vio is aleady associated to the thread when it is in the kill
1299 immune mode. THD::awake() closes the active_vio.
1300 */
1301 if (kill_immunizer != nullptr)
1302 kill_immunizer->save_killed_state(THD::KILL_CONNECTION);
1303 else {
1304 killed = THD::KILL_CONNECTION;
1305
1306 /*
1307 Since a active vio might might have not been set yet, in
1308 any case save a reference to avoid closing a inexistent
1309 one or closing the vio twice if there is a active one.
1310 */
1311 vio = active_vio;
1312 shutdown_active_vio();
1313
1314 /* Disconnect even if a active vio is not associated. */
1315 if (is_classic_protocol() && get_protocol_classic()->get_vio() != vio &&
1316 get_protocol_classic()->connection_alive()) {
1317 m_protocol->shutdown(server_shutdown);
1318 }
1319 }
1320
1321 mysql_mutex_unlock(&LOCK_thd_data);
1322 }
1323
notify_shared_lock(MDL_context_owner * ctx_in_use,bool needs_thr_lock_abort)1324 void THD::notify_shared_lock(MDL_context_owner *ctx_in_use,
1325 bool needs_thr_lock_abort) {
1326 THD *in_use = ctx_in_use->get_thd();
1327
1328 if (needs_thr_lock_abort) {
1329 mysql_mutex_lock(&in_use->LOCK_thd_data);
1330 for (TABLE *thd_table = in_use->open_tables; thd_table;
1331 thd_table = thd_table->next) {
1332 /*
1333 Check for TABLE::needs_reopen() is needed since in some places we call
1334 handler::close() for table instance (and set TABLE::db_stat to 0)
1335 and do not remove such instances from the THD::open_tables
1336 for some time, during which other thread can see those instances
1337 (e.g. see partitioning code).
1338 */
1339 if (!thd_table->needs_reopen())
1340 mysql_lock_abort_for_thread(this, thd_table);
1341 }
1342 mysql_mutex_unlock(&in_use->LOCK_thd_data);
1343 }
1344 }
1345
1346 /*
1347 Remember the location of thread info, the structure needed for
1348 (*THR_MALLOC)->Alloc() and the structure for the net buffer
1349 */
1350
store_globals()1351 void THD::store_globals() {
1352 /*
1353 Assert that thread_stack is initialized: it's necessary to be able
1354 to track stack overrun.
1355 */
1356 DBUG_ASSERT(thread_stack);
1357
1358 current_thd = this;
1359 THR_MALLOC = &mem_root;
1360 /*
1361 is_killable is concurrently readable by a killer thread.
1362 It is protected by LOCK_thd_data, it is not needed to lock while the
1363 value is changing from false not true. If the kill thread reads
1364 true we need to ensure that the thread doesn't proceed to assign
1365 another thread to the same TLS reference.
1366 */
1367 is_killable = true;
1368 #ifndef DBUG_OFF
1369 /*
1370 Let mysqld define the thread id (not mysys)
1371 This allows us to move THD to different threads if needed.
1372 */
1373 set_my_thread_var_id(m_thread_id);
1374 #endif
1375 real_id = my_thread_self(); // For debugging
1376 }
1377
1378 /*
1379 Remove the thread specific info (THD and mem_root pointer) stored during
1380 store_global call for this thread.
1381 */
restore_globals()1382 void THD::restore_globals() {
1383 /*
1384 Assert that thread_stack is initialized: it's necessary to be able
1385 to track stack overrun.
1386 */
1387 DBUG_ASSERT(thread_stack);
1388
1389 /* Undocking the thread specific data. */
1390 current_thd = nullptr;
1391 THR_MALLOC = nullptr;
1392 }
1393
1394 /*
1395 Cleanup after query.
1396
1397 SYNOPSIS
1398 THD::cleanup_after_query()
1399
1400 DESCRIPTION
1401 This function is used to reset thread data to its default state.
1402
1403 NOTE
1404 This function is not suitable for setting thread data to some
1405 non-default values, as there is only one replication thread, so
1406 different master threads may overwrite data of each other on
1407 slave.
1408 */
1409
cleanup_after_query()1410 void THD::cleanup_after_query() {
1411 /*
1412 Reset rand_used so that detection of calls to rand() will save random
1413 seeds if needed by the slave.
1414
1415 Do not reset rand_used if inside a stored function or trigger because
1416 only the call to these operations is logged. Thus only the calling
1417 statement needs to detect rand() calls made by its substatements. These
1418 substatements must not set rand_used to 0 because it would remove the
1419 detection of rand() by the calling statement.
1420 */
1421 if (!in_sub_stmt) /* stored functions and triggers are a special case */
1422 {
1423 /* Forget those values, for next binlogger: */
1424 stmt_depends_on_first_successful_insert_id_in_prev_stmt = false;
1425 auto_inc_intervals_in_cur_stmt_for_binlog.empty();
1426 rand_used = false;
1427 binlog_accessed_db_names = nullptr;
1428
1429 /*
1430 Clean possible unused INSERT_ID events by current statement.
1431 is_update_query() is needed to ignore SET statements:
1432 Statements that don't update anything directly and don't
1433 used stored functions. This is mostly necessary to ignore
1434 statements in binlog between SET INSERT_ID and DML statement
1435 which is intended to consume its event (there can be other
1436 SET statements between them).
1437 */
1438 if ((rli_slave || rli_fake) && is_update_query(lex->sql_command))
1439 auto_inc_intervals_forced.empty();
1440 }
1441
1442 /*
1443 In case of stored procedures, stored functions, triggers and events
1444 m_trans_fixed_log_file will not be set to NULL. The memory will be reused.
1445 */
1446 if (!sp_runtime_ctx) m_trans_fixed_log_file = nullptr;
1447
1448 /*
1449 Forget the binlog stmt filter for the next query.
1450 There are some code paths that:
1451 - do not call THD::decide_logging_format()
1452 - do call THD::binlog_query(),
1453 making this reset necessary.
1454 */
1455 reset_binlog_local_stmt_filter();
1456 if (first_successful_insert_id_in_cur_stmt > 0) {
1457 /* set what LAST_INSERT_ID() will return */
1458 first_successful_insert_id_in_prev_stmt =
1459 first_successful_insert_id_in_cur_stmt;
1460 first_successful_insert_id_in_cur_stmt = 0;
1461 }
1462 arg_of_last_insert_id_function = false;
1463 /* Hack for cleaning up view security contexts */
1464 List_iterator<Security_context> it(m_view_ctx_list);
1465 while (Security_context *ctx = it++) {
1466 ctx->logout();
1467 }
1468 m_view_ctx_list.empty();
1469 /* Free Items that were created during this execution */
1470 free_items();
1471 /* Reset where. */
1472 where = THD::DEFAULT_WHERE;
1473 /* reset table map for multi-table update */
1474 table_map_for_update = 0;
1475 m_binlog_invoker = false;
1476 /* reset replication info structure */
1477 if (lex) {
1478 lex->mi.repl_ignore_server_ids.clear();
1479 }
1480 if (rli_slave) rli_slave->cleanup_after_query();
1481 // Set the default "cute" mode for the execution environment:
1482 check_for_truncated_fields = CHECK_FIELD_IGNORE;
1483 }
1484
1485 /*
1486 Convert a string to another character set
1487
1488 @param to Store new allocated string here
1489 @param to_cs New character set for allocated string
1490 @param from String to convert
1491 @param from_length Length of string to convert
1492 @param from_cs Original character set
1493 @param report_error Raise error (when true) or warning (when false) if
1494 there is problem when doing conversion
1495
1496 @note to will be 0-terminated to make it easy to pass to system funcs
1497
1498 @retval false ok
1499 @retval true End of memory.
1500 In this case to->str will point to 0 and to->length will be 0.
1501 */
1502
convert_string(LEX_STRING * to,const CHARSET_INFO * to_cs,const char * from,size_t from_length,const CHARSET_INFO * from_cs,bool report_error)1503 bool THD::convert_string(LEX_STRING *to, const CHARSET_INFO *to_cs,
1504 const char *from, size_t from_length,
1505 const CHARSET_INFO *from_cs, bool report_error) {
1506 DBUG_TRACE;
1507 size_t new_length = to_cs->mbmaxlen * from_length;
1508 if (!(to->str = (char *)alloc(new_length + 1))) {
1509 to->length = 0; // Safety fix
1510 return true; // EOM
1511 }
1512 uint errors = 0;
1513 to->length = copy_and_convert(to->str, new_length, to_cs, from, from_length,
1514 from_cs, &errors);
1515 to->str[to->length] = 0; // Safety
1516 if (errors != 0) {
1517 char printable_buff[32];
1518 convert_to_printable(printable_buff, sizeof(printable_buff), from,
1519 from_length, from_cs, 6);
1520 if (report_error) {
1521 my_error(ER_CANNOT_CONVERT_STRING, MYF(0), printable_buff,
1522 from_cs->csname, to_cs->csname);
1523 return true;
1524 } else {
1525 push_warning_printf(this, Sql_condition::SL_WARNING,
1526 ER_INVALID_CHARACTER_STRING,
1527 ER_THD(this, ER_CANNOT_CONVERT_STRING),
1528 printable_buff, from_cs->csname, to_cs->csname);
1529 }
1530 }
1531
1532 return false;
1533 }
1534
1535 /*
1536 Update some cache variables when character set changes
1537 */
1538
update_charset()1539 void THD::update_charset() {
1540 size_t not_used;
1541 charset_is_system_charset = !String::needs_conversion(
1542 0, variables.character_set_client, system_charset_info, ¬_used);
1543 charset_is_collation_connection =
1544 !String::needs_conversion(0, variables.character_set_client,
1545 variables.collation_connection, ¬_used);
1546 charset_is_character_set_filesystem =
1547 !String::needs_conversion(0, variables.character_set_client,
1548 variables.character_set_filesystem, ¬_used);
1549 }
1550
send_explain_fields(Query_result * result)1551 int THD::send_explain_fields(Query_result *result) {
1552 List<Item> field_list;
1553 Item *item;
1554 CHARSET_INFO *cs = system_charset_info;
1555 field_list.push_back(new Item_return_int("id", 3, MYSQL_TYPE_LONGLONG));
1556 field_list.push_back(new Item_empty_string("select_type", 19, cs));
1557 field_list.push_back(item =
1558 new Item_empty_string("table", NAME_CHAR_LEN, cs));
1559 item->maybe_null = true;
1560 /* Maximum length of string that make_used_partitions_str() can produce */
1561 item = new Item_empty_string("partitions", MAX_PARTITIONS * (1 + FN_LEN), cs);
1562 field_list.push_back(item);
1563 item->maybe_null = true;
1564 field_list.push_back(item = new Item_empty_string("type", 10, cs));
1565 item->maybe_null = true;
1566 field_list.push_back(item = new Item_empty_string(
1567 "possible_keys", NAME_CHAR_LEN * MAX_KEY, cs));
1568 item->maybe_null = true;
1569 field_list.push_back(item = new Item_empty_string("key", NAME_CHAR_LEN, cs));
1570 item->maybe_null = true;
1571 field_list.push_back(
1572 item = new Item_empty_string("key_len", NAME_CHAR_LEN * MAX_KEY));
1573 item->maybe_null = true;
1574 field_list.push_back(
1575 item = new Item_empty_string("ref", NAME_CHAR_LEN * MAX_REF_PARTS, cs));
1576 item->maybe_null = true;
1577 field_list.push_back(
1578 item = new Item_return_int("rows", 10, MYSQL_TYPE_LONGLONG));
1579 item->maybe_null = true;
1580 field_list.push_back(
1581 item = new Item_float(NAME_STRING("filtered"), 0.1234, 2, 4));
1582 item->maybe_null = true;
1583 field_list.push_back(new Item_empty_string("Extra", 255, cs));
1584 item->maybe_null = true;
1585 return (result->send_result_set_metadata(
1586 this, field_list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF));
1587 }
1588
get_vio_type() const1589 enum_vio_type THD::get_vio_type() const {
1590 DBUG_TRACE;
1591 return get_protocol()->connection_type();
1592 }
1593
shutdown_active_vio()1594 void THD::shutdown_active_vio() {
1595 DBUG_TRACE;
1596 mysql_mutex_assert_owner(&LOCK_thd_data);
1597 if (active_vio) {
1598 vio_shutdown(active_vio);
1599 active_vio = nullptr;
1600 m_SSL = nullptr;
1601 }
1602 }
1603
shutdown_clone_vio()1604 void THD::shutdown_clone_vio() {
1605 DBUG_TRACE;
1606 mysql_mutex_assert_owner(&LOCK_thd_data);
1607 if (clone_vio != nullptr) {
1608 vio_shutdown(clone_vio);
1609 clone_vio = nullptr;
1610 }
1611 }
1612
1613 /*
1614 Register an item tree tree transformation, performed by the query
1615 optimizer.
1616 */
1617
nocheck_register_item_tree_change(Item ** place,Item * new_value)1618 void THD::nocheck_register_item_tree_change(Item **place, Item *new_value) {
1619 Item_change_record *change;
1620 /*
1621 Now we use one node per change, which adds some memory overhead,
1622 but still is rather fast as we use alloc_root for allocations.
1623 A list of item tree changes of an average query should be short.
1624 */
1625 void *change_mem = mem_root->Alloc(sizeof(*change));
1626 if (change_mem == nullptr) {
1627 /*
1628 OOM, thd->fatal_error() is called by the error handler of the
1629 memroot. Just return.
1630 */
1631 return;
1632 }
1633 change = new (change_mem) Item_change_record(place, new_value);
1634 change_list.push_front(change);
1635 }
1636
replace_rollback_place(Item ** new_place)1637 Item *THD::replace_rollback_place(Item **new_place) {
1638 I_List_iterator<Item_change_record> it(change_list);
1639 Item_change_record *change;
1640 while ((change = it++)) {
1641 if (change->new_value == *new_place) {
1642 DBUG_PRINT("info", ("replace_rollback_place new_value %p place %p",
1643 *new_place, new_place));
1644 change->place = new_place;
1645 return change->old_value;
1646 }
1647 }
1648 return nullptr;
1649 }
1650
alias_rollback(Item ** place)1651 void THD::alias_rollback(Item **place) {
1652 if (stmt_arena->is_regular()) return;
1653
1654 Item *new_value = *place;
1655 Item *old_value = nullptr;
1656 I_List_iterator<Item_change_record> it(change_list);
1657 Item_change_record *change;
1658 while ((change = it++)) {
1659 if (change->new_value == new_value) {
1660 old_value = change->old_value;
1661 break;
1662 }
1663 }
1664 DBUG_ASSERT(old_value != nullptr);
1665 *place = old_value;
1666 nocheck_register_item_tree_change(place, new_value);
1667 *place = new_value;
1668 }
1669
1670 /**
1671 After a permant transformation by SELECT_LEX::transform_grouped_to_derived,
1672 a block's from list is moved to a new derived table.
1673 We may have fields that originally resolved to tables in orig_block
1674 but that now belong to tables in new_block.
1675 Such field may be rolled back and thus need their name resolution contexts
1676 updated, so they will resolve correctly on EXECUTE a being rolled back at the
1677 end of a PREPARE. Can be removed after WL#6570.
1678
1679 @param orig_block The query block to which these fields originally belonged
1680 @param new_block The query block they now belong to and whose name
1681 resolution context they need.
1682 */
update_ident_context(SELECT_LEX * orig_block,SELECT_LEX * new_block)1683 void THD::update_ident_context(SELECT_LEX *orig_block, SELECT_LEX *new_block) {
1684 I_List_iterator<Item_change_record> it(change_list);
1685 Item_change_record *change;
1686 while ((change = it++)) {
1687 Item *old_item = change->old_value;
1688 if (old_item->type() == Item::FIELD_ITEM) {
1689 Item_field *orig_field = down_cast<Item_field *>(old_item);
1690 if (orig_field->context->select_lex == orig_block)
1691 orig_field->context = &new_block->context;
1692 }
1693 }
1694 }
1695
cancel_rollback(Item * i)1696 void THD::cancel_rollback(Item *i) {
1697 I_List_iterator<Item_change_record> it(change_list);
1698 Item_change_record *change;
1699 while ((change = it++)) {
1700 if (change->new_value == i) {
1701 change->m_cancel = true;
1702 // Find any other change records for this location also
1703 cancel_rollback_at(change->place);
1704 }
1705 }
1706 }
1707
cancel_rollback_at(Item ** place)1708 void THD::cancel_rollback_at(Item **place) {
1709 I_List_iterator<Item_change_record> it(change_list);
1710 Item_change_record *change;
1711 while ((change = it++)) {
1712 if (change->place == place) {
1713 change->m_cancel = true;
1714 }
1715 }
1716 }
rollback_item_tree_changes()1717 void THD::rollback_item_tree_changes() {
1718 I_List_iterator<Item_change_record> it(change_list);
1719 Item_change_record *change;
1720 DBUG_TRACE;
1721
1722 while ((change = it++)) {
1723 if (change->m_cancel) continue;
1724
1725 DBUG_PRINT("info", ("rollback_item_tree_changes "
1726 "place %p curr_value %p old_value %p",
1727 change->place, *change->place, change->old_value));
1728 *change->place = change->old_value;
1729 }
1730 /* We can forget about changes memory: it's allocated in runtime memroot */
1731 change_list.empty();
1732 }
1733
add_item(Item * item)1734 void Query_arena::add_item(Item *item) {
1735 item->next_free = m_item_list;
1736 m_item_list = item;
1737 }
1738
free_items()1739 void Query_arena::free_items() {
1740 Item *next;
1741 DBUG_TRACE;
1742 /* This works because items are allocated with (*THR_MALLOC)->Alloc() */
1743 for (; m_item_list; m_item_list = next) {
1744 next = m_item_list->next_free;
1745 m_item_list->delete_self();
1746 }
1747 /* Postcondition: free_list is 0 */
1748 }
1749
set_query_arena(const Query_arena & set)1750 void Query_arena::set_query_arena(const Query_arena &set) {
1751 mem_root = set.mem_root;
1752 set_item_list(set.item_list());
1753 state = set.state;
1754 }
1755
swap_query_arena(const Query_arena & source,Query_arena * backup)1756 void Query_arena::swap_query_arena(const Query_arena &source,
1757 Query_arena *backup) {
1758 backup->set_query_arena(*this);
1759 set_query_arena(source);
1760 }
1761
end_statement()1762 void THD::end_statement() {
1763 DBUG_TRACE;
1764 /* Cleanup SQL processing state to reuse this statement in next query. */
1765 lex_end(lex);
1766 //@todo Check lifetime of Query_result objects.
1767 // delete lex->result;
1768 lex->result = nullptr; // Prepare for next statement
1769 /* Note that item list is freed in cleanup_after_query() */
1770
1771 /*
1772 Don't free mem_root, as mem_root is freed in the end of dispatch_command
1773 (once for any command).
1774 */
1775 }
1776
Prepared_statement_map()1777 Prepared_statement_map::Prepared_statement_map()
1778 : st_hash(key_memory_prepared_statement_map),
1779 names_hash(system_charset_info, key_memory_prepared_statement_map),
1780 m_last_found_statement(nullptr) {}
1781
insert(Prepared_statement * statement)1782 int Prepared_statement_map::insert(Prepared_statement *statement) {
1783 st_hash.emplace(statement->id, unique_ptr<Prepared_statement>(statement));
1784 if (statement->name().str) {
1785 names_hash.emplace(to_string(statement->name()), statement);
1786 }
1787 mysql_mutex_lock(&LOCK_prepared_stmt_count);
1788 /*
1789 We don't check that prepared_stmt_count is <= max_prepared_stmt_count
1790 because we would like to allow to lower the total limit
1791 of prepared statements below the current count. In that case
1792 no new statements can be added until prepared_stmt_count drops below
1793 the limit.
1794 */
1795 if (prepared_stmt_count >= max_prepared_stmt_count) {
1796 mysql_mutex_unlock(&LOCK_prepared_stmt_count);
1797 my_error(ER_MAX_PREPARED_STMT_COUNT_REACHED, MYF(0),
1798 max_prepared_stmt_count);
1799 goto err_max;
1800 }
1801 prepared_stmt_count++;
1802 mysql_mutex_unlock(&LOCK_prepared_stmt_count);
1803
1804 m_last_found_statement = statement;
1805 return 0;
1806
1807 err_max:
1808 if (statement->name().str) names_hash.erase(to_string(statement->name()));
1809 st_hash.erase(statement->id);
1810 return 1;
1811 }
1812
find_by_name(const LEX_CSTRING & name)1813 Prepared_statement *Prepared_statement_map::find_by_name(
1814 const LEX_CSTRING &name) {
1815 return find_or_nullptr(names_hash, to_string(name));
1816 }
1817
find(ulong id)1818 Prepared_statement *Prepared_statement_map::find(ulong id) {
1819 if (m_last_found_statement == nullptr || id != m_last_found_statement->id) {
1820 Prepared_statement *stmt = find_or_nullptr(st_hash, id);
1821 if (stmt && stmt->name().str) return nullptr;
1822 m_last_found_statement = stmt;
1823 }
1824 return m_last_found_statement;
1825 }
1826
erase(Prepared_statement * statement)1827 void Prepared_statement_map::erase(Prepared_statement *statement) {
1828 if (statement == m_last_found_statement) m_last_found_statement = nullptr;
1829 if (statement->name().str) names_hash.erase(to_string(statement->name()));
1830
1831 st_hash.erase(statement->id);
1832 mysql_mutex_lock(&LOCK_prepared_stmt_count);
1833 DBUG_ASSERT(prepared_stmt_count > 0);
1834 prepared_stmt_count--;
1835 mysql_mutex_unlock(&LOCK_prepared_stmt_count);
1836 }
1837
claim_memory_ownership()1838 void Prepared_statement_map::claim_memory_ownership() {
1839 for (const auto &key_and_value : st_hash) {
1840 my_claim(key_and_value.second.get());
1841 }
1842 }
1843
reset()1844 void Prepared_statement_map::reset() {
1845 if (!st_hash.empty()) {
1846 #ifdef HAVE_PSI_PS_INTERFACE
1847 for (auto &key_and_value : st_hash) {
1848 Prepared_statement *stmt = key_and_value.second.get();
1849 MYSQL_DESTROY_PS(stmt->get_PS_prepared_stmt());
1850 }
1851 #endif
1852 mysql_mutex_lock(&LOCK_prepared_stmt_count);
1853 DBUG_ASSERT(prepared_stmt_count >= st_hash.size());
1854 prepared_stmt_count -= st_hash.size();
1855 mysql_mutex_unlock(&LOCK_prepared_stmt_count);
1856 }
1857 names_hash.clear();
1858 st_hash.clear();
1859 m_last_found_statement = nullptr;
1860 }
1861
~Prepared_statement_map()1862 Prepared_statement_map::~Prepared_statement_map() {
1863 /*
1864 We do not want to grab the global LOCK_prepared_stmt_count mutex here.
1865 reset() should already have been called to maintain prepared_stmt_count.
1866 */
1867 DBUG_ASSERT(st_hash.empty());
1868 }
1869
send_kill_message() const1870 void THD::send_kill_message() const {
1871 int err = killed;
1872 if (err && !get_stmt_da()->is_set()) {
1873 if ((err == KILL_CONNECTION) && !connection_events_loop_aborted())
1874 err = KILL_QUERY;
1875 /*
1876 KILL is fatal because:
1877 - if a condition handler was allowed to trap and ignore a KILL, one
1878 could create routines which the DBA could not kill
1879 - INSERT/UPDATE IGNORE should fail: if KILL arrives during
1880 JOIN::optimize(), statement cannot possibly run as its caller expected
1881 => "OK" would be misleading the caller.
1882
1883 EXPLAIN ANALYZE still succeeds (but with a warning in the output),
1884 assuming it's come as far as the execution stage, so that the user
1885 can look at the execution plan and statistics so far.
1886 */
1887 if (!running_explain_analyze) {
1888 my_error(err, MYF(ME_FATALERROR));
1889 }
1890 }
1891 }
1892
1893 /****************************************************************************
1894 Handling of open and locked tables states.
1895
1896 This is used when we want to open/lock (and then close) some tables when
1897 we already have a set of tables open and locked. We use these methods for
1898 access to mysql.proc table to find definitions of stored routines.
1899 ****************************************************************************/
1900
reset_n_backup_open_tables_state(Open_tables_backup * backup,uint add_state_flags)1901 void THD::reset_n_backup_open_tables_state(Open_tables_backup *backup,
1902 uint add_state_flags) {
1903 DBUG_TRACE;
1904 backup->set_open_tables_state(this);
1905 backup->mdl_system_tables_svp = mdl_context.mdl_savepoint();
1906 reset_open_tables_state();
1907 state_flags |= (Open_tables_state::BACKUPS_AVAIL | add_state_flags);
1908 }
1909
restore_backup_open_tables_state(Open_tables_backup * backup)1910 void THD::restore_backup_open_tables_state(Open_tables_backup *backup) {
1911 DBUG_TRACE;
1912 mdl_context.rollback_to_savepoint(backup->mdl_system_tables_svp);
1913 /*
1914 Before we will throw away current open tables state we want
1915 to be sure that it was properly cleaned up.
1916 */
1917 DBUG_ASSERT(open_tables == nullptr && temporary_tables == nullptr &&
1918 lock == nullptr && locked_tables_mode == LTM_NONE &&
1919 get_reprepare_observer() == nullptr);
1920
1921 set_open_tables_state(backup);
1922 }
1923
begin_attachable_ro_transaction()1924 void THD::begin_attachable_ro_transaction() {
1925 m_attachable_trx = new Attachable_trx(this, m_attachable_trx);
1926 }
1927
end_attachable_transaction()1928 void THD::end_attachable_transaction() {
1929 Attachable_trx *prev_trx = m_attachable_trx->get_prev_attachable_trx();
1930 delete m_attachable_trx;
1931 // Restore attachable transaction which was active before we started
1932 // the one which just has ended. NULL in most cases.
1933 m_attachable_trx = prev_trx;
1934 }
1935
begin_attachable_rw_transaction()1936 void THD::begin_attachable_rw_transaction() {
1937 DBUG_ASSERT(!m_attachable_trx);
1938
1939 m_attachable_trx = new Attachable_trx_rw(this);
1940 }
1941
1942 /****************************************************************************
1943 Handling of statement states in functions and triggers.
1944
1945 This is used to ensure that the function/trigger gets a clean state
1946 to work with and does not cause any side effects of the calling statement.
1947
1948 It also allows most stored functions and triggers to replicate even
1949 if they are used items that would normally be stored in the binary
1950 replication (like last_insert_id() etc...)
1951
1952 The following things is done
1953 - Disable binary logging for the duration of the statement
1954 - Disable multi-result-sets for the duration of the statement
1955 - Value of last_insert_id() is saved and restored
1956 - Value set by 'SET INSERT_ID=#' is reset and restored
1957 - Value for found_rows() is reset and restored
1958 - examined_row_count is added to the total
1959 - num_truncated_fields is added to the total
1960 - new savepoint level is created and destroyed
1961
1962 NOTES:
1963 Seed for random() is saved for the first! usage of RAND()
1964 We reset examined_row_count and num_truncated_fields and add these to the
1965 result to ensure that if we have a bug that would reset these within
1966 a function, we are not loosing any rows from the main statement.
1967
1968 We do not reset value of last_insert_id().
1969 ****************************************************************************/
1970
reset_sub_statement_state(Sub_statement_state * backup,uint new_state)1971 void THD::reset_sub_statement_state(Sub_statement_state *backup,
1972 uint new_state) {
1973 /* BUG#33029, if we are replicating from a buggy master, reset
1974 auto_inc_intervals_forced to prevent substatement
1975 (triggers/functions) from using erroneous INSERT_ID value
1976 */
1977 if (rpl_master_erroneous_autoinc(this)) {
1978 DBUG_ASSERT(backup->auto_inc_intervals_forced.nb_elements() == 0);
1979 auto_inc_intervals_forced.swap(&backup->auto_inc_intervals_forced);
1980 }
1981
1982 backup->option_bits = variables.option_bits;
1983 backup->check_for_truncated_fields = check_for_truncated_fields;
1984 backup->in_sub_stmt = in_sub_stmt;
1985 backup->enable_slow_log = enable_slow_log;
1986 backup->current_found_rows = current_found_rows;
1987 backup->previous_found_rows = previous_found_rows;
1988 backup->examined_row_count = m_examined_row_count;
1989 backup->sent_row_count = m_sent_row_count;
1990 backup->num_truncated_fields = num_truncated_fields;
1991 backup->client_capabilities = m_protocol->get_client_capabilities();
1992 backup->savepoints = get_transaction()->m_savepoints;
1993 backup->first_successful_insert_id_in_prev_stmt =
1994 first_successful_insert_id_in_prev_stmt;
1995 backup->first_successful_insert_id_in_cur_stmt =
1996 first_successful_insert_id_in_cur_stmt;
1997
1998 if ((!lex->requires_prelocking() || is_update_query(lex->sql_command)) &&
1999 !is_current_stmt_binlog_format_row()) {
2000 variables.option_bits &= ~OPTION_BIN_LOG;
2001 }
2002
2003 if ((backup->option_bits & OPTION_BIN_LOG) &&
2004 is_update_query(lex->sql_command) && !is_current_stmt_binlog_format_row())
2005 mysql_bin_log.start_union_events(this, this->query_id);
2006
2007 /* Disable result sets */
2008 if (is_classic_protocol())
2009 get_protocol_classic()->remove_client_capability(CLIENT_MULTI_RESULTS);
2010 in_sub_stmt |= new_state;
2011 m_examined_row_count = 0;
2012 m_sent_row_count = 0;
2013 num_truncated_fields = 0;
2014 get_transaction()->m_savepoints = nullptr;
2015 first_successful_insert_id_in_cur_stmt = 0;
2016
2017 /* Reset savepoint on transaction write set */
2018 if (is_current_stmt_binlog_row_enabled_with_write_set_extraction()) {
2019 get_transaction()->get_transaction_write_set_ctx()->reset_savepoint_list();
2020 }
2021 }
2022
restore_sub_statement_state(Sub_statement_state * backup)2023 void THD::restore_sub_statement_state(Sub_statement_state *backup) {
2024 DBUG_TRACE;
2025 /* BUG#33029, if we are replicating from a buggy master, restore
2026 auto_inc_intervals_forced so that the top statement can use the
2027 INSERT_ID value set before this statement.
2028 */
2029 if (rpl_master_erroneous_autoinc(this)) {
2030 backup->auto_inc_intervals_forced.swap(&auto_inc_intervals_forced);
2031 DBUG_ASSERT(backup->auto_inc_intervals_forced.nb_elements() == 0);
2032 }
2033
2034 /*
2035 To save resources we want to release savepoints which were created
2036 during execution of function or trigger before leaving their savepoint
2037 level. It is enough to release first savepoint set on this level since
2038 all later savepoints will be released automatically.
2039 */
2040 if (get_transaction()->m_savepoints) {
2041 SAVEPOINT *sv;
2042 for (sv = get_transaction()->m_savepoints; sv->prev; sv = sv->prev) {
2043 }
2044 /* ha_release_savepoint() never returns error. */
2045 (void)ha_release_savepoint(this, sv);
2046 }
2047 check_for_truncated_fields = backup->check_for_truncated_fields;
2048 get_transaction()->m_savepoints = backup->savepoints;
2049 variables.option_bits = backup->option_bits;
2050 in_sub_stmt = backup->in_sub_stmt;
2051 enable_slow_log = backup->enable_slow_log;
2052 first_successful_insert_id_in_prev_stmt =
2053 backup->first_successful_insert_id_in_prev_stmt;
2054 first_successful_insert_id_in_cur_stmt =
2055 backup->first_successful_insert_id_in_cur_stmt;
2056 current_found_rows = backup->current_found_rows;
2057 previous_found_rows = backup->previous_found_rows;
2058 set_sent_row_count(backup->sent_row_count);
2059 if (is_classic_protocol())
2060 get_protocol_classic()->set_client_capabilities(
2061 backup->client_capabilities);
2062
2063 /*
2064 If we've left sub-statement mode, reset the fatal error flag.
2065 Otherwise keep the current value, to propagate it up the sub-statement
2066 stack.
2067
2068 NOTE: is_fatal_sub_stmt_error can be set only if we've been in the
2069 sub-statement mode.
2070 */
2071
2072 if (!in_sub_stmt) is_fatal_sub_stmt_error = false;
2073
2074 if ((variables.option_bits & OPTION_BIN_LOG) &&
2075 is_update_query(lex->sql_command) && !is_current_stmt_binlog_format_row())
2076 mysql_bin_log.stop_union_events(this);
2077
2078 /*
2079 The below assert mostly serves as reminder that optimization in
2080 DML_prelocking_strategy::handle_table() relies on the fact
2081 that stored function/trigger can't change FOREIGN_KEY_CHECKS
2082 value for the top-level statement which invokes them.
2083 */
2084 DBUG_ASSERT((variables.option_bits & OPTION_NO_FOREIGN_KEY_CHECKS) ==
2085 (backup->option_bits & OPTION_NO_FOREIGN_KEY_CHECKS));
2086
2087 /*
2088 The following is added to the old values as we are interested in the
2089 total complexity of the query
2090 */
2091 inc_examined_row_count(backup->examined_row_count);
2092 num_truncated_fields += backup->num_truncated_fields;
2093
2094 /* Restore savepoint on transaction write set */
2095 if (is_current_stmt_binlog_row_enabled_with_write_set_extraction()) {
2096 get_transaction()
2097 ->get_transaction_write_set_ctx()
2098 ->restore_savepoint_list();
2099 }
2100 }
2101
set_sent_row_count(ha_rows count)2102 void THD::set_sent_row_count(ha_rows count) {
2103 m_sent_row_count = count;
2104 MYSQL_SET_STATEMENT_ROWS_SENT(m_statement_psi, m_sent_row_count);
2105 }
2106
inc_sent_row_count(ha_rows count)2107 void THD::inc_sent_row_count(ha_rows count) {
2108 m_sent_row_count += count;
2109 MYSQL_SET_STATEMENT_ROWS_SENT(m_statement_psi, m_sent_row_count);
2110 }
2111
inc_examined_row_count(ha_rows count)2112 void THD::inc_examined_row_count(ha_rows count) {
2113 m_examined_row_count += count;
2114 MYSQL_SET_STATEMENT_ROWS_EXAMINED(m_statement_psi, m_examined_row_count);
2115 }
2116
inc_status_created_tmp_disk_tables()2117 void THD::inc_status_created_tmp_disk_tables() {
2118 DBUG_ASSERT(!status_var_aggregated);
2119 status_var.created_tmp_disk_tables++;
2120 #ifdef HAVE_PSI_STATEMENT_INTERFACE
2121 PSI_STATEMENT_CALL(inc_statement_created_tmp_disk_tables)(m_statement_psi, 1);
2122 #endif
2123 }
2124
inc_status_created_tmp_tables()2125 void THD::inc_status_created_tmp_tables() {
2126 DBUG_ASSERT(!status_var_aggregated);
2127 status_var.created_tmp_tables++;
2128 #ifdef HAVE_PSI_STATEMENT_INTERFACE
2129 PSI_STATEMENT_CALL(inc_statement_created_tmp_tables)(m_statement_psi, 1);
2130 #endif
2131 }
2132
inc_status_select_full_join()2133 void THD::inc_status_select_full_join() {
2134 DBUG_ASSERT(!status_var_aggregated);
2135 status_var.select_full_join_count++;
2136 #ifdef HAVE_PSI_STATEMENT_INTERFACE
2137 PSI_STATEMENT_CALL(inc_statement_select_full_join)(m_statement_psi, 1);
2138 #endif
2139 }
2140
inc_status_select_full_range_join()2141 void THD::inc_status_select_full_range_join() {
2142 DBUG_ASSERT(!status_var_aggregated);
2143 status_var.select_full_range_join_count++;
2144 #ifdef HAVE_PSI_STATEMENT_INTERFACE
2145 PSI_STATEMENT_CALL(inc_statement_select_full_range_join)(m_statement_psi, 1);
2146 #endif
2147 }
2148
inc_status_select_range()2149 void THD::inc_status_select_range() {
2150 DBUG_ASSERT(!status_var_aggregated);
2151 status_var.select_range_count++;
2152 #ifdef HAVE_PSI_STATEMENT_INTERFACE
2153 PSI_STATEMENT_CALL(inc_statement_select_range)(m_statement_psi, 1);
2154 #endif
2155 }
2156
inc_status_select_range_check()2157 void THD::inc_status_select_range_check() {
2158 DBUG_ASSERT(!status_var_aggregated);
2159 status_var.select_range_check_count++;
2160 #ifdef HAVE_PSI_STATEMENT_INTERFACE
2161 PSI_STATEMENT_CALL(inc_statement_select_range_check)(m_statement_psi, 1);
2162 #endif
2163 }
2164
inc_status_select_scan()2165 void THD::inc_status_select_scan() {
2166 DBUG_ASSERT(!status_var_aggregated);
2167 status_var.select_scan_count++;
2168 #ifdef HAVE_PSI_STATEMENT_INTERFACE
2169 PSI_STATEMENT_CALL(inc_statement_select_scan)(m_statement_psi, 1);
2170 #endif
2171 }
2172
inc_status_sort_merge_passes()2173 void THD::inc_status_sort_merge_passes() {
2174 DBUG_ASSERT(!status_var_aggregated);
2175 status_var.filesort_merge_passes++;
2176 #ifdef HAVE_PSI_STATEMENT_INTERFACE
2177 PSI_STATEMENT_CALL(inc_statement_sort_merge_passes)(m_statement_psi, 1);
2178 #endif
2179 }
2180
inc_status_sort_range()2181 void THD::inc_status_sort_range() {
2182 DBUG_ASSERT(!status_var_aggregated);
2183 status_var.filesort_range_count++;
2184 #ifdef HAVE_PSI_STATEMENT_INTERFACE
2185 PSI_STATEMENT_CALL(inc_statement_sort_range)(m_statement_psi, 1);
2186 #endif
2187 }
2188
inc_status_sort_rows(ha_rows count)2189 void THD::inc_status_sort_rows(ha_rows count) {
2190 DBUG_ASSERT(!status_var_aggregated);
2191 status_var.filesort_rows += count;
2192 #ifdef HAVE_PSI_STATEMENT_INTERFACE
2193 PSI_STATEMENT_CALL(inc_statement_sort_rows)
2194 (m_statement_psi, static_cast<ulong>(count));
2195 #endif
2196 }
2197
inc_status_sort_scan()2198 void THD::inc_status_sort_scan() {
2199 DBUG_ASSERT(!status_var_aggregated);
2200 status_var.filesort_scan_count++;
2201 #ifdef HAVE_PSI_STATEMENT_INTERFACE
2202 PSI_STATEMENT_CALL(inc_statement_sort_scan)(m_statement_psi, 1);
2203 #endif
2204 }
2205
set_status_no_index_used()2206 void THD::set_status_no_index_used() {
2207 server_status |= SERVER_QUERY_NO_INDEX_USED;
2208 #ifdef HAVE_PSI_STATEMENT_INTERFACE
2209 PSI_STATEMENT_CALL(set_statement_no_index_used)(m_statement_psi);
2210 #endif
2211 }
2212
set_status_no_good_index_used()2213 void THD::set_status_no_good_index_used() {
2214 server_status |= SERVER_QUERY_NO_GOOD_INDEX_USED;
2215 #ifdef HAVE_PSI_STATEMENT_INTERFACE
2216 PSI_STATEMENT_CALL(set_statement_no_good_index_used)(m_statement_psi);
2217 #endif
2218 }
2219
set_command(enum enum_server_command command)2220 void THD::set_command(enum enum_server_command command) {
2221 m_command = command;
2222 #ifdef HAVE_PSI_THREAD_INTERFACE
2223 PSI_THREAD_CALL(set_thread_command)(m_command);
2224 #endif
2225 }
2226
debug_assert_query_locked() const2227 void THD::debug_assert_query_locked() const {
2228 if (current_thd != this) mysql_mutex_assert_owner(&LOCK_thd_query);
2229 }
2230
set_query(LEX_CSTRING query_arg)2231 void THD::set_query(LEX_CSTRING query_arg) {
2232 DBUG_ASSERT(this == current_thd);
2233 mysql_mutex_lock(&LOCK_thd_query);
2234 m_query_string = query_arg;
2235 mysql_mutex_unlock(&LOCK_thd_query);
2236 }
2237
2238 /**
2239 Leave explicit LOCK TABLES or prelocked mode and restore value of
2240 transaction sentinel in MDL subsystem.
2241 */
2242
leave_locked_tables_mode()2243 void THD::leave_locked_tables_mode() {
2244 if (locked_tables_mode == LTM_LOCK_TABLES) {
2245 /*
2246 When leaving LOCK TABLES mode we have to change the duration of most
2247 of the metadata locks being held, except for HANDLER and GRL locks,
2248 to transactional for them to be properly released at UNLOCK TABLES.
2249 */
2250 mdl_context.set_transaction_duration_for_all_locks();
2251 /*
2252 Make sure we don't release the global read lock and commit blocker
2253 when leaving LTM.
2254 */
2255 global_read_lock.set_explicit_lock_duration(this);
2256 /*
2257 Also ensure that we don't release metadata locks for open HANDLERs
2258 and user-level locks.
2259 */
2260 if (!handler_tables_hash.empty()) mysql_ha_set_explicit_lock_duration(this);
2261 if (!ull_hash.empty()) mysql_ull_set_explicit_lock_duration(this);
2262 }
2263 locked_tables_mode = LTM_NONE;
2264 }
2265
get_definer(LEX_USER * definer)2266 void THD::get_definer(LEX_USER *definer) {
2267 binlog_invoker();
2268 if (slave_thread && has_invoker()) {
2269 definer->user = m_invoker_user;
2270 definer->host = m_invoker_host;
2271 definer->plugin.str = "";
2272 definer->plugin.length = 0;
2273 definer->auth.str = nullptr;
2274 definer->auth.length = 0;
2275 } else
2276 get_default_definer(this, definer);
2277 }
2278
2279 /**
2280 Mark transaction to rollback and mark error as fatal to a sub-statement.
2281
2282 @param all true <=> rollback main transaction.
2283 */
2284
mark_transaction_to_rollback(bool all)2285 void THD::mark_transaction_to_rollback(bool all) {
2286 /*
2287 There is no point in setting is_fatal_sub_stmt_error unless
2288 we are actually in_sub_stmt.
2289 */
2290 if (in_sub_stmt) is_fatal_sub_stmt_error = true;
2291
2292 transaction_rollback_request = all;
2293 }
2294
set_next_event_pos(const char * _filename,ulonglong _pos)2295 void THD::set_next_event_pos(const char *_filename, ulonglong _pos) {
2296 char *&filename = binlog_next_event_pos.file_name;
2297 if (filename == nullptr) {
2298 /* First time, allocate maximal buffer */
2299 filename =
2300 (char *)my_malloc(key_memory_LOG_POS_COORD, FN_REFLEN + 1, MYF(MY_WME));
2301 if (filename == nullptr) return;
2302 }
2303
2304 assert(strlen(_filename) <= FN_REFLEN);
2305 strcpy(filename, _filename);
2306 filename[FN_REFLEN] = 0;
2307
2308 binlog_next_event_pos.pos = _pos;
2309 }
2310
clear_next_event_pos()2311 void THD::clear_next_event_pos() {
2312 if (binlog_next_event_pos.file_name != nullptr) {
2313 my_free(binlog_next_event_pos.file_name);
2314 }
2315 binlog_next_event_pos.file_name = nullptr;
2316 binlog_next_event_pos.pos = 0;
2317 }
2318
set_original_commit_timestamp_for_slave_thread()2319 void THD::set_original_commit_timestamp_for_slave_thread() {
2320 /*
2321 This function may be called in four cases:
2322
2323 - From SQL thread while executing Gtid_log_event::do_apply_event
2324
2325 - From an mts worker thread that executes a Gtid_log_event::do_apply_event.
2326
2327 - From an mts worker thread that is processing an old binlog that
2328 is missing Gtid events completely, from gtid_pre_statement_checks().
2329
2330 - From a normal client thread that is executing output from
2331 mysqlbinlog when mysqlbinlog is processing an old binlog file
2332 that is missing Gtid events completely, from
2333 gtid_pre_statement_checks() for a statement that appears after a
2334 BINLOG statement containing a Format_description_log_event
2335 originating from the master.
2336
2337 Because of the last case, we need to add the following conditions to set
2338 original_commit_timestamp.
2339 */
2340 if (system_thread == SYSTEM_THREAD_SLAVE_SQL ||
2341 system_thread == SYSTEM_THREAD_SLAVE_WORKER) {
2342 rli_slave->original_commit_timestamp = variables.original_commit_timestamp;
2343 }
2344 }
2345
set_user_connect(USER_CONN * uc)2346 void THD::set_user_connect(USER_CONN *uc) {
2347 DBUG_TRACE;
2348
2349 m_user_connect = uc;
2350 }
2351
increment_user_connections_counter()2352 void THD::increment_user_connections_counter() {
2353 DBUG_TRACE;
2354
2355 m_user_connect->connections++;
2356 }
2357
decrement_user_connections_counter()2358 void THD::decrement_user_connections_counter() {
2359 DBUG_TRACE;
2360
2361 DBUG_ASSERT(m_user_connect->connections > 0);
2362 m_user_connect->connections--;
2363 }
2364
increment_con_per_hour_counter()2365 void THD::increment_con_per_hour_counter() {
2366 DBUG_TRACE;
2367
2368 m_user_connect->conn_per_hour++;
2369 }
2370
increment_updates_counter()2371 void THD::increment_updates_counter() {
2372 DBUG_TRACE;
2373
2374 m_user_connect->updates++;
2375 }
2376
increment_questions_counter()2377 void THD::increment_questions_counter() {
2378 DBUG_TRACE;
2379
2380 m_user_connect->questions++;
2381 }
2382
2383 /*
2384 Reset per-hour user resource limits when it has been more than
2385 an hour since they were last checked
2386
2387 SYNOPSIS:
2388 time_out_user_resource_limits()
2389
2390 NOTE:
2391 This assumes that the LOCK_user_conn mutex has been acquired, so it is
2392 safe to test and modify members of the USER_CONN structure.
2393 */
time_out_user_resource_limits()2394 void THD::time_out_user_resource_limits() {
2395 mysql_mutex_assert_owner(&LOCK_user_conn);
2396 ulonglong check_time = start_utime;
2397 DBUG_TRACE;
2398
2399 /* If more than a hour since last check, reset resource checking */
2400 if (check_time - m_user_connect->reset_utime >= 3600000000LL) {
2401 m_user_connect->questions = 1;
2402 m_user_connect->updates = 0;
2403 m_user_connect->conn_per_hour = 0;
2404 m_user_connect->reset_utime = check_time;
2405 }
2406 }
2407
2408 #ifndef DBUG_OFF
assert_plan_is_locked_if_other() const2409 void THD::Query_plan::assert_plan_is_locked_if_other() const {
2410 if (current_thd != thd) mysql_mutex_assert_owner(&thd->LOCK_query_plan);
2411 }
2412 #endif
2413
set_query_plan(enum_sql_command sql_cmd,LEX * lex_arg,bool ps)2414 void THD::Query_plan::set_query_plan(enum_sql_command sql_cmd, LEX *lex_arg,
2415 bool ps) {
2416 DBUG_ASSERT(current_thd == thd);
2417
2418 // No need to grab mutex for repeated (SQLCOM_END, NULL, false).
2419 if (sql_command == sql_cmd && lex == lex_arg && is_ps == ps) {
2420 return;
2421 }
2422
2423 thd->lock_query_plan();
2424 sql_command = sql_cmd;
2425 lex = lex_arg;
2426 is_ps = ps;
2427 thd->unlock_query_plan();
2428 }
2429
set_modification_plan(Modification_plan * plan_arg)2430 void THD::Query_plan::set_modification_plan(Modification_plan *plan_arg) {
2431 DBUG_ASSERT(current_thd == thd);
2432 mysql_mutex_assert_owner(&thd->LOCK_query_plan);
2433 modification_plan = plan_arg;
2434 }
2435
2436 /**
2437 Push an error message into MySQL diagnostic area with line number and position
2438
2439 This function provides semantic action implementers with a way
2440 to push the famous "You have a syntax error near..." error
2441 message into the diagnostic area, which is normally produced only if
2442 a syntax error is discovered according to the Bison grammar.
2443 Unlike the syntax_error_at() function, the error position points to the last
2444 parsed token.
2445
2446 @note Parse-time only function!
2447
2448 @param format Error format message. NULL means ER(ER_SYNTAX_ERROR).
2449 */
syntax_error(const char * format,...)2450 void THD::syntax_error(const char *format, ...) {
2451 va_list args;
2452 va_start(args, format);
2453 vsyntax_error_at(m_parser_state->m_lip.get_tok_start(), format, args);
2454 va_end(args);
2455 }
2456
2457 /**
2458 Push an error message into MySQL diagnostic area with line number and position
2459
2460 This function provides semantic action implementers with a way
2461 to push the famous "You have a syntax error near..." error
2462 message into the diagnostic area, which is normally produced only if
2463 a syntax error is discovered according to the Bison grammar.
2464 Unlike the syntax_error_at() function, the error position points to the last
2465 parsed token.
2466
2467 @note Parse-time only function!
2468
2469 @param mysql_errno Error number to get a format string with ER_THD().
2470 */
syntax_error(int mysql_errno,...)2471 void THD::syntax_error(int mysql_errno, ...) {
2472 va_list args;
2473 va_start(args, mysql_errno);
2474 vsyntax_error_at(m_parser_state->m_lip.get_tok_start(),
2475 ER_THD_NONCONST(this, mysql_errno), args);
2476 va_end(args);
2477 }
2478
2479 /**
2480 Push a syntax error message into MySQL diagnostic area with line
2481 and position information.
2482
2483 This function provides semantic action implementers with a way
2484 to push the famous "You have a syntax error near..." error
2485 message into the diagnostic area, which is normally produced only if
2486 a parse error is discovered internally by the Bison generated
2487 parser.
2488
2489 @note Parse-time only function!
2490
2491 @param location YYSTYPE object: error position.
2492 @param format Error format message. NULL means ER(ER_SYNTAX_ERROR).
2493 */
2494
syntax_error_at(const YYLTYPE & location,const char * format,...)2495 void THD::syntax_error_at(const YYLTYPE &location, const char *format, ...) {
2496 va_list args;
2497 va_start(args, format);
2498 vsyntax_error_at(location, format, args);
2499 va_end(args);
2500 }
2501
2502 /**
2503 Push a syntax error message into MySQL diagnostic area with line
2504 and position information.
2505
2506 This function provides semantic action implementers with a way
2507 to push the famous "You have a syntax error near..." error
2508 message into the diagnostic area, which is normally produced only if
2509 a parse error is discovered internally by the Bison generated
2510 parser.
2511
2512 @note Parse-time only function!
2513
2514 @param location YYSTYPE object: error position
2515 @param mysql_errno Error number to get a format string with ER_THD()
2516 */
syntax_error_at(const YYLTYPE & location,int mysql_errno,...)2517 void THD::syntax_error_at(const YYLTYPE &location, int mysql_errno, ...) {
2518 va_list args;
2519 va_start(args, mysql_errno);
2520 vsyntax_error_at(location, ER_THD_NONCONST(this, mysql_errno), args);
2521 va_end(args);
2522 }
2523
vsyntax_error_at(const YYLTYPE & location,const char * format,va_list args)2524 void THD::vsyntax_error_at(const YYLTYPE &location, const char *format,
2525 va_list args) {
2526 vsyntax_error_at(location.raw.start, format, args);
2527 }
2528
2529 /**
2530 Push a syntax error message into MySQL diagnostic area with line number and
2531 position
2532
2533 This function provides semantic action implementers with a way
2534 to push the famous "You have a syntax error near..." error
2535 message into the error stack, which is normally produced only if
2536 a parse error is discovered internally by the Bison generated
2537 parser.
2538
2539 @param pos_in_lexer_raw_buffer Pointer into LEX::m_buf or NULL.
2540 @param format An error message format string.
2541 @param args Arguments to the format string.
2542 */
2543
vsyntax_error_at(const char * pos_in_lexer_raw_buffer,const char * format,va_list args)2544 void THD::vsyntax_error_at(const char *pos_in_lexer_raw_buffer,
2545 const char *format, va_list args) {
2546 DBUG_ASSERT(
2547 pos_in_lexer_raw_buffer == nullptr ||
2548 (pos_in_lexer_raw_buffer >= m_parser_state->m_lip.get_buf() &&
2549 pos_in_lexer_raw_buffer <= m_parser_state->m_lip.get_end_of_query()));
2550
2551 char buff[MYSQL_ERRMSG_SIZE];
2552 if (check_stack_overrun(this, STACK_MIN_SIZE, (uchar *)buff)) return;
2553
2554 const uint lineno =
2555 pos_in_lexer_raw_buffer
2556 ? m_parser_state->m_lip.get_lineno(pos_in_lexer_raw_buffer)
2557 : 1;
2558 const char *pos = pos_in_lexer_raw_buffer ? pos_in_lexer_raw_buffer : "";
2559 ErrConvString err(pos, variables.character_set_client);
2560 (void)vsnprintf(buff, sizeof(buff), format, args);
2561 my_printf_error(ER_PARSE_ERROR, ER_THD(this, ER_PARSE_ERROR), MYF(0), buff,
2562 err.ptr(), lineno);
2563 }
2564
send_result_metadata(List<Item> * list,uint flags)2565 bool THD::send_result_metadata(List<Item> *list, uint flags) {
2566 DBUG_TRACE;
2567 List_iterator_fast<Item> it(*list);
2568 Item *item;
2569 uchar buff[MAX_FIELD_WIDTH];
2570 String tmp((char *)buff, sizeof(buff), &my_charset_bin);
2571
2572 if (m_protocol->start_result_metadata(list->elements, flags,
2573 variables.character_set_results))
2574 goto err;
2575 switch (variables.resultset_metadata) {
2576 case RESULTSET_METADATA_FULL:
2577 /* Sent metadata. */
2578 while ((item = it++)) {
2579 Send_field field;
2580 item->make_field(&field);
2581 m_protocol->start_row();
2582 if (m_protocol->send_field_metadata(&field,
2583 item->charset_for_protocol()))
2584 goto err;
2585 if (flags & Protocol::SEND_DEFAULTS) item->send(m_protocol, &tmp);
2586 if (m_protocol->end_row()) return true;
2587 }
2588 break;
2589
2590 case RESULTSET_METADATA_NONE:
2591 /* Skip metadata. */
2592 break;
2593
2594 default:
2595 /* Unknown @@resultset_metadata value. */
2596 return true;
2597 }
2598
2599 return m_protocol->end_result_metadata();
2600
2601 err:
2602 my_error(ER_OUT_OF_RESOURCES, MYF(0)); /* purecov: inspected */
2603 return true; /* purecov: inspected */
2604 }
2605
send_result_set_row(List<Item> * row_items)2606 bool THD::send_result_set_row(List<Item> *row_items) {
2607 char buffer[MAX_FIELD_WIDTH];
2608 String str_buffer(buffer, sizeof(buffer), &my_charset_bin);
2609 List_iterator_fast<Item> it(*row_items);
2610
2611 DBUG_TRACE;
2612
2613 for (Item *item = it++; item; item = it++) {
2614 if (item->send(m_protocol, &str_buffer) || is_error()) return true;
2615 /*
2616 Reset str_buffer to its original state, as it may have been altered in
2617 Item::send().
2618 */
2619 str_buffer.set(buffer, sizeof(buffer), &my_charset_bin);
2620 }
2621 return false;
2622 }
2623
send_statement_status()2624 void THD::send_statement_status() {
2625 DBUG_TRACE;
2626 DBUG_ASSERT(!get_stmt_da()->is_sent());
2627 bool error = false;
2628 Diagnostics_area *da = get_stmt_da();
2629
2630 /* Can not be true, but do not take chances in production. */
2631 if (da->is_sent()) return;
2632
2633 switch (da->status()) {
2634 case Diagnostics_area::DA_ERROR:
2635 /* The query failed, send error to log and abort bootstrap. */
2636 error = m_protocol->send_error(da->mysql_errno(), da->message_text(),
2637 da->returned_sqlstate());
2638 break;
2639 case Diagnostics_area::DA_EOF:
2640 error =
2641 m_protocol->send_eof(server_status, da->last_statement_cond_count());
2642 break;
2643 case Diagnostics_area::DA_OK:
2644 error = m_protocol->send_ok(
2645 server_status, da->last_statement_cond_count(), da->affected_rows(),
2646 da->last_insert_id(), da->message_text());
2647 break;
2648 case Diagnostics_area::DA_DISABLED:
2649 break;
2650 case Diagnostics_area::DA_EMPTY:
2651 default:
2652 DBUG_ASSERT(0);
2653 error = m_protocol->send_ok(server_status, 0, 0, 0, nullptr);
2654 break;
2655 }
2656 if (!error) da->set_is_sent(true);
2657 }
2658
claim_memory_ownership()2659 void THD::claim_memory_ownership() {
2660 /*
2661 Ownership of the THD object is transfered to this thread.
2662 This happens typically:
2663 - in the event scheduler,
2664 when the scheduler thread creates a work item and
2665 starts a worker thread to run it
2666 - in the main thread, when the code that accepts a new
2667 network connection creates a work item and starts a
2668 connection thread to run it.
2669 Accounting for memory statistics needs to be told
2670 that memory allocated by thread X now belongs to thread Y,
2671 so that statistics by thread/account/user/host are accurate.
2672 Inspect every piece of memory allocated in THD,
2673 and call PSI_MEMORY_CALL(memory_claim)().
2674 */
2675 #ifdef HAVE_PSI_MEMORY_INTERFACE
2676 main_mem_root.Claim();
2677 my_claim(m_token_array);
2678 Protocol_classic *p = get_protocol_classic();
2679 if (p != nullptr) p->claim_memory_ownership();
2680 session_tracker.claim_memory_ownership();
2681 session_sysvar_res_mgr.claim_memory_ownership();
2682 for (const auto &key_and_value : user_vars) {
2683 my_claim(key_and_value.second.get());
2684 }
2685 #if defined(ENABLED_DEBUG_SYNC)
2686 debug_sync_claim_memory_ownership(this);
2687 #endif /* defined(ENABLED_DEBUG_SYNC) */
2688 get_transaction()->claim_memory_ownership();
2689 stmt_map.claim_memory_ownership();
2690 #endif /* HAVE_PSI_MEMORY_INTERFACE */
2691 }
2692
rpl_detach_engine_ha_data()2693 void THD::rpl_detach_engine_ha_data() {
2694 Relay_log_info *rli =
2695 is_binlog_applier() ? rli_fake : (slave_thread ? rli_slave : nullptr);
2696
2697 DBUG_ASSERT(!rli_fake || !rli_fake->is_engine_ha_data_detached);
2698 DBUG_ASSERT(!rli_slave || !rli_slave->is_engine_ha_data_detached);
2699
2700 if (rli) rli->detach_engine_ha_data(this);
2701 }
2702
rpl_reattach_engine_ha_data()2703 void THD::rpl_reattach_engine_ha_data() {
2704 Relay_log_info *rli =
2705 is_binlog_applier() ? rli_fake : (slave_thread ? rli_slave : nullptr);
2706
2707 DBUG_ASSERT(!rli_fake || !rli_fake->is_engine_ha_data_detached);
2708 DBUG_ASSERT(!rli_slave || !rli_slave->is_engine_ha_data_detached);
2709
2710 if (rli) rli->reattach_engine_ha_data(this);
2711 }
2712
rpl_unflag_detached_engine_ha_data() const2713 bool THD::rpl_unflag_detached_engine_ha_data() const {
2714 Relay_log_info *rli =
2715 is_binlog_applier() ? rli_fake : (slave_thread ? rli_slave : nullptr);
2716 return rli ? rli->unflag_detached_engine_ha_data() : false;
2717 }
2718
is_current_stmt_binlog_disabled() const2719 bool THD::is_current_stmt_binlog_disabled() const {
2720 return (!(variables.option_bits & OPTION_BIN_LOG) ||
2721 !mysql_bin_log.is_open());
2722 }
2723
is_current_stmt_binlog_log_slave_updates_disabled() const2724 bool THD::is_current_stmt_binlog_log_slave_updates_disabled() const {
2725 return ((!opt_bin_log || (slave_thread && !opt_log_slave_updates)) ||
2726 !mysql_bin_log.is_open());
2727 }
2728
is_current_stmt_binlog_row_enabled_with_write_set_extraction() const2729 bool THD::is_current_stmt_binlog_row_enabled_with_write_set_extraction() const {
2730 return ((variables.transaction_write_set_extraction != HASH_ALGORITHM_OFF) &&
2731 is_current_stmt_binlog_format_row() &&
2732 !is_current_stmt_binlog_disabled());
2733 }
2734
is_single_table_plan() const2735 bool THD::Query_plan::is_single_table_plan() const {
2736 assert_plan_is_locked_if_other();
2737 return lex->m_sql_cmd->is_single_table_plan();
2738 }
2739
normalized_query()2740 const String THD::normalized_query() {
2741 m_normalized_query.mem_free();
2742 lex->unit->print(this, &m_normalized_query, QT_NORMALIZED_FORMAT);
2743 return m_normalized_query;
2744 }
2745
add_item_to_list(THD * thd,Item * item)2746 bool add_item_to_list(THD *thd, Item *item) {
2747 return thd->lex->select_lex->add_item_to_list(item);
2748 }
2749
Transaction_state()2750 THD::Transaction_state::Transaction_state()
2751 : m_query_tables_list(new Query_tables_list()),
2752 m_ha_data(PSI_NOT_INSTRUMENTED, m_ha_data.initial_capacity) {}
2753
~Transaction_state()2754 THD::Transaction_state::~Transaction_state() { delete m_query_tables_list; }
2755
change_item_tree(Item ** place,Item * new_value)2756 void THD::change_item_tree(Item **place, Item *new_value) {
2757 if (m_permanent_transform) {
2758 // Delete any change records for this location
2759 I_List_iterator<Item_change_record> it(change_list);
2760 Item_change_record *change;
2761 while ((change = it++))
2762 if (change->place == place) change->m_cancel = true;
2763
2764 *place = new_value;
2765 } else {
2766 /* TODO: check for OOM condition here */
2767 if (!stmt_arena->is_regular()) {
2768 DBUG_PRINT("info", ("change_item_tree place %p old_value %p new_value %p",
2769 place, *place, new_value));
2770 if (new_value)
2771 new_value->set_runtime_created(); /* Note the change of item tree */
2772 nocheck_register_item_tree_change(place, new_value);
2773 }
2774 *place = new_value;
2775 }
2776 }
2777
notify_hton_pre_acquire_exclusive(const MDL_key * mdl_key,bool * victimized)2778 bool THD::notify_hton_pre_acquire_exclusive(const MDL_key *mdl_key,
2779 bool *victimized) {
2780 return ha_notify_exclusive_mdl(this, mdl_key, HA_NOTIFY_PRE_EVENT,
2781 victimized);
2782 }
2783
notify_hton_post_release_exclusive(const MDL_key * mdl_key)2784 void THD::notify_hton_post_release_exclusive(const MDL_key *mdl_key) {
2785 bool unused_arg;
2786 ha_notify_exclusive_mdl(this, mdl_key, HA_NOTIFY_POST_EVENT, &unused_arg);
2787 }
2788
reattach_engine_ha_data_to_thd(THD * thd,const struct handlerton * hton)2789 void reattach_engine_ha_data_to_thd(THD *thd, const struct handlerton *hton) {
2790 DBUG_TRACE;
2791 if (hton->replace_native_transaction_in_thd) {
2792 /* restore the saved original engine transaction's link with thd */
2793 void **trx_backup = &thd->get_ha_data(hton->slot)->ha_ptr_backup;
2794
2795 hton->replace_native_transaction_in_thd(thd, *trx_backup, nullptr);
2796 *trx_backup = nullptr;
2797 }
2798 }
2799
2800 /**
2801 Call parser to transform statement into a parse tree.
2802 Then, transform the parse tree further into an AST, ready for resolving.
2803 */
sql_parser()2804 bool THD::sql_parser() {
2805 /*
2806 SQL parser function generated by YACC from sql_yacc.yy.
2807
2808 In the case of success returns 0, and THD::is_error() is false.
2809 Otherwise returns 1, or THD::>is_error() is true.
2810
2811 The second (output) parameter "root" returns the new parse tree.
2812 It is undefined (unchanged) on error. If "root" is NULL on success,
2813 then the parser has already called lex->make_sql_cmd() internally.
2814 */
2815 extern int MYSQLparse(class THD * thd, class Parse_tree_root * *root);
2816
2817 Parse_tree_root *root = nullptr;
2818 if (MYSQLparse(this, &root) || is_error()) {
2819 /*
2820 Restore the original LEX if it was replaced when parsing
2821 a stored procedure. We must ensure that a parsing error
2822 does not leave any side effects in the THD.
2823 */
2824 cleanup_after_parse_error();
2825 return true;
2826 }
2827 if (root != nullptr && lex->make_sql_cmd(root)) {
2828 return true;
2829 }
2830 return false;
2831 }
2832
is_one_phase_commit()2833 bool THD::is_one_phase_commit() {
2834 /* Check if XA Commit. */
2835 if (lex->sql_command != SQLCOM_XA_COMMIT) {
2836 return (false);
2837 }
2838 auto xa_commit_cmd = static_cast<Sql_cmd_xa_commit *>(lex->m_sql_cmd);
2839 auto xa_op = xa_commit_cmd->get_xa_opt();
2840 return (xa_op == XA_ONE_PHASE);
2841 }
2842
secondary_storage_engine_eligible() const2843 bool THD::secondary_storage_engine_eligible() const {
2844 return secondary_engine_optimization() !=
2845 Secondary_engine_optimization::PRIMARY_ONLY &&
2846 variables.use_secondary_engine != SECONDARY_ENGINE_OFF &&
2847 locked_tables_mode == LTM_NONE && !in_multi_stmt_transaction_mode() &&
2848 sp_runtime_ctx == nullptr;
2849 }
2850
2851 /**
2852 Set the rewritten query (with passwords obfuscated etc.) on the THD.
2853 Wraps this in the LOCK_thd_query mutex to protect against race conditions
2854 with SHOW PROCESSLIST inspecting that string.
2855
2856 This uses swap() and therefore changes the argument in the caller.
2857 That behavior is expected by (save|restore)_rlb() in sql_prepare.cc,
2858 and harmless in sql_rewrite.cc. Using it elsewhere is almost certainly
2859 wrong and must be reviewed with extreme prejudice. If in doubt, please
2860 check with the runtime team.
2861
2862 @param query_arg The rewritten query to use for slow/bin/general logging.
2863 The value will be changed in the caller.
2864 */
swap_rewritten_query(String & query_arg)2865 void THD::swap_rewritten_query(String &query_arg) {
2866 DBUG_ASSERT(this == current_thd);
2867
2868 mysql_mutex_lock(&LOCK_thd_query);
2869 m_rewritten_query.swap(query_arg);
2870 // The rewritten query should always be a valid C string, just in case.
2871 (void)m_rewritten_query.c_ptr_safe();
2872 mysql_mutex_unlock(&LOCK_thd_query);
2873 }
2874
2875 /**
2876 Restore session state in case of parse error.
2877
2878 This is a clean up function that is invoked after the Bison generated
2879 parser before returning an error from THD::sql_parser(). If your
2880 semantic actions manipulate with the session state (which
2881 is a very bad practice and should not normally be employed) and
2882 need a clean-up in case of error, and you can not use %destructor
2883 rule in the grammar file itself, this function should be used
2884 to implement the clean up.
2885 */
2886
cleanup_after_parse_error()2887 void THD::cleanup_after_parse_error() {
2888 sp_head *sp = lex->sphead;
2889
2890 if (sp) {
2891 sp->m_parser_data.finish_parsing_sp_body(this);
2892 // Do not delete sp_head if is invoked in the context of sp execution.
2893 if (sp_runtime_ctx == nullptr) {
2894 sp_head::destroy(sp);
2895 lex->sphead = nullptr;
2896 }
2897 }
2898 }
2899
is_classic_protocol() const2900 bool THD::is_classic_protocol() const {
2901 return get_protocol()->type() == Protocol::PROTOCOL_BINARY ||
2902 get_protocol()->type() == Protocol::PROTOCOL_TEXT;
2903 }
2904
is_connected()2905 bool THD::is_connected() {
2906 /*
2907 All system threads (e.g., the slave IO thread) are connected but
2908 not using vio. So this function always returns true for all
2909 system threads.
2910 */
2911 if (system_thread) return true;
2912
2913 if (is_classic_protocol())
2914 return get_protocol()->connection_alive() &&
2915 vio_is_connected(get_protocol_classic()->get_vio());
2916
2917 return get_protocol()->connection_alive();
2918 }
2919
push_protocol(Protocol * protocol)2920 void THD::push_protocol(Protocol *protocol) {
2921 DBUG_ASSERT(m_protocol != nullptr);
2922 DBUG_ASSERT(protocol != nullptr);
2923 m_protocol->push_protocol(protocol);
2924 m_protocol = protocol;
2925 }
2926
pop_protocol()2927 void THD::pop_protocol() {
2928 DBUG_ASSERT(m_protocol != nullptr);
2929 m_protocol = m_protocol->pop_protocol();
2930 DBUG_ASSERT(m_protocol != nullptr);
2931 }
2932
set_time()2933 void THD::set_time() {
2934 start_utime = utime_after_lock = my_micro_time();
2935 if (user_time.tv_sec || user_time.tv_usec)
2936 start_time = user_time;
2937 else
2938 my_micro_time_to_timeval(start_utime, &start_time);
2939
2940 #ifdef HAVE_PSI_THREAD_INTERFACE
2941 PSI_THREAD_CALL(set_thread_start_time)(query_start_in_secs());
2942 #endif
2943 }
2944
set_time_after_lock()2945 void THD::set_time_after_lock() {
2946 /*
2947 If mysql_lock_tables() is called multiple times,
2948 we stick with the first timestamp. This prevents
2949 anomalities with things like CREATE INDEX, where
2950 otherwise, we'll get the lock timestamp for the
2951 data dictionary update.
2952 */
2953 if (utime_after_lock != start_utime) return;
2954 utime_after_lock = my_micro_time();
2955 MYSQL_SET_STATEMENT_LOCK_TIME(m_statement_psi,
2956 (utime_after_lock - start_utime));
2957 }
2958
update_slow_query_status()2959 void THD::update_slow_query_status() {
2960 if (my_micro_time() > utime_after_lock + variables.long_query_time)
2961 server_status |= SERVER_QUERY_WAS_SLOW;
2962 }
2963
2964 /**
2965 Initialize the transactional ddl context when executing CREATE TABLE ...
2966 SELECT command with engine which supports atomic DDL.
2967
2968 @param db Schema name in which table is being created.
2969 @param tablename Table name being created.
2970 @param hton Handlerton representing engine used for table.
2971
2972 @returns void
2973 */
init(dd::String_type db,dd::String_type tablename,const handlerton * hton)2974 void Transactional_ddl_context::init(dd::String_type db,
2975 dd::String_type tablename,
2976 const handlerton *hton) {
2977 DBUG_ASSERT(m_hton == nullptr);
2978 m_db = db;
2979 m_tablename = tablename;
2980 m_hton = hton;
2981 }
2982
2983 /**
2984 Remove the table share used while creating the table, if the transaction
2985 is being rolledback.
2986
2987 @returns void
2988 */
rollback()2989 void Transactional_ddl_context::rollback() {
2990 if (!inited()) return;
2991 table_cache_manager.lock_all_and_tdc();
2992 TABLE_SHARE *share =
2993 get_cached_table_share(m_db.c_str(), m_tablename.c_str());
2994 if (share) {
2995 tdc_remove_table(m_thd, TDC_RT_REMOVE_ALL, m_db.c_str(),
2996 m_tablename.c_str(), true);
2997
2998 #ifdef HAVE_PSI_TABLE_INTERFACE
2999 // quick_rm_table() was not called, so remove the P_S table share here.
3000 PSI_TABLE_CALL(drop_table_share)
3001 (false, m_db.c_str(), strlen(m_db.c_str()), m_tablename.c_str(),
3002 strlen(m_tablename.c_str()));
3003 #endif
3004 }
3005 table_cache_manager.unlock_all_and_tdc();
3006 }
3007
3008 /**
3009 End the transactional context created by calling post ddl hook for engine
3010 on which table is being created. This is done after transaction rollback
3011 and commit.
3012
3013 @returns void
3014 */
post_ddl()3015 void Transactional_ddl_context::post_ddl() {
3016 if (!inited()) return;
3017 if (m_hton && m_hton->post_ddl) {
3018 m_hton->post_ddl(m_thd);
3019 }
3020 m_hton = nullptr;
3021 m_db = "";
3022 m_tablename = "";
3023 }
3024
my_ok(THD * thd,ulonglong affected_rows,ulonglong id,const char * message)3025 void my_ok(THD *thd, ulonglong affected_rows, ulonglong id,
3026 const char *message) {
3027 thd->set_row_count_func(affected_rows);
3028 thd->get_stmt_da()->set_ok_status(affected_rows, id, message);
3029 }
3030
my_eof(THD * thd)3031 void my_eof(THD *thd) {
3032 thd->set_row_count_func(-1);
3033 thd->get_stmt_da()->set_eof_status(thd);
3034 if (thd->variables.session_track_transaction_info > TX_TRACK_NONE) {
3035 TX_TRACKER_GET(tst);
3036 tst->add_trx_state(thd, TX_RESULT_SET);
3037 }
3038 }
3039