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, &not_used);
1543   charset_is_collation_connection =
1544       !String::needs_conversion(0, variables.character_set_client,
1545                                 variables.collation_connection, &not_used);
1546   charset_is_character_set_filesystem =
1547       !String::needs_conversion(0, variables.character_set_client,
1548                                 variables.character_set_filesystem, &not_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