1 /*
2    Copyright (c) 2000, 2021, Oracle and/or its affiliates.
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 
26 /*****************************************************************************
27 **
28 ** This file implements classes defined in sql_class.h
29 ** Especially the classes to handle a result from a select
30 **
31 *****************************************************************************/
32 
33 #include "sql_class.h"
34 
35 #include "mysys_err.h"                       // EE_DELETE
36 #include "connection_handler_manager.h"      // Connection_handler_manager
37 #include "debug_sync.h"                      // DEBUG_SYNC
38 #include "lock.h"                            // mysql_lock_abort_for_thread
39 #include "locking_service.h"                 // release_all_locking_service_locks
40 #include "mysqld_thd_manager.h"              // Global_THD_manager
41 #include "parse_tree_nodes.h"                // PT_select_var
42 #include "rpl_filter.h"                      // binlog_filter
43 #include "rpl_rli.h"                         // Relay_log_info
44 #include "sp_cache.h"                        // sp_cache_clear
45 #include "sp_rcontext.h"                     // sp_rcontext
46 #include "sql_audit.h"                       // mysql_audit_release
47 #include "sql_base.h"                        // close_temporary_tables
48 #include "sql_callback.h"                    // MYSQL_CALLBACK
49 #include "sql_handler.h"                     // mysql_ha_cleanup
50 #include "sql_parse.h"                       // is_update_query
51 #include "sql_plugin.h"                      // plugin_unlock
52 #include "sql_prepare.h"                     // Prepared_statement
53 #include "sql_time.h"                        // my_timeval_trunc
54 #include "sql_timer.h"                       // thd_timer_destroy
55 #include "sql_thd_internal_api.h"
56 #include "transaction.h"                     // trans_rollback
57 #ifdef HAVE_REPLICATION
58 #include "rpl_rli_pdb.h"                     // Slave_worker
59 #include "rpl_slave_commit_order_manager.h"
60 #include "rpl_master.h"                      // unregister_slave
61 #endif
62 
63 #include "pfs_file_provider.h"
64 #include "mysql/psi/mysql_file.h"
65 
66 #include "pfs_idle_provider.h"
67 #include "mysql/psi/mysql_idle.h"
68 
69 #include "mysql/psi/mysql_ps.h"
70 #ifdef WITH_WSREP
71 #include "wsrep_mysqld.h"
72 #include "wsrep_thd.h"
73 #endif
74 
75 using std::min;
76 using std::max;
77 
78 /*
79   The following is used to initialise Table_ident with a internal
80   table name
81 */
82 char internal_table_name[2]= "";
83 char empty_c_string[1]= {0};    /* used for not defined db */
84 
85 LEX_STRING EMPTY_STR= { (char *) "", 0 };
86 LEX_STRING NULL_STR=  { NULL, 0 };
87 LEX_CSTRING EMPTY_CSTR= { "", 0 };
88 LEX_CSTRING NULL_CSTR=  { NULL, 0 };
89 
90 const char * const THD::DEFAULT_WHERE= "field list";
91 
92 
backup(THD * thd)93 void THD::Transaction_state::backup(THD *thd)
94 {
95   this->m_sql_command= thd->lex->sql_command;
96   this->m_trx= thd->get_transaction();
97 
98   for (int i= 0; i < MAX_HA; ++i)
99     this->m_ha_data[i]= thd->ha_data[i];
100 
101   this->m_tx_isolation= thd->tx_isolation;
102   this->m_tx_read_only= thd->tx_read_only;
103   this->m_thd_option_bits= thd->variables.option_bits;
104   this->m_sql_mode= thd->variables.sql_mode;
105   this->m_transaction_psi= thd->m_transaction_psi;
106   this->m_server_status= thd->server_status;
107 }
108 
109 
restore(THD * thd)110 void THD::Transaction_state::restore(THD *thd)
111 {
112   thd->set_transaction(this->m_trx);
113 
114   for (int i= 0; i < MAX_HA; ++i)
115     thd->ha_data[i]= this->m_ha_data[i];
116 
117   thd->tx_isolation= this->m_tx_isolation;
118   thd->variables.sql_mode= this->m_sql_mode;
119   thd->tx_read_only= this->m_tx_read_only;
120   thd->variables.option_bits= this->m_thd_option_bits;
121 
122   thd->m_transaction_psi= this->m_transaction_psi;
123   thd->server_status= this->m_server_status;
124   thd->lex->sql_command= this->m_sql_command;
125 }
126 
Attachable_trx(THD * thd)127 THD::Attachable_trx::Attachable_trx(THD *thd)
128  :m_thd(thd)
129 {
130   // The THD::transaction_rollback_request is expected to be unset in the
131   // attachable transaction. It's weird to start attachable transaction when the
132   // SE asked to rollback the regular transaction.
133   assert(!m_thd->transaction_rollback_request);
134 
135   // Save the transaction state.
136 
137   m_trx_state.backup(m_thd);
138 
139   // Save and reset query-tables-list and reset the sql-command.
140   //
141   // NOTE: ha_innobase::store_lock() takes the current sql-command into account.
142   // It must be SQLCOM_SELECT.
143   //
144   // Do NOT reset LEX if we're running tests. LEX is used by SELECT statements.
145 
146   if (DBUG_EVALUATE_IF("use_attachable_trx", false, true))
147   {
148     m_thd->lex->reset_n_backup_query_tables_list(&m_trx_state.m_query_tables_list);
149     m_thd->lex->sql_command= SQLCOM_SELECT;
150   }
151 
152   // Save and reset open-tables.
153 
154   m_thd->reset_n_backup_open_tables_state(&m_trx_state.m_open_tables_state);
155 
156   // Reset transaction state.
157 
158   m_thd->m_transaction.release(); // it's been backed up.
159   m_thd->m_transaction.reset(new Transaction_ctx());
160 
161   // Prepare for a new attachable transaction for read-only DD-transaction.
162 
163   for (int i= 0; i < MAX_HA; ++i)
164     m_thd->ha_data[i]= Ha_data();
165 
166   // The attachable transaction must used READ COMMITTED isolation level.
167 
168   m_thd->tx_isolation= ISO_READ_COMMITTED;
169 
170   // The attachable transaction must be read-only.
171 
172   m_thd->tx_read_only= true;
173 
174   // The attachable transaction must be AUTOCOMMIT.
175 
176   m_thd->variables.option_bits|= OPTION_AUTOCOMMIT;
177   m_thd->variables.option_bits&= ~OPTION_NOT_AUTOCOMMIT;
178   m_thd->variables.option_bits&= ~OPTION_BEGIN;
179 
180   // Possible parent's involvement to multi-statement transaction is masked
181 
182   m_thd->server_status&= ~SERVER_STATUS_IN_TRANS;
183   m_thd->server_status&= ~SERVER_STATUS_IN_TRANS_READONLY;
184 
185   // Reset SQL_MODE during system operations.
186 
187   m_thd->variables.sql_mode= 0;
188 
189   // Reset transaction instrumentation.
190 
191   m_thd->m_transaction_psi= NULL;
192 }
193 
194 
~Attachable_trx()195 THD::Attachable_trx::~Attachable_trx()
196 {
197   // Ensure that the SE didn't request rollback in the attachable transaction.
198   // Having THD::transaction_rollback_request set most likely means that we've
199   // experienced some sort of deadlock/timeout while processing the attachable
200   // transaction. That is not possible by the definition of an attachable
201   // transaction.
202   assert(!m_thd->transaction_rollback_request);
203 
204   // Commit the attachable transaction before discarding transaction state.
205   // This is mostly needed to properly reset transaction state in SE.
206   // Note: We can't rely on InnoDB hack which auto-magically commits InnoDB
207   // transaction when the last table for a statement in auto-commit mode is
208   // unlocked. Apparently it doesn't work correctly in some corner cases
209   // (for example, when statement is killed just after tables are locked but
210   // before any other operations on the table happes). We try not to rely on
211   // it in other places on SQL-layer as well.
212   trans_commit_attachable(m_thd);
213 
214   // Close all the tables that are open till now.
215 
216   close_thread_tables(m_thd);
217 
218   // Cleanup connection specific state which was created for attachable
219   // transaction (for InnoDB removes cached transaction object).
220   //
221   // Note that we need to call handlerton::close_connection for all SEs
222   // and not only SEs which participated in attachable transaction since
223   // connection specific state can be created when TABLE object is simply
224   // expelled from the Table Cache (e.g. this happens for MyISAM).
225   ha_close_connection(m_thd);
226 
227   // Restore the transaction state.
228 
229   m_trx_state.restore(m_thd);
230 
231   m_thd->restore_backup_open_tables_state(&m_trx_state.m_open_tables_state);
232 
233   if (DBUG_EVALUATE_IF("use_attachable_trx", false, true))
234   {
235     m_thd->lex->restore_backup_query_tables_list(
236       &m_trx_state.m_query_tables_list);
237   }
238 }
239 
240 
241 /****************************************************************************
242 ** User variables
243 ****************************************************************************/
244 
get_var_key(user_var_entry * entry,size_t * length,my_bool not_used MY_ATTRIBUTE ((unused)))245 extern "C" uchar *get_var_key(user_var_entry *entry, size_t *length,
246                               my_bool not_used MY_ATTRIBUTE((unused)))
247 {
248   *length= entry->entry_name.length();
249   return (uchar*) entry->entry_name.ptr();
250 }
251 
free_user_var(user_var_entry * entry)252 extern "C" void free_user_var(user_var_entry *entry)
253 {
254   entry->destroy();
255 }
256 
operator ==(const Key_part_spec & other) const257 bool Key_part_spec::operator==(const Key_part_spec& other) const
258 {
259   return length == other.length &&
260          !my_strcasecmp(system_charset_info, field_name.str,
261                         other.field_name.str);
262 }
263 
264 /**
265   Construct an (almost) deep copy of this key. Only those
266   elements that are known to never change are not copied.
267   If out of memory, a partial copy is returned and an error is set
268   in THD.
269 */
270 
Key(const Key & rhs,MEM_ROOT * mem_root)271 Key::Key(const Key &rhs, MEM_ROOT *mem_root)
272   :type(rhs.type),
273   key_create_info(rhs.key_create_info),
274   columns(rhs.columns, mem_root),
275   name(rhs.name),
276   generated(rhs.generated)
277 {
278   list_copy_and_replace_each_value(columns, mem_root);
279 }
280 
281 /**
282   Construct an (almost) deep copy of this foreign key. Only those
283   elements that are known to never change are not copied.
284   If out of memory, a partial copy is returned and an error is set
285   in THD.
286 */
287 
Foreign_key(const Foreign_key & rhs,MEM_ROOT * mem_root)288 Foreign_key::Foreign_key(const Foreign_key &rhs, MEM_ROOT *mem_root)
289   :Key(rhs, mem_root),
290   ref_db(rhs.ref_db),
291   ref_table(rhs.ref_table),
292   ref_columns(rhs.ref_columns, mem_root),
293   delete_opt(rhs.delete_opt),
294   update_opt(rhs.update_opt),
295   match_opt(rhs.match_opt)
296 {
297   list_copy_and_replace_each_value(ref_columns, mem_root);
298 }
299 
300 /*
301   Test if a foreign key (= generated key) is a prefix of the given key
302   (ignoring key name, key type and order of columns)
303 
304   NOTES:
305     This is only used to test if an index for a FOREIGN KEY exists
306 
307   IMPLEMENTATION
308     We only compare field names
309 
310   RETURN
311     0	Generated key is a prefix of other key
312     1	Not equal
313 */
314 
foreign_key_prefix(Key * a,Key * b)315 bool foreign_key_prefix(Key *a, Key *b)
316 {
317   /* Ensure that 'a' is the generated key */
318   if (a->generated)
319   {
320     if (b->generated && a->columns.elements > b->columns.elements)
321       swap_variables(Key*, a, b);               // Put shorter key in 'a'
322   }
323   else
324   {
325     if (!b->generated)
326       return TRUE;                              // No foreign key
327     swap_variables(Key*, a, b);                 // Put generated key in 'a'
328   }
329 
330   /* Test if 'a' is a prefix of 'b' */
331   if (a->columns.elements > b->columns.elements)
332     return TRUE;                                // Can't be prefix
333 
334   List_iterator<Key_part_spec> col_it1(a->columns);
335   List_iterator<Key_part_spec> col_it2(b->columns);
336   const Key_part_spec *col1, *col2;
337 
338 #ifdef ENABLE_WHEN_INNODB_CAN_HANDLE_SWAPED_FOREIGN_KEY_COLUMNS
339   while ((col1= col_it1++))
340   {
341     bool found= 0;
342     col_it2.rewind();
343     while ((col2= col_it2++))
344     {
345       if (*col1 == *col2)
346       {
347         found= TRUE;
348 	break;
349       }
350     }
351     if (!found)
352       return TRUE;                              // Error
353   }
354   return FALSE;                                 // Is prefix
355 #else
356   while ((col1= col_it1++))
357   {
358     col2= col_it2++;
359     if (!(*col1 == *col2))
360       return TRUE;
361   }
362   return FALSE;                                 // Is prefix
363 #endif
364 }
365 
366 /**
367   @brief  validate
368     Check if the foreign key options are compatible with columns
369     on which the FK is created.
370 
371   @param table_fields         List of columns
372 
373   @return
374     false   Key valid
375   @return
376     true   Key invalid
377  */
validate(List<Create_field> & table_fields)378 bool Foreign_key::validate(List<Create_field> &table_fields)
379 {
380   Create_field  *sql_field;
381   Key_part_spec *column;
382   List_iterator<Key_part_spec> cols(columns);
383   List_iterator<Create_field> it(table_fields);
384   DBUG_ENTER("Foreign_key::validate");
385   while ((column= cols++))
386   {
387     it.rewind();
388     while ((sql_field= it++) &&
389            my_strcasecmp(system_charset_info,
390                          column->field_name.str,
391                          sql_field->field_name)) {}
392     if (!sql_field)
393     {
394       my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name.str);
395       DBUG_RETURN(TRUE);
396     }
397     if (type == KEYTYPE_FOREIGN && sql_field->gcol_info)
398     {
399       if (delete_opt == FK_OPTION_SET_NULL)
400       {
401         my_error(ER_WRONG_FK_OPTION_FOR_GENERATED_COLUMN, MYF(0),
402                  "ON DELETE SET NULL");
403         DBUG_RETURN(TRUE);
404       }
405       if (update_opt == FK_OPTION_SET_NULL)
406       {
407         my_error(ER_WRONG_FK_OPTION_FOR_GENERATED_COLUMN, MYF(0),
408                  "ON UPDATE SET NULL");
409         DBUG_RETURN(TRUE);
410       }
411       if (update_opt == FK_OPTION_CASCADE)
412       {
413         my_error(ER_WRONG_FK_OPTION_FOR_GENERATED_COLUMN, MYF(0),
414                  "ON UPDATE CASCADE");
415         DBUG_RETURN(TRUE);
416       }
417     }
418   }
419   DBUG_RETURN(FALSE);
420 }
421 
422 /****************************************************************************
423 ** Thread specific functions
424 ****************************************************************************/
425 
426 /**
427   Get reference to scheduler data object
428 
429   @param thd            THD object
430 
431   @retval               Scheduler data object on THD
432 */
thd_get_scheduler_data(THD * thd)433 void *thd_get_scheduler_data(THD *thd)
434 {
435   return thd->scheduler.data;
436 }
437 
438 /**
439   Set reference to Scheduler data object for THD object
440 
441   @param thd            THD object
442   @param psi            Scheduler data object to set on THD
443 */
thd_set_scheduler_data(THD * thd,void * data)444 void thd_set_scheduler_data(THD *thd, void *data)
445 {
446   thd->scheduler.data= data;
447 }
448 
get_psi()449 PSI_thread* THD::get_psi()
450 {
451   void *addr= & m_psi;
452   void * volatile * typed_addr= static_cast<void * volatile *>(addr);
453   void *ptr;
454   ptr= my_atomic_loadptr(typed_addr);
455   return static_cast<PSI_thread*>(ptr);
456 }
457 
set_psi(PSI_thread * psi)458 void THD::set_psi(PSI_thread *psi)
459 {
460   void *addr= & m_psi;
461   void * volatile * typed_addr= static_cast<void * volatile *>(addr);
462   my_atomic_storeptr(typed_addr, psi);
463 }
464 
465 /**
466   Get reference to Performance Schema object for THD object
467 
468   @param thd            THD object
469 
470   @return               Performance schema object for thread on THD
471 */
thd_get_psi(THD * thd)472 PSI_thread *thd_get_psi(THD *thd)
473 {
474   return thd->get_psi();
475 }
476 
477 
478 /**
479   Get net_wait_timeout for THD object
480 
481   @param thd            THD object
482 
483   @retval               net_wait_timeout value for thread on THD
484 */
thd_get_net_wait_timeout(THD * thd)485 ulong thd_get_net_wait_timeout(THD* thd)
486 {
487   return thd->variables.net_wait_timeout;
488 }
489 
490 /**
491   Set reference to Performance Schema object for THD object
492 
493   @param thd            THD object
494   @param psi            Performance schema object for thread
495 */
thd_set_psi(THD * thd,PSI_thread * psi)496 void thd_set_psi(THD *thd, PSI_thread *psi)
497 {
498   thd->set_psi(psi);
499 }
500 
501 /**
502   Set the state on connection to killed
503 
504   @param thd               THD object
505 */
thd_set_killed(THD * thd)506 void thd_set_killed(THD *thd)
507 {
508   thd->killed= THD::KILL_CONNECTION;
509 }
510 
511 /**
512   Clear errors from the previous THD
513 
514   @param thd              THD object
515 */
thd_clear_errors(THD * thd)516 void thd_clear_errors(THD *thd)
517 {
518   set_my_errno(0);
519 }
520 
521 /**
522   Close the socket used by this connection
523 
524   @param thd                THD object
525 */
thd_close_connection(THD * thd)526 void thd_close_connection(THD *thd)
527 {
528   thd->get_protocol_classic()->shutdown();
529 }
530 
531 /**
532   Get current THD object from thread local data
533 
534   @retval     The THD object for the thread, NULL if not connection thread
535 */
thd_get_current_thd()536 THD *thd_get_current_thd()
537 {
538   return current_thd;
539 }
540 
541 /**
542   Reset thread globals associated.
543 
544   @param thd     THD object
545 */
reset_thread_globals(THD * thd)546 void reset_thread_globals(THD* thd)
547 {
548   thd->restore_globals();
549   thd->set_is_killable(false);
550 }
551 
552 extern "C"
thd_binlog_pos(const THD * thd,const char ** file_var,unsigned long long * pos_var)553 void thd_binlog_pos(const THD *thd,
554                     const char **file_var,
555                     unsigned long long *pos_var)
556 {
557   thd->get_trans_pos(file_var, pos_var);
558 }
559 
560 /**
561   Lock data that needs protection in THD object
562 
563   @param thd                   THD object
564 */
thd_lock_data(THD * thd)565 void thd_lock_data(THD *thd)
566 {
567   mysql_mutex_lock(&thd->LOCK_thd_data);
568 }
569 
570 /**
571   Unlock data that needs protection in THD object
572 
573   @param thd                   THD object
574 */
thd_unlock_data(THD * thd)575 void thd_unlock_data(THD *thd)
576 {
577   mysql_mutex_unlock(&thd->LOCK_thd_data);
578 }
579 
580 /**
581   Support method to check if connection has already started transaction
582 
583   @param client_cntx    Low level client context
584 
585   @retval               TRUE if connection already started transaction
586 */
thd_is_transaction_active(THD * thd)587 bool thd_is_transaction_active(THD *thd)
588 {
589   return thd->get_transaction()->is_active(Transaction_ctx::SESSION);
590 }
591 
592 /**
593   Check if there is buffered data on the socket representing the connection
594 
595   @param thd                  THD object
596 */
thd_connection_has_data(THD * thd)597 int thd_connection_has_data(THD *thd)
598 {
599   Vio *vio= thd->get_protocol_classic()->get_vio();
600   return vio->has_data(vio);
601 }
602 
603 /**
604   Set reading/writing on socket, used by SHOW PROCESSLIST
605 
606   @param thd                       THD object
607   @param val                       Value to set it to (0 or 1)
608 */
thd_set_net_read_write(THD * thd,uint val)609 void thd_set_net_read_write(THD *thd, uint val)
610 {
611   thd->get_protocol_classic()->get_net()->reading_or_writing= val;
612 }
613 
614 /**
615   Get reading/writing on socket from THD object
616   @param thd                       THD object
617 
618   @retval               net.reading_or_writing value for thread on THD.
619 */
thd_get_net_read_write(THD * thd)620 uint thd_get_net_read_write(THD *thd)
621 {
622   return thd->get_protocol_classic()->get_rw_status();
623 }
624 
625 /**
626   Mark the THD as not killable as it is not currently used by a thread.
627 
628   @param thd             THD object
629 */
thd_set_not_killable(THD * thd)630 void thd_set_not_killable(THD *thd)
631 {
632   thd->set_is_killable(false);
633 }
634 
635 /**
636   Get socket file descriptor for this connection
637 
638   @param thd            THD object
639 
640   @retval               Socket of the connection
641 */
thd_get_fd(THD * thd)642 my_socket thd_get_fd(THD *thd)
643 {
644   return thd->get_protocol_classic()->get_socket();
645 }
646 
647 /**
648   Set thread specific environment required for thd cleanup in thread pool.
649 
650   @param thd            THD object
651 
652   @retval               1 if thread-specific enviroment could be set else 0
653 */
thd_store_globals(THD * thd)654 int thd_store_globals(THD* thd)
655 {
656   return thd->store_globals();
657 }
658 
659 /**
660   Get thread attributes for connection threads
661 
662   @retval      Reference to thread attribute for connection threads
663 */
get_connection_attrib(void)664 my_thread_attr_t *get_connection_attrib(void)
665 {
666   return &connection_attrib;
667 }
668 
669 /**
670   Get max number of connections
671 
672   @retval         Max number of connections for MySQL Server
673 */
get_max_connections(void)674 ulong get_max_connections(void)
675 {
676   return max_connections;
677 }
678 
679 /*
680   The following functions form part of the C plugin API
681 */
682 
mysql_tmpfile(const char * prefix)683 extern "C" int mysql_tmpfile(const char *prefix)
684 {
685   return mysql_tmpfile_path(mysql_tmpdir, prefix);
686 }
687 
688 
689 extern "C"
thd_in_lock_tables(const THD * thd)690 int thd_in_lock_tables(const THD *thd)
691 {
692   return MY_TEST(thd->in_lock_tables);
693 }
694 
695 
696 extern "C"
thd_tablespace_op(const THD * thd)697 int thd_tablespace_op(const THD *thd)
698 {
699   return MY_TEST(thd->tablespace_op);
700 }
701 
702 
703 extern "C"
set_thd_proc_info(MYSQL_THD thd_arg,const char * info,const char * calling_function,const char * calling_file,const unsigned int calling_line)704 const char *set_thd_proc_info(MYSQL_THD thd_arg, const char *info,
705                               const char *calling_function,
706                               const char *calling_file,
707                               const unsigned int calling_line)
708 {
709   PSI_stage_info old_stage;
710   PSI_stage_info new_stage;
711 
712   old_stage.m_key= 0;
713   old_stage.m_name= info;
714 
715   set_thd_stage_info(thd_arg, & old_stage, & new_stage,
716                      calling_function, calling_file, calling_line);
717 
718   return new_stage.m_name;
719 }
720 
721 extern "C"
set_thd_stage_info(void * opaque_thd,const PSI_stage_info * new_stage,PSI_stage_info * old_stage,const char * calling_func,const char * calling_file,const unsigned int calling_line)722 void set_thd_stage_info(void *opaque_thd,
723                         const PSI_stage_info *new_stage,
724                         PSI_stage_info *old_stage,
725                         const char *calling_func,
726                         const char *calling_file,
727                         const unsigned int calling_line)
728 {
729   THD *thd= (THD*) opaque_thd;
730   if (thd == NULL)
731     thd= current_thd;
732 
733   thd->enter_stage(new_stage, old_stage, calling_func, calling_file, calling_line);
734 }
735 
736 
enter_stage(const PSI_stage_info * new_stage,PSI_stage_info * old_stage,const char * calling_func,const char * calling_file,const unsigned int calling_line)737 void THD::enter_stage(const PSI_stage_info *new_stage,
738                       PSI_stage_info *old_stage,
739                       const char *calling_func,
740                       const char *calling_file,
741                       const unsigned int calling_line)
742 {
743   DBUG_PRINT("THD::enter_stage",
744              ("'%s' %s:%d", new_stage ? new_stage->m_name : "",
745               calling_file, calling_line));
746 
747   if (old_stage != NULL)
748   {
749     old_stage->m_key= m_current_stage_key;
750     old_stage->m_name= proc_info;
751   }
752 
753   if (new_stage != NULL)
754   {
755     const char *msg= new_stage->m_name;
756 
757 #if defined(ENABLED_PROFILING)
758     profiling.status_change(msg, calling_func, calling_file, calling_line);
759 #endif
760 
761     m_current_stage_key= new_stage->m_key;
762     proc_info= msg;
763 
764     m_stage_progress_psi= MYSQL_SET_STAGE(m_current_stage_key, calling_file, calling_line);
765   }
766   else
767   {
768     m_stage_progress_psi= NULL;
769   }
770 
771   return;
772 }
773 
774 extern "C"
thd_enter_cond(void * opaque_thd,mysql_cond_t * cond,mysql_mutex_t * mutex,const PSI_stage_info * stage,PSI_stage_info * old_stage,const char * src_function,const char * src_file,int src_line)775 void thd_enter_cond(void *opaque_thd, mysql_cond_t *cond, mysql_mutex_t *mutex,
776                     const PSI_stage_info *stage, PSI_stage_info *old_stage,
777                     const char *src_function, const char *src_file,
778                     int src_line)
779 {
780   THD *thd= static_cast<THD*>(opaque_thd);
781   if (!thd)
782     thd= current_thd;
783 
784   return thd->enter_cond(cond, mutex, stage, old_stage,
785                          src_function, src_file, src_line);
786 }
787 
788 extern "C"
thd_exit_cond(void * opaque_thd,const PSI_stage_info * stage,const char * src_function,const char * src_file,int src_line)789 void thd_exit_cond(void *opaque_thd, const PSI_stage_info *stage,
790                    const char *src_function, const char *src_file,
791                    int src_line)
792 {
793   THD *thd= static_cast<THD*>(opaque_thd);
794   if (!thd)
795     thd= current_thd;
796 
797   thd->exit_cond(stage, src_function, src_file, src_line);
798 }
799 
800 extern "C"
thd_ha_data(const THD * thd,const struct handlerton * hton)801 void **thd_ha_data(const THD *thd, const struct handlerton *hton)
802 {
803   return (void **) &thd->ha_data[hton->slot].ha_ptr;
804 }
805 
806 extern "C"
thd_storage_lock_wait(THD * thd,long long value)807 void thd_storage_lock_wait(THD *thd, long long value)
808 {
809   thd->utime_after_lock+= value;
810 }
811 
812 /**
813   Provide a handler data getter to simplify coding
814 */
815 extern "C"
thd_get_ha_data(const THD * thd,const struct handlerton * hton)816 void *thd_get_ha_data(const THD *thd, const struct handlerton *hton)
817 {
818   return *thd_ha_data(thd, hton);
819 }
820 
821 #ifdef WITH_WSREP
wsrep_on(void * thd)822 extern int wsrep_on(void *thd)
823 {
824   return (int)(WSREP(((THD*)thd)));
825 }
wsrep_thd_is_wsrep_on(THD * thd)826 extern "C" bool wsrep_thd_is_wsrep_on(THD *thd)
827 {
828   return thd->variables.wsrep_on;
829 }
830 
wsrep_consistency_check(void * thd)831 extern "C" bool wsrep_consistency_check(void *thd)
832 {
833   return ((THD*)thd)->wsrep_consistency_check == CONSISTENCY_CHECK_RUNNING;
834 }
835 
wsrep_thd_set_exec_mode(THD * thd,enum wsrep_exec_mode mode)836 extern "C" void wsrep_thd_set_exec_mode(THD *thd, enum wsrep_exec_mode mode)
837 {
838   thd->wsrep_exec_mode= mode;
839 }
wsrep_thd_set_query_state(THD * thd,enum wsrep_query_state state)840 extern "C" void wsrep_thd_set_query_state(
841 	THD *thd, enum wsrep_query_state state)
842 {
843   if (!WSREP(thd)) return;
844   /* async slave thread should never flag IDLE state, as it may
845      give rollbacker thread chance to interfere and rollback async slave
846      transaction.
847      in fact, async slave thread is never idle as it reads complete
848      transactions from relay log and applies them, as a whole.
849      BF abort happens voluntarily by async slave thread.
850   */
851   if (thd->slave_thread && state == QUERY_IDLE) {
852     WSREP_DEBUG("Skipping IDLE state change for slave SQL");
853     return;
854   }
855 
856   thd->wsrep_query_state= state;
857 }
wsrep_thd_set_conflict_state(THD * thd,bool lock,enum wsrep_conflict_state state)858 extern "C" void wsrep_thd_set_conflict_state(
859          THD *thd, bool lock, enum wsrep_conflict_state state)
860 {
861   if (WSREP(thd))
862   {
863     if (lock) mysql_mutex_lock(&thd->LOCK_wsrep_thd);
864     thd->wsrep_conflict_state= state;
865     if (lock) mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
866   }
867 }
868 
869 
wsrep_thd_exec_mode(THD * thd)870 extern "C" enum wsrep_exec_mode wsrep_thd_exec_mode(THD *thd)
871 {
872   return thd->wsrep_exec_mode;
873 }
874 
wsrep_thd_exec_mode_str(THD * thd)875 extern "C" const char *wsrep_thd_exec_mode_str(THD *thd)
876 {
877   return
878     (!thd) ? "void" :
879     (thd->wsrep_exec_mode == LOCAL_STATE)  ? "local"         :
880     (thd->wsrep_exec_mode == REPL_RECV)    ? "applier"       :
881     (thd->wsrep_exec_mode == TOTAL_ORDER)  ? "total order"   :
882     (thd->wsrep_exec_mode == LOCAL_COMMIT) ? "local commit"  : "void";
883 }
884 
wsrep_thd_query_state(THD * thd)885 extern "C" enum wsrep_query_state wsrep_thd_query_state(THD *thd)
886 {
887   return thd->wsrep_query_state;
888 }
889 
wsrep_thd_query_state_str(THD * thd)890 extern "C" const char *wsrep_thd_query_state_str(THD *thd)
891 {
892   return
893     (!thd) ? "void" :
894     (thd->wsrep_query_state == QUERY_IDLE)        ? "idle"          :
895     (thd->wsrep_query_state == QUERY_EXEC)        ? "executing"     :
896     (thd->wsrep_query_state == QUERY_COMMITTING)  ? "committing"    :
897     (thd->wsrep_query_state == QUERY_EXITING)     ? "exiting"       :
898     (thd->wsrep_query_state == QUERY_ROLLINGBACK) ? "rolling back"  : "void";
899 }
900 
wsrep_thd_conflict_state(THD * thd)901 extern "C" enum wsrep_conflict_state wsrep_thd_conflict_state(THD *thd)
902 {
903   return thd->wsrep_conflict_state;
904 }
wsrep_thd_conflict_state_str(THD * thd)905 extern "C" const char *wsrep_thd_conflict_state_str(THD *thd)
906 {
907   return
908     (!thd) ? "void" :
909     (thd->wsrep_conflict_state == NO_CONFLICT)      ? "no conflict"  :
910     (thd->wsrep_conflict_state == MUST_ABORT)       ? "must abort"   :
911     (thd->wsrep_conflict_state == ABORTING)         ? "aborting"     :
912     (thd->wsrep_conflict_state == ABORTED)          ? "aborted"      :
913     (thd->wsrep_conflict_state == MUST_REPLAY)      ? "must replay"  :
914     (thd->wsrep_conflict_state == REPLAYING)        ? "replaying"    :
915     (thd->wsrep_conflict_state == RETRY_AUTOCOMMIT) ? "retrying"     :
916     (thd->wsrep_conflict_state == CERT_FAILURE)     ? "cert failure" : "void";
917 }
918 
wsrep_thd_ws_handle(THD * thd)919 extern "C" wsrep_ws_handle_t* wsrep_thd_ws_handle(THD *thd)
920 {
921   return &thd->wsrep_ws_handle;
922 }
923 
wsrep_thd_LOCK(THD * thd)924 extern "C" void wsrep_thd_LOCK(THD *thd)
925 {
926   mysql_mutex_lock(&thd->LOCK_wsrep_thd);
927 }
wsrep_thd_UNLOCK(THD * thd)928 extern "C" void wsrep_thd_UNLOCK(THD *thd)
929 {
930   mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
931 }
wsrep_thd_query_start(THD * thd)932 extern "C" time_t wsrep_thd_query_start(THD *thd)
933 {
934   return thd->query_start();
935 }
wsrep_thd_wsrep_rand(THD * thd)936 extern "C" uint32 wsrep_thd_wsrep_rand(THD *thd)
937 {
938   return thd->wsrep_rand;
939 }
wsrep_thd_thread_id(THD * thd)940 extern "C" my_thread_id wsrep_thd_thread_id(THD *thd)
941 {
942   return thd->thread_id();
943 }
wsrep_thd_trx_seqno(THD * thd)944 extern "C" wsrep_seqno_t wsrep_thd_trx_seqno(THD *thd)
945 {
946   return (thd) ? thd->wsrep_trx_meta.gtid.seqno : WSREP_SEQNO_UNDEFINED;
947 }
wsrep_thd_query_id(THD * thd)948 extern "C" query_id_t wsrep_thd_query_id(THD *thd)
949 {
950   return thd->query_id;
951 }
wsrep_thd_next_trx_id(THD * thd)952 extern "C" wsrep_trx_id_t wsrep_thd_next_trx_id(THD *thd)
953 {
954   return thd->wsrep_next_trx_id();
955 }
wsrep_thd_set_next_trx_id(THD * thd)956 extern "C" void wsrep_thd_set_next_trx_id(THD *thd)
957 {
958   if (thd->wsrep_trx_id() == WSREP_UNDEFINED_TRX_ID)
959   {
960     thd->set_wsrep_next_trx_id(thd->query_id);
961   }
962 }
wsrep_thd_trx_id(THD * thd)963 extern "C" wsrep_trx_id_t wsrep_thd_trx_id(THD *thd)
964 {
965   return thd->wsrep_trx_id();
966 }
wsrep_thd_query(THD * thd)967 extern "C" const char *wsrep_thd_query(THD *thd)
968 {
969   return (thd) ? thd->query().str : NULL;
970 }
wsrep_thd_wsrep_last_query_id(THD * thd)971 extern "C" query_id_t wsrep_thd_wsrep_last_query_id(THD *thd)
972 {
973   return thd->wsrep_last_query_id;
974 }
wsrep_thd_set_wsrep_last_query_id(THD * thd,query_id_t id)975 extern "C" void wsrep_thd_set_wsrep_last_query_id(THD *thd, query_id_t id)
976 {
977   thd->wsrep_last_query_id= id;
978 }
wsrep_thd_awake(THD * thd,my_bool signal)979 extern "C" void wsrep_thd_awake(THD *thd, my_bool signal)
980 {
981   if (signal)
982   {
983     mysql_mutex_lock(&thd->LOCK_thd_data);
984     thd->awake(THD::KILL_QUERY);
985     mysql_mutex_unlock(&thd->LOCK_thd_data);
986   }
987   else
988   {
989     mysql_mutex_lock(&LOCK_wsrep_replaying);
990     mysql_cond_broadcast(&COND_wsrep_replaying);
991     mysql_mutex_unlock(&LOCK_wsrep_replaying);
992   }
993 }
wsrep_thd_retry_counter(THD * thd)994 extern "C" int wsrep_thd_retry_counter(THD *thd)
995 {
996   return(thd->wsrep_retry_counter);
997 }
998 
999 extern int
wsrep_trx_order_before(void * thd1,void * thd2)1000 wsrep_trx_order_before(void *thd1, void *thd2)
1001 {
1002     if (wsrep_thd_trx_seqno((THD*)thd1) < wsrep_thd_trx_seqno((THD*)thd2)) {
1003         WSREP_DEBUG("BF conflict, order: %lld %lld\n",
1004                     (long long)wsrep_thd_trx_seqno((THD*)thd1),
1005                     (long long)wsrep_thd_trx_seqno((THD*)thd2));
1006         return 1;
1007     }
1008     WSREP_DEBUG("waiting for BF, trx order: %lld %lld\n",
1009                 (long long)wsrep_thd_trx_seqno((THD*)thd1),
1010                 (long long)wsrep_thd_trx_seqno((THD*)thd2));
1011     return 0;
1012 }
1013 extern "C" int
wsrep_trx_is_aborting(void * thd_ptr)1014 wsrep_trx_is_aborting(void *thd_ptr)
1015 {
1016   mysql_mutex_lock(&((THD*)thd_ptr)->LOCK_wsrep_thd);
1017   if (thd_ptr) {
1018     if ((((THD *)thd_ptr)->wsrep_conflict_state == MUST_ABORT) ||
1019         (((THD *)thd_ptr)->wsrep_conflict_state == ABORTING)) {
1020       mysql_mutex_unlock(&((THD*)thd_ptr)->LOCK_wsrep_thd);
1021       return 1;
1022     }
1023   }
1024   mysql_mutex_unlock(&((THD*)thd_ptr)->LOCK_wsrep_thd);
1025   return 0;
1026 }
1027 #endif
1028 
1029 /**
1030   Provide a handler data setter to simplify coding
1031   @see thd_set_ha_data() definition in plugin.h
1032 */
1033 extern "C"
thd_set_ha_data(THD * thd,const struct handlerton * hton,const void * ha_data)1034 void thd_set_ha_data(THD *thd, const struct handlerton *hton,
1035                      const void *ha_data)
1036 {
1037   plugin_ref *lock= &thd->ha_data[hton->slot].lock;
1038   if (ha_data && !*lock)
1039     *lock= ha_lock_engine(NULL, (handlerton*) hton);
1040   else if (!ha_data && *lock)
1041   {
1042     plugin_unlock(NULL, *lock);
1043     *lock= NULL;
1044   }
1045   *thd_ha_data(thd, hton)= (void*) ha_data;
1046 }
1047 
1048 
1049 extern "C"
thd_test_options(const THD * thd,long long test_options)1050 long long thd_test_options(const THD *thd, long long test_options)
1051 {
1052   return thd->variables.option_bits & test_options;
1053 }
1054 
1055 extern "C"
thd_sql_command(const THD * thd)1056 int thd_sql_command(const THD *thd)
1057 {
1058   return (int) thd->lex->sql_command;
1059 }
1060 
1061 extern "C"
thd_tx_isolation(const THD * thd)1062 int thd_tx_isolation(const THD *thd)
1063 {
1064   return (int) thd->tx_isolation;
1065 }
1066 
1067 extern "C"
thd_tx_is_read_only(const THD * thd)1068 int thd_tx_is_read_only(const THD *thd)
1069 {
1070   return (int) thd->tx_read_only;
1071 }
1072 
1073 extern "C"
thd_tx_priority(const THD * thd)1074 int thd_tx_priority(const THD* thd)
1075 {
1076   return (thd->thd_tx_priority != 0
1077           ? thd->thd_tx_priority
1078           : thd->tx_priority);
1079 }
1080 
1081 extern "C"
thd_tx_arbitrate(THD * requestor,THD * holder)1082 THD* thd_tx_arbitrate(THD *requestor, THD* holder)
1083 {
1084  /* Should be different sessions. */
1085   assert(holder != requestor);
1086 
1087  return(thd_tx_priority(requestor) == thd_tx_priority(holder)
1088 	? requestor
1089 	: ((thd_tx_priority(requestor)
1090 	    > thd_tx_priority(holder)) ? holder : requestor));
1091 }
1092 
thd_tx_is_dd_trx(const THD * thd)1093 int thd_tx_is_dd_trx(const THD *thd)
1094 {
1095   return (int) thd->is_attachable_ro_transaction_active();
1096 }
1097 
1098 extern "C"
thd_inc_row_count(THD * thd)1099 void thd_inc_row_count(THD *thd)
1100 {
1101   thd->get_stmt_da()->inc_current_row_for_condition();
1102 }
1103 
1104 
1105 /**
1106   Dumps a text description of a thread, its security context
1107   (user, host) and the current query.
1108 
1109   @param thd thread context
1110   @param buffer pointer to preferred result buffer
1111   @param length length of buffer
1112   @param max_query_len how many chars of query to copy (0 for all)
1113 
1114   @return Pointer to string
1115 */
1116 
1117 extern "C"
thd_security_context(THD * thd,char * buffer,size_t length,size_t max_query_len)1118 char *thd_security_context(THD *thd, char *buffer, size_t length,
1119                            size_t max_query_len)
1120 {
1121   String str(buffer, length, &my_charset_latin1);
1122   Security_context *sctx= &thd->m_main_security_ctx;
1123   char header[256];
1124   size_t len;
1125   /*
1126     The pointers thd->query and thd->proc_info might change since they are
1127     being modified concurrently. This is acceptable for proc_info since its
1128     values doesn't have to very accurate and the memory it points to is static,
1129     but we need to attempt a snapshot on the pointer values to avoid using NULL
1130     values. The pointer to thd->query however, doesn't point to static memory
1131     and has to be protected by LOCK_thd_query or risk pointing to
1132     uninitialized memory.
1133   */
1134   const char *proc_info= thd->proc_info;
1135 
1136   len= my_snprintf(header, sizeof(header),
1137                    "MySQL thread id %u, OS thread handle %lu, query id %lu",
1138                    thd->thread_id(), (ulong)thd->real_id, (ulong)thd->query_id);
1139   str.length(0);
1140   str.append(header, len);
1141 
1142   if (sctx->host().length)
1143   {
1144     str.append(' ');
1145     str.append(sctx->host().str);
1146   }
1147 
1148   if (sctx->ip().length)
1149   {
1150     str.append(' ');
1151     str.append(sctx->ip().str);
1152   }
1153 
1154   if (sctx->user().str)
1155   {
1156     str.append(' ');
1157     str.append(sctx->user().str);
1158   }
1159 
1160   if (proc_info)
1161   {
1162     str.append(' ');
1163     str.append(proc_info);
1164   }
1165 
1166   mysql_mutex_lock(&thd->LOCK_thd_query);
1167 
1168   if (thd->query().str)
1169   {
1170     if (max_query_len < 1)
1171       len= thd->query().length;
1172     else
1173       len= min(thd->query().length, max_query_len);
1174     str.append('\n');
1175     str.append(thd->query().str, len);
1176   }
1177 
1178   mysql_mutex_unlock(&thd->LOCK_thd_query);
1179 
1180   if (str.c_ptr_safe() == buffer)
1181     return buffer;
1182 
1183   /*
1184     We have to copy the new string to the destination buffer because the string
1185     was reallocated to a larger buffer to be able to fit.
1186   */
1187   assert(buffer != NULL);
1188   length= min(str.length(), length-1);
1189   memcpy(buffer, str.c_ptr_quick(), length);
1190   /* Make sure that the new string is null terminated */
1191   buffer[length]= '\0';
1192   return buffer;
1193 }
1194 
1195 
1196 /**
1197   Returns the partition_info working copy.
1198   Used to see if a table should be created with partitioning.
1199 
1200   @param thd thread context
1201 
1202   @return Pointer to the working copy of partition_info or NULL.
1203 */
1204 
1205 extern "C"
thd_get_work_part_info(THD * thd)1206 partition_info *thd_get_work_part_info(THD *thd)
1207 {
1208   return thd->work_part_info;
1209 }
1210 
1211 
1212 /**
1213   Implementation of Drop_table_error_handler::handle_condition().
1214   The reason in having this implementation is to silence technical low-level
1215   warnings during DROP TABLE operation. Currently we don't want to expose
1216   the following warnings during DROP TABLE:
1217     - Some of table files are missed or invalid (the table is going to be
1218       deleted anyway, so why bother that something was missed);
1219     - A trigger associated with the table does not have DEFINER (One of the
1220       MySQL specifics now is that triggers are loaded for the table being
1221       dropped. So, we may have a warning that trigger does not have DEFINER
1222       attribute during DROP TABLE operation).
1223 
1224   @return true if the condition is handled.
1225 */
handle_condition(THD * thd,uint sql_errno,const char * sqlstate,Sql_condition::enum_severity_level * level,const char * msg)1226 bool Drop_table_error_handler::handle_condition(THD *thd,
1227                                                 uint sql_errno,
1228                                                 const char* sqlstate,
1229                                                 Sql_condition::enum_severity_level *level,
1230                                                 const char* msg)
1231 {
1232   return ((sql_errno == EE_DELETE && my_errno() == ENOENT) ||
1233           sql_errno == ER_TRG_NO_DEFINER);
1234 }
1235 
set_open_tables_state(Open_tables_state * state)1236 void Open_tables_state::set_open_tables_state(Open_tables_state *state)
1237 {
1238   this->open_tables= state->open_tables;
1239 
1240   this->temporary_tables= state->temporary_tables;
1241   this->derived_tables= state->derived_tables;
1242 
1243   this->lock= state->lock;
1244   this->extra_lock= state->extra_lock;
1245 
1246   this->locked_tables_mode= state->locked_tables_mode;
1247 
1248   this->state_flags= state->state_flags;
1249 
1250   this->m_reprepare_observers= state->m_reprepare_observers;
1251 }
1252 
1253 
reset_open_tables_state()1254 void Open_tables_state::reset_open_tables_state()
1255 {
1256   open_tables= NULL;
1257   temporary_tables= NULL;
1258   derived_tables= NULL;
1259   lock= NULL;
1260   extra_lock= NULL;
1261   locked_tables_mode= LTM_NONE;
1262   state_flags= 0U;
1263   reset_reprepare_observers();
1264 }
1265 
1266 
1267 #ifdef WITH_WSREP
THD(bool enable_plugins,bool is_applier)1268 THD::THD(bool enable_plugins, bool is_applier)
1269 #else
1270 THD::THD(bool enable_plugins)
1271 #endif
1272   :Query_arena(&main_mem_root, STMT_CONVENTIONAL_EXECUTION),
1273    mark_used_columns(MARK_COLUMNS_READ),
1274    want_privilege(0),
1275    lex(&main_lex),
1276    gtid_executed_warning_issued(false),
1277    m_query_string(NULL_CSTR),
1278    m_db(NULL_CSTR),
1279    rli_fake(0), rli_slave(NULL),
1280 #ifdef EMBEDDED_LIBRARY
1281    mysql(NULL),
1282 #endif
1283    initial_status_var(NULL),
1284    status_var_aggregated(false),
1285    query_plan(this),
1286    m_current_stage_key(0),
1287    current_mutex(NULL),
1288    current_cond(NULL),
1289    in_sub_stmt(0),
1290    fill_status_recursion_level(0),
1291    fill_variables_recursion_level(0),
1292    binlog_row_event_extra_data(NULL),
1293    skip_readonly_check(false),
1294    binlog_unsafe_warning_flags(0),
1295    binlog_table_maps(0),
1296    binlog_accessed_db_names(NULL),
1297    m_trans_log_file(NULL),
1298    m_trans_fixed_log_file(NULL),
1299    m_trans_end_pos(0),
1300    m_transaction(new Transaction_ctx()),
1301    m_attachable_trx(NULL),
1302    table_map_for_update(0),
1303    m_examined_row_count(0),
1304    m_stage_progress_psi(NULL),
1305    m_digest(NULL),
1306    m_statement_psi(NULL),
1307    m_transaction_psi(NULL),
1308    m_idle_psi(NULL),
1309    m_server_idle(false),
1310    user_var_events(key_memory_user_var_entry),
1311    next_to_commit(NULL),
1312    binlog_need_explicit_defaults_ts(false),
1313    is_fatal_error(0),
1314    transaction_rollback_request(0),
1315    is_fatal_sub_stmt_error(false),
1316    rand_used(0),
1317    time_zone_used(0),
1318    in_lock_tables(0),
1319    bootstrap(0),
1320    derived_tables_processing(FALSE),
1321    sp_runtime_ctx(NULL),
1322 #ifdef WITH_WSREP
1323    wsrep_applier(is_applier),
1324    wsrep_applier_closing(FALSE),
1325    wsrep_client_thread(0),
1326    wsrep_po_handle(WSREP_PO_INITIALIZER),
1327    wsrep_po_cnt(0),
1328    wsrep_po_in_trans(FALSE),
1329    wsrep_apply_format(0),
1330    wsrep_apply_toi(false),
1331    wsrep_gtid_event_buf(NULL),
1332    wsrep_gtid_event_buf_len(0),
1333 #endif
1334    m_parser_state(NULL),
1335    work_part_info(NULL),
1336 #ifndef EMBEDDED_LIBRARY
1337    // No need to instrument, highly unlikely to have that many plugins.
1338    audit_class_plugins(PSI_NOT_INSTRUMENTED),
1339    audit_class_mask(PSI_NOT_INSTRUMENTED),
1340 #endif
1341 #if defined(ENABLED_DEBUG_SYNC)
1342    debug_sync_control(0),
1343 #endif /* defined(ENABLED_DEBUG_SYNC) */
1344    m_enable_plugins(enable_plugins),
1345 #ifdef HAVE_GTID_NEXT_LIST
1346    owned_gtid_set(global_sid_map),
1347 #endif
1348    skip_gtid_rollback(false),
1349    is_commit_in_middle_of_statement(false),
1350    has_gtid_consistency_violation(false),
1351    main_da(false),
1352    m_parser_da(false),
1353    m_query_rewrite_plugin_da(false),
1354    m_query_rewrite_plugin_da_ptr(&m_query_rewrite_plugin_da),
1355    m_stmt_da(&main_da),
1356    duplicate_slave_id(false),
1357    is_a_srv_session_thd(false)
1358 {
1359   main_lex.reset();
1360   set_psi(NULL);
1361   mdl_context.init(this);
1362   init_sql_alloc(key_memory_thd_main_mem_root,
1363                  &main_mem_root,
1364                  global_system_variables.query_alloc_block_size,
1365                  global_system_variables.query_prealloc_size);
1366   stmt_arena= this;
1367   thread_stack= 0;
1368   m_catalog.str= "std";
1369   m_catalog.length= 3;
1370   m_security_ctx= &m_main_security_ctx;
1371   no_errors= 0;
1372   password= 0;
1373   query_start_usec_used= 0;
1374   count_cuted_fields= CHECK_FIELD_IGNORE;
1375   killed= NOT_KILLED;
1376   col_access=0;
1377   is_slave_error= thread_specific_used= FALSE;
1378   my_hash_clear(&handler_tables_hash);
1379   my_hash_clear(&ull_hash);
1380   tmp_table=0;
1381   cuted_fields= 0L;
1382   m_sent_row_count= 0L;
1383   current_found_rows= 0;
1384   previous_found_rows= 0;
1385   is_operating_gtid_table_implicitly= false;
1386   is_operating_substatement_implicitly= false;
1387   m_row_count_func= -1;
1388   statement_id_counter= 0UL;
1389   // Must be reset to handle error with THD's created for init of mysqld
1390   lex->thd= NULL;
1391   lex->set_current_select(0);
1392   utime_after_lock= 0L;
1393   current_linfo =  0;
1394   slave_thread = 0;
1395   memset(&variables, 0, sizeof(variables));
1396   m_thread_id= Global_THD_manager::reserved_thread_id;
1397   file_id = 0;
1398   query_id= 0;
1399   query_name_consts= 0;
1400   db_charset= global_system_variables.collation_database;
1401   memset(ha_data, 0, sizeof(ha_data));
1402   is_killable= false;
1403   binlog_evt_union.do_union= FALSE;
1404   enable_slow_log= 0;
1405   commit_error= CE_NONE;
1406   durability_property= HA_REGULAR_DURABILITY;
1407 #ifndef NDEBUG
1408   dbug_sentry=THD_SENTRY_MAGIC;
1409 #endif
1410 #ifndef EMBEDDED_LIBRARY
1411   mysql_audit_init_thd(this);
1412   net.vio=0;
1413 #endif
1414   system_thread= NON_SYSTEM_THREAD;
1415   cleanup_done= 0;
1416   m_release_resources_done= false;
1417   peer_port= 0;					// For SHOW PROCESSLIST
1418   get_transaction()->m_flags.enabled= true;
1419   active_vio = 0;
1420   m_SSL = NULL;
1421   my_atomic_store32(&m_safe_to_display, 0);
1422   mysql_mutex_init(key_LOCK_thd_data, &LOCK_thd_data, MY_MUTEX_INIT_FAST);
1423   mysql_mutex_init(key_LOCK_thd_query, &LOCK_thd_query, MY_MUTEX_INIT_FAST);
1424   mysql_mutex_init(key_LOCK_thd_sysvar, &LOCK_thd_sysvar, MY_MUTEX_INIT_FAST);
1425   mysql_mutex_init(key_LOCK_query_plan, &LOCK_query_plan, MY_MUTEX_INIT_FAST);
1426   mysql_mutex_init(key_LOCK_current_cond, &LOCK_current_cond,
1427                    MY_MUTEX_INIT_FAST);
1428   mysql_cond_init(key_COND_thr_lock, &COND_thr_lock);
1429 
1430   /* Variables with default values */
1431   proc_info="login";
1432   where= THD::DEFAULT_WHERE;
1433   server_id = ::server_id;
1434   unmasked_server_id = server_id;
1435   slave_net = 0;
1436   set_command(COM_CONNECT);
1437   *scramble= '\0';
1438 
1439 #ifdef WITH_WSREP
1440   mysql_mutex_init(key_LOCK_wsrep_thd, &LOCK_wsrep_thd, MY_MUTEX_INIT_FAST);
1441   mysql_cond_init(key_COND_wsrep_thd, &COND_wsrep_thd);
1442   wsrep_ws_handle.trx_id = WSREP_UNDEFINED_TRX_ID;
1443   wsrep_ws_handle.opaque = NULL;
1444   wsrep_retry_counter     = 0;
1445   wsrep_PA_safe           = true;
1446   wsrep_retry_query       = NULL;
1447   wsrep_retry_query_len   = 0;
1448   wsrep_retry_command     = COM_CONNECT;
1449   wsrep_consistency_check = NO_CONSISTENCY_CHECK;
1450   wsrep_status_vars       = 0;
1451   wsrep_mysql_replicated  = 0;
1452   wsrep_TOI_pre_query     = NULL;
1453   wsrep_TOI_pre_query_len = 0;
1454   wsrep_sync_wait_gtid    = WSREP_GTID_UNDEFINED;
1455   wsrep_affected_rows     = 0;
1456   wsrep_replicate_GTID    = false;
1457   wsrep_skip_wsrep_GTID   = false;
1458   m_wsrep_next_trx_id     = WSREP_UNDEFINED_TRX_ID;
1459 #endif
1460   /* Call to init() below requires fully initialized Open_tables_state. */
1461   reset_open_tables_state();
1462 
1463   init();
1464 #if defined(ENABLED_PROFILING)
1465   profiling.set_thd(this);
1466 #endif
1467   m_user_connect= NULL;
1468   my_hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
1469                (my_hash_get_key) get_var_key,
1470                (my_hash_free_key) free_user_var, 0,
1471                key_memory_user_var_entry);
1472 
1473   sp_proc_cache= NULL;
1474   sp_func_cache= NULL;
1475 
1476   /* Protocol */
1477   m_protocol= &protocol_text;			// Default protocol
1478   protocol_text.init(this);
1479   protocol_binary.init(this);
1480   protocol_text.set_client_capabilities(0); // minimalistic client
1481 
1482   tablespace_op= false;
1483   substitute_null_with_insert_id = FALSE;
1484 
1485   /*
1486     Make sure thr_lock_info_init() is called for threads which do not get
1487     assigned a proper thread_id value but keep using reserved_thread_id.
1488   */
1489   thr_lock_info_init(&lock_info, m_thread_id, &COND_thr_lock);
1490 #ifdef WITH_WSREP
1491   lock_info.mysql_thd= (void *)this;
1492   lock_info.in_lock_tables= false;
1493 #ifdef WSREP_PROC_INFO
1494   wsrep_info[sizeof(wsrep_info) - 1] = '\0'; /* make sure it is 0-terminated */
1495 #endif /* WSREP_PROC_INFO */
1496 #endif /* WITH_WSREP */
1497 
1498   m_internal_handler= NULL;
1499   m_binlog_invoker= FALSE;
1500   memset(&m_invoker_user, 0, sizeof(m_invoker_user));
1501   memset(&m_invoker_host, 0, sizeof(m_invoker_host));
1502 
1503   binlog_next_event_pos.file_name= NULL;
1504   binlog_next_event_pos.pos= 0;
1505 
1506   timer= NULL;
1507   timer_cache= NULL;
1508 
1509   m_token_array= NULL;
1510   if (max_digest_length > 0)
1511   {
1512     m_token_array= (unsigned char*) my_malloc(PSI_INSTRUMENT_ME,
1513                                               max_digest_length,
1514                                               MYF(MY_WME));
1515   }
1516 }
1517 
1518 
set_transaction(Transaction_ctx * transaction_ctx)1519 void THD::set_transaction(Transaction_ctx *transaction_ctx)
1520 {
1521   assert(is_attachable_ro_transaction_active());
1522 
1523   delete m_transaction.release();
1524   m_transaction.reset(transaction_ctx);
1525 }
1526 
1527 
push_internal_handler(Internal_error_handler * handler)1528 void THD::push_internal_handler(Internal_error_handler *handler)
1529 {
1530   if (m_internal_handler)
1531   {
1532     handler->m_prev_internal_handler= m_internal_handler;
1533     m_internal_handler= handler;
1534   }
1535   else
1536     m_internal_handler= handler;
1537 }
1538 
1539 
handle_condition(uint sql_errno,const char * sqlstate,Sql_condition::enum_severity_level * level,const char * msg)1540 bool THD::handle_condition(uint sql_errno,
1541                            const char* sqlstate,
1542                            Sql_condition::enum_severity_level *level,
1543                            const char* msg)
1544 {
1545   if (!m_internal_handler)
1546     return false;
1547 
1548   for (Internal_error_handler *error_handler= m_internal_handler;
1549        error_handler;
1550        error_handler= error_handler->m_prev_internal_handler)
1551   {
1552     if (error_handler->handle_condition(this, sql_errno, sqlstate, level, msg))
1553       return true;
1554   }
1555   return false;
1556 }
1557 
1558 
pop_internal_handler()1559 Internal_error_handler *THD::pop_internal_handler()
1560 {
1561   assert(m_internal_handler != NULL);
1562   Internal_error_handler *popped_handler= m_internal_handler;
1563   m_internal_handler= m_internal_handler->m_prev_internal_handler;
1564   return popped_handler;
1565 }
1566 
1567 
raise_error(uint sql_errno)1568 void THD::raise_error(uint sql_errno)
1569 {
1570   const char* msg= ER(sql_errno);
1571   (void) raise_condition(sql_errno,
1572                          NULL,
1573                          Sql_condition::SL_ERROR,
1574                          msg);
1575 }
1576 
raise_error_printf(uint sql_errno,...)1577 void THD::raise_error_printf(uint sql_errno, ...)
1578 {
1579   va_list args;
1580   char ebuff[MYSQL_ERRMSG_SIZE];
1581   DBUG_ENTER("THD::raise_error_printf");
1582   DBUG_PRINT("my", ("nr: %d  errno: %d", sql_errno, errno));
1583   const char* format= ER(sql_errno);
1584   va_start(args, sql_errno);
1585   my_vsnprintf(ebuff, sizeof(ebuff), format, args);
1586   va_end(args);
1587   (void) raise_condition(sql_errno,
1588                          NULL,
1589                          Sql_condition::SL_ERROR,
1590                          ebuff);
1591   DBUG_VOID_RETURN;
1592 }
1593 
raise_warning(uint sql_errno)1594 void THD::raise_warning(uint sql_errno)
1595 {
1596   const char* msg= ER(sql_errno);
1597   (void) raise_condition(sql_errno,
1598                          NULL,
1599                          Sql_condition::SL_WARNING,
1600                          msg);
1601 }
1602 
raise_warning_printf(uint sql_errno,...)1603 void THD::raise_warning_printf(uint sql_errno, ...)
1604 {
1605   va_list args;
1606   char    ebuff[MYSQL_ERRMSG_SIZE];
1607   DBUG_ENTER("THD::raise_warning_printf");
1608   DBUG_PRINT("enter", ("warning: %u", sql_errno));
1609   const char* format= ER(sql_errno);
1610   va_start(args, sql_errno);
1611   my_vsnprintf(ebuff, sizeof(ebuff), format, args);
1612   va_end(args);
1613   (void) raise_condition(sql_errno,
1614                          NULL,
1615                          Sql_condition::SL_WARNING,
1616                          ebuff);
1617   DBUG_VOID_RETURN;
1618 }
1619 
raise_note(uint sql_errno)1620 void THD::raise_note(uint sql_errno)
1621 {
1622   DBUG_ENTER("THD::raise_note");
1623   DBUG_PRINT("enter", ("code: %d", sql_errno));
1624   if (!(variables.option_bits & OPTION_SQL_NOTES))
1625     DBUG_VOID_RETURN;
1626   const char* msg= ER(sql_errno);
1627   (void) raise_condition(sql_errno,
1628                          NULL,
1629                          Sql_condition::SL_NOTE,
1630                          msg);
1631   DBUG_VOID_RETURN;
1632 }
1633 
raise_note_printf(uint sql_errno,...)1634 void THD::raise_note_printf(uint sql_errno, ...)
1635 {
1636   va_list args;
1637   char    ebuff[MYSQL_ERRMSG_SIZE];
1638   DBUG_ENTER("THD::raise_note_printf");
1639   DBUG_PRINT("enter",("code: %u", sql_errno));
1640   if (!(variables.option_bits & OPTION_SQL_NOTES))
1641     DBUG_VOID_RETURN;
1642   const char* format= ER(sql_errno);
1643   va_start(args, sql_errno);
1644   my_vsnprintf(ebuff, sizeof(ebuff), format, args);
1645   va_end(args);
1646   (void) raise_condition(sql_errno,
1647                          NULL,
1648                          Sql_condition::SL_NOTE,
1649                          ebuff);
1650   DBUG_VOID_RETURN;
1651 }
1652 
1653 
query_start_timeval_trunc(uint decimals)1654 struct timeval THD::query_start_timeval_trunc(uint decimals)
1655 {
1656   struct timeval tv;
1657   tv.tv_sec= start_time.tv_sec;
1658   if (decimals)
1659   {
1660     tv.tv_usec= start_time.tv_usec;
1661     my_timeval_trunc(&tv, decimals);
1662     query_start_usec_used= 1;
1663   }
1664   else
1665   {
1666     tv.tv_usec= 0;
1667   }
1668   return tv;
1669 }
1670 
1671 
raise_condition(uint sql_errno,const char * sqlstate,Sql_condition::enum_severity_level level,const char * msg,bool use_condition_handler)1672 Sql_condition* THD::raise_condition(uint sql_errno,
1673                                     const char* sqlstate,
1674                                     Sql_condition::enum_severity_level level,
1675                                     const char* msg,
1676                                     bool use_condition_handler)
1677 {
1678   DBUG_ENTER("THD::raise_condition");
1679 
1680   if (!(variables.option_bits & OPTION_SQL_NOTES) &&
1681       (level == Sql_condition::SL_NOTE))
1682     DBUG_RETURN(NULL);
1683 
1684   assert(sql_errno != 0);
1685   if (sql_errno == 0) /* Safety in release build */
1686     sql_errno= ER_UNKNOWN_ERROR;
1687   if (msg == NULL)
1688     msg= ER(sql_errno);
1689   if (sqlstate == NULL)
1690    sqlstate= mysql_errno_to_sqlstate(sql_errno);
1691 
1692   if (use_condition_handler &&
1693       handle_condition(sql_errno, sqlstate, &level, msg))
1694     DBUG_RETURN(NULL);
1695 
1696   if (level == Sql_condition::SL_NOTE || level == Sql_condition::SL_WARNING)
1697     got_warning= true;
1698 
1699   query_cache.abort(&query_cache_tls);
1700 
1701   Diagnostics_area *da= get_stmt_da();
1702   if (level == Sql_condition::SL_ERROR)
1703   {
1704     is_slave_error= true; // needed to catch query errors during replication
1705 
1706     if (!da->is_error())
1707     {
1708       set_row_count_func(-1);
1709       da->set_error_status(sql_errno, msg, sqlstate);
1710     }
1711   }
1712 
1713   /*
1714     Avoid pushing a condition for fatal out of memory errors as this will
1715     require memory allocation and therefore might fail. Non fatal out of
1716     memory errors can occur if raised by SIGNAL/RESIGNAL statement.
1717   */
1718   Sql_condition *cond= NULL;
1719   if (!(is_fatal_error && (sql_errno == EE_OUTOFMEMORY ||
1720                            sql_errno == ER_OUTOFMEMORY)))
1721   {
1722     cond= da->push_warning(this, sql_errno, sqlstate, level, msg);
1723   }
1724   DBUG_RETURN(cond);
1725 }
1726 
1727 extern "C"
thd_alloc(MYSQL_THD thd,size_t size)1728 void *thd_alloc(MYSQL_THD thd, size_t size)
1729 {
1730   return thd->alloc(size);
1731 }
1732 
1733 extern "C"
thd_calloc(MYSQL_THD thd,size_t size)1734 void *thd_calloc(MYSQL_THD thd, size_t size)
1735 {
1736   return thd->mem_calloc(size);
1737 }
1738 
1739 extern "C"
thd_strdup(MYSQL_THD thd,const char * str)1740 char *thd_strdup(MYSQL_THD thd, const char *str)
1741 {
1742   return thd->mem_strdup(str);
1743 }
1744 
1745 extern "C"
thd_strmake(MYSQL_THD thd,const char * str,size_t size)1746 char *thd_strmake(MYSQL_THD thd, const char *str, size_t size)
1747 {
1748   return thd->strmake(str, size);
1749 }
1750 
1751 extern "C"
thd_make_lex_string(THD * thd,LEX_STRING * lex_str,const char * str,size_t size,int allocate_lex_string)1752 LEX_STRING *thd_make_lex_string(THD *thd, LEX_STRING *lex_str,
1753                                 const char *str, size_t size,
1754                                 int allocate_lex_string)
1755 {
1756   return thd->make_lex_string(lex_str, str, size,
1757                               (bool) allocate_lex_string);
1758 }
1759 
1760 extern "C"
thd_memdup(MYSQL_THD thd,const void * str,size_t size)1761 void *thd_memdup(MYSQL_THD thd, const void* str, size_t size)
1762 {
1763   return thd->memdup(str, size);
1764 }
1765 
1766 extern "C"
thd_get_xid(const MYSQL_THD thd,MYSQL_XID * xid)1767 void thd_get_xid(const MYSQL_THD thd, MYSQL_XID *xid)
1768 {
1769   *xid = *(MYSQL_XID *) thd->get_transaction()->xid_state()->get_xid();
1770 }
1771 
1772 #if defined(_WIN32)
_current_thd_noinline(void)1773 extern "C"   THD *_current_thd_noinline(void)
1774 {
1775   return my_thread_get_THR_THD();
1776 }
1777 #endif
1778 /*
1779   Init common variables that has to be reset on start and on cleanup_connection
1780 */
1781 
init(void)1782 void THD::init(void)
1783 {
1784   mysql_mutex_lock(&LOCK_global_system_variables);
1785   plugin_thdvar_init(this, m_enable_plugins);
1786   /*
1787     variables= global_system_variables above has reset
1788     variables.pseudo_thread_id to 0. We need to correct it here to
1789     avoid temporary tables replication failure.
1790   */
1791   variables.pseudo_thread_id= m_thread_id;
1792   mysql_mutex_unlock(&LOCK_global_system_variables);
1793 
1794   /*
1795     NOTE: reset_connection command will reset the THD to its default state.
1796     All system variables whose scope is SESSION ONLY should be set to their
1797     default values here.
1798   */
1799   reset_first_successful_insert_id();
1800   user_time.tv_sec= user_time.tv_usec= 0;
1801   start_time.tv_sec= start_time.tv_usec= 0;
1802   set_time();
1803   auto_inc_intervals_forced.empty();
1804   {
1805     ulong tmp;
1806     tmp= sql_rnd_with_mutex();
1807     randominit(&rand, tmp + (ulong) &rand, tmp + (ulong) ::global_query_id);
1808   }
1809 
1810   server_status= SERVER_STATUS_AUTOCOMMIT;
1811   if (variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES)
1812     server_status|= SERVER_STATUS_NO_BACKSLASH_ESCAPES;
1813 
1814   get_transaction()->reset_unsafe_rollback_flags(Transaction_ctx::SESSION);
1815   get_transaction()->reset_unsafe_rollback_flags(Transaction_ctx::STMT);
1816   open_options=ha_open_options;
1817   update_lock_default= (variables.low_priority_updates ?
1818 			TL_WRITE_LOW_PRIORITY :
1819 			TL_WRITE);
1820   insert_lock_default= (variables.low_priority_updates ?
1821                         TL_WRITE_LOW_PRIORITY :
1822                         TL_WRITE_CONCURRENT_INSERT);
1823   tx_isolation= (enum_tx_isolation) variables.tx_isolation;
1824   tx_read_only= variables.tx_read_only;
1825   tx_priority= 0;
1826   thd_tx_priority= 0;
1827   update_charset();
1828   reset_current_stmt_binlog_format_row();
1829   reset_binlog_local_stmt_filter();
1830   memset(&status_var, 0, sizeof(status_var));
1831 #ifdef WITH_WSREP
1832   wsrep_exec_mode= wsrep_applier ? REPL_RECV :  LOCAL_STATE;
1833   wsrep_conflict_state= NO_CONFLICT;
1834   wsrep_thd_set_query_state(this, QUERY_IDLE);
1835   wsrep_last_query_id= 0;
1836   wsrep_trx_meta.gtid= WSREP_GTID_UNDEFINED;
1837   wsrep_trx_meta.depends_on= WSREP_SEQNO_UNDEFINED;
1838   wsrep_converted_lock_session= false;
1839   wsrep_retry_counter= 0;
1840   wsrep_rli= NULL;
1841   wsrep_PA_safe= true;
1842   wsrep_consistency_check = NO_CONSISTENCY_CHECK;
1843   wsrep_mysql_replicated  = 0;
1844   wsrep_TOI_pre_query     = NULL;
1845   wsrep_TOI_pre_query_len = 0;
1846   wsrep_sync_wait_gtid    = WSREP_GTID_UNDEFINED;
1847   wsrep_affected_rows     = 0;
1848   wsrep_replicate_GTID    = false;
1849   wsrep_skip_wsrep_GTID   = false;
1850   wsrep_gtid_event_buf    = NULL;
1851   wsrep_gtid_event_buf_len = 0;
1852   m_wsrep_next_trx_id     = WSREP_UNDEFINED_TRX_ID;
1853 #endif
1854   status_var_aggregated= false;
1855   binlog_row_event_extra_data= 0;
1856 
1857   if (variables.sql_log_bin)
1858     variables.option_bits|= OPTION_BIN_LOG;
1859   else
1860     variables.option_bits&= ~OPTION_BIN_LOG;
1861 
1862 #if defined(ENABLED_DEBUG_SYNC)
1863   /* Initialize the Debug Sync Facility. See debug_sync.cc. */
1864   debug_sync_init_thread(this);
1865 #endif /* defined(ENABLED_DEBUG_SYNC) */
1866 
1867   /* Initialize session_tracker and create all tracker objects */
1868   session_tracker.init(this->charset());
1869   session_tracker.enable(this);
1870 
1871   owned_gtid.clear();
1872   owned_sid.clear();
1873   owned_gtid.dbug_print(NULL, "set owned_gtid (clear) in THD::init");
1874 
1875   rpl_thd_ctx.dependency_tracker_ctx().set_last_session_sequence_number(0);
1876 }
1877 
1878 
1879 /*
1880   Init THD for query processing.
1881   This has to be called once before we call mysql_parse.
1882   See also comments in sql_class.h.
1883 */
1884 
init_for_queries(Relay_log_info * rli)1885 void THD::init_for_queries(Relay_log_info *rli)
1886 {
1887   set_time();
1888   ha_enable_transaction(this,TRUE);
1889 
1890   reset_root_defaults(mem_root, variables.query_alloc_block_size,
1891                       variables.query_prealloc_size);
1892   get_transaction()->init_mem_root_defaults(variables.trans_alloc_block_size,
1893                                             variables.trans_prealloc_size);
1894   get_transaction()->xid_state()->reset();
1895 #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION)
1896   if (rli)
1897   {
1898     if ((rli->deferred_events_collecting= rpl_filter->is_on()))
1899     {
1900       rli->deferred_events= new Deferred_log_events(rli);
1901     }
1902     rli_slave= rli;
1903 
1904     assert(rli_slave->info_thd == this && slave_thread);
1905   }
1906 #endif
1907 }
1908 
1909 
set_new_thread_id()1910 void THD::set_new_thread_id()
1911 {
1912   m_thread_id= Global_THD_manager::get_instance()->get_new_thread_id();
1913   variables.pseudo_thread_id= m_thread_id;
1914   thr_lock_info_init(&lock_info, m_thread_id, &COND_thr_lock);
1915 }
1916 
1917 
1918 /*
1919   Do what's needed when one invokes change user
1920 
1921   SYNOPSIS
1922     cleanup_connection()
1923 
1924   IMPLEMENTATION
1925     Reset all resources that are connection specific
1926 */
1927 
1928 
cleanup_connection(void)1929 void THD::cleanup_connection(void)
1930 {
1931   mysql_mutex_lock(&LOCK_status);
1932   add_to_status(&global_status_var, &status_var, true);
1933   mysql_mutex_unlock(&LOCK_status);
1934 
1935   cleanup();
1936 #if defined(ENABLED_DEBUG_SYNC)
1937   /* End the Debug Sync Facility. See debug_sync.cc. */
1938   debug_sync_end_thread(this);
1939 #endif /* defined(ENABLED_DEBUG_SYNC) */
1940   killed= NOT_KILLED;
1941   cleanup_done= 0;
1942   init();
1943   stmt_map.reset();
1944   my_hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
1945                (my_hash_get_key) get_var_key,
1946                (my_hash_free_key) free_user_var, 0,
1947                key_memory_user_var_entry);
1948   sp_cache_clear(&sp_proc_cache);
1949   sp_cache_clear(&sp_func_cache);
1950 
1951   clear_error();
1952   // clear the warnings
1953   get_stmt_da()->reset_condition_info(this);
1954   // clear profiling information
1955 #if defined(ENABLED_PROFILING)
1956   profiling.cleanup();
1957 #endif
1958 
1959 #ifndef NDEBUG
1960     /* DEBUG code only (begin) */
1961     bool check_cleanup= FALSE;
1962     DBUG_EXECUTE_IF("debug_test_cleanup_connection", check_cleanup= TRUE;);
1963     if(check_cleanup)
1964     {
1965       /* isolation level should be default */
1966       assert(variables.tx_isolation == ISO_REPEATABLE_READ);
1967       /* check autocommit is ON by default */
1968       assert(server_status == SERVER_STATUS_AUTOCOMMIT);
1969       /* check prepared stmts are cleaned up */
1970       assert(prepared_stmt_count == 0);
1971       /* check diagnostic area is cleaned up */
1972       assert(get_stmt_da()->status() == Diagnostics_area::DA_EMPTY);
1973       /* check if temp tables are deleted */
1974       assert(temporary_tables == NULL);
1975       /* check if tables are unlocked */
1976       assert(locked_tables_list.locked_tables() == NULL);
1977     }
1978     /* DEBUG code only (end) */
1979 #endif
1980 
1981 }
1982 
1983 
1984 /*
1985   Do what's needed when one invokes change user.
1986   Also used during THD::release_resources, i.e. prior to THD destruction.
1987 */
cleanup(void)1988 void THD::cleanup(void)
1989 {
1990   Transaction_ctx *trn_ctx= get_transaction();
1991   XID_STATE *xs= trn_ctx->xid_state();
1992 
1993   DBUG_ENTER("THD::cleanup");
1994   assert(cleanup_done == 0);
1995   DEBUG_SYNC(this, "thd_cleanup_start");
1996 
1997   killed= KILL_CONNECTION;
1998   if (trn_ctx->xid_state()->has_state(XID_STATE::XA_PREPARED))
1999   {
2000     transaction_cache_detach(trn_ctx);
2001   }
2002   else
2003   {
2004     xs->set_state(XID_STATE::XA_NOTR);
2005     trans_rollback(this);
2006     transaction_cache_delete(trn_ctx);
2007   }
2008 
2009   locked_tables_list.unlock_locked_tables(this);
2010   mysql_ha_cleanup(this);
2011 
2012   assert(open_tables == NULL);
2013   /*
2014     If the thread was in the middle of an ongoing transaction (rolled
2015     back a few lines above) or under LOCK TABLES (unlocked the tables
2016     and left the mode a few lines above), there will be outstanding
2017     metadata locks. Release them.
2018   */
2019   mdl_context.release_transactional_locks();
2020 
2021   /* Release the global read lock, if acquired. */
2022   if (global_read_lock.is_acquired())
2023     global_read_lock.unlock_global_read_lock(this);
2024 
2025   mysql_ull_cleanup(this);
2026   /*
2027     All locking service locks must be released on disconnect.
2028   */
2029   release_all_locking_service_locks(this);
2030 
2031   /* All metadata locks must have been released by now. */
2032   assert(!mdl_context.has_locks());
2033 
2034   /* Protects user_vars. */
2035   mysql_mutex_lock(&LOCK_thd_data);
2036   my_hash_free(&user_vars);
2037   mysql_mutex_unlock(&LOCK_thd_data);
2038 
2039   /*
2040     When we call drop table for temporary tables, the
2041     user_var_events container is not cleared this might
2042     cause error if the container was filled before the
2043     drop table command is called.
2044     So call this before calling close_temporary_tables.
2045   */
2046   user_var_events.clear();
2047   close_temporary_tables(this);
2048   sp_cache_clear(&sp_proc_cache);
2049   sp_cache_clear(&sp_func_cache);
2050 
2051   /*
2052     Actions above might generate events for the binary log, so we
2053     commit the current transaction coordinator after executing cleanup
2054     actions.
2055    */
2056   if (tc_log && !trn_ctx->xid_state()->has_state(XID_STATE::XA_PREPARED))
2057     tc_log->commit(this, true);
2058 
2059   /*
2060     Destroy trackers only after finishing manipulations with transaction
2061     state to avoid issues with Transaction_state_tracker.
2062   */
2063   session_tracker.deinit();
2064 
2065   cleanup_done=1;
2066   DBUG_VOID_RETURN;
2067 }
2068 
2069 
2070 /**
2071   Release most resources, prior to THD destruction.
2072  */
release_resources()2073 void THD::release_resources()
2074 {
2075   assert(m_release_resources_done == false);
2076 
2077   Global_THD_manager::get_instance()->release_thread_id(m_thread_id);
2078 
2079   /* Ensure that no one is using THD */
2080   mysql_mutex_lock(&LOCK_thd_data);
2081   mysql_mutex_lock(&LOCK_query_plan);
2082 
2083   /* Close connection */
2084 #ifndef EMBEDDED_LIBRARY
2085   if (is_classic_protocol() && get_protocol_classic()->get_vio())
2086   {
2087     vio_delete(get_protocol_classic()->get_vio());
2088     get_protocol_classic()->end_net();
2089   }
2090 #endif
2091 
2092   /* modification plan for UPDATE/DELETE should be freed. */
2093   assert(query_plan.get_modification_plan() == NULL);
2094   mysql_mutex_unlock(&LOCK_query_plan);
2095   mysql_mutex_unlock(&LOCK_thd_data);
2096   mysql_mutex_lock(&LOCK_thd_query);
2097   mysql_mutex_unlock(&LOCK_thd_query);
2098 
2099   stmt_map.reset();                     /* close all prepared statements */
2100   if (!cleanup_done)
2101     cleanup();
2102 
2103   mdl_context.destroy();
2104   ha_close_connection(this);
2105 
2106   /*
2107     Debug sync system must be closed after ha_close_connection, because
2108     DEBUG_SYNC is used in InnoDB connection handlerton close.
2109   */
2110 #if defined(ENABLED_DEBUG_SYNC)
2111   /* End the Debug Sync Facility. See debug_sync.cc. */
2112   debug_sync_end_thread(this);
2113 #endif /* defined(ENABLED_DEBUG_SYNC) */
2114 
2115   plugin_thdvar_cleanup(this, m_enable_plugins);
2116 
2117   assert(timer == NULL);
2118 
2119   if (timer_cache)
2120     thd_timer_destroy(timer_cache);
2121 
2122 #ifndef EMBEDDED_LIBRARY
2123   if (rli_fake)
2124   {
2125     rli_fake->end_info();
2126     delete rli_fake;
2127     rli_fake= NULL;
2128   }
2129   mysql_audit_free_thd(this);
2130 #endif
2131 
2132   if (current_thd == this)
2133     restore_globals();
2134 
2135   mysql_mutex_lock(&LOCK_status);
2136   add_to_status(&global_status_var, &status_var, false);
2137   /*
2138     Status queries after this point should not aggregate THD::status_var
2139     since the values has been added to global_status_var.
2140     The status values are not reset so that they can still be read
2141     by performance schema.
2142   */
2143   status_var_aggregated= true;
2144   mysql_mutex_unlock(&LOCK_status);
2145 
2146   m_release_resources_done= true;
2147 #ifdef WITH_WSREP
2148   mysql_mutex_lock(&LOCK_wsrep_thd);
2149   mysql_mutex_unlock(&LOCK_wsrep_thd);
2150   mysql_mutex_destroy(&LOCK_wsrep_thd);
2151   mysql_cond_destroy(&COND_wsrep_thd);
2152   if (wsrep_rli)
2153   {
2154     delete wsrep_rli->current_mts_submode;
2155     wsrep_rli->current_mts_submode = 0;
2156     delete wsrep_rli;
2157     if (rli_slave == wsrep_rli) {
2158       rli_slave = NULL;
2159     }
2160     wsrep_rli = NULL;
2161   }
2162   wsrep_free_status(this);
2163 #endif
2164 }
2165 
2166 
~THD()2167 THD::~THD()
2168 {
2169   THD_CHECK_SENTRY(this);
2170   DBUG_ENTER("~THD()");
2171   DBUG_PRINT("info", ("THD dtor, this %p", this));
2172 
2173   if (!m_release_resources_done)
2174     release_resources();
2175 
2176   clear_next_event_pos();
2177 
2178   /* Ensure that no one is using THD */
2179   mysql_mutex_lock(&LOCK_thd_data);
2180   mysql_mutex_unlock(&LOCK_thd_data);
2181   mysql_mutex_lock(&LOCK_thd_query);
2182   mysql_mutex_unlock(&LOCK_thd_query);
2183 
2184   assert(!m_attachable_trx);
2185 
2186   my_free(const_cast<char*>(m_db.str));
2187   m_db= NULL_CSTR;
2188   get_transaction()->free_memory(MYF(0));
2189   mysql_mutex_destroy(&LOCK_query_plan);
2190   mysql_mutex_destroy(&LOCK_thd_data);
2191   mysql_mutex_destroy(&LOCK_thd_query);
2192   mysql_mutex_destroy(&LOCK_thd_sysvar);
2193   mysql_mutex_destroy(&LOCK_current_cond);
2194   mysql_cond_destroy(&COND_thr_lock);
2195 #ifndef NDEBUG
2196   dbug_sentry= THD_SENTRY_GONE;
2197 #endif
2198 
2199 #ifndef EMBEDDED_LIBRARY
2200   if (variables.gtid_next_list.gtid_set != NULL)
2201   {
2202 #ifdef HAVE_GTID_NEXT_LIST
2203     delete variables.gtid_next_list.gtid_set;
2204     variables.gtid_next_list.gtid_set= NULL;
2205     variables.gtid_next_list.is_non_null= false;
2206 #else
2207     assert(0);
2208 #endif
2209   }
2210   if (rli_slave)
2211     rli_slave->cleanup_after_session();
2212   /*
2213     As slaves can be added in one mysql command like COM_REGISTER_SLAVE
2214     but then need to be removed on error scenarios, we call this method
2215     here.
2216   */
2217   unregister_slave(this, true, true);
2218 #endif
2219 
2220   free_root(&main_mem_root, MYF(0));
2221 
2222   if (m_token_array != NULL)
2223   {
2224     my_free(m_token_array);
2225   }
2226   DBUG_VOID_RETURN;
2227 }
2228 
2229 
2230 /*
2231   Add all status variables to another status variable array
2232 
2233   SYNOPSIS
2234    add_to_status()
2235    to_var       add to this array
2236    from_var     from this array
2237    reset_from_var if true, then memset from_var variable with 0
2238 
2239   NOTES
2240     This function assumes that all variables are longlong/ulonglong.
2241     If this assumption will change, then we have to explictely add
2242     the other variables after the while loop
2243 */
2244 
add_to_status(STATUS_VAR * to_var,STATUS_VAR * from_var,bool reset_from_var)2245 void add_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var, bool reset_from_var)
2246 {
2247   int        c;
2248   ulonglong *end= (ulonglong*) ((uchar*) to_var +
2249                                 offsetof(STATUS_VAR, LAST_STATUS_VAR) +
2250                                 sizeof(ulonglong));
2251   ulonglong *to= (ulonglong*) to_var, *from= (ulonglong*) from_var;
2252 
2253   while (to != end)
2254     *(to++)+= *(from++);
2255 
2256   to_var->com_other+= from_var->com_other;
2257 
2258   for (c= 0; c< SQLCOM_END; c++)
2259     to_var->com_stat[(uint) c] += from_var->com_stat[(uint) c];
2260 
2261   if (reset_from_var)
2262   {
2263     memset (from_var, 0, sizeof(*from_var));
2264   }
2265 }
2266 
2267 /*
2268   Add the difference between two status variable arrays to another one.
2269 
2270   SYNOPSIS
2271     add_diff_to_status
2272     to_var       add to this array
2273     from_var     from this array
2274     dec_var      minus this array
2275 
2276   NOTE
2277     This function assumes that all variables are longlong/ulonglong.
2278 */
2279 
add_diff_to_status(STATUS_VAR * to_var,STATUS_VAR * from_var,STATUS_VAR * dec_var)2280 void add_diff_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var,
2281                         STATUS_VAR *dec_var)
2282 {
2283   int        c;
2284   ulonglong *end= (ulonglong*) ((uchar*) to_var + offsetof(STATUS_VAR, LAST_STATUS_VAR) +
2285                                                   sizeof(ulonglong));
2286   ulonglong *to= (ulonglong*) to_var,
2287             *from= (ulonglong*) from_var,
2288             *dec= (ulonglong*) dec_var;
2289 
2290   while (to != end)
2291     *(to++)+= *(from++) - *(dec++);
2292 
2293   to_var->com_other+= from_var->com_other - dec_var->com_other;
2294 
2295   for (c= 0; c< SQLCOM_END; c++)
2296     to_var->com_stat[(uint) c] += from_var->com_stat[(uint) c] -dec_var->com_stat[(uint) c];
2297 }
2298 
2299 
2300 /**
2301   Awake a thread.
2302 
2303   @param[in]  state_to_set    value for THD::killed
2304 
2305   This is normally called from another thread's THD object.
2306 
2307   @note Do always call this while holding LOCK_thd_data.
2308 */
2309 
awake(THD::killed_state state_to_set)2310 void THD::awake(THD::killed_state state_to_set)
2311 {
2312   DBUG_ENTER("THD::awake");
2313   DBUG_PRINT("enter", ("this: %p current_thd: %p", this, current_thd));
2314   THD_CHECK_SENTRY(this);
2315   mysql_mutex_assert_owner(&LOCK_thd_data);
2316 
2317   /*
2318     Set killed flag if the connection is being killed (state_to_set
2319     is KILL_CONNECTION) or the connection is processing a query
2320     (state_to_set is KILL_QUERY and m_server_idle flag is not set).
2321     If the connection is idle and state_to_set is KILL QUERY, the
2322     the killed flag is not set so that it doesn't affect the next
2323     command incorrectly.
2324   */
2325   if (this->m_server_idle && state_to_set == KILL_QUERY)
2326   { /* nothing */ }
2327   else
2328   {
2329     killed= state_to_set;
2330   }
2331 
2332   if (state_to_set != THD::KILL_QUERY && state_to_set != THD::KILL_TIMEOUT)
2333   {
2334     if (this != current_thd)
2335     {
2336       /*
2337         Before sending a signal, let's close the socket of the thread
2338         that is being killed ("this", which is not the current thread).
2339         This is to make sure it does not block if the signal is lost.
2340         This needs to be done only on platforms where signals are not
2341         a reliable interruption mechanism.
2342 
2343         Note that the downside of this mechanism is that we could close
2344         the connection while "this" target thread is in the middle of
2345         sending a result to the application, thus violating the client-
2346         server protocol.
2347 
2348         On the other hand, without closing the socket we have a race
2349         condition. If "this" target thread passes the check of
2350         thd->killed, and then the current thread runs through
2351         THD::awake(), sets the 'killed' flag and completes the
2352         signaling, and then the target thread runs into read(), it will
2353         block on the socket. As a result of the discussions around
2354         Bug#37780, it has been decided that we accept the race
2355         condition. A second KILL awakes the target from read().
2356 
2357         If we are killing ourselves, we know that we are not blocked.
2358         We also know that we will check thd->killed before we go for
2359         reading the next statement.
2360       */
2361 
2362       shutdown_active_vio();
2363     }
2364 
2365     /* Send an event to the scheduler that a thread should be killed. */
2366     if (!slave_thread)
2367       MYSQL_CALLBACK(Connection_handler_manager::event_functions,
2368                      post_kill_notification, (this));
2369   }
2370 
2371   /* Interrupt target waiting inside a storage engine. */
2372   if (state_to_set != THD::NOT_KILLED)
2373     ha_kill_connection(this);
2374 
2375   if (state_to_set == THD::KILL_TIMEOUT)
2376   {
2377     assert(!status_var_aggregated);
2378     status_var.max_execution_time_exceeded++;
2379   }
2380 
2381 
2382   /* Broadcast a condition to kick the target if it is waiting on it. */
2383   if (is_killable)
2384   {
2385     mysql_mutex_lock(&LOCK_current_cond);
2386     /*
2387       This broadcast could be up in the air if the victim thread
2388       exits the cond in the time between read and broadcast, but that is
2389       ok since all we want to do is to make the victim thread get out
2390       of waiting on current_cond.
2391       If we see a non-zero current_cond: it cannot be an old value (because
2392       then exit_cond() should have run and it can't because we have mutex); so
2393       it is the true value but maybe current_mutex is not yet non-zero (we're
2394       in the middle of enter_cond() and there is a "memory order
2395       inversion"). So we test the mutex too to not lock 0.
2396 
2397       Note that there is a small chance we fail to kill. If victim has locked
2398       current_mutex, but hasn't yet entered enter_cond() (which means that
2399       current_cond and current_mutex are 0), then the victim will not get
2400       a signal and it may wait "forever" on the cond (until
2401       we issue a second KILL or the status it's waiting for happens).
2402       It's true that we have set its thd->killed but it may not
2403       see it immediately and so may have time to reach the cond_wait().
2404 
2405       However, where possible, we test for killed once again after
2406       enter_cond(). This should make the signaling as safe as possible.
2407       However, there is still a small chance of failure on platforms with
2408       instruction or memory write reordering.
2409     */
2410     if (current_cond && current_mutex)
2411     {
2412       DBUG_EXECUTE_IF("before_dump_thread_acquires_current_mutex",
2413                       {
2414                       const char act[]=
2415                       "now signal dump_thread_signal wait_for go_dump_thread";
2416                       assert(!debug_sync_set_action(current_thd,
2417                                                     STRING_WITH_LEN(act)));
2418                       };);
2419       mysql_mutex_lock(current_mutex);
2420       mysql_cond_broadcast(current_cond);
2421       mysql_mutex_unlock(current_mutex);
2422     }
2423     mysql_mutex_unlock(&LOCK_current_cond);
2424   }
2425   DBUG_VOID_RETURN;
2426 }
2427 
2428 
2429 /**
2430   Close the Vio associated this session.
2431 
2432   @remark LOCK_thd_data is taken due to the fact that
2433           the Vio might be disassociated concurrently.
2434 */
2435 
disconnect(bool server_shutdown)2436 void THD::disconnect(bool server_shutdown)
2437 {
2438   Vio *vio= NULL;
2439 
2440   mysql_mutex_lock(&LOCK_thd_data);
2441 
2442   killed= THD::KILL_CONNECTION;
2443 
2444   /*
2445     Since a active vio might might have not been set yet, in
2446     any case save a reference to avoid closing a inexistent
2447     one or closing the vio twice if there is a active one.
2448   */
2449   vio= active_vio;
2450   shutdown_active_vio();
2451 
2452   /* Disconnect even if a active vio is not associated. */
2453   if (is_classic_protocol() &&
2454       get_protocol_classic()->get_vio() != vio &&
2455       get_protocol_classic()->connection_alive())
2456   {
2457     m_protocol->shutdown(server_shutdown);
2458   }
2459 
2460   mysql_mutex_unlock(&LOCK_thd_data);
2461 }
2462 
2463 
notify_shared_lock(MDL_context_owner * ctx_in_use,bool needs_thr_lock_abort)2464 void THD::notify_shared_lock(MDL_context_owner *ctx_in_use,
2465                              bool needs_thr_lock_abort)
2466 {
2467   THD *in_use= ctx_in_use->get_thd();
2468 
2469   if (needs_thr_lock_abort)
2470   {
2471     mysql_mutex_lock(&in_use->LOCK_thd_data);
2472     for (TABLE *thd_table= in_use->open_tables;
2473          thd_table ;
2474          thd_table= thd_table->next)
2475     {
2476       /*
2477         Check for TABLE::needs_reopen() is needed since in some places we call
2478         handler::close() for table instance (and set TABLE::db_stat to 0)
2479         and do not remove such instances from the THD::open_tables
2480         for some time, during which other thread can see those instances
2481         (e.g. see partitioning code).
2482       */
2483       if (!thd_table->needs_reopen())
2484 #ifdef WITH_WSREP
2485       {
2486 #endif /* WITH_WSREP */
2487         mysql_lock_abort_for_thread(this, thd_table);
2488 #ifdef WITH_WSREP
2489         if (WSREP_NNULL(this) && wsrep_thd_is_BF((void *)this, FALSE))
2490         {
2491           wsrep_abort_thd((void *)this, (void *)in_use, FALSE);
2492         }
2493       }
2494 #endif /* WITH_WSREP */
2495     }
2496     mysql_mutex_unlock(&in_use->LOCK_thd_data);
2497   }
2498 }
2499 
2500 
2501 /*
2502   Remember the location of thread info, the structure needed for
2503   sql_alloc() and the structure for the net buffer
2504 */
2505 
store_globals()2506 bool THD::store_globals()
2507 {
2508   /*
2509     Assert that thread_stack is initialized: it's necessary to be able
2510     to track stack overrun.
2511   */
2512   assert(thread_stack);
2513 
2514   if (my_thread_set_THR_THD(this) ||
2515       my_thread_set_THR_MALLOC(&mem_root))
2516     return true;
2517   /*
2518     is_killable is concurrently readable by a killer thread.
2519     It is protected by LOCK_thd_data, it is not needed to lock while the
2520     value is changing from false not true. If the kill thread reads
2521     true we need to ensure that the thread doesn't proceed to assign
2522     another thread to the same TLS reference.
2523   */
2524   is_killable= true;
2525 #ifndef NDEBUG
2526   /*
2527     Let mysqld define the thread id (not mysys)
2528     This allows us to move THD to different threads if needed.
2529   */
2530   set_my_thread_var_id(m_thread_id);
2531 #endif
2532   real_id= my_thread_self();                      // For debugging
2533 
2534   return false;
2535 }
2536 
2537 /*
2538   Remove the thread specific info (THD and mem_root pointer) stored during
2539   store_global call for this thread.
2540 */
restore_globals()2541 void THD::restore_globals()
2542 {
2543   /*
2544     Assert that thread_stack is initialized: it's necessary to be able
2545     to track stack overrun.
2546   */
2547   assert(thread_stack);
2548 
2549   /* Undocking the thread specific data. */
2550   my_thread_set_THR_THD(NULL);
2551   my_thread_set_THR_MALLOC(NULL);
2552 }
2553 
2554 
2555 /*
2556   Cleanup after query.
2557 
2558   SYNOPSIS
2559     THD::cleanup_after_query()
2560 
2561   DESCRIPTION
2562     This function is used to reset thread data to its default state.
2563 
2564   NOTE
2565     This function is not suitable for setting thread data to some
2566     non-default values, as there is only one replication thread, so
2567     different master threads may overwrite data of each other on
2568     slave.
2569 */
2570 
cleanup_after_query()2571 void THD::cleanup_after_query()
2572 {
2573 
2574   /*
2575     Reset rand_used so that detection of calls to rand() will save random
2576     seeds if needed by the slave.
2577 
2578     Do not reset rand_used if inside a stored function or trigger because
2579     only the call to these operations is logged. Thus only the calling
2580     statement needs to detect rand() calls made by its substatements. These
2581     substatements must not set rand_used to 0 because it would remove the
2582     detection of rand() by the calling statement.
2583   */
2584   if (!in_sub_stmt) /* stored functions and triggers are a special case */
2585   {
2586     /* Forget those values, for next binlogger: */
2587     stmt_depends_on_first_successful_insert_id_in_prev_stmt= 0;
2588     auto_inc_intervals_in_cur_stmt_for_binlog.empty();
2589     rand_used= 0;
2590     binlog_accessed_db_names= NULL;
2591 
2592 #ifndef EMBEDDED_LIBRARY
2593     /*
2594       Clean possible unused INSERT_ID events by current statement.
2595       is_update_query() is needed to ignore SET statements:
2596         Statements that don't update anything directly and don't
2597         used stored functions. This is mostly necessary to ignore
2598         statements in binlog between SET INSERT_ID and DML statement
2599         which is intended to consume its event (there can be other
2600         SET statements between them).
2601     */
2602     if ((rli_slave || rli_fake) && is_update_query(lex->sql_command))
2603       auto_inc_intervals_forced.empty();
2604 #endif
2605   }
2606 
2607   /*
2608     In case of stored procedures, stored functions, triggers and events
2609     m_trans_fixed_log_file will not be set to NULL. The memory will be reused.
2610   */
2611   if (!sp_runtime_ctx)
2612     m_trans_fixed_log_file= NULL;
2613 
2614   /*
2615     Forget the binlog stmt filter for the next query.
2616     There are some code paths that:
2617     - do not call THD::decide_logging_format()
2618     - do call THD::binlog_query(),
2619     making this reset necessary.
2620   */
2621   reset_binlog_local_stmt_filter();
2622   if (first_successful_insert_id_in_cur_stmt > 0)
2623   {
2624     /* set what LAST_INSERT_ID() will return */
2625     first_successful_insert_id_in_prev_stmt=
2626       first_successful_insert_id_in_cur_stmt;
2627     first_successful_insert_id_in_cur_stmt= 0;
2628     substitute_null_with_insert_id= TRUE;
2629   }
2630   arg_of_last_insert_id_function= 0;
2631   /* Free Items that were created during this execution */
2632   free_items();
2633   /* Reset where. */
2634   where= THD::DEFAULT_WHERE;
2635   /* reset table map for multi-table update */
2636   table_map_for_update= 0;
2637   m_binlog_invoker= FALSE;
2638   /* reset replication info structure */
2639   if (lex)
2640   {
2641     lex->mi.repl_ignore_server_ids.clear();
2642   }
2643 #ifndef EMBEDDED_LIBRARY
2644   if (rli_slave)
2645     rli_slave->cleanup_after_query();
2646 #endif
2647 
2648 #ifdef WITH_WSREP
2649   wsrep_sync_wait_gtid= WSREP_GTID_UNDEFINED;
2650   if (!in_active_multi_stmt_transaction())
2651     wsrep_affected_rows= 0;
2652 #endif /* WITH_WSREP */
2653 }
2654 
2655 LEX_CSTRING *
make_lex_string_root(MEM_ROOT * mem_root,LEX_CSTRING * lex_str,const char * str,size_t length,bool allocate_lex_string)2656 make_lex_string_root(MEM_ROOT *mem_root,
2657                      LEX_CSTRING *lex_str, const char* str, size_t length,
2658                      bool allocate_lex_string)
2659 {
2660   if (allocate_lex_string)
2661     if (!(lex_str= (LEX_CSTRING *)alloc_root(mem_root, sizeof(LEX_CSTRING))))
2662       return 0;
2663   if (!(lex_str->str= strmake_root(mem_root, str, length)))
2664     return 0;
2665   lex_str->length= length;
2666   return lex_str;
2667 }
2668 
2669 
2670 LEX_STRING *
make_lex_string_root(MEM_ROOT * mem_root,LEX_STRING * lex_str,const char * str,size_t length,bool allocate_lex_string)2671 make_lex_string_root(MEM_ROOT *mem_root,
2672                      LEX_STRING *lex_str, const char* str, size_t length,
2673                      bool allocate_lex_string)
2674 {
2675   if (allocate_lex_string)
2676     if (!(lex_str= (LEX_STRING *)alloc_root(mem_root, sizeof(LEX_STRING))))
2677       return 0;
2678   if (!(lex_str->str= strmake_root(mem_root, str, length)))
2679     return 0;
2680   lex_str->length= length;
2681   return lex_str;
2682 }
2683 
2684 
2685 
make_lex_string(LEX_CSTRING * lex_str,const char * str,size_t length,bool allocate_lex_string)2686 LEX_CSTRING *THD::make_lex_string(LEX_CSTRING *lex_str,
2687                                  const char* str, size_t length,
2688                                  bool allocate_lex_string)
2689 {
2690   return make_lex_string_root (mem_root, lex_str, str,
2691                                length, allocate_lex_string);
2692 }
2693 
2694 
2695 
2696 /**
2697   Create a LEX_STRING in this connection.
2698 
2699   @param lex_str  pointer to LEX_STRING object to be initialized
2700   @param str      initializer to be copied into lex_str
2701   @param length   length of str, in bytes
2702   @param allocate_lex_string  if TRUE, allocate new LEX_STRING object,
2703                               instead of using lex_str value
2704   @return  NULL on failure, or pointer to the LEX_STRING object
2705 */
make_lex_string(LEX_STRING * lex_str,const char * str,size_t length,bool allocate_lex_string)2706 LEX_STRING *THD::make_lex_string(LEX_STRING *lex_str,
2707                                  const char* str, size_t length,
2708                                  bool allocate_lex_string)
2709 {
2710   return make_lex_string_root (mem_root, lex_str, str,
2711                                length, allocate_lex_string);
2712 }
2713 
2714 
2715 /*
2716   Convert a string to another character set
2717 
2718   @param to             Store new allocated string here
2719   @param to_cs          New character set for allocated string
2720   @param from           String to convert
2721   @param from_length    Length of string to convert
2722   @param from_cs        Original character set
2723 
2724   @note to will be 0-terminated to make it easy to pass to system funcs
2725 
2726   @retval false ok
2727   @retval true  End of memory.
2728                 In this case to->str will point to 0 and to->length will be 0.
2729 */
2730 
convert_string(LEX_STRING * to,const CHARSET_INFO * to_cs,const char * from,size_t from_length,const CHARSET_INFO * from_cs)2731 bool THD::convert_string(LEX_STRING *to, const CHARSET_INFO *to_cs,
2732 			 const char *from, size_t from_length,
2733 			 const CHARSET_INFO *from_cs)
2734 {
2735   DBUG_ENTER("convert_string");
2736   size_t new_length= to_cs->mbmaxlen * from_length;
2737   uint errors= 0;
2738   if (!(to->str= (char*) alloc(new_length+1)))
2739   {
2740     to->length= 0;				// Safety fix
2741     DBUG_RETURN(1);				// EOM
2742   }
2743   to->length= copy_and_convert(to->str, new_length, to_cs,
2744 			       from, from_length, from_cs, &errors);
2745   to->str[to->length]=0;			// Safety
2746   if (errors != 0)
2747   {
2748     char printable_buff[32];
2749     convert_to_printable(printable_buff, sizeof(printable_buff),
2750                          from, from_length, from_cs, 6);
2751     push_warning_printf(this, Sql_condition::SL_WARNING,
2752                         ER_INVALID_CHARACTER_STRING,
2753                         ER_THD(this, ER_INVALID_CHARACTER_STRING),
2754                         from_cs->csname, printable_buff);
2755   }
2756 
2757   DBUG_RETURN(0);
2758 }
2759 
2760 
2761 /*
2762   Convert string from source character set to target character set inplace.
2763 
2764   SYNOPSIS
2765     THD::convert_string
2766 
2767   DESCRIPTION
2768     Convert string using convert_buffer - buffer for character set
2769     conversion shared between all protocols.
2770 
2771   RETURN
2772     0   ok
2773    !0   out of memory
2774 */
2775 
convert_string(String * s,const CHARSET_INFO * from_cs,const CHARSET_INFO * to_cs)2776 bool THD::convert_string(String *s, const CHARSET_INFO *from_cs,
2777                          const CHARSET_INFO *to_cs)
2778 {
2779   uint dummy_errors;
2780   if (convert_buffer.copy(s->ptr(), s->length(), from_cs, to_cs, &dummy_errors))
2781     return TRUE;
2782   /* If convert_buffer >> s copying is more efficient long term */
2783   if (convert_buffer.alloced_length() >= convert_buffer.length() * 2 ||
2784       !s->is_alloced())
2785   {
2786     return s->copy(convert_buffer);
2787   }
2788   s->swap(convert_buffer);
2789   return FALSE;
2790 }
2791 
2792 
2793 /*
2794   Update some cache variables when character set changes
2795 */
2796 
update_charset()2797 void THD::update_charset()
2798 {
2799   size_t not_used;
2800   charset_is_system_charset=
2801     !String::needs_conversion(0,
2802                               variables.character_set_client,
2803                               system_charset_info,
2804                               &not_used);
2805   charset_is_collation_connection=
2806     !String::needs_conversion(0,
2807                               variables.character_set_client,
2808                               variables.collation_connection,
2809                               &not_used);
2810   charset_is_character_set_filesystem=
2811     !String::needs_conversion(0,
2812                               variables.character_set_client,
2813                               variables.character_set_filesystem,
2814                               &not_used);
2815 }
2816 
2817 
2818 /* add table to list of changed in transaction tables */
2819 
add_changed_table(TABLE * table)2820 void THD::add_changed_table(TABLE *table)
2821 {
2822   DBUG_ENTER("THD::add_changed_table(table)");
2823 
2824   assert(in_multi_stmt_transaction_mode() && table->file->has_transactions());
2825   add_changed_table(table->s->table_cache_key.str,
2826                     (long) table->s->table_cache_key.length);
2827   DBUG_VOID_RETURN;
2828 }
2829 
2830 
add_changed_table(const char * key,long key_length)2831 void THD::add_changed_table(const char *key, long key_length)
2832 {
2833   DBUG_ENTER("THD::add_changed_table(key)");
2834   if (get_transaction()->add_changed_table(key, key_length))
2835     killed= KILL_CONNECTION;
2836   DBUG_VOID_RETURN;
2837 }
2838 
2839 
send_explain_fields(Query_result * result)2840 int THD::send_explain_fields(Query_result *result)
2841 {
2842   List<Item> field_list;
2843   Item *item;
2844   CHARSET_INFO *cs= system_charset_info;
2845   field_list.push_back(new Item_return_int("id",3, MYSQL_TYPE_LONGLONG));
2846   field_list.push_back(new Item_empty_string("select_type", 19, cs));
2847   field_list.push_back(item= new Item_empty_string("table", NAME_CHAR_LEN, cs));
2848   item->maybe_null= 1;
2849   /* Maximum length of string that make_used_partitions_str() can produce */
2850   item= new Item_empty_string("partitions", MAX_PARTITIONS * (1 + FN_LEN),
2851                               cs);
2852   field_list.push_back(item);
2853   item->maybe_null= 1;
2854   field_list.push_back(item= new Item_empty_string("type", 10, cs));
2855   item->maybe_null= 1;
2856   field_list.push_back(item=new Item_empty_string("possible_keys",
2857 						  NAME_CHAR_LEN*MAX_KEY, cs));
2858   item->maybe_null=1;
2859   field_list.push_back(item=new Item_empty_string("key", NAME_CHAR_LEN, cs));
2860   item->maybe_null=1;
2861   field_list.push_back(item=new Item_empty_string("key_len",
2862 						  NAME_CHAR_LEN*MAX_KEY));
2863   item->maybe_null=1;
2864   field_list.push_back(item=new Item_empty_string("ref",
2865                                                   NAME_CHAR_LEN*MAX_REF_PARTS,
2866                                                   cs));
2867   item->maybe_null=1;
2868   field_list.push_back(item= new Item_return_int("rows", 10,
2869                                                  MYSQL_TYPE_LONGLONG));
2870   item->maybe_null= 1;
2871   field_list.push_back(item= new Item_float(NAME_STRING("filtered"),
2872                                             0.1234, 2, 4));
2873   item->maybe_null=1;
2874   field_list.push_back(new Item_empty_string("Extra", 255, cs));
2875   item->maybe_null= 1;
2876   return (result->send_result_set_metadata(field_list, Protocol::SEND_NUM_ROWS |
2877                                            Protocol::SEND_EOF));
2878 }
2879 
get_vio_type()2880 enum_vio_type THD::get_vio_type()
2881 {
2882 #ifndef EMBEDDED_LIBRARY
2883   DBUG_ENTER("THD::get_vio_type");
2884   DBUG_RETURN(get_protocol()->connection_type());
2885 #else
2886   return NO_VIO_TYPE;
2887 #endif
2888 }
2889 
shutdown_active_vio()2890 void THD::shutdown_active_vio()
2891 {
2892   DBUG_ENTER("shutdown_active_vio");
2893   mysql_mutex_assert_owner(&LOCK_thd_data);
2894 #ifndef EMBEDDED_LIBRARY
2895   if (active_vio)
2896   {
2897     vio_shutdown(active_vio);
2898     active_vio = 0;
2899     m_SSL = NULL;
2900   }
2901 #endif
2902   DBUG_VOID_RETURN;
2903 }
2904 
2905 
2906 /*
2907   Register an item tree tree transformation, performed by the query
2908   optimizer.
2909 */
2910 
nocheck_register_item_tree_change(Item ** place,Item * new_value)2911 void THD::nocheck_register_item_tree_change(Item **place,
2912                                             Item *new_value)
2913 {
2914   Item_change_record *change;
2915   /*
2916     Now we use one node per change, which adds some memory overhead,
2917     but still is rather fast as we use alloc_root for allocations.
2918     A list of item tree changes of an average query should be short.
2919   */
2920   void *change_mem= alloc_root(mem_root, sizeof(*change));
2921   if (change_mem == 0)
2922   {
2923     /*
2924       OOM, thd->fatal_error() is called by the error handler of the
2925       memroot. Just return.
2926     */
2927     return;
2928   }
2929   change= new (change_mem) Item_change_record(place, new_value);
2930   change_list.push_front(change);
2931 }
2932 
2933 
replace_rollback_place(Item ** new_place)2934 void THD::replace_rollback_place(Item **new_place)
2935 {
2936   I_List_iterator<Item_change_record> it(change_list);
2937   Item_change_record *change;
2938   while ((change= it++))
2939   {
2940     if (change->new_value == *new_place)
2941     {
2942       DBUG_PRINT("info", ("replace_rollback_place new_value %p place %p",
2943                           *new_place, new_place));
2944       change->place= new_place;
2945       break;
2946     }
2947   }
2948 }
2949 
2950 
rollback_item_tree_changes()2951 void THD::rollback_item_tree_changes()
2952 {
2953   I_List_iterator<Item_change_record> it(change_list);
2954   Item_change_record *change;
2955   DBUG_ENTER("rollback_item_tree_changes");
2956 
2957   while ((change= it++))
2958   {
2959     DBUG_PRINT("info",
2960                ("rollback_item_tree_changes "
2961                 "place %p curr_value %p old_value %p",
2962                 change->place, *change->place, change->old_value));
2963     *change->place= change->old_value;
2964   }
2965   /* We can forget about changes memory: it's allocated in runtime memroot */
2966   change_list.empty();
2967   DBUG_VOID_RETURN;
2968 }
2969 
2970 
2971 /*****************************************************************************
2972 ** Functions to provide a interface to select results
2973 *****************************************************************************/
2974 
2975 static const String default_line_term("\n",default_charset_info);
2976 static const String default_escaped("\\",default_charset_info);
2977 static const String default_field_term("\t",default_charset_info);
2978 static const String default_xml_row_term("<row>", default_charset_info);
2979 static const String my_empty_string("",default_charset_info);
2980 
2981 
sql_exchange(const char * name,bool flag,enum enum_filetype filetype_arg)2982 sql_exchange::sql_exchange(const char *name, bool flag,
2983                            enum enum_filetype filetype_arg)
2984   :file_name(name), dumpfile(flag), skip_lines(0)
2985 {
2986   field.opt_enclosed= 0;
2987   filetype= filetype_arg;
2988   field.field_term= &default_field_term;
2989   field.enclosed= line.line_start= &my_empty_string;
2990   line.line_term= filetype == FILETYPE_CSV ?
2991               &default_line_term : &default_xml_row_term;
2992   field.escaped= &default_escaped;
2993   cs= NULL;
2994 }
2995 
escaped_given(void)2996 bool sql_exchange::escaped_given(void)
2997 {
2998   return field.escaped != &default_escaped;
2999 }
3000 
3001 
send_result_set_metadata(List<Item> & list,uint flags)3002 bool Query_result_send::send_result_set_metadata(List<Item> &list, uint flags)
3003 {
3004   bool res;
3005 #ifdef WITH_WSREP
3006   if (WSREP(thd) && thd->wsrep_retry_query)
3007   {
3008     WSREP_DEBUG("skipping select metadata");
3009     return FALSE;
3010   }
3011 #endif /* WITH_WSREP */
3012   if (!(res= thd->send_result_metadata(&list, flags)))
3013     is_result_set_started= 1;
3014   return res;
3015 }
3016 
abort_result_set()3017 void Query_result_send::abort_result_set()
3018 {
3019   DBUG_ENTER("Query_result_send::abort_result_set");
3020 
3021   if (is_result_set_started && thd->sp_runtime_ctx)
3022   {
3023     /*
3024       We're executing a stored procedure, have an open result
3025       set and an SQL exception condition. In this situation we
3026       must abort the current statement, silence the error and
3027       start executing the continue/exit handler if one is found.
3028       Before aborting the statement, let's end the open result set, as
3029       otherwise the client will hang due to the violation of the
3030       client/server protocol.
3031     */
3032     thd->sp_runtime_ctx->end_partial_result_set= TRUE;
3033   }
3034   DBUG_VOID_RETURN;
3035 }
3036 
3037 
3038 /* Send data to client. Returns 0 if ok */
3039 
send_data(List<Item> & items)3040 bool Query_result_send::send_data(List<Item> &items)
3041 {
3042   Protocol *protocol= thd->get_protocol();
3043   DBUG_ENTER("Query_result_send::send_data");
3044 
3045   if (unit->offset_limit_cnt)
3046   {						// using limit offset,count
3047     unit->offset_limit_cnt--;
3048     DBUG_RETURN(FALSE);
3049   }
3050 
3051   /*
3052     We may be passing the control from mysqld to the client: release the
3053     InnoDB adaptive hash S-latch to avoid thread deadlocks if it was reserved
3054     by thd
3055   */
3056   ha_release_temporary_latches(thd);
3057 
3058   protocol->start_row();
3059   if (thd->send_result_set_row(&items))
3060   {
3061     protocol->abort_row();
3062     DBUG_RETURN(TRUE);
3063   }
3064 
3065   thd->inc_sent_row_count(1);
3066   DBUG_RETURN(protocol->end_row());
3067 }
3068 
send_eof()3069 bool Query_result_send::send_eof()
3070 {
3071   /*
3072     We may be passing the control from mysqld to the client: release the
3073     InnoDB adaptive hash S-latch to avoid thread deadlocks if it was reserved
3074     by thd
3075   */
3076   ha_release_temporary_latches(thd);
3077 
3078   /*
3079     Don't send EOF if we're in error condition (which implies we've already
3080     sent or are sending an error)
3081   */
3082   if (thd->is_error())
3083     return TRUE;
3084   ::my_eof(thd);
3085   is_result_set_started= 0;
3086   return FALSE;
3087 }
3088 
3089 
3090 /************************************************************************
3091   Handling writing to file
3092 ************************************************************************/
3093 
send_error(uint errcode,const char * err)3094 void Query_result_to_file::send_error(uint errcode,const char *err)
3095 {
3096   my_message(errcode, err, MYF(0));
3097   if (file > 0)
3098   {
3099     (void) end_io_cache(&cache);
3100     mysql_file_close(file, MYF(0));
3101     /* Delete file on error */
3102     mysql_file_delete(key_select_to_file, path, MYF(0));
3103     file= -1;
3104   }
3105 }
3106 
3107 
send_eof()3108 bool Query_result_to_file::send_eof()
3109 {
3110   int error= MY_TEST(end_io_cache(&cache));
3111   if (mysql_file_close(file, MYF(MY_WME)) || thd->is_error())
3112     error= true;
3113 
3114   if (!error)
3115   {
3116     ::my_ok(thd,row_count);
3117   }
3118   file= -1;
3119   return error;
3120 }
3121 
3122 
cleanup()3123 void Query_result_to_file::cleanup()
3124 {
3125   /* In case of error send_eof() may be not called: close the file here. */
3126   if (file >= 0)
3127   {
3128     (void) end_io_cache(&cache);
3129     mysql_file_close(file, MYF(0));
3130     file= -1;
3131   }
3132   path[0]= '\0';
3133   row_count= 0;
3134 }
3135 
3136 
~Query_result_to_file()3137 Query_result_to_file::~Query_result_to_file()
3138 {
3139   if (file >= 0)
3140   {					// This only happens in case of error
3141     (void) end_io_cache(&cache);
3142     mysql_file_close(file, MYF(0));
3143     file= -1;
3144   }
3145 }
3146 
3147 /***************************************************************************
3148 ** Export of select to textfile
3149 ***************************************************************************/
3150 
3151 /*
3152   Create file with IO cache
3153 
3154   SYNOPSIS
3155     create_file()
3156     thd			Thread handle
3157     path		File name
3158     exchange		Excange class
3159     cache		IO cache
3160 
3161   RETURN
3162     >= 0 	File handle
3163    -1		Error
3164 */
3165 
3166 
create_file(THD * thd,char * path,sql_exchange * exchange,IO_CACHE * cache)3167 static File create_file(THD *thd, char *path, sql_exchange *exchange,
3168 			IO_CACHE *cache)
3169 {
3170   File file;
3171   uint option= MY_UNPACK_FILENAME | MY_RELATIVE_PATH;
3172 
3173   if (!dirname_length(exchange->file_name))
3174   {
3175     strxnmov(path, FN_REFLEN-1, mysql_real_data_home,
3176              thd->db().str ? thd->db().str : "",
3177              NullS);
3178     (void) fn_format(path, exchange->file_name, path, "", option);
3179   }
3180   else
3181     (void) fn_format(path, exchange->file_name, mysql_real_data_home, "", option);
3182 
3183   if (!is_secure_file_path(path))
3184   {
3185     /* Write only allowed to dir or subdir specified by secure_file_priv */
3186     my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
3187     return -1;
3188   }
3189 
3190   if (!access(path, F_OK))
3191   {
3192     my_error(ER_FILE_EXISTS_ERROR, MYF(0), exchange->file_name);
3193     return -1;
3194   }
3195   /* Create the file world readable */
3196   if ((file= mysql_file_create(key_select_to_file,
3197                                path, 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
3198     return file;
3199 #ifdef HAVE_FCHMOD
3200   (void) fchmod(file, 0666);			// Because of umask()
3201 #else
3202   (void) chmod(path, 0666);
3203 #endif
3204   if (init_io_cache(cache, file, 0L, WRITE_CACHE, 0L, 1, MYF(MY_WME)))
3205   {
3206     mysql_file_close(file, MYF(0));
3207     /* Delete file on error, it was just created */
3208     mysql_file_delete(key_select_to_file, path, MYF(0));
3209     return -1;
3210   }
3211   return file;
3212 }
3213 
3214 
prepare(List<Item> & list,SELECT_LEX_UNIT * u)3215 int Query_result_export::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
3216 {
3217   bool blob_flag=0;
3218   bool string_results= FALSE, non_string_results= FALSE;
3219   unit= u;
3220   if (strlen(exchange->file_name) + NAME_LEN >= FN_REFLEN)
3221     strmake(path,exchange->file_name,FN_REFLEN-1);
3222 
3223   write_cs= exchange->cs ? exchange->cs : &my_charset_bin;
3224 
3225   if ((file= create_file(thd, path, exchange, &cache)) < 0)
3226     return 1;
3227   /* Check if there is any blobs in data */
3228   {
3229     List_iterator_fast<Item> li(list);
3230     Item *item;
3231     while ((item=li++))
3232     {
3233       if (item->max_length >= MAX_BLOB_WIDTH)
3234       {
3235 	blob_flag=1;
3236 	break;
3237       }
3238       if (item->result_type() == STRING_RESULT)
3239         string_results= TRUE;
3240       else
3241         non_string_results= TRUE;
3242     }
3243   }
3244   if (exchange->field.escaped->numchars() > 1 ||
3245       exchange->field.enclosed->numchars() > 1)
3246   {
3247     my_error(ER_WRONG_FIELD_TERMINATORS, MYF(0));
3248     return TRUE;
3249   }
3250   if (exchange->field.escaped->length() > 1 ||
3251       exchange->field.enclosed->length() > 1 ||
3252       !my_isascii(exchange->field.escaped->ptr()[0]) ||
3253       !my_isascii(exchange->field.enclosed->ptr()[0]) ||
3254       !exchange->field.field_term->is_ascii() ||
3255       !exchange->line.line_term->is_ascii() ||
3256       !exchange->line.line_start->is_ascii())
3257   {
3258     /*
3259       Current LOAD DATA INFILE recognizes field/line separators "as is" without
3260       converting from client charset to data file charset. So, it is supposed,
3261       that input file of LOAD DATA INFILE consists of data in one charset and
3262       separators in other charset. For the compatibility with that [buggy]
3263       behaviour SELECT INTO OUTFILE implementation has been saved "as is" too,
3264       but the new warning message has been added:
3265 
3266         Non-ASCII separator arguments are not fully supported
3267     */
3268     push_warning(thd, Sql_condition::SL_WARNING,
3269                  WARN_NON_ASCII_SEPARATOR_NOT_IMPLEMENTED,
3270                  ER(WARN_NON_ASCII_SEPARATOR_NOT_IMPLEMENTED));
3271   }
3272   field_term_length=exchange->field.field_term->length();
3273   field_term_char= field_term_length ?
3274                    (int) (uchar) (*exchange->field.field_term)[0] : INT_MAX;
3275   if (!exchange->line.line_term->length())
3276     exchange->line.line_term=exchange->field.field_term;// Use this if it exists
3277   field_sep_char= (exchange->field.enclosed->length() ?
3278                   (int) (uchar) (*exchange->field.enclosed)[0] :
3279                   field_term_char);
3280   if (exchange->field.escaped->length() && (exchange->escaped_given() ||
3281       !(thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES)))
3282     escape_char= (int) (uchar) (*exchange->field.escaped)[0];
3283   else
3284     escape_char= -1;
3285   is_ambiguous_field_sep= MY_TEST(strchr(ESCAPE_CHARS, field_sep_char));
3286   is_unsafe_field_sep= MY_TEST(strchr(NUMERIC_CHARS, field_sep_char));
3287   line_sep_char= (exchange->line.line_term->length() ?
3288                  (int) (uchar) (*exchange->line.line_term)[0] : INT_MAX);
3289   if (!field_term_length)
3290     exchange->field.opt_enclosed=0;
3291   if (!exchange->field.enclosed->length())
3292     exchange->field.opt_enclosed=1;                     // A little quicker loop
3293   fixed_row_size= (!field_term_length && !exchange->field.enclosed->length() &&
3294 		   !blob_flag);
3295   if ((is_ambiguous_field_sep && exchange->field.enclosed->is_empty() &&
3296        (string_results || is_unsafe_field_sep)) ||
3297       (exchange->field.opt_enclosed && non_string_results &&
3298        field_term_length && strchr(NUMERIC_CHARS, field_term_char)))
3299   {
3300     push_warning(thd, Sql_condition::SL_WARNING,
3301                  ER_AMBIGUOUS_FIELD_TERM, ER(ER_AMBIGUOUS_FIELD_TERM));
3302     is_ambiguous_field_term= TRUE;
3303   }
3304   else
3305     is_ambiguous_field_term= FALSE;
3306 
3307   return 0;
3308 }
3309 
3310 
3311 #define NEED_ESCAPING(x) ((int) (uchar) (x) == escape_char    || \
3312                           (enclosed ? (int) (uchar) (x) == field_sep_char      \
3313                                     : (int) (uchar) (x) == field_term_char) || \
3314                           (int) (uchar) (x) == line_sep_char  || \
3315                           !(x))
3316 
send_data(List<Item> & items)3317 bool Query_result_export::send_data(List<Item> &items)
3318 {
3319 
3320   DBUG_ENTER("Query_result_export::send_data");
3321   char buff[MAX_FIELD_WIDTH],null_buff[2],space[MAX_FIELD_WIDTH];
3322   char cvt_buff[MAX_FIELD_WIDTH];
3323   String cvt_str(cvt_buff, sizeof(cvt_buff), write_cs);
3324   bool space_inited=0;
3325   String tmp(buff,sizeof(buff),&my_charset_bin),*res;
3326   tmp.length(0);
3327 
3328   if (unit->offset_limit_cnt)
3329   {						// using limit offset,count
3330     unit->offset_limit_cnt--;
3331     DBUG_RETURN(0);
3332   }
3333   row_count++;
3334   Item *item;
3335   size_t used_length=0;
3336   uint items_left=items.elements;
3337   List_iterator_fast<Item> li(items);
3338 
3339   if (my_b_write(&cache,(uchar*) exchange->line.line_start->ptr(),
3340 		 exchange->line.line_start->length()))
3341     goto err;
3342   while ((item=li++))
3343   {
3344     Item_result result_type=item->result_type();
3345     bool enclosed = (exchange->field.enclosed->length() &&
3346                      (!exchange->field.opt_enclosed ||
3347                       result_type == STRING_RESULT));
3348     res=item->str_result(&tmp);
3349     if (res && !my_charset_same(write_cs, res->charset()) &&
3350         !my_charset_same(write_cs, &my_charset_bin))
3351     {
3352       const char *well_formed_error_pos;
3353       const char *cannot_convert_error_pos;
3354       const char *from_end_pos;
3355       const char *error_pos;
3356       size_t bytes;
3357       uint64 estimated_bytes=
3358         ((uint64) res->length() / res->charset()->mbminlen + 1) *
3359         write_cs->mbmaxlen + 1;
3360       set_if_smaller(estimated_bytes, UINT_MAX32);
3361       if (cvt_str.mem_realloc((uint32) estimated_bytes))
3362       {
3363         my_error(ER_OUTOFMEMORY, MYF(ME_FATALERROR), (uint32) estimated_bytes);
3364         goto err;
3365       }
3366 
3367       bytes= well_formed_copy_nchars(write_cs, (char *) cvt_str.ptr(),
3368                                      cvt_str.alloced_length(),
3369                                      res->charset(), res->ptr(), res->length(),
3370                                      UINT_MAX32, // copy all input chars,
3371                                                  // i.e. ignore nchars parameter
3372                                      &well_formed_error_pos,
3373                                      &cannot_convert_error_pos,
3374                                      &from_end_pos);
3375       error_pos= well_formed_error_pos ? well_formed_error_pos
3376                                        : cannot_convert_error_pos;
3377       if (error_pos)
3378       {
3379         char printable_buff[32];
3380         convert_to_printable(printable_buff, sizeof(printable_buff),
3381                              error_pos, res->ptr() + res->length() - error_pos,
3382                              res->charset(), 6);
3383         push_warning_printf(thd, Sql_condition::SL_WARNING,
3384                             ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
3385                             ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
3386                             "string", printable_buff,
3387                             item->item_name.ptr(), static_cast<long>(row_count));
3388       }
3389       else if (from_end_pos < res->ptr() + res->length())
3390       {
3391         /*
3392           result is longer than UINT_MAX32 and doesn't fit into String
3393         */
3394         push_warning_printf(thd, Sql_condition::SL_WARNING,
3395                             WARN_DATA_TRUNCATED, ER(WARN_DATA_TRUNCATED),
3396                             item->full_name(), static_cast<long>(row_count));
3397       }
3398       cvt_str.length(bytes);
3399       res= &cvt_str;
3400     }
3401     if (res && enclosed)
3402     {
3403       if (my_b_write(&cache,(uchar*) exchange->field.enclosed->ptr(),
3404 		     exchange->field.enclosed->length()))
3405 	goto err;
3406     }
3407     if (!res)
3408     {						// NULL
3409       if (!fixed_row_size)
3410       {
3411 	if (escape_char != -1)			// Use \N syntax
3412 	{
3413 	  null_buff[0]=escape_char;
3414 	  null_buff[1]='N';
3415 	  if (my_b_write(&cache,(uchar*) null_buff,2))
3416 	    goto err;
3417 	}
3418 	else if (my_b_write(&cache,(uchar*) "NULL",4))
3419 	  goto err;
3420       }
3421       else
3422       {
3423 	used_length=0;				// Fill with space
3424       }
3425     }
3426     else
3427     {
3428       if (fixed_row_size)
3429 	used_length=min<size_t>(res->length(),item->max_length);
3430       else
3431 	used_length=res->length();
3432       if ((result_type == STRING_RESULT || is_unsafe_field_sep) &&
3433            escape_char != -1)
3434       {
3435         char *pos, *start, *end;
3436         bool escape_4_bytes= false;
3437         int in_escapable_4_bytes= 0;
3438         const CHARSET_INFO *res_charset= res->charset();
3439         const CHARSET_INFO *character_set_client=
3440           thd->variables.character_set_client;
3441         bool check_following_byte= (res_charset == &my_charset_bin) &&
3442                                     character_set_client->
3443                                     escape_with_backslash_is_dangerous;
3444         /*
3445           The judgement of mbmaxlenlen == 2 is for gb18030 only.
3446           Since there are several charsets with mbmaxlen == 4,
3447           so we have to use mbmaxlenlen == 2 here, which is only true
3448           for gb18030 currently.
3449         */
3450         assert(character_set_client->mbmaxlen == 2 ||
3451                my_mbmaxlenlen(character_set_client) == 2 ||
3452                !character_set_client->escape_with_backslash_is_dangerous);
3453 	for (start=pos=(char*) res->ptr(),end=pos+used_length ;
3454 	     pos != end ;
3455 	     pos++)
3456 	{
3457           bool need_escape= false;
3458 	  if (use_mb(res_charset))
3459 	  {
3460 	    int l;
3461 	    if ((l=my_ismbchar(res_charset, pos, end)))
3462 	    {
3463 	      pos += l-1;
3464 	      continue;
3465 	    }
3466 	  }
3467 
3468           /*
3469             Special case when dumping BINARY/VARBINARY/BLOB values
3470             for the clients with character sets big5, cp932, gbk, sjis
3471             and gb18030, which can have the escape character
3472             (0x5C "\" by default) as the second byte of a multi-byte sequence.
3473 
3474             The escape character had better be single-byte character,
3475             non-ASCII characters are not prohibited, but not fully supported.
3476 
3477             If
3478             - pos[0] is a valid multi-byte head (e.g 0xEE) and
3479             - pos[1] is 0x00, which will be escaped as "\0",
3480 
3481             then we'll get "0xEE + 0x5C + 0x30" in the output file.
3482 
3483             If this file is later loaded using this sequence of commands:
3484 
3485             mysql> create table t1 (a varchar(128)) character set big5;
3486             mysql> LOAD DATA INFILE 'dump.txt' INTO TABLE t1;
3487 
3488             then 0x5C will be misinterpreted as the second byte
3489             of a multi-byte character "0xEE + 0x5C", instead of
3490             escape character for 0x00.
3491 
3492             To avoid this confusion, we'll escape the multi-byte
3493             head character too, so the sequence "0xEE + 0x00" will be
3494             dumped as "0x5C + 0xEE + 0x5C + 0x30".
3495 
3496             Note, in the condition below we only check if
3497             mbcharlen is equal to 2, because there are no
3498             character sets with mbmaxlen longer than 2
3499             and with escape_with_backslash_is_dangerous set.
3500             assert before the loop makes that sure.
3501 
3502             But gb18030 is an exception. First of all, 2-byte codes
3503             would be affected by the issue above without doubt.
3504             Then, 4-byte gb18030 codes would be affected as well.
3505 
3506             Supposing the input is GB+81358130, and the
3507             field_term_char is set to '5', escape char is 0x5C by default.
3508             When we come to the first byte 0x81, if we don't escape it but
3509             escape the second byte 0x35 as it's the field_term_char,
3510             we would get 0x81 0x5C 0x35 0x81 0x30 for the gb18030 character.
3511             That would be the same issue as mentioned above.
3512 
3513             Also, if we just escape the leading 2 bytes, we would get
3514             0x5C 0x81 0x5C 0x35 0x81 0x30 in this case.
3515             The reader of this sequence would assume that 0x81 0x30
3516             is the starting of a new gb18030 character, which would
3517             result in further confusion.
3518 
3519             Once we find any byte of the 4-byte gb18030 character should
3520             be escaped, we have to escape all the 4 bytes.
3521             So for GB+81358130, we will get:
3522             0x5C 0x81 0x5C 0x35 0x5C 0x81 0x30
3523 
3524             The byte 0x30 shouldn't be escaped(no matter it's the second
3525             or fourth byte in the sequence), since '\0' would be treated
3526             as 0x00, which is not what we expect. And 0x30 would be treated as
3527             an ASCII char when we read it, which is correct.
3528           */
3529 
3530           assert(in_escapable_4_bytes >= 0);
3531           if (in_escapable_4_bytes > 0)
3532           {
3533             assert(check_following_byte);
3534             /* We should escape or not escape all the 4 bytes. */
3535             need_escape= escape_4_bytes;
3536           }
3537           else if (NEED_ESCAPING(*pos))
3538           {
3539             need_escape= true;
3540             if (my_mbmaxlenlen(character_set_client) == 2 &&
3541                 my_mbcharlen_ptr(character_set_client, pos, end) == 4)
3542             {
3543               in_escapable_4_bytes= 4;
3544               escape_4_bytes= true;
3545             }
3546           }
3547           else if (check_following_byte)
3548           {
3549              int len= my_mbcharlen_ptr(character_set_client, pos, end);
3550              if (len == 2 && pos + 1 < end && NEED_ESCAPING(pos[1]))
3551                need_escape= true;
3552              else if (len == 4 && my_mbmaxlenlen(character_set_client) == 2 &&
3553                       pos + 3 < end)
3554              {
3555                in_escapable_4_bytes= 4;
3556                escape_4_bytes= (NEED_ESCAPING(pos[1]) ||
3557                                 NEED_ESCAPING(pos[2]) ||
3558                                 NEED_ESCAPING(pos[3]));
3559                need_escape= escape_4_bytes;
3560              }
3561           }
3562           /* Mark how many coming bytes should be escaped, only for gb18030 */
3563           if (in_escapable_4_bytes > 0)
3564           {
3565             in_escapable_4_bytes--;
3566             /*
3567              Note that '0' (0x30) in the middle of a 4-byte sequence
3568              can't be escaped. Please read more details from above comments.
3569              2-byte codes won't be affected by this issue.
3570             */
3571             if (pos[0] == 0x30)
3572               need_escape= false;
3573           }
3574 
3575           if (need_escape &&
3576               /*
3577                Don't escape field_term_char by doubling - doubling is only
3578                valid for ENCLOSED BY characters:
3579               */
3580               (enclosed || !is_ambiguous_field_term ||
3581                (int) (uchar) *pos != field_term_char))
3582           {
3583 	    char tmp_buff[2];
3584             tmp_buff[0]= ((int) (uchar) *pos == field_sep_char &&
3585                           is_ambiguous_field_sep) ?
3586                           field_sep_char : escape_char;
3587 	    tmp_buff[1]= *pos ? *pos : '0';
3588 	    if (my_b_write(&cache,(uchar*) start,(uint) (pos-start)) ||
3589 		my_b_write(&cache,(uchar*) tmp_buff,2))
3590 	      goto err;
3591 	    start=pos+1;
3592 	  }
3593 	}
3594 
3595         /* Assert that no escape mode is active here */
3596         assert(in_escapable_4_bytes == 0);
3597 
3598 	if (my_b_write(&cache,(uchar*) start,(uint) (pos-start)))
3599 	  goto err;
3600       }
3601       else if (my_b_write(&cache,(uchar*) res->ptr(),used_length))
3602 	goto err;
3603     }
3604     if (fixed_row_size)
3605     {						// Fill with space
3606       if (item->max_length > used_length)
3607       {
3608 	/* QQ:  Fix by adding a my_b_fill() function */
3609 	if (!space_inited)
3610 	{
3611 	  space_inited=1;
3612 	  memset(space, ' ', sizeof(space));
3613 	}
3614 	size_t length=item->max_length-used_length;
3615 	for (; length > sizeof(space) ; length-=sizeof(space))
3616 	{
3617 	  if (my_b_write(&cache,(uchar*) space,sizeof(space)))
3618 	    goto err;
3619 	}
3620 	if (my_b_write(&cache,(uchar*) space,length))
3621 	  goto err;
3622       }
3623     }
3624     if (res && enclosed)
3625     {
3626       if (my_b_write(&cache, (uchar*) exchange->field.enclosed->ptr(),
3627                      exchange->field.enclosed->length()))
3628         goto err;
3629     }
3630     if (--items_left)
3631     {
3632       if (my_b_write(&cache, (uchar*) exchange->field.field_term->ptr(),
3633                      field_term_length))
3634         goto err;
3635     }
3636   }
3637   if (my_b_write(&cache,(uchar*) exchange->line.line_term->ptr(),
3638 		 exchange->line.line_term->length()))
3639     goto err;
3640   DBUG_RETURN(0);
3641 err:
3642   DBUG_RETURN(1);
3643 }
3644 
3645 
3646 /***************************************************************************
3647 ** Dump of query to a binary file
3648 ***************************************************************************/
3649 
3650 
prepare(List<Item> & list MY_ATTRIBUTE ((unused)),SELECT_LEX_UNIT * u)3651 int Query_result_dump::prepare(List<Item> &list MY_ATTRIBUTE((unused)),
3652                                SELECT_LEX_UNIT *u)
3653 {
3654   unit= u;
3655   return (int) ((file= create_file(thd, path, exchange, &cache)) < 0);
3656 }
3657 
3658 
send_data(List<Item> & items)3659 bool Query_result_dump::send_data(List<Item> &items)
3660 {
3661   List_iterator_fast<Item> li(items);
3662   char buff[MAX_FIELD_WIDTH];
3663   String tmp(buff,sizeof(buff),&my_charset_bin),*res;
3664   tmp.length(0);
3665   Item *item;
3666   DBUG_ENTER("Query_result_dump::send_data");
3667 
3668   if (unit->offset_limit_cnt)
3669   {						// using limit offset,count
3670     unit->offset_limit_cnt--;
3671     DBUG_RETURN(0);
3672   }
3673   if (row_count++ > 1)
3674   {
3675     my_message(ER_TOO_MANY_ROWS, ER(ER_TOO_MANY_ROWS), MYF(0));
3676     goto err;
3677   }
3678   while ((item=li++))
3679   {
3680     res=item->str_result(&tmp);
3681     if (!res)					// If NULL
3682     {
3683       if (my_b_write(&cache,(uchar*) "",1))
3684 	goto err;
3685     }
3686     else if (my_b_write(&cache,(uchar*) res->ptr(),res->length()))
3687     {
3688       char errbuf[MYSYS_STRERROR_SIZE];
3689       my_error(ER_ERROR_ON_WRITE, MYF(0), path, my_errno(),
3690                my_strerror(errbuf, sizeof(errbuf), my_errno()));
3691       goto err;
3692     }
3693   }
3694   DBUG_RETURN(0);
3695 err:
3696   DBUG_RETURN(1);
3697 }
3698 
3699 
3700 /***************************************************************************
3701   Dump of select to variables
3702 ***************************************************************************/
3703 
prepare(List<Item> & list,SELECT_LEX_UNIT * u)3704 int Query_dumpvar::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
3705 {
3706   unit= u;
3707 
3708   if (var_list.elements != list.elements)
3709   {
3710     my_message(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT,
3711                ER(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT), MYF(0));
3712     return 1;
3713   }
3714 
3715   return 0;
3716 }
3717 
3718 
check_simple_select() const3719 bool Query_dumpvar::check_simple_select() const
3720 {
3721   my_error(ER_SP_BAD_CURSOR_SELECT, MYF(0));
3722   return TRUE;
3723 }
3724 
3725 
free_items()3726 void Query_arena::free_items()
3727 {
3728   Item *next;
3729   DBUG_ENTER("Query_arena::free_items");
3730   /* This works because items are allocated with sql_alloc() */
3731   for (; free_list; free_list= next)
3732   {
3733     next= free_list->next;
3734     free_list->delete_self();
3735   }
3736   /* Postcondition: free_list is 0 */
3737   DBUG_VOID_RETURN;
3738 }
3739 
3740 
set_query_arena(Query_arena * set)3741 void Query_arena::set_query_arena(Query_arena *set)
3742 {
3743   mem_root=  set->mem_root;
3744   free_list= set->free_list;
3745   state= set->state;
3746 }
3747 
3748 
cleanup_stmt()3749 void Query_arena::cleanup_stmt()
3750 {
3751   assert(! "Query_arena::cleanup_stmt() not implemented");
3752 }
3753 
3754 
end_statement()3755 void THD::end_statement()
3756 {
3757   /* Cleanup SQL processing state to reuse this statement in next query. */
3758   lex_end(lex);
3759   delete lex->result;
3760   lex->result= 0;
3761   /* Note that free_list is freed in cleanup_after_query() */
3762 
3763   /*
3764     Don't free mem_root, as mem_root is freed in the end of dispatch_command
3765     (once for any command).
3766   */
3767 }
3768 
3769 
set_n_backup_active_arena(Query_arena * set,Query_arena * backup)3770 void THD::set_n_backup_active_arena(Query_arena *set, Query_arena *backup)
3771 {
3772   DBUG_ENTER("THD::set_n_backup_active_arena");
3773   assert(backup->is_backup_arena == FALSE);
3774 
3775   backup->set_query_arena(this);
3776   set_query_arena(set);
3777 #ifndef NDEBUG
3778   backup->is_backup_arena= TRUE;
3779 #endif
3780   DBUG_VOID_RETURN;
3781 }
3782 
3783 
restore_active_arena(Query_arena * set,Query_arena * backup)3784 void THD::restore_active_arena(Query_arena *set, Query_arena *backup)
3785 {
3786   DBUG_ENTER("THD::restore_active_arena");
3787   assert(backup->is_backup_arena);
3788   set->set_query_arena(this);
3789   set_query_arena(backup);
3790 #ifndef NDEBUG
3791   backup->is_backup_arena= FALSE;
3792 #endif
3793   DBUG_VOID_RETURN;
3794 }
3795 
3796 C_MODE_START
3797 
3798 static uchar *
get_statement_id_as_hash_key(const uchar * record,size_t * key_length,my_bool not_used MY_ATTRIBUTE ((unused)))3799 get_statement_id_as_hash_key(const uchar *record, size_t *key_length,
3800                              my_bool not_used MY_ATTRIBUTE((unused)))
3801 {
3802   const Prepared_statement *statement= (const Prepared_statement *) record;
3803   *key_length= sizeof(statement->id);
3804   return (uchar *) &(statement)->id;
3805 }
3806 
delete_statement_as_hash_key(void * key)3807 static void delete_statement_as_hash_key(void *key)
3808 {
3809   delete (Prepared_statement *) key;
3810 }
3811 
get_stmt_name_hash_key(Prepared_statement * entry,size_t * length,my_bool not_used MY_ATTRIBUTE ((unused)))3812 static uchar *get_stmt_name_hash_key(Prepared_statement *entry, size_t *length,
3813                                      my_bool not_used MY_ATTRIBUTE((unused)))
3814 {
3815   *length= entry->name().length;
3816   return reinterpret_cast<uchar *>(const_cast<char *>(entry->name().str));
3817 }
3818 
3819 C_MODE_END
3820 
Prepared_statement_map()3821 Prepared_statement_map::Prepared_statement_map()
3822  :m_last_found_statement(NULL)
3823 {
3824   enum
3825   {
3826     START_STMT_HASH_SIZE = 16,
3827     START_NAME_HASH_SIZE = 16
3828   };
3829   my_hash_init(&st_hash, &my_charset_bin, START_STMT_HASH_SIZE, 0, 0,
3830                get_statement_id_as_hash_key,
3831                delete_statement_as_hash_key, MYF(0),
3832                key_memory_prepared_statement_map);
3833   my_hash_init(&names_hash, system_charset_info, START_NAME_HASH_SIZE, 0, 0,
3834                (my_hash_get_key) get_stmt_name_hash_key,
3835                NULL, MYF(0),
3836                key_memory_prepared_statement_map);
3837 }
3838 
3839 
insert(THD * thd,Prepared_statement * statement)3840 int Prepared_statement_map::insert(THD *thd, Prepared_statement *statement)
3841 {
3842   if (my_hash_insert(&st_hash, (uchar*) statement))
3843   {
3844     /*
3845       Delete is needed only in case of an insert failure. In all other
3846       cases hash_delete will also delete the statement.
3847     */
3848     delete statement;
3849     my_error(ER_OUT_OF_RESOURCES, MYF(0));
3850     goto err_st_hash;
3851   }
3852   if (statement->name().str && my_hash_insert(&names_hash, (uchar*) statement))
3853   {
3854     my_error(ER_OUT_OF_RESOURCES, MYF(0));
3855     goto err_names_hash;
3856   }
3857   mysql_mutex_lock(&LOCK_prepared_stmt_count);
3858   /*
3859     We don't check that prepared_stmt_count is <= max_prepared_stmt_count
3860     because we would like to allow to lower the total limit
3861     of prepared statements below the current count. In that case
3862     no new statements can be added until prepared_stmt_count drops below
3863     the limit.
3864   */
3865   if (prepared_stmt_count >= max_prepared_stmt_count)
3866   {
3867     mysql_mutex_unlock(&LOCK_prepared_stmt_count);
3868     my_error(ER_MAX_PREPARED_STMT_COUNT_REACHED, MYF(0),
3869              max_prepared_stmt_count);
3870     goto err_max;
3871   }
3872   prepared_stmt_count++;
3873   mysql_mutex_unlock(&LOCK_prepared_stmt_count);
3874 
3875   m_last_found_statement= statement;
3876   return 0;
3877 
3878 err_max:
3879   if (statement->name().str)
3880     my_hash_delete(&names_hash, (uchar*) statement);
3881 err_names_hash:
3882   my_hash_delete(&st_hash, (uchar*) statement);
3883 err_st_hash:
3884   return 1;
3885 }
3886 
3887 
3888 Prepared_statement
find_by_name(const LEX_CSTRING & name)3889 *Prepared_statement_map::find_by_name(const LEX_CSTRING &name)
3890 {
3891   return reinterpret_cast<Prepared_statement*>
3892     (my_hash_search(&names_hash, (uchar*)name.str, name.length));
3893 }
3894 
3895 
find(ulong id)3896 Prepared_statement *Prepared_statement_map::find(ulong id)
3897 {
3898   if (m_last_found_statement == NULL || id != m_last_found_statement->id)
3899   {
3900     Prepared_statement *stmt=
3901       reinterpret_cast<Prepared_statement*>
3902       (my_hash_search(&st_hash, (uchar *) &id, sizeof(id)));
3903     if (stmt && stmt->name().str)
3904       return NULL;
3905     m_last_found_statement= stmt;
3906   }
3907   return m_last_found_statement;
3908 }
3909 
3910 
erase(Prepared_statement * statement)3911 void Prepared_statement_map::erase(Prepared_statement *statement)
3912 {
3913   if (statement == m_last_found_statement)
3914     m_last_found_statement= NULL;
3915   if (statement->name().str)
3916     my_hash_delete(&names_hash, (uchar *) statement);
3917 
3918   my_hash_delete(&st_hash, (uchar *) statement);
3919   mysql_mutex_lock(&LOCK_prepared_stmt_count);
3920   assert(prepared_stmt_count > 0);
3921   prepared_stmt_count--;
3922   mysql_mutex_unlock(&LOCK_prepared_stmt_count);
3923 }
3924 
claim_memory_ownership()3925 void Prepared_statement_map::claim_memory_ownership()
3926 {
3927   my_hash_claim(&names_hash);
3928   my_hash_claim(&st_hash);
3929 }
3930 
reset()3931 void Prepared_statement_map::reset()
3932 {
3933   /* Must be first, hash_free will reset st_hash.records */
3934   if (st_hash.records > 0)
3935   {
3936 #ifdef HAVE_PSI_PS_INTERFACE
3937     for (uint i=0 ; i < st_hash.records ; i++)
3938     {
3939       Prepared_statement *stmt=
3940         reinterpret_cast<Prepared_statement *>(my_hash_element(&st_hash, i));
3941       MYSQL_DESTROY_PS(stmt->get_PS_prepared_stmt());
3942     }
3943 #endif
3944     mysql_mutex_lock(&LOCK_prepared_stmt_count);
3945     assert(prepared_stmt_count >= st_hash.records);
3946     prepared_stmt_count-= st_hash.records;
3947     mysql_mutex_unlock(&LOCK_prepared_stmt_count);
3948   }
3949   my_hash_reset(&names_hash);
3950   my_hash_reset(&st_hash);
3951   m_last_found_statement= NULL;
3952 }
3953 
3954 
~Prepared_statement_map()3955 Prepared_statement_map::~Prepared_statement_map()
3956 {
3957   /*
3958     We do not want to grab the global LOCK_prepared_stmt_count mutex here.
3959     reset() should already have been called to maintain prepared_stmt_count.
3960    */
3961   assert(st_hash.records == 0);
3962 
3963   my_hash_free(&names_hash);
3964   my_hash_free(&st_hash);
3965 }
3966 
3967 
send_data(List<Item> & items)3968 bool Query_dumpvar::send_data(List<Item> &items)
3969 {
3970   List_iterator_fast<PT_select_var> var_li(var_list);
3971   List_iterator<Item> it(items);
3972   Item *item;
3973   PT_select_var *mv;
3974   DBUG_ENTER("Query_dumpvar::send_data");
3975 
3976   if (unit->offset_limit_cnt)
3977   {						// using limit offset,count
3978     unit->offset_limit_cnt--;
3979     DBUG_RETURN(false);
3980   }
3981   if (row_count++)
3982   {
3983     my_message(ER_TOO_MANY_ROWS, ER(ER_TOO_MANY_ROWS), MYF(0));
3984     DBUG_RETURN(true);
3985   }
3986   while ((mv= var_li++) && (item= it++))
3987   {
3988     if (mv->is_local())
3989     {
3990       if (thd->sp_runtime_ctx->set_variable(thd, mv->get_offset(), &item))
3991 	    DBUG_RETURN(true);
3992     }
3993     else
3994     {
3995       /*
3996         Create Item_func_set_user_vars with delayed non-constness. We
3997         do this so that Item_get_user_var::const_item() will return
3998         the same result during
3999         Item_func_set_user_var::save_item_result() as they did during
4000         optimization and execution.
4001        */
4002       Item_func_set_user_var *suv=
4003         new Item_func_set_user_var(mv->name, item, true);
4004       if (suv->fix_fields(thd, 0))
4005         DBUG_RETURN(true);
4006       suv->save_item_result(item);
4007       if (suv->update())
4008         DBUG_RETURN(true);
4009     }
4010   }
4011   DBUG_RETURN(thd->is_error());
4012 }
4013 
send_eof()4014 bool Query_dumpvar::send_eof()
4015 {
4016   if (! row_count)
4017     push_warning(thd, Sql_condition::SL_WARNING,
4018                  ER_SP_FETCH_NO_DATA, ER(ER_SP_FETCH_NO_DATA));
4019   /*
4020     Don't send EOF if we're in error condition (which implies we've already
4021     sent or are sending an error)
4022   */
4023   if (thd->is_error())
4024     return true;
4025 
4026   ::my_ok(thd,row_count);
4027   return 0;
4028 }
4029 
4030 
thd_increment_bytes_sent(size_t length)4031 void thd_increment_bytes_sent(size_t length)
4032 {
4033   THD *thd= current_thd;
4034   if (likely(thd != NULL))
4035   { /* current_thd==NULL when close_connection() calls net_send_error() */
4036     thd->status_var.bytes_sent+= length;
4037   }
4038 }
4039 
4040 
thd_increment_bytes_received(size_t length)4041 void thd_increment_bytes_received(size_t length)
4042 {
4043   THD *thd= current_thd;
4044   if (likely(thd != NULL))
4045     thd->status_var.bytes_received+= length;
4046 }
4047 
4048 
set_status_var_init()4049 void THD::set_status_var_init()
4050 {
4051   memset(&status_var, 0, sizeof(status_var));
4052 }
4053 
4054 
4055 /****************************************************************************
4056   Handling of open and locked tables states.
4057 
4058   This is used when we want to open/lock (and then close) some tables when
4059   we already have a set of tables open and locked. We use these methods for
4060   access to mysql.proc table to find definitions of stored routines.
4061 ****************************************************************************/
4062 
reset_n_backup_open_tables_state(Open_tables_backup * backup)4063 void THD::reset_n_backup_open_tables_state(Open_tables_backup *backup)
4064 {
4065   DBUG_ENTER("reset_n_backup_open_tables_state");
4066   backup->set_open_tables_state(this);
4067   backup->mdl_system_tables_svp= mdl_context.mdl_savepoint();
4068   reset_open_tables_state();
4069   state_flags|= Open_tables_state::BACKUPS_AVAIL;
4070   DBUG_VOID_RETURN;
4071 }
4072 
4073 
restore_backup_open_tables_state(Open_tables_backup * backup)4074 void THD::restore_backup_open_tables_state(Open_tables_backup *backup)
4075 {
4076   DBUG_ENTER("restore_backup_open_tables_state");
4077   mdl_context.rollback_to_savepoint(backup->mdl_system_tables_svp);
4078   /*
4079     Before we will throw away current open tables state we want
4080     to be sure that it was properly cleaned up.
4081   */
4082   assert(open_tables == 0 && temporary_tables == 0 &&
4083          derived_tables == 0 &&
4084          lock == 0 &&
4085          locked_tables_mode == LTM_NONE &&
4086          get_reprepare_observer() == NULL);
4087 
4088   set_open_tables_state(backup);
4089   DBUG_VOID_RETURN;
4090 }
4091 
4092 
begin_attachable_ro_transaction()4093 void THD::begin_attachable_ro_transaction()
4094 {
4095   assert(!m_attachable_trx);
4096 
4097   m_attachable_trx= new Attachable_trx(this);
4098 }
4099 
4100 
end_attachable_transaction()4101 void THD::end_attachable_transaction()
4102 {
4103   assert(m_attachable_trx);
4104 
4105   delete m_attachable_trx;
4106   m_attachable_trx= NULL;
4107 }
4108 
4109 
4110 /**
4111   Check the killed state of a user thread
4112   @param thd  user thread
4113   @retval 0 the user thread is active
4114   @retval 1 the user thread has been killed
4115 */
thd_killed(const MYSQL_THD thd)4116 extern "C" int thd_killed(const MYSQL_THD thd)
4117 {
4118   if (thd == NULL)
4119     return current_thd != NULL ? current_thd->killed : 0;
4120   return thd->killed;
4121 }
4122 
4123 /**
4124   Set the killed status of the current statement.
4125 
4126   @param thd  user thread connection handle
4127 */
thd_set_kill_status(const MYSQL_THD thd)4128 extern "C" void thd_set_kill_status(const MYSQL_THD thd)
4129 {
4130   thd->send_kill_message();
4131 }
4132 
4133 /**
4134   Return the thread id of a user thread
4135   @param thd user thread
4136   @return thread id
4137 */
thd_get_thread_id(const MYSQL_THD thd)4138 extern "C" unsigned long thd_get_thread_id(const MYSQL_THD thd)
4139 {
4140   return((unsigned long)thd->thread_id());
4141 }
4142 
4143 /**
4144   Check if batching is allowed for the thread
4145   @param thd  user thread
4146   @retval 1 batching allowed
4147   @retval 0 batching not allowed
4148 */
thd_allow_batch(MYSQL_THD thd)4149 extern "C" int thd_allow_batch(MYSQL_THD thd)
4150 {
4151   if ((thd->variables.option_bits & OPTION_ALLOW_BATCH) ||
4152       (thd->slave_thread && opt_slave_allow_batching))
4153     return 1;
4154   return 0;
4155 }
4156 
thd_get_trx_isolation(const MYSQL_THD thd)4157 enum_tx_isolation thd_get_trx_isolation(const MYSQL_THD thd)
4158 {
4159 	return thd->tx_isolation;
4160 }
4161 
4162 #ifdef INNODB_COMPATIBILITY_HOOKS
thd_charset(MYSQL_THD thd)4163 extern "C" const struct charset_info_st *thd_charset(MYSQL_THD thd)
4164 {
4165   return(thd->charset());
4166 }
4167 
4168 /**
4169   Get the current query string for the thread.
4170 
4171   @param thd   The MySQL internal thread pointer
4172 
4173   @return query string and length. May be non-null-terminated.
4174 
4175   @note This function is not thread safe and should only be called
4176         from the thread owning thd. @see thd_query_safe().
4177 */
thd_query_unsafe(MYSQL_THD thd)4178 extern "C" LEX_CSTRING thd_query_unsafe(MYSQL_THD thd)
4179 {
4180   assert(current_thd == thd);
4181   return thd->query();
4182 }
4183 
4184 /**
4185   Get the current query string for the thread.
4186 
4187   @param thd     The MySQL internal thread pointer
4188   @param buf     Buffer where the query string will be copied
4189   @param buflen  Length of the buffer
4190 
4191   @return Length of the query
4192 
4193   @note This function is thread safe as the query string is
4194         accessed under mutex protection and the string is copied
4195         into the provided buffer. @see thd_query_unsafe().
4196 */
thd_query_safe(MYSQL_THD thd,char * buf,size_t buflen)4197 extern "C" size_t thd_query_safe(MYSQL_THD thd, char *buf, size_t buflen)
4198 {
4199   mysql_mutex_lock(&thd->LOCK_thd_query);
4200   LEX_CSTRING query_string= thd->query();
4201   size_t len= MY_MIN(buflen - 1, query_string.length);
4202   strncpy(buf, query_string.str, len);
4203   buf[len]= '\0';
4204   mysql_mutex_unlock(&thd->LOCK_thd_query);
4205   return len;
4206 }
4207 
thd_slave_thread(const MYSQL_THD thd)4208 extern "C" int thd_slave_thread(const MYSQL_THD thd)
4209 {
4210   return(thd->slave_thread);
4211 }
4212 
thd_non_transactional_update(const MYSQL_THD thd)4213 extern "C" int thd_non_transactional_update(const MYSQL_THD thd)
4214 {
4215   return thd->get_transaction()->has_modified_non_trans_table(
4216     Transaction_ctx::SESSION);
4217 }
4218 
thd_has_active_attachable_trx(const MYSQL_THD thd)4219 extern "C" int thd_has_active_attachable_trx(const MYSQL_THD thd)
4220 {
4221   return thd->is_attachable_transaction_active();
4222 }
4223 
thd_is_operating_gtid_table_implicitly(const MYSQL_THD thd)4224 extern "C" int thd_is_operating_gtid_table_implicitly(const MYSQL_THD thd)
4225 {
4226   return thd->is_operating_gtid_table_implicitly;
4227 }
4228 
thd_binlog_format(const MYSQL_THD thd)4229 extern "C" int thd_binlog_format(const MYSQL_THD thd)
4230 {
4231 #ifdef WITH_WSREP
4232   if (WSREP(thd))
4233   {
4234     /* for wsrep binlog format is meaningful also when binlogging is off */
4235      return (int) WSREP_BINLOG_FORMAT(thd->variables.binlog_format);
4236   }
4237 #endif /* WITH_WSREP */
4238   if (mysql_bin_log.is_open() && (thd->variables.option_bits & OPTION_BIN_LOG))
4239     return (int) thd->variables.binlog_format;
4240   else
4241    return BINLOG_FORMAT_UNSPEC;
4242 }
4243 
thd_mark_transaction_to_rollback(MYSQL_THD thd,int all)4244 extern "C" void thd_mark_transaction_to_rollback(MYSQL_THD thd, int all)
4245 {
4246   DBUG_ENTER("thd_mark_transaction_to_rollback");
4247   assert(thd);
4248   /*
4249     The parameter "all" has type int since the function is defined
4250     in plugin.h. The corresponding parameter in the call below has
4251     type bool. The comment in plugin.h states that "all != 0"
4252     means to rollback the main transaction. Thus, check this
4253     specifically.
4254   */
4255   thd->mark_transaction_to_rollback((all != 0));
4256   DBUG_VOID_RETURN;
4257 }
4258 
thd_binlog_filter_ok(const MYSQL_THD thd)4259 extern "C" bool thd_binlog_filter_ok(const MYSQL_THD thd)
4260 {
4261   return binlog_filter->db_ok(thd->db().str);
4262 }
4263 
thd_sqlcom_can_generate_row_events(const MYSQL_THD thd)4264 extern "C" bool thd_sqlcom_can_generate_row_events(const MYSQL_THD thd)
4265 {
4266   return sqlcom_can_generate_row_events(thd->lex->sql_command);
4267 }
4268 
thd_get_durability_property(const MYSQL_THD thd)4269 extern "C" enum durability_properties thd_get_durability_property(const MYSQL_THD thd)
4270 {
4271   enum durability_properties ret= HA_REGULAR_DURABILITY;
4272 
4273   if (thd != NULL)
4274     ret= thd->durability_property;
4275 
4276   return ret;
4277 }
4278 
4279 /** Get the auto_increment_offset auto_increment_increment.
4280 Needed by InnoDB.
4281 @param thd	Thread object
4282 @param off	auto_increment_offset
4283 @param inc	auto_increment_increment */
thd_get_autoinc(const MYSQL_THD thd,ulong * off,ulong * inc)4284 extern "C" void thd_get_autoinc(const MYSQL_THD thd, ulong* off, ulong* inc)
4285 {
4286   *off = thd->variables.auto_increment_offset;
4287   *inc = thd->variables.auto_increment_increment;
4288 }
4289 
4290 
4291 /**
4292   Is strict sql_mode set.
4293   Needed by InnoDB.
4294   @param thd	Thread object
4295   @return True if sql_mode has strict mode (all or trans).
4296     @retval true  sql_mode has strict mode (all or trans).
4297     @retval false sql_mode has not strict mode (all or trans).
4298 */
thd_is_strict_mode(const MYSQL_THD thd)4299 extern "C" bool thd_is_strict_mode(const MYSQL_THD thd)
4300 {
4301   return thd->is_strict_mode();
4302 }
4303 
4304 
4305 #ifndef EMBEDDED_LIBRARY
4306 extern "C" void thd_pool_wait_begin(MYSQL_THD thd, int wait_type);
4307 extern "C" void thd_pool_wait_end(MYSQL_THD thd);
4308 
4309 /*
4310   Interface for MySQL Server, plugins and storage engines to report
4311   when they are going to sleep/stall.
4312 
4313   SYNOPSIS
4314   thd_wait_begin()
4315   thd                     Thread object
4316   wait_type               Type of wait
4317                           1 -- short wait (e.g. for mutex)
4318                           2 -- medium wait (e.g. for disk io)
4319                           3 -- large wait (e.g. for locked row/table)
4320   NOTES
4321     This is used by the threadpool to have better knowledge of which
4322     threads that currently are actively running on CPUs. When a thread
4323     reports that it's going to sleep/stall, the threadpool scheduler is
4324     free to start another thread in the pool most likely. The expected wait
4325     time is simply an indication of how long the wait is expected to
4326     become, the real wait time could be very different.
4327 
4328   thd_wait_end MUST be called immediately after waking up again.
4329 */
thd_wait_begin(MYSQL_THD thd,int wait_type)4330 extern "C" void thd_wait_begin(MYSQL_THD thd, int wait_type)
4331 {
4332   MYSQL_CALLBACK(Connection_handler_manager::event_functions,
4333                  thd_wait_begin, (thd, wait_type));
4334 }
4335 
4336 /**
4337   Interface for MySQL Server, plugins and storage engines to report
4338   when they waking up from a sleep/stall.
4339 
4340   @param  thd   Thread handle
4341 */
thd_wait_end(MYSQL_THD thd)4342 extern "C" void thd_wait_end(MYSQL_THD thd)
4343 {
4344   MYSQL_CALLBACK(Connection_handler_manager::event_functions,
4345                  thd_wait_end, (thd));
4346 }
4347 #else
thd_wait_begin(MYSQL_THD thd,int wait_type)4348 extern "C" void thd_wait_begin(MYSQL_THD thd, int wait_type)
4349 {
4350   /* do NOTHING for the embedded library */
4351   return;
4352 }
4353 
thd_wait_end(MYSQL_THD thd)4354 extern "C" void thd_wait_end(MYSQL_THD thd)
4355 {
4356   /* do NOTHING for the embedded library */
4357   return;
4358 }
4359 #endif
4360 #endif // INNODB_COMPATIBILITY_HOOKS */
4361 
4362 #ifndef EMBEDDED_LIBRARY
4363 /**
4364    Interface for Engine to report row lock conflict.
4365    The caller should guarantee thd_wait_for does not be freed, when it is
4366    called.
4367 */
4368 extern "C"
thd_report_row_lock_wait(THD * self,THD * wait_for)4369 void thd_report_row_lock_wait(THD* self, THD *wait_for)
4370 {
4371   DBUG_ENTER("thd_report_row_lock_wait");
4372 
4373   if (self != NULL && wait_for != NULL &&
4374       is_mts_worker(self) && is_mts_worker(wait_for))
4375     commit_order_manager_check_deadlock(self, wait_for);
4376 
4377   DBUG_VOID_RETURN;
4378 }
4379 #else
4380 extern "C"
thd_report_row_lock_wait(THD * thd_wait_for)4381 void thd_report_row_lock_wait(THD *thd_wait_for)
4382 {
4383   return;
4384 }
4385 #endif
4386 
4387 /****************************************************************************
4388   Handling of statement states in functions and triggers.
4389 
4390   This is used to ensure that the function/trigger gets a clean state
4391   to work with and does not cause any side effects of the calling statement.
4392 
4393   It also allows most stored functions and triggers to replicate even
4394   if they are used items that would normally be stored in the binary
4395   replication (like last_insert_id() etc...)
4396 
4397   The following things is done
4398   - Disable binary logging for the duration of the statement
4399   - Disable multi-result-sets for the duration of the statement
4400   - Value of last_insert_id() is saved and restored
4401   - Value set by 'SET INSERT_ID=#' is reset and restored
4402   - Value for found_rows() is reset and restored
4403   - examined_row_count is added to the total
4404   - cuted_fields is added to the total
4405   - new savepoint level is created and destroyed
4406 
4407   NOTES:
4408     Seed for random() is saved for the first! usage of RAND()
4409     We reset examined_row_count and cuted_fields and add these to the
4410     result to ensure that if we have a bug that would reset these within
4411     a function, we are not loosing any rows from the main statement.
4412 
4413     We do not reset value of last_insert_id().
4414 ****************************************************************************/
4415 
reset_sub_statement_state(Sub_statement_state * backup,uint new_state)4416 void THD::reset_sub_statement_state(Sub_statement_state *backup,
4417                                     uint new_state)
4418 {
4419 #ifndef EMBEDDED_LIBRARY
4420   /* BUG#33029, if we are replicating from a buggy master, reset
4421      auto_inc_intervals_forced to prevent substatement
4422      (triggers/functions) from using erroneous INSERT_ID value
4423    */
4424   if (rpl_master_erroneous_autoinc(this))
4425   {
4426     assert(backup->auto_inc_intervals_forced.nb_elements() == 0);
4427     auto_inc_intervals_forced.swap(&backup->auto_inc_intervals_forced);
4428   }
4429 #endif
4430 
4431   backup->option_bits=     variables.option_bits;
4432   backup->count_cuted_fields= count_cuted_fields;
4433   backup->in_sub_stmt=     in_sub_stmt;
4434   backup->enable_slow_log= enable_slow_log;
4435   backup->current_found_rows= current_found_rows;
4436   backup->previous_found_rows= previous_found_rows;
4437   backup->examined_row_count= m_examined_row_count;
4438   backup->sent_row_count= m_sent_row_count;
4439   backup->cuted_fields=     cuted_fields;
4440   backup->client_capabilities= m_protocol->get_client_capabilities();
4441   backup->savepoints= get_transaction()->m_savepoints;
4442   backup->first_successful_insert_id_in_prev_stmt=
4443     first_successful_insert_id_in_prev_stmt;
4444   backup->first_successful_insert_id_in_cur_stmt=
4445     first_successful_insert_id_in_cur_stmt;
4446 
4447   if ((!lex->requires_prelocking() || is_update_query(lex->sql_command)) &&
4448       !is_current_stmt_binlog_format_row())
4449   {
4450     variables.option_bits&= ~OPTION_BIN_LOG;
4451   }
4452 
4453   if ((backup->option_bits & OPTION_BIN_LOG) &&
4454        is_update_query(lex->sql_command) &&
4455        !is_current_stmt_binlog_format_row())
4456     mysql_bin_log.start_union_events(this, this->query_id);
4457 
4458   /* Disable result sets */
4459   if (is_classic_protocol())
4460     get_protocol_classic()->remove_client_capability(CLIENT_MULTI_RESULTS);
4461   in_sub_stmt|= new_state;
4462   m_examined_row_count= 0;
4463   m_sent_row_count= 0;
4464   cuted_fields= 0;
4465   get_transaction()->m_savepoints= 0;
4466   first_successful_insert_id_in_cur_stmt= 0;
4467 
4468   /* Reset savepoint on transaction write set */
4469   if (is_current_stmt_binlog_row_enabled_with_write_set_extraction())
4470   {
4471       get_transaction()->get_transaction_write_set_ctx()
4472           ->reset_savepoint_list();
4473   }
4474 }
4475 
4476 
restore_sub_statement_state(Sub_statement_state * backup)4477 void THD::restore_sub_statement_state(Sub_statement_state *backup)
4478 {
4479   DBUG_ENTER("THD::restore_sub_statement_state");
4480 #ifndef EMBEDDED_LIBRARY
4481   /* BUG#33029, if we are replicating from a buggy master, restore
4482      auto_inc_intervals_forced so that the top statement can use the
4483      INSERT_ID value set before this statement.
4484    */
4485   if (rpl_master_erroneous_autoinc(this))
4486   {
4487     backup->auto_inc_intervals_forced.swap(&auto_inc_intervals_forced);
4488     assert(backup->auto_inc_intervals_forced.nb_elements() == 0);
4489   }
4490 #endif
4491 
4492   /*
4493     To save resources we want to release savepoints which were created
4494     during execution of function or trigger before leaving their savepoint
4495     level. It is enough to release first savepoint set on this level since
4496     all later savepoints will be released automatically.
4497   */
4498   if (get_transaction()->m_savepoints)
4499   {
4500     SAVEPOINT *sv;
4501     for (sv= get_transaction()->m_savepoints; sv->prev; sv= sv->prev)
4502     {}
4503     /* ha_release_savepoint() never returns error. */
4504     (void)ha_release_savepoint(this, sv);
4505   }
4506   count_cuted_fields= backup->count_cuted_fields;
4507   get_transaction()->m_savepoints= backup->savepoints;
4508   variables.option_bits= backup->option_bits;
4509   in_sub_stmt=      backup->in_sub_stmt;
4510   enable_slow_log=  backup->enable_slow_log;
4511   first_successful_insert_id_in_prev_stmt=
4512     backup->first_successful_insert_id_in_prev_stmt;
4513   first_successful_insert_id_in_cur_stmt=
4514     backup->first_successful_insert_id_in_cur_stmt;
4515   current_found_rows= backup->current_found_rows;
4516   previous_found_rows= backup->previous_found_rows;
4517   set_sent_row_count(backup->sent_row_count);
4518   if (is_classic_protocol())
4519     get_protocol_classic()->set_client_capabilities(backup->client_capabilities);
4520 
4521   /*
4522     If we've left sub-statement mode, reset the fatal error flag.
4523     Otherwise keep the current value, to propagate it up the sub-statement
4524     stack.
4525 
4526     NOTE: is_fatal_sub_stmt_error can be set only if we've been in the
4527     sub-statement mode.
4528   */
4529 
4530   if (!in_sub_stmt)
4531     is_fatal_sub_stmt_error= false;
4532 
4533   if ((variables.option_bits & OPTION_BIN_LOG) && is_update_query(lex->sql_command) &&
4534        !is_current_stmt_binlog_format_row())
4535     mysql_bin_log.stop_union_events(this);
4536 
4537   /*
4538     The following is added to the old values as we are interested in the
4539     total complexity of the query
4540   */
4541   inc_examined_row_count(backup->examined_row_count);
4542   cuted_fields+=       backup->cuted_fields;
4543 
4544   /* Restore savepoint on transaction write set */
4545   if (is_current_stmt_binlog_row_enabled_with_write_set_extraction())
4546   {
4547       get_transaction()->get_transaction_write_set_ctx()
4548           ->restore_savepoint_list();
4549   }
4550 
4551   DBUG_VOID_RETURN;
4552 }
4553 
set_sent_row_count(ha_rows count)4554 void THD::set_sent_row_count(ha_rows count)
4555 {
4556   m_sent_row_count= count;
4557   MYSQL_SET_STATEMENT_ROWS_SENT(m_statement_psi, m_sent_row_count);
4558 }
4559 
set_examined_row_count(ha_rows count)4560 void THD::set_examined_row_count(ha_rows count)
4561 {
4562   m_examined_row_count= count;
4563   MYSQL_SET_STATEMENT_ROWS_EXAMINED(m_statement_psi, m_examined_row_count);
4564 }
4565 
inc_sent_row_count(ha_rows count)4566 void THD::inc_sent_row_count(ha_rows count)
4567 {
4568   m_sent_row_count+= count;
4569   MYSQL_SET_STATEMENT_ROWS_SENT(m_statement_psi, m_sent_row_count);
4570 }
4571 
inc_examined_row_count(ha_rows count)4572 void THD::inc_examined_row_count(ha_rows count)
4573 {
4574   m_examined_row_count+= count;
4575   MYSQL_SET_STATEMENT_ROWS_EXAMINED(m_statement_psi, m_examined_row_count);
4576 }
4577 
inc_status_created_tmp_disk_tables()4578 void THD::inc_status_created_tmp_disk_tables()
4579 {
4580   assert(!status_var_aggregated);
4581   status_var.created_tmp_disk_tables++;
4582 #ifdef HAVE_PSI_STATEMENT_INTERFACE
4583   PSI_STATEMENT_CALL(inc_statement_created_tmp_disk_tables)(m_statement_psi, 1);
4584 #endif
4585 }
4586 
inc_status_created_tmp_tables()4587 void THD::inc_status_created_tmp_tables()
4588 {
4589   assert(!status_var_aggregated);
4590   status_var.created_tmp_tables++;
4591 #ifdef HAVE_PSI_STATEMENT_INTERFACE
4592   PSI_STATEMENT_CALL(inc_statement_created_tmp_tables)(m_statement_psi, 1);
4593 #endif
4594 }
4595 
inc_status_select_full_join()4596 void THD::inc_status_select_full_join()
4597 {
4598   assert(!status_var_aggregated);
4599   status_var.select_full_join_count++;
4600 #ifdef HAVE_PSI_STATEMENT_INTERFACE
4601   PSI_STATEMENT_CALL(inc_statement_select_full_join)(m_statement_psi, 1);
4602 #endif
4603 }
4604 
inc_status_select_full_range_join()4605 void THD::inc_status_select_full_range_join()
4606 {
4607   assert(!status_var_aggregated);
4608   status_var.select_full_range_join_count++;
4609 #ifdef HAVE_PSI_STATEMENT_INTERFACE
4610   PSI_STATEMENT_CALL(inc_statement_select_full_range_join)(m_statement_psi, 1);
4611 #endif
4612 }
4613 
inc_status_select_range()4614 void THD::inc_status_select_range()
4615 {
4616   assert(!status_var_aggregated);
4617   status_var.select_range_count++;
4618 #ifdef HAVE_PSI_STATEMENT_INTERFACE
4619   PSI_STATEMENT_CALL(inc_statement_select_range)(m_statement_psi, 1);
4620 #endif
4621 }
4622 
inc_status_select_range_check()4623 void THD::inc_status_select_range_check()
4624 {
4625   assert(!status_var_aggregated);
4626   status_var.select_range_check_count++;
4627 #ifdef HAVE_PSI_STATEMENT_INTERFACE
4628   PSI_STATEMENT_CALL(inc_statement_select_range_check)(m_statement_psi, 1);
4629 #endif
4630 }
4631 
inc_status_select_scan()4632 void THD::inc_status_select_scan()
4633 {
4634   assert(!status_var_aggregated);
4635   status_var.select_scan_count++;
4636 #ifdef HAVE_PSI_STATEMENT_INTERFACE
4637   PSI_STATEMENT_CALL(inc_statement_select_scan)(m_statement_psi, 1);
4638 #endif
4639 }
4640 
inc_status_sort_merge_passes()4641 void THD::inc_status_sort_merge_passes()
4642 {
4643   assert(!status_var_aggregated);
4644   status_var.filesort_merge_passes++;
4645 #ifdef HAVE_PSI_STATEMENT_INTERFACE
4646   PSI_STATEMENT_CALL(inc_statement_sort_merge_passes)(m_statement_psi, 1);
4647 #endif
4648 }
4649 
inc_status_sort_range()4650 void THD::inc_status_sort_range()
4651 {
4652   assert(!status_var_aggregated);
4653   status_var.filesort_range_count++;
4654 #ifdef HAVE_PSI_STATEMENT_INTERFACE
4655   PSI_STATEMENT_CALL(inc_statement_sort_range)(m_statement_psi, 1);
4656 #endif
4657 }
4658 
inc_status_sort_rows(ha_rows count)4659 void THD::inc_status_sort_rows(ha_rows count)
4660 {
4661   status_var.filesort_rows+= count;
4662 #ifdef HAVE_PSI_STATEMENT_INTERFACE
4663   PSI_STATEMENT_CALL(inc_statement_sort_rows)(m_statement_psi,
4664                                               static_cast<ulong>(count));
4665 #endif
4666 }
4667 
inc_status_sort_scan()4668 void THD::inc_status_sort_scan()
4669 {
4670   assert(!status_var_aggregated);
4671   status_var.filesort_scan_count++;
4672 #ifdef HAVE_PSI_STATEMENT_INTERFACE
4673   PSI_STATEMENT_CALL(inc_statement_sort_scan)(m_statement_psi, 1);
4674 #endif
4675 }
4676 
set_status_no_index_used()4677 void THD::set_status_no_index_used()
4678 {
4679   server_status|= SERVER_QUERY_NO_INDEX_USED;
4680 #ifdef HAVE_PSI_STATEMENT_INTERFACE
4681   PSI_STATEMENT_CALL(set_statement_no_index_used)(m_statement_psi);
4682 #endif
4683 }
4684 
set_status_no_good_index_used()4685 void THD::set_status_no_good_index_used()
4686 {
4687   server_status|= SERVER_QUERY_NO_GOOD_INDEX_USED;
4688 #ifdef HAVE_PSI_STATEMENT_INTERFACE
4689   PSI_STATEMENT_CALL(set_statement_no_good_index_used)(m_statement_psi);
4690 #endif
4691 }
4692 
set_command(enum enum_server_command command)4693 void THD::set_command(enum enum_server_command command)
4694 {
4695   m_command= command;
4696 #ifdef HAVE_PSI_THREAD_INTERFACE
4697   PSI_STATEMENT_CALL(set_thread_command)(m_command);
4698 #endif
4699 }
4700 
4701 
set_query(const LEX_CSTRING & query_arg)4702 void THD::set_query(const LEX_CSTRING& query_arg)
4703 {
4704   assert(this == current_thd);
4705   mysql_mutex_lock(&LOCK_thd_query);
4706   m_query_string= query_arg;
4707   mysql_mutex_unlock(&LOCK_thd_query);
4708 }
4709 
4710 
4711 /**
4712   Set the rewritten query (with passwords obfuscated etc.) on the THD.
4713   Wraps this in the LOCK_thd_query mutex to protect against race conditions
4714   with SHOW PROCESSLIST inspecting that string.
4715 
4716   This uses swap() and therefore "steals" the argument from the caller;
4717   the caller MUST take care not to try to use its own string after calling
4718   this function! This is an optimization for mysql_rewrite_query() so we
4719   don't copy its temporary string (which may get very long, up to
4720   @@max_allowed_packet).
4721 
4722   Using this outside of mysql_rewrite_query() is almost certainly wrong;
4723   please check with the runtime team!
4724 
4725   @param query_arg  The rewritten query to use for slow/bin/general logging.
4726                     The value will be released in the caller and MUST NOT
4727                     be used there after calling this function.
4728 */
swap_rewritten_query(String & query_arg)4729 void THD::swap_rewritten_query(String& query_arg)
4730 {
4731   assert(this == current_thd);
4732 
4733   mysql_mutex_lock(&LOCK_thd_query);
4734   m_rewritten_query.mem_free();
4735   m_rewritten_query.swap(query_arg);
4736   // The rewritten query should always be a valid C string, just in case.
4737   (void) m_rewritten_query.c_ptr_safe();
4738   mysql_mutex_unlock(&LOCK_thd_query);
4739 }
4740 
4741 
4742 /**
4743   Leave explicit LOCK TABLES or prelocked mode and restore value of
4744   transaction sentinel in MDL subsystem.
4745 */
4746 
leave_locked_tables_mode()4747 void THD::leave_locked_tables_mode()
4748 {
4749   if (locked_tables_mode == LTM_LOCK_TABLES)
4750   {
4751     /*
4752       When leaving LOCK TABLES mode we have to change the duration of most
4753       of the metadata locks being held, except for HANDLER and GRL locks,
4754       to transactional for them to be properly released at UNLOCK TABLES.
4755     */
4756     mdl_context.set_transaction_duration_for_all_locks();
4757     /*
4758       Make sure we don't release the global read lock and commit blocker
4759       when leaving LTM.
4760     */
4761     global_read_lock.set_explicit_lock_duration(this);
4762     /*
4763       Also ensure that we don't release metadata locks for open HANDLERs
4764       and user-level locks.
4765     */
4766     if (handler_tables_hash.records)
4767       mysql_ha_set_explicit_lock_duration(this);
4768     if (ull_hash.records)
4769       mysql_ull_set_explicit_lock_duration(this);
4770   }
4771   locked_tables_mode= LTM_NONE;
4772 }
4773 
get_definer(LEX_USER * definer)4774 void THD::get_definer(LEX_USER *definer)
4775 {
4776   binlog_invoker();
4777 #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
4778   if (slave_thread && has_invoker())
4779   {
4780     definer->user= m_invoker_user;
4781     definer->host= m_invoker_host;
4782     definer->plugin.str= (char *) "";
4783     definer->plugin.length= 0;
4784     definer->auth.str=  NULL;
4785     definer->auth.length= 0;
4786   }
4787   else
4788 #endif
4789     get_default_definer(this, definer);
4790 }
4791 
4792 
4793 /**
4794   Mark transaction to rollback and mark error as fatal to a sub-statement.
4795 
4796   @param  all   TRUE <=> rollback main transaction.
4797 */
4798 
mark_transaction_to_rollback(bool all)4799 void THD::mark_transaction_to_rollback(bool all)
4800 {
4801   /*
4802     There is no point in setting is_fatal_sub_stmt_error unless
4803     we are actually in_sub_stmt.
4804   */
4805   if (in_sub_stmt)
4806     is_fatal_sub_stmt_error= true;
4807 
4808   transaction_rollback_request= all;
4809 
4810 }
4811 
4812 
set_next_event_pos(const char * _filename,ulonglong _pos)4813 void THD::set_next_event_pos(const char* _filename, ulonglong _pos)
4814 {
4815   char*& filename= binlog_next_event_pos.file_name;
4816   if (filename == NULL)
4817   {
4818     /* First time, allocate maximal buffer */
4819     filename= (char*) my_malloc(key_memory_LOG_POS_COORD,
4820                                 FN_REFLEN+1, MYF(MY_WME));
4821     if (filename == NULL) return;
4822   }
4823 
4824   assert(strlen(_filename) <= FN_REFLEN);
4825   strcpy(filename, _filename);
4826   filename[ FN_REFLEN ]= 0;
4827 
4828   binlog_next_event_pos.pos= _pos;
4829 };
4830 
clear_next_event_pos()4831 void THD::clear_next_event_pos()
4832 {
4833   if (binlog_next_event_pos.file_name != NULL)
4834   {
4835     my_free(binlog_next_event_pos.file_name);
4836   }
4837   binlog_next_event_pos.file_name= NULL;
4838   binlog_next_event_pos.pos= 0;
4839 };
4840 
4841 #ifdef HAVE_REPLICATION
set_currently_executing_gtid_for_slave_thread()4842 void THD::set_currently_executing_gtid_for_slave_thread()
4843 {
4844   /*
4845     This function may be called in four cases:
4846 
4847     - From SQL thread while executing Gtid_log_event::do_apply_event
4848 
4849     - From an mts worker thread that executes a Gtid_log_event::do_apply_event.
4850 
4851     - From an mts worker thread that is processing an old binlog that
4852       is missing Gtid events completely, from gtid_pre_statement_checks().
4853 
4854     - From a normal client thread that is executing output from
4855       mysqlbinlog when mysqlbinlog is processing an old binlog file
4856       that is missing Gtid events completely, from
4857       gtid_pre_statement_checks() for a statement that appears after a
4858       BINLOG statement containing a Format_description_log_event
4859       originating from the master.
4860 
4861     Because of the last case, we need to add the following conditions to set
4862     currently_executing_gtid.
4863   */
4864   if (system_thread == SYSTEM_THREAD_SLAVE_SQL ||
4865       system_thread == SYSTEM_THREAD_SLAVE_WORKER)
4866     rli_slave->currently_executing_gtid= variables.gtid_next;
4867 }
4868 #endif
4869 
set_user_connect(USER_CONN * uc)4870 void THD::set_user_connect(USER_CONN *uc)
4871 {
4872   DBUG_ENTER("THD::set_user_connect");
4873 
4874   m_user_connect= uc;
4875 
4876   DBUG_VOID_RETURN;
4877 }
4878 
increment_user_connections_counter()4879 void THD::increment_user_connections_counter()
4880 {
4881   DBUG_ENTER("THD::increment_user_connections_counter");
4882 
4883   m_user_connect->connections++;
4884 
4885   DBUG_VOID_RETURN;
4886 }
4887 
decrement_user_connections_counter()4888 void THD::decrement_user_connections_counter()
4889 {
4890   DBUG_ENTER("THD::decrement_user_connections_counter");
4891 
4892   assert(m_user_connect->connections > 0);
4893   m_user_connect->connections--;
4894 
4895   DBUG_VOID_RETURN;
4896 }
4897 
increment_con_per_hour_counter()4898 void THD::increment_con_per_hour_counter()
4899 {
4900   DBUG_ENTER("THD::increment_con_per_hour_counter");
4901 
4902   m_user_connect->conn_per_hour++;
4903 
4904   DBUG_VOID_RETURN;
4905 }
4906 
increment_updates_counter()4907 void THD::increment_updates_counter()
4908 {
4909   DBUG_ENTER("THD::increment_updates_counter");
4910 
4911   m_user_connect->updates++;
4912 
4913   DBUG_VOID_RETURN;
4914 }
4915 
increment_questions_counter()4916 void THD::increment_questions_counter()
4917 {
4918   DBUG_ENTER("THD::increment_questions_counter");
4919 
4920   m_user_connect->questions++;
4921 
4922   DBUG_VOID_RETURN;
4923 }
4924 
4925 /*
4926   Reset per-hour user resource limits when it has been more than
4927   an hour since they were last checked
4928 
4929   SYNOPSIS:
4930     time_out_user_resource_limits()
4931 
4932   NOTE:
4933     This assumes that the LOCK_user_conn mutex has been acquired, so it is
4934     safe to test and modify members of the USER_CONN structure.
4935 */
time_out_user_resource_limits()4936 void THD::time_out_user_resource_limits()
4937 {
4938   mysql_mutex_assert_owner(&LOCK_user_conn);
4939   ulonglong check_time= start_utime;
4940   DBUG_ENTER("time_out_user_resource_limits");
4941 
4942   /* If more than a hour since last check, reset resource checking */
4943   if (check_time - m_user_connect->reset_utime >= 3600000000LL)
4944   {
4945     m_user_connect->questions=1;
4946     m_user_connect->updates=0;
4947     m_user_connect->conn_per_hour=0;
4948     m_user_connect->reset_utime= check_time;
4949   }
4950 
4951   DBUG_VOID_RETURN;
4952 }
4953 
4954 
4955 #ifndef NDEBUG
assert_plan_is_locked_if_other() const4956 void THD::Query_plan::assert_plan_is_locked_if_other() const
4957 {
4958   if (current_thd != thd)
4959     mysql_mutex_assert_owner(&thd->LOCK_query_plan);
4960 }
4961 #endif
4962 
set_query_plan(enum_sql_command sql_cmd,LEX * lex_arg,bool ps)4963 void THD::Query_plan::set_query_plan(enum_sql_command sql_cmd,
4964                                      LEX *lex_arg, bool ps)
4965 {
4966   assert(current_thd == thd);
4967 
4968   // No need to grab mutex for repeated (SQLCOM_END, NULL, false).
4969   if (sql_command == sql_cmd &&
4970       lex == lex_arg &&
4971       is_ps == ps)
4972   {
4973     return;
4974   }
4975 
4976   thd->lock_query_plan();
4977   sql_command= sql_cmd;
4978   lex= lex_arg;
4979   is_ps= ps;
4980   thd->unlock_query_plan();
4981 }
4982 
4983 
set_modification_plan(Modification_plan * plan_arg)4984 void THD::Query_plan::set_modification_plan(Modification_plan *plan_arg)
4985 {
4986   assert(current_thd == thd);
4987   mysql_mutex_assert_owner(&thd->LOCK_query_plan);
4988   modification_plan= plan_arg;
4989 }
4990 
4991 /**
4992   Push an error message into MySQL diagnostic area with line
4993   and position information.
4994 
4995   This function provides semantic action implementers with a way
4996   to push the famous "You have a syntax error near..." error
4997   message into the diagnostic area, which is normally produced only if
4998   a parse error is discovered internally by the Bison generated
4999   parser.
5000 
5001   @note Parse-time only function!
5002 
5003   @param thd            YYTHD
5004   @param location       YYSTYPE object: error position
5005   @param s              error message: NULL default means ER(ER_SYNTAX_ERROR)
5006 */
5007 
parse_error_at(const YYLTYPE & location,const char * s)5008 void THD::parse_error_at(const YYLTYPE &location, const char *s)
5009 {
5010   uint lineno= location.raw.start ?
5011     m_parser_state->m_lip.get_lineno(location.raw.start) : 1;
5012   const char *pos= location.raw.start ? location.raw.start : "";
5013   ErrConvString err(pos, variables.character_set_client);
5014   my_printf_error(ER_PARSE_ERROR,  ER(ER_PARSE_ERROR), MYF(0),
5015                   s ? s : ER(ER_SYNTAX_ERROR), err.ptr(), lineno);
5016 }
5017 
send_result_metadata(List<Item> * list,uint flags)5018 bool THD::send_result_metadata(List<Item> *list, uint flags)
5019 {
5020   DBUG_ENTER("send_result_metadata");
5021   List_iterator_fast<Item> it(*list);
5022   Item *item;
5023   uchar buff[MAX_FIELD_WIDTH];
5024   String tmp((char *) buff, sizeof(buff), &my_charset_bin);
5025 
5026   if (m_protocol->start_result_metadata(list->elements, flags,
5027           variables.character_set_results))
5028     goto err;
5029 
5030 #ifdef EMBEDDED_LIBRARY                  // bootstrap file handling
5031     if(!mysql)
5032       DBUG_RETURN(false);
5033 #endif
5034 
5035   while ((item= it++))
5036   {
5037     Send_field field;
5038     item->make_field(&field);
5039 #ifndef EMBEDDED_LIBRARY
5040     m_protocol->start_row();
5041     if (m_protocol->send_field_metadata(&field,
5042             item->charset_for_protocol()))
5043       goto err;
5044     if (flags & Protocol::SEND_DEFAULTS)
5045       item->send(m_protocol, &tmp);
5046     if (m_protocol->end_row())
5047       DBUG_RETURN(true);
5048 #else
5049       if(m_protocol->send_field_metadata(&field, item->charset_for_protocol()))
5050         goto err;
5051       if (flags & Protocol::SEND_DEFAULTS)
5052         get_protocol_classic()->send_string_metadata(item->val_str(&tmp));
5053 #endif
5054   }
5055 
5056   DBUG_RETURN(m_protocol->end_result_metadata());
5057 
5058   err:
5059   my_error(ER_OUT_OF_RESOURCES, MYF(0));        /* purecov: inspected */
5060   DBUG_RETURN(1);                               /* purecov: inspected */
5061 }
5062 
send_result_set_row(List<Item> * row_items)5063 bool THD::send_result_set_row(List<Item> *row_items)
5064 {
5065   char buffer[MAX_FIELD_WIDTH];
5066   String str_buffer(buffer, sizeof (buffer), &my_charset_bin);
5067   List_iterator_fast<Item> it(*row_items);
5068 
5069   DBUG_ENTER("send_result_set_row");
5070 
5071   for (Item *item= it++; item; item= it++)
5072   {
5073     if (item->send(m_protocol, &str_buffer) || is_error())
5074       DBUG_RETURN(true);
5075     /*
5076       Reset str_buffer to its original state, as it may have been altered in
5077       Item::send().
5078     */
5079     str_buffer.set(buffer, sizeof(buffer), &my_charset_bin);
5080   }
5081   DBUG_RETURN(false);
5082 }
5083 
send_statement_status()5084 void THD::send_statement_status()
5085 {
5086   DBUG_ENTER("send_statement_status");
5087   assert(!get_stmt_da()->is_sent());
5088   bool error= false;
5089   Diagnostics_area *da= get_stmt_da();
5090 
5091   /* Can not be true, but do not take chances in production. */
5092   if (da->is_sent())
5093     DBUG_VOID_RETURN;
5094 
5095   switch (da->status())
5096   {
5097     case Diagnostics_area::DA_ERROR:
5098       /* The query failed, send error to log and abort bootstrap. */
5099       error= m_protocol->send_error(
5100               da->mysql_errno(), da->message_text(), da->returned_sqlstate());
5101           break;
5102     case Diagnostics_area::DA_EOF:
5103       error= m_protocol->send_eof(
5104               server_status, da->last_statement_cond_count());
5105           break;
5106     case Diagnostics_area::DA_OK:
5107       error= m_protocol->send_ok(
5108               server_status, da->last_statement_cond_count(),
5109               da->affected_rows(), da->last_insert_id(), da->message_text());
5110           break;
5111     case Diagnostics_area::DA_DISABLED:
5112       break;
5113     case Diagnostics_area::DA_EMPTY:
5114     default:
5115       assert(0);
5116           error= m_protocol->send_ok(server_status, 0, 0, 0, NULL);
5117           break;
5118   }
5119   if (!error)
5120     da->set_is_sent(true);
5121   DBUG_VOID_RETURN;
5122 }
5123 
claim_memory_ownership()5124 void THD::claim_memory_ownership()
5125 {
5126   /*
5127     Ownership of the THD object is transfered to this thread.
5128     This happens typically:
5129     - in the event scheduler,
5130       when the scheduler thread creates a work item and
5131       starts a worker thread to run it
5132     - in the main thread, when the code that accepts a new
5133       network connection creates a work item and starts a
5134       connection thread to run it.
5135     Accounting for memory statistics needs to be told
5136     that memory allocated by thread X now belongs to thread Y,
5137     so that statistics by thread/account/user/host are accurate.
5138     Inspect every piece of memory allocated in THD,
5139     and call PSI_MEMORY_CALL(memory_claim)().
5140   */
5141 #ifdef HAVE_PSI_MEMORY_INTERFACE
5142   claim_root(&main_mem_root);
5143   my_claim(m_token_array);
5144   Protocol_classic *p= get_protocol_classic();
5145   if (p != NULL)
5146     p->claim_memory_ownership();
5147   session_tracker.claim_memory_ownership();
5148   session_sysvar_res_mgr.claim_memory_ownership();
5149   my_hash_claim(&user_vars);
5150 #if defined(ENABLED_DEBUG_SYNC)
5151   debug_sync_claim_memory_ownership(this);
5152 #endif /* defined(ENABLED_DEBUG_SYNC) */
5153   get_transaction()->claim_memory_ownership();
5154   stmt_map.claim_memory_ownership();
5155 #endif /* HAVE_PSI_MEMORY_INTERFACE */
5156 }
5157 
5158 
rpl_detach_engine_ha_data()5159 void THD::rpl_detach_engine_ha_data()
5160 {
5161 #ifdef HAVE_REPLICATION
5162   Relay_log_info *rli=
5163     is_binlog_applier() ? rli_fake : (slave_thread ? rli_slave : NULL);
5164 
5165   assert(!rli_fake  || !rli_fake-> is_engine_ha_data_detached);
5166   assert(!rli_slave || !rli_slave->is_engine_ha_data_detached);
5167 
5168   if (rli)
5169     rli->detach_engine_ha_data(this);
5170 #endif
5171 };
5172 
rpl_reattach_engine_ha_data()5173 void THD::rpl_reattach_engine_ha_data()
5174 {
5175 #ifdef HAVE_REPLICATION
5176   Relay_log_info *rli =
5177       is_binlog_applier() ? rli_fake : (slave_thread ? rli_slave : NULL);
5178 
5179   assert(!rli_fake || !rli_fake->is_engine_ha_data_detached);
5180   assert(!rli_slave || !rli_slave->is_engine_ha_data_detached);
5181 
5182   if (rli) rli->reattach_engine_ha_data(this);
5183 #endif
5184 }
5185 
rpl_unflag_detached_engine_ha_data()5186 bool THD::rpl_unflag_detached_engine_ha_data()
5187 {
5188 #ifdef HAVE_REPLICATION
5189   Relay_log_info *rli=
5190     is_binlog_applier() ? rli_fake : (slave_thread ? rli_slave : NULL);
5191   return rli ? rli->unflag_detached_engine_ha_data() : false;
5192 #else
5193   return false;
5194 #endif
5195 }
5196 
5197 /**
5198   Determine if binlogging is disabled for this session
5199   @retval 0 if the current statement binlogging is disabled
5200   (could be because of binlog closed/binlog option
5201   is set to false).
5202   @retval 1 if the current statement will be binlogged
5203 */
is_current_stmt_binlog_disabled() const5204 bool THD::is_current_stmt_binlog_disabled() const
5205 {
5206   return (!(variables.option_bits & OPTION_BIN_LOG) ||
5207           !mysql_bin_log.is_open());
5208 }
5209 
is_current_stmt_binlog_row_enabled_with_write_set_extraction() const5210 bool THD::is_current_stmt_binlog_row_enabled_with_write_set_extraction() const
5211 {
5212   return ((variables.transaction_write_set_extraction != HASH_ALGORITHM_OFF) &&
5213           is_current_stmt_binlog_format_row() &&
5214           !is_current_stmt_binlog_disabled());
5215 }
5216