1 /* Copyright (c) 2000, 2021, Oracle and/or its affiliates.
2 
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License, version 2.0,
5    as published by the Free Software Foundation.
6 
7    This program is also distributed with certain software (including
8    but not limited to OpenSSL) that is licensed under separate terms,
9    as designated in a particular file or component or in included license
10    documentation.  The authors of MySQL hereby grant you an additional
11    permission to link the program and your derivative works with the
12    separately licensed software that they have included with MySQL.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License, version 2.0, for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
22 
23 #include "sql_parse.h"
24 
25 #include "auth_common.h"      // acl_authenticate
26 #include "binlog.h"           // purge_master_logs
27 #include "debug_sync.h"       // DEBUG_SYNC
28 #include "events.h"           // Events
29 #include "item_timefunc.h"    // Item_func_unix_timestamp
30 #include "log.h"              // query_logger
31 #include "log_event.h"        // slave_execute_deferred_events
32 #include "mysys_err.h"        // EE_CAPACITY_EXCEEDED
33 #include "opt_explain.h"      // mysql_explain_other
34 #include "opt_trace.h"        // Opt_trace_start
35 #include "partition_info.h"   // partition_info
36 #include "probes_mysql.h"     // MYSQL_COMMAND_START
37 #include "rpl_filter.h"       // rpl_filter
38 #include "rpl_master.h"       // register_slave
39 #include "rpl_rli.h"          // mysql_show_relaylog_events
40 #include "rpl_slave.h"        // change_master_cmd
41 #include "sp.h"               // sp_create_routine
42 #include "sp_cache.h"         // sp_cache_enforce_limit
43 #include "sp_head.h"          // sp_head
44 #include "sql_admin.h"        // mysql_assign_to_keycache
45 #include "sql_analyse.h"      // Query_result_analyse
46 #include "sql_audit.h"        // MYSQL_AUDIT_NOTIFY_CONNECTION_CHANGE_USER
47 #include "sql_base.h"         // find_temporary_table
48 #include "sql_binlog.h"       // mysql_client_binlog_statement
49 #include "sql_cache.h"        // query_cache
50 #include "sql_connect.h"      // decrease_user_connections
51 #include "sql_db.h"           // mysql_change_db
52 #include "sql_delete.h"       // mysql_delete
53 #include "sql_do.h"           // mysql_do
54 #include "sql_handler.h"      // mysql_ha_rm_tables
55 #include "sql_help.h"         // mysqld_help
56 #include "sql_insert.h"       // Query_result_create
57 #include "sql_load.h"         // mysql_load
58 #include "sql_prepare.h"      // mysql_stmt_execute
59 #include "partition_info.h"   // has_external_data_or_index_dir
60 #include "sql_reload.h"       // reload_acl_and_cache
61 #include "sql_rename.h"       // mysql_rename_tables
62 #include "sql_select.h"       // handle_query
63 #include "sql_show.h"         // find_schema_table
64 #include "sql_table.h"        // mysql_create_table
65 #include "sql_tablespace.h"   // mysql_alter_tablespace
66 #include "sql_test.h"         // mysql_print_status
67 #include "sql_select.h"       // handle_query
68 #include "sql_load.h"         // mysql_load
69 #include "sql_servers.h"      // create_servers, alter_servers,
70                               // drop_servers, servers_reload
71 #include "sql_handler.h"      // mysql_ha_open, mysql_ha_close,
72                               // mysql_ha_read
73 #include "sql_binlog.h"       // mysql_client_binlog_statement
74 #include "sql_do.h"           // mysql_do
75 #include "sql_help.h"         // mysqld_help
76 #include "rpl_constants.h"    // Incident, INCIDENT_LOST_EVENTS
77 #include "log_event.h"
78 #include "rpl_slave.h"
79 #include "rpl_master.h"
80 #include "rpl_msr.h"        /* Multisource replication */
81 #include "rpl_filter.h"
82 #include <m_ctype.h>
83 #include <myisam.h>
84 #include <my_dir.h>
85 #include <dur_prop.h>
86 #include "rpl_handler.h"
87 
88 #include "sp_head.h"
89 #include "sp.h"
90 #include "sp_cache.h"
91 #include "events.h"
92 #include "sql_trigger.h"      // mysql_create_or_drop_trigger
93 #include "transaction.h"
94 #include "xa.h"
95 #include "sql_audit.h"
96 #include "sql_prepare.h"
97 #include "debug_sync.h"
98 #include "probes_mysql.h"
99 #include "set_var.h"
100 #include "opt_trace.h"
101 #include "mysql/psi/mysql_statement.h"
102 #include "opt_explain.h"
103 #include "sql_rewrite.h"
104 #include "sql_analyse.h"
105 #include "table_cache.h" // table_cache_manager
106 #include "sql_timer.h"   // thd_timer_set, thd_timer_reset
107 #include "sp_rcontext.h"
108 #include "parse_location.h"
109 #include "sql_digest.h"
110 #include "sql_timer.h"        // thd_timer_set
111 #include "sql_trigger.h"      // add_table_for_trigger
112 #include "sql_update.h"       // mysql_update
113 #include "sql_view.h"         // mysql_create_view
114 #include "table_cache.h"      // table_cache_manager
115 #include "transaction.h"      // trans_commit_implicit
116 #include "sql_query_rewrite.h"
117 
118 #include "rpl_group_replication.h"
119 #include <algorithm>
120 using std::max;
121 
122 /**
123   @defgroup Runtime_Environment Runtime Environment
124   @{
125 */
126 
127 /* Used in error handling only */
128 #define SP_COM_STRING(LP) \
129   ((LP)->sql_command == SQLCOM_CREATE_SPFUNCTION || \
130    (LP)->sql_command == SQLCOM_ALTER_FUNCTION || \
131    (LP)->sql_command == SQLCOM_SHOW_CREATE_FUNC || \
132    (LP)->sql_command == SQLCOM_DROP_FUNCTION ? \
133    "FUNCTION" : "PROCEDURE")
134 
135 static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables);
136 static void sql_kill(THD *thd, my_thread_id id, bool only_kill_query);
137 
138 const LEX_STRING command_name[]={
139   { C_STRING_WITH_LEN("Sleep") },
140   { C_STRING_WITH_LEN("Quit") },
141   { C_STRING_WITH_LEN("Init DB") },
142   { C_STRING_WITH_LEN("Query") },
143   { C_STRING_WITH_LEN("Field List") },
144   { C_STRING_WITH_LEN("Create DB") },
145   { C_STRING_WITH_LEN("Drop DB") },
146   { C_STRING_WITH_LEN("Refresh") },
147   { C_STRING_WITH_LEN("Shutdown") },
148   { C_STRING_WITH_LEN("Statistics") },
149   { C_STRING_WITH_LEN("Processlist") },
150   { C_STRING_WITH_LEN("Connect") },
151   { C_STRING_WITH_LEN("Kill") },
152   { C_STRING_WITH_LEN("Debug") },
153   { C_STRING_WITH_LEN("Ping") },
154   { C_STRING_WITH_LEN("Time") },
155   { C_STRING_WITH_LEN("Delayed insert") },
156   { C_STRING_WITH_LEN("Change user") },
157   { C_STRING_WITH_LEN("Binlog Dump") },
158   { C_STRING_WITH_LEN("Table Dump") },
159   { C_STRING_WITH_LEN("Connect Out") },
160   { C_STRING_WITH_LEN("Register Slave") },
161   { C_STRING_WITH_LEN("Prepare") },
162   { C_STRING_WITH_LEN("Execute") },
163   { C_STRING_WITH_LEN("Long Data") },
164   { C_STRING_WITH_LEN("Close stmt") },
165   { C_STRING_WITH_LEN("Reset stmt") },
166   { C_STRING_WITH_LEN("Set option") },
167   { C_STRING_WITH_LEN("Fetch") },
168   { C_STRING_WITH_LEN("Daemon") },
169   { C_STRING_WITH_LEN("Binlog Dump GTID") },
170   { C_STRING_WITH_LEN("Reset Connection") },
171   { C_STRING_WITH_LEN("Error") }  // Last command number
172 };
173 
174 #ifdef HAVE_REPLICATION
175 /**
176   Returns true if all tables should be ignored.
177 */
all_tables_not_ok(THD * thd,TABLE_LIST * tables)178 bool all_tables_not_ok(THD *thd, TABLE_LIST *tables)
179 {
180   return rpl_filter->is_on() && tables && !thd->sp_runtime_ctx &&
181          !rpl_filter->tables_ok(thd->db().str, tables);
182 }
183 
184 /**
185   Checks whether the event for the given database, db, should
186   be ignored or not. This is done by checking whether there are
187   active rules in ignore_db or in do_db containers. If there
188   are, then check if there is a match, if not then check the
189   wild_do rules.
190 
191   NOTE: This means that when using this function replicate-do-db
192         and replicate-ignore-db take precedence over wild do
193         rules.
194 
195   @param thd  Thread handle.
196   @param db   Database name used while evaluating the filtering
197               rules.
198   @param sql_cmd Represents the current query that needs to be
199                  verified against the database filter rules.
200   @return TRUE Query should not be filtered out from the execution.
201           FALSE Query should be filtered out from the execution.
202 
203 */
check_database_filters(THD * thd,const char * db,enum_sql_command sql_cmd)204 inline bool check_database_filters(THD *thd, const char* db, enum_sql_command sql_cmd)
205 {
206   DBUG_ENTER("check_database_filters");
207   assert(thd->slave_thread);
208   if (!db)
209     DBUG_RETURN(TRUE);
210   switch (sql_cmd)
211   {
212   case SQLCOM_BEGIN:
213   case SQLCOM_COMMIT:
214   case SQLCOM_SAVEPOINT:
215   case SQLCOM_ROLLBACK:
216   case SQLCOM_ROLLBACK_TO_SAVEPOINT:
217     DBUG_RETURN(TRUE);
218   default:
219     break;
220   }
221   bool db_ok= rpl_filter->db_ok(db);
222   /*
223     No filters exist in ignore/do_db ? Then, just check
224     wild_do_table filtering for 'DATABASE' related
225     statements (CREATE/DROP/ATLER DATABASE)
226   */
227   if (db_ok &&
228       (rpl_filter->get_do_db()->is_empty() &&
229        rpl_filter->get_ignore_db()->is_empty()))
230   {
231     switch (sql_cmd)
232     {
233     case SQLCOM_CREATE_DB:
234     case SQLCOM_ALTER_DB:
235     case SQLCOM_ALTER_DB_UPGRADE:
236     case SQLCOM_DROP_DB:
237       db_ok= rpl_filter->db_ok_with_wild_table(db);
238     default:
239       break;
240     }
241   }
242   DBUG_RETURN(db_ok);
243 }
244 
245 #endif
246 
247 
some_non_temp_table_to_be_updated(THD * thd,TABLE_LIST * tables)248 bool some_non_temp_table_to_be_updated(THD *thd, TABLE_LIST *tables)
249 {
250   for (TABLE_LIST *table= tables; table; table= table->next_global)
251   {
252     assert(table->db && table->table_name);
253     /*
254       Update on performance_schema and temp tables are allowed
255       in readonly mode.
256     */
257     if (table->updating && !find_temporary_table(thd, table) &&
258         !is_perfschema_db(table->db, table->db_length))
259       return 1;
260   }
261   return 0;
262 }
263 
264 
265 /*
266   Implicitly commit a active transaction if statement requires so.
267 
268   @param thd    Thread handle.
269   @param mask   Bitmask used for the SQL command match.
270 
271 */
stmt_causes_implicit_commit(const THD * thd,uint mask)272 bool stmt_causes_implicit_commit(const THD *thd, uint mask)
273 {
274   const LEX *lex= thd->lex;
275   bool skip= FALSE;
276   DBUG_ENTER("stmt_causes_implicit_commit");
277 
278   if (!(sql_command_flags[lex->sql_command] & mask))
279     DBUG_RETURN(FALSE);
280 
281   switch (lex->sql_command) {
282   case SQLCOM_DROP_TABLE:
283     skip= lex->drop_temporary;
284     break;
285   case SQLCOM_ALTER_TABLE:
286   case SQLCOM_CREATE_TABLE:
287     /* If CREATE TABLE of non-temporary table, do implicit commit */
288     skip= (lex->create_info.options & HA_LEX_CREATE_TMP_TABLE);
289     break;
290   case SQLCOM_SET_OPTION:
291     /* Implicitly commit a transaction started by a SET statement */
292     skip= lex->autocommit ? FALSE : TRUE;
293     break;
294   default:
295     break;
296   }
297 
298   DBUG_RETURN(!skip);
299 }
300 
301 
302 /**
303   Mark all commands that somehow changes a table.
304 
305   This is used to check number of updates / hour.
306 
307   sql_command is actually set to SQLCOM_END sometimes
308   so we need the +1 to include it in the array.
309 
310   See COMMAND_FLAG_xxx for different type of commands
311      2  - query that returns meaningful ROW_COUNT() -
312           a number of modified rows
313 */
314 
315 uint sql_command_flags[SQLCOM_END+1];
316 uint server_command_flags[COM_END+1];
317 
init_update_queries(void)318 void init_update_queries(void)
319 {
320   /* Initialize the server command flags array. */
321   memset(server_command_flags, 0, sizeof(server_command_flags));
322 
323   server_command_flags[COM_SLEEP]=               CF_ALLOW_PROTOCOL_PLUGIN;
324   server_command_flags[COM_INIT_DB]=             CF_ALLOW_PROTOCOL_PLUGIN;
325   server_command_flags[COM_QUERY]=               CF_ALLOW_PROTOCOL_PLUGIN;
326   server_command_flags[COM_FIELD_LIST]=          CF_ALLOW_PROTOCOL_PLUGIN;
327   server_command_flags[COM_REFRESH]=             CF_ALLOW_PROTOCOL_PLUGIN;
328   server_command_flags[COM_SHUTDOWN]=            CF_ALLOW_PROTOCOL_PLUGIN;
329   server_command_flags[COM_STATISTICS]=          CF_SKIP_QUESTIONS;
330   server_command_flags[COM_PROCESS_KILL]=        CF_ALLOW_PROTOCOL_PLUGIN;
331   server_command_flags[COM_PING]=                CF_SKIP_QUESTIONS;
332   server_command_flags[COM_STMT_PREPARE]=        CF_SKIP_QUESTIONS |
333                                                  CF_ALLOW_PROTOCOL_PLUGIN;
334   server_command_flags[COM_STMT_EXECUTE]=        CF_ALLOW_PROTOCOL_PLUGIN;
335   server_command_flags[COM_STMT_SEND_LONG_DATA]= CF_ALLOW_PROTOCOL_PLUGIN;
336   server_command_flags[COM_STMT_CLOSE]=          CF_SKIP_QUESTIONS |
337                                                  CF_ALLOW_PROTOCOL_PLUGIN;
338   server_command_flags[COM_STMT_RESET]=          CF_SKIP_QUESTIONS |
339                                                  CF_ALLOW_PROTOCOL_PLUGIN;
340   server_command_flags[COM_STMT_FETCH]=          CF_ALLOW_PROTOCOL_PLUGIN;
341   server_command_flags[COM_END]=                 CF_ALLOW_PROTOCOL_PLUGIN;
342 
343   /* Initialize the sql command flags array. */
344   memset(sql_command_flags, 0, sizeof(sql_command_flags));
345 
346   /*
347     In general, DDL statements do not generate row events and do not go
348     through a cache before being written to the binary log. However, the
349     CREATE TABLE...SELECT is an exception because it may generate row
350     events. For that reason,  the SQLCOM_CREATE_TABLE  which represents
351     a CREATE TABLE, including the CREATE TABLE...SELECT, has the
352     CF_CAN_GENERATE_ROW_EVENTS flag. The distinction between a regular
353     CREATE TABLE and the CREATE TABLE...SELECT is made in other parts of
354     the code, in particular in the Query_log_event's constructor.
355   */
356   sql_command_flags[SQLCOM_CREATE_TABLE]=   CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
357                                             CF_AUTO_COMMIT_TRANS |
358                                             CF_CAN_GENERATE_ROW_EVENTS;
359   sql_command_flags[SQLCOM_CREATE_INDEX]=   CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
360   sql_command_flags[SQLCOM_ALTER_TABLE]=    CF_CHANGES_DATA | CF_WRITE_LOGS_COMMAND |
361                                             CF_AUTO_COMMIT_TRANS;
362   sql_command_flags[SQLCOM_TRUNCATE]=       CF_CHANGES_DATA | CF_WRITE_LOGS_COMMAND |
363                                             CF_AUTO_COMMIT_TRANS;
364   sql_command_flags[SQLCOM_DROP_TABLE]=     CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
365   sql_command_flags[SQLCOM_LOAD]=           CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
366                                             CF_CAN_GENERATE_ROW_EVENTS;
367   sql_command_flags[SQLCOM_CREATE_DB]=      CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
368   sql_command_flags[SQLCOM_DROP_DB]=        CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
369   sql_command_flags[SQLCOM_ALTER_DB_UPGRADE]= CF_AUTO_COMMIT_TRANS;
370   sql_command_flags[SQLCOM_ALTER_DB]=       CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
371   sql_command_flags[SQLCOM_RENAME_TABLE]=   CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
372   sql_command_flags[SQLCOM_DROP_INDEX]=     CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
373   sql_command_flags[SQLCOM_CREATE_VIEW]=    CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
374                                             CF_AUTO_COMMIT_TRANS;
375   sql_command_flags[SQLCOM_DROP_VIEW]=      CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
376   sql_command_flags[SQLCOM_CREATE_TRIGGER]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
377   sql_command_flags[SQLCOM_DROP_TRIGGER]=   CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
378   sql_command_flags[SQLCOM_CREATE_EVENT]=   CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
379   sql_command_flags[SQLCOM_ALTER_EVENT]=    CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
380   sql_command_flags[SQLCOM_DROP_EVENT]=     CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
381 
382   sql_command_flags[SQLCOM_UPDATE]=	    CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
383                                             CF_CAN_GENERATE_ROW_EVENTS |
384                                             CF_OPTIMIZER_TRACE |
385                                             CF_CAN_BE_EXPLAINED;
386   sql_command_flags[SQLCOM_UPDATE_MULTI]=   CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
387                                             CF_CAN_GENERATE_ROW_EVENTS |
388                                             CF_OPTIMIZER_TRACE |
389                                             CF_CAN_BE_EXPLAINED;
390   // This is INSERT VALUES(...), can be VALUES(stored_func()) so we trace it
391   sql_command_flags[SQLCOM_INSERT]=	    CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
392                                             CF_CAN_GENERATE_ROW_EVENTS |
393                                             CF_OPTIMIZER_TRACE |
394                                             CF_CAN_BE_EXPLAINED;
395   sql_command_flags[SQLCOM_INSERT_SELECT]=  CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
396                                             CF_CAN_GENERATE_ROW_EVENTS |
397                                             CF_OPTIMIZER_TRACE |
398                                             CF_CAN_BE_EXPLAINED;
399   sql_command_flags[SQLCOM_DELETE]=         CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
400                                             CF_CAN_GENERATE_ROW_EVENTS |
401                                             CF_OPTIMIZER_TRACE |
402                                             CF_CAN_BE_EXPLAINED;
403   sql_command_flags[SQLCOM_DELETE_MULTI]=   CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
404                                             CF_CAN_GENERATE_ROW_EVENTS |
405                                             CF_OPTIMIZER_TRACE |
406                                             CF_CAN_BE_EXPLAINED;
407   sql_command_flags[SQLCOM_REPLACE]=        CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
408                                             CF_CAN_GENERATE_ROW_EVENTS |
409                                             CF_OPTIMIZER_TRACE |
410                                             CF_CAN_BE_EXPLAINED;
411   sql_command_flags[SQLCOM_REPLACE_SELECT]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
412                                             CF_CAN_GENERATE_ROW_EVENTS |
413                                             CF_OPTIMIZER_TRACE |
414                                             CF_CAN_BE_EXPLAINED;
415   sql_command_flags[SQLCOM_SELECT]=         CF_REEXECUTION_FRAGILE |
416                                             CF_CAN_GENERATE_ROW_EVENTS |
417                                             CF_OPTIMIZER_TRACE |
418                                             CF_CAN_BE_EXPLAINED;
419   // (1) so that subquery is traced when doing "SET @var = (subquery)"
420   /*
421     @todo SQLCOM_SET_OPTION should have CF_CAN_GENERATE_ROW_EVENTS
422     set, because it may invoke a stored function that generates row
423     events. /Sven
424   */
425   sql_command_flags[SQLCOM_SET_OPTION]=     CF_REEXECUTION_FRAGILE |
426                                             CF_AUTO_COMMIT_TRANS |
427                                             CF_CAN_GENERATE_ROW_EVENTS |
428                                             CF_OPTIMIZER_TRACE; // (1)
429   // (1) so that subquery is traced when doing "DO @var := (subquery)"
430   sql_command_flags[SQLCOM_DO]=             CF_REEXECUTION_FRAGILE |
431                                             CF_CAN_GENERATE_ROW_EVENTS |
432                                             CF_OPTIMIZER_TRACE; // (1)
433 
434   sql_command_flags[SQLCOM_SHOW_STATUS_PROC]= CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
435   sql_command_flags[SQLCOM_SHOW_STATUS]=      CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
436   sql_command_flags[SQLCOM_SHOW_DATABASES]=   CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
437   sql_command_flags[SQLCOM_SHOW_TRIGGERS]=    CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
438   sql_command_flags[SQLCOM_SHOW_EVENTS]=      CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
439   sql_command_flags[SQLCOM_SHOW_OPEN_TABLES]= CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
440   sql_command_flags[SQLCOM_SHOW_PLUGINS]=     CF_STATUS_COMMAND;
441   sql_command_flags[SQLCOM_SHOW_FIELDS]=      CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
442   sql_command_flags[SQLCOM_SHOW_KEYS]=        CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
443   sql_command_flags[SQLCOM_SHOW_VARIABLES]=   CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
444   sql_command_flags[SQLCOM_SHOW_CHARSETS]=    CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
445   sql_command_flags[SQLCOM_SHOW_COLLATIONS]=  CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
446   sql_command_flags[SQLCOM_SHOW_BINLOGS]=     CF_STATUS_COMMAND;
447   sql_command_flags[SQLCOM_SHOW_SLAVE_HOSTS]= CF_STATUS_COMMAND;
448   sql_command_flags[SQLCOM_SHOW_BINLOG_EVENTS]= CF_STATUS_COMMAND;
449   sql_command_flags[SQLCOM_SHOW_STORAGE_ENGINES]= CF_STATUS_COMMAND;
450   sql_command_flags[SQLCOM_SHOW_PRIVILEGES]=  CF_STATUS_COMMAND;
451   sql_command_flags[SQLCOM_SHOW_WARNS]=       CF_STATUS_COMMAND | CF_DIAGNOSTIC_STMT;
452   sql_command_flags[SQLCOM_SHOW_ERRORS]=      CF_STATUS_COMMAND | CF_DIAGNOSTIC_STMT;
453   sql_command_flags[SQLCOM_SHOW_ENGINE_STATUS]= CF_STATUS_COMMAND;
454   sql_command_flags[SQLCOM_SHOW_ENGINE_MUTEX]= CF_STATUS_COMMAND;
455   sql_command_flags[SQLCOM_SHOW_ENGINE_LOGS]= CF_STATUS_COMMAND;
456   sql_command_flags[SQLCOM_SHOW_PROCESSLIST]= CF_STATUS_COMMAND;
457   sql_command_flags[SQLCOM_SHOW_GRANTS]=      CF_STATUS_COMMAND;
458   sql_command_flags[SQLCOM_SHOW_CREATE_DB]=   CF_STATUS_COMMAND;
459   sql_command_flags[SQLCOM_SHOW_CREATE]=  CF_STATUS_COMMAND;
460   sql_command_flags[SQLCOM_SHOW_MASTER_STAT]= CF_STATUS_COMMAND;
461   sql_command_flags[SQLCOM_SHOW_SLAVE_STAT]=  CF_STATUS_COMMAND;
462   sql_command_flags[SQLCOM_SHOW_CREATE_PROC]= CF_STATUS_COMMAND;
463   sql_command_flags[SQLCOM_SHOW_CREATE_FUNC]= CF_STATUS_COMMAND;
464   sql_command_flags[SQLCOM_SHOW_CREATE_TRIGGER]=  CF_STATUS_COMMAND;
465   sql_command_flags[SQLCOM_SHOW_STATUS_FUNC]= CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
466   sql_command_flags[SQLCOM_SHOW_PROC_CODE]=   CF_STATUS_COMMAND;
467   sql_command_flags[SQLCOM_SHOW_FUNC_CODE]=   CF_STATUS_COMMAND;
468   sql_command_flags[SQLCOM_SHOW_CREATE_EVENT]= CF_STATUS_COMMAND;
469   sql_command_flags[SQLCOM_SHOW_PROFILES]=    CF_STATUS_COMMAND;
470   sql_command_flags[SQLCOM_SHOW_PROFILE]=     CF_STATUS_COMMAND;
471   sql_command_flags[SQLCOM_BINLOG_BASE64_EVENT]= CF_STATUS_COMMAND |
472                                                  CF_CAN_GENERATE_ROW_EVENTS;
473 
474    sql_command_flags[SQLCOM_SHOW_TABLES]=       (CF_STATUS_COMMAND |
475                                                  CF_SHOW_TABLE_COMMAND |
476                                                  CF_REEXECUTION_FRAGILE);
477   sql_command_flags[SQLCOM_SHOW_TABLE_STATUS]= (CF_STATUS_COMMAND |
478                                                 CF_SHOW_TABLE_COMMAND |
479                                                 CF_REEXECUTION_FRAGILE);
480 
481   sql_command_flags[SQLCOM_CREATE_USER]=       CF_CHANGES_DATA;
482   sql_command_flags[SQLCOM_RENAME_USER]=       CF_CHANGES_DATA;
483   sql_command_flags[SQLCOM_DROP_USER]=         CF_CHANGES_DATA;
484   sql_command_flags[SQLCOM_ALTER_USER]=        CF_CHANGES_DATA;
485   sql_command_flags[SQLCOM_GRANT]=             CF_CHANGES_DATA;
486   sql_command_flags[SQLCOM_REVOKE]=            CF_CHANGES_DATA;
487   sql_command_flags[SQLCOM_REVOKE_ALL]=        CF_CHANGES_DATA;
488   sql_command_flags[SQLCOM_OPTIMIZE]=          CF_CHANGES_DATA;
489   sql_command_flags[SQLCOM_ALTER_INSTANCE]=    CF_CHANGES_DATA;
490   sql_command_flags[SQLCOM_CREATE_FUNCTION]=   CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
491   sql_command_flags[SQLCOM_CREATE_PROCEDURE]=  CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
492   sql_command_flags[SQLCOM_CREATE_SPFUNCTION]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
493   sql_command_flags[SQLCOM_DROP_PROCEDURE]=    CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
494   sql_command_flags[SQLCOM_DROP_FUNCTION]=     CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
495   sql_command_flags[SQLCOM_ALTER_PROCEDURE]=   CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
496   sql_command_flags[SQLCOM_ALTER_FUNCTION]=    CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
497   sql_command_flags[SQLCOM_INSTALL_PLUGIN]=    CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
498   sql_command_flags[SQLCOM_UNINSTALL_PLUGIN]=  CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
499 
500   /* Does not change the contents of the Diagnostics Area. */
501   sql_command_flags[SQLCOM_GET_DIAGNOSTICS]= CF_DIAGNOSTIC_STMT;
502 
503   /*
504     (1): without it, in "CALL some_proc((subq))", subquery would not be
505     traced.
506   */
507   sql_command_flags[SQLCOM_CALL]=      CF_REEXECUTION_FRAGILE |
508                                        CF_CAN_GENERATE_ROW_EVENTS |
509                                        CF_OPTIMIZER_TRACE; // (1)
510   sql_command_flags[SQLCOM_EXECUTE]=   CF_CAN_GENERATE_ROW_EVENTS;
511 
512   /*
513     The following admin table operations are allowed
514     on log tables.
515   */
516   sql_command_flags[SQLCOM_REPAIR]=    CF_WRITE_LOGS_COMMAND | CF_AUTO_COMMIT_TRANS;
517   sql_command_flags[SQLCOM_OPTIMIZE]|= CF_WRITE_LOGS_COMMAND | CF_AUTO_COMMIT_TRANS;
518   sql_command_flags[SQLCOM_ANALYZE]=   CF_WRITE_LOGS_COMMAND | CF_AUTO_COMMIT_TRANS;
519   sql_command_flags[SQLCOM_CHECK]=     CF_WRITE_LOGS_COMMAND | CF_AUTO_COMMIT_TRANS;
520 
521   sql_command_flags[SQLCOM_CREATE_USER]|=       CF_AUTO_COMMIT_TRANS;
522   sql_command_flags[SQLCOM_DROP_USER]|=         CF_AUTO_COMMIT_TRANS;
523   sql_command_flags[SQLCOM_RENAME_USER]|=       CF_AUTO_COMMIT_TRANS;
524   sql_command_flags[SQLCOM_ALTER_USER]|=        CF_AUTO_COMMIT_TRANS;
525   sql_command_flags[SQLCOM_REVOKE]|=            CF_AUTO_COMMIT_TRANS;
526   sql_command_flags[SQLCOM_REVOKE_ALL]|=        CF_AUTO_COMMIT_TRANS;
527   sql_command_flags[SQLCOM_GRANT]|=             CF_AUTO_COMMIT_TRANS;
528 
529   sql_command_flags[SQLCOM_ASSIGN_TO_KEYCACHE]= CF_AUTO_COMMIT_TRANS;
530   sql_command_flags[SQLCOM_PRELOAD_KEYS]=       CF_AUTO_COMMIT_TRANS;
531   sql_command_flags[SQLCOM_ALTER_INSTANCE]|=    CF_AUTO_COMMIT_TRANS;
532 
533   sql_command_flags[SQLCOM_FLUSH]=              CF_AUTO_COMMIT_TRANS;
534   sql_command_flags[SQLCOM_RESET]=              CF_AUTO_COMMIT_TRANS;
535   sql_command_flags[SQLCOM_CREATE_SERVER]=      CF_AUTO_COMMIT_TRANS;
536   sql_command_flags[SQLCOM_ALTER_SERVER]=       CF_AUTO_COMMIT_TRANS;
537   sql_command_flags[SQLCOM_DROP_SERVER]=        CF_AUTO_COMMIT_TRANS;
538   sql_command_flags[SQLCOM_CHANGE_MASTER]=      CF_AUTO_COMMIT_TRANS;
539   sql_command_flags[SQLCOM_CHANGE_REPLICATION_FILTER]=    CF_AUTO_COMMIT_TRANS;
540   sql_command_flags[SQLCOM_SLAVE_START]=        CF_AUTO_COMMIT_TRANS;
541   sql_command_flags[SQLCOM_SLAVE_STOP]=         CF_AUTO_COMMIT_TRANS;
542   sql_command_flags[SQLCOM_ALTER_TABLESPACE]|=  CF_AUTO_COMMIT_TRANS;
543 
544   /*
545     The following statements can deal with temporary tables,
546     so temporary tables should be pre-opened for those statements to
547     simplify privilege checking.
548 
549     There are other statements that deal with temporary tables and open
550     them, but which are not listed here. The thing is that the order of
551     pre-opening temporary tables for those statements is somewhat custom.
552   */
553   sql_command_flags[SQLCOM_CREATE_TABLE]|=    CF_PREOPEN_TMP_TABLES;
554   sql_command_flags[SQLCOM_DROP_TABLE]|=      CF_PREOPEN_TMP_TABLES;
555   sql_command_flags[SQLCOM_CREATE_INDEX]|=    CF_PREOPEN_TMP_TABLES;
556   sql_command_flags[SQLCOM_ALTER_TABLE]|=     CF_PREOPEN_TMP_TABLES;
557   sql_command_flags[SQLCOM_TRUNCATE]|=        CF_PREOPEN_TMP_TABLES;
558   sql_command_flags[SQLCOM_LOAD]|=            CF_PREOPEN_TMP_TABLES;
559   sql_command_flags[SQLCOM_DROP_INDEX]|=      CF_PREOPEN_TMP_TABLES;
560   sql_command_flags[SQLCOM_UPDATE]|=          CF_PREOPEN_TMP_TABLES;
561   sql_command_flags[SQLCOM_UPDATE_MULTI]|=    CF_PREOPEN_TMP_TABLES;
562   sql_command_flags[SQLCOM_INSERT_SELECT]|=   CF_PREOPEN_TMP_TABLES;
563   sql_command_flags[SQLCOM_DELETE]|=          CF_PREOPEN_TMP_TABLES;
564   sql_command_flags[SQLCOM_DELETE_MULTI]|=    CF_PREOPEN_TMP_TABLES;
565   sql_command_flags[SQLCOM_REPLACE_SELECT]|=  CF_PREOPEN_TMP_TABLES;
566   sql_command_flags[SQLCOM_SELECT]|=          CF_PREOPEN_TMP_TABLES;
567   sql_command_flags[SQLCOM_SET_OPTION]|=      CF_PREOPEN_TMP_TABLES;
568   sql_command_flags[SQLCOM_DO]|=              CF_PREOPEN_TMP_TABLES;
569   sql_command_flags[SQLCOM_CALL]|=            CF_PREOPEN_TMP_TABLES;
570   sql_command_flags[SQLCOM_CHECKSUM]|=        CF_PREOPEN_TMP_TABLES;
571   sql_command_flags[SQLCOM_ANALYZE]|=         CF_PREOPEN_TMP_TABLES;
572   sql_command_flags[SQLCOM_CHECK]|=           CF_PREOPEN_TMP_TABLES;
573   sql_command_flags[SQLCOM_OPTIMIZE]|=        CF_PREOPEN_TMP_TABLES;
574   sql_command_flags[SQLCOM_REPAIR]|=          CF_PREOPEN_TMP_TABLES;
575   sql_command_flags[SQLCOM_PRELOAD_KEYS]|=    CF_PREOPEN_TMP_TABLES;
576   sql_command_flags[SQLCOM_ASSIGN_TO_KEYCACHE]|= CF_PREOPEN_TMP_TABLES;
577 
578   /*
579     DDL statements that should start with closing opened handlers.
580 
581     We use this flag only for statements for which open HANDLERs
582     have to be closed before emporary tables are pre-opened.
583   */
584   sql_command_flags[SQLCOM_CREATE_TABLE]|=    CF_HA_CLOSE;
585   sql_command_flags[SQLCOM_DROP_TABLE]|=      CF_HA_CLOSE;
586   sql_command_flags[SQLCOM_ALTER_TABLE]|=     CF_HA_CLOSE;
587   sql_command_flags[SQLCOM_TRUNCATE]|=        CF_HA_CLOSE;
588   sql_command_flags[SQLCOM_REPAIR]|=          CF_HA_CLOSE;
589   sql_command_flags[SQLCOM_OPTIMIZE]|=        CF_HA_CLOSE;
590   sql_command_flags[SQLCOM_ANALYZE]|=         CF_HA_CLOSE;
591   sql_command_flags[SQLCOM_CHECK]|=           CF_HA_CLOSE;
592   sql_command_flags[SQLCOM_CREATE_INDEX]|=    CF_HA_CLOSE;
593   sql_command_flags[SQLCOM_DROP_INDEX]|=      CF_HA_CLOSE;
594   sql_command_flags[SQLCOM_PRELOAD_KEYS]|=    CF_HA_CLOSE;
595   sql_command_flags[SQLCOM_ASSIGN_TO_KEYCACHE]|=  CF_HA_CLOSE;
596 
597   /*
598     Mark statements that always are disallowed in read-only
599     transactions. Note that according to the SQL standard,
600     even temporary table DDL should be disallowed.
601   */
602   sql_command_flags[SQLCOM_CREATE_TABLE]|=     CF_DISALLOW_IN_RO_TRANS;
603   sql_command_flags[SQLCOM_ALTER_TABLE]|=      CF_DISALLOW_IN_RO_TRANS;
604   sql_command_flags[SQLCOM_DROP_TABLE]|=       CF_DISALLOW_IN_RO_TRANS;
605   sql_command_flags[SQLCOM_RENAME_TABLE]|=     CF_DISALLOW_IN_RO_TRANS;
606   sql_command_flags[SQLCOM_CREATE_INDEX]|=     CF_DISALLOW_IN_RO_TRANS;
607   sql_command_flags[SQLCOM_DROP_INDEX]|=       CF_DISALLOW_IN_RO_TRANS;
608   sql_command_flags[SQLCOM_CREATE_DB]|=        CF_DISALLOW_IN_RO_TRANS;
609   sql_command_flags[SQLCOM_DROP_DB]|=          CF_DISALLOW_IN_RO_TRANS;
610   sql_command_flags[SQLCOM_ALTER_DB_UPGRADE]|= CF_DISALLOW_IN_RO_TRANS;
611   sql_command_flags[SQLCOM_ALTER_DB]|=         CF_DISALLOW_IN_RO_TRANS;
612   sql_command_flags[SQLCOM_CREATE_VIEW]|=      CF_DISALLOW_IN_RO_TRANS;
613   sql_command_flags[SQLCOM_DROP_VIEW]|=        CF_DISALLOW_IN_RO_TRANS;
614   sql_command_flags[SQLCOM_CREATE_TRIGGER]|=   CF_DISALLOW_IN_RO_TRANS;
615   sql_command_flags[SQLCOM_DROP_TRIGGER]|=     CF_DISALLOW_IN_RO_TRANS;
616   sql_command_flags[SQLCOM_CREATE_EVENT]|=     CF_DISALLOW_IN_RO_TRANS;
617   sql_command_flags[SQLCOM_ALTER_EVENT]|=      CF_DISALLOW_IN_RO_TRANS;
618   sql_command_flags[SQLCOM_DROP_EVENT]|=       CF_DISALLOW_IN_RO_TRANS;
619   sql_command_flags[SQLCOM_CREATE_USER]|=      CF_DISALLOW_IN_RO_TRANS;
620   sql_command_flags[SQLCOM_RENAME_USER]|=      CF_DISALLOW_IN_RO_TRANS;
621   sql_command_flags[SQLCOM_ALTER_USER]|=       CF_DISALLOW_IN_RO_TRANS;
622   sql_command_flags[SQLCOM_DROP_USER]|=        CF_DISALLOW_IN_RO_TRANS;
623   sql_command_flags[SQLCOM_CREATE_SERVER]|=    CF_DISALLOW_IN_RO_TRANS;
624   sql_command_flags[SQLCOM_ALTER_SERVER]|=     CF_DISALLOW_IN_RO_TRANS;
625   sql_command_flags[SQLCOM_DROP_SERVER]|=      CF_DISALLOW_IN_RO_TRANS;
626   sql_command_flags[SQLCOM_CREATE_FUNCTION]|=  CF_DISALLOW_IN_RO_TRANS;
627   sql_command_flags[SQLCOM_CREATE_PROCEDURE]|= CF_DISALLOW_IN_RO_TRANS;
628   sql_command_flags[SQLCOM_CREATE_SPFUNCTION]|=CF_DISALLOW_IN_RO_TRANS;
629   sql_command_flags[SQLCOM_DROP_PROCEDURE]|=   CF_DISALLOW_IN_RO_TRANS;
630   sql_command_flags[SQLCOM_DROP_FUNCTION]|=    CF_DISALLOW_IN_RO_TRANS;
631   sql_command_flags[SQLCOM_ALTER_PROCEDURE]|=  CF_DISALLOW_IN_RO_TRANS;
632   sql_command_flags[SQLCOM_ALTER_FUNCTION]|=   CF_DISALLOW_IN_RO_TRANS;
633   sql_command_flags[SQLCOM_TRUNCATE]|=         CF_DISALLOW_IN_RO_TRANS;
634   sql_command_flags[SQLCOM_ALTER_TABLESPACE]|= CF_DISALLOW_IN_RO_TRANS;
635   sql_command_flags[SQLCOM_REPAIR]|=           CF_DISALLOW_IN_RO_TRANS;
636   sql_command_flags[SQLCOM_OPTIMIZE]|=         CF_DISALLOW_IN_RO_TRANS;
637   sql_command_flags[SQLCOM_GRANT]|=            CF_DISALLOW_IN_RO_TRANS;
638   sql_command_flags[SQLCOM_REVOKE]|=           CF_DISALLOW_IN_RO_TRANS;
639   sql_command_flags[SQLCOM_REVOKE_ALL]|=       CF_DISALLOW_IN_RO_TRANS;
640   sql_command_flags[SQLCOM_INSTALL_PLUGIN]|=   CF_DISALLOW_IN_RO_TRANS;
641   sql_command_flags[SQLCOM_UNINSTALL_PLUGIN]|= CF_DISALLOW_IN_RO_TRANS;
642   sql_command_flags[SQLCOM_ALTER_INSTANCE]|=   CF_DISALLOW_IN_RO_TRANS;
643 
644   /*
645     Mark statements that are allowed to be executed by the plugins.
646   */
647   sql_command_flags[SQLCOM_SELECT]|=                  CF_ALLOW_PROTOCOL_PLUGIN;
648   sql_command_flags[SQLCOM_CREATE_TABLE]|=            CF_ALLOW_PROTOCOL_PLUGIN;
649   sql_command_flags[SQLCOM_CREATE_INDEX]|=            CF_ALLOW_PROTOCOL_PLUGIN;
650   sql_command_flags[SQLCOM_ALTER_TABLE]|=             CF_ALLOW_PROTOCOL_PLUGIN;
651   sql_command_flags[SQLCOM_UPDATE]|=                  CF_ALLOW_PROTOCOL_PLUGIN;
652   sql_command_flags[SQLCOM_INSERT]|=                  CF_ALLOW_PROTOCOL_PLUGIN;
653   sql_command_flags[SQLCOM_INSERT_SELECT]|=           CF_ALLOW_PROTOCOL_PLUGIN;
654   sql_command_flags[SQLCOM_DELETE]|=                  CF_ALLOW_PROTOCOL_PLUGIN;
655   sql_command_flags[SQLCOM_TRUNCATE]|=                CF_ALLOW_PROTOCOL_PLUGIN;
656   sql_command_flags[SQLCOM_DROP_TABLE]|=              CF_ALLOW_PROTOCOL_PLUGIN;
657   sql_command_flags[SQLCOM_DROP_INDEX]|=              CF_ALLOW_PROTOCOL_PLUGIN;
658   sql_command_flags[SQLCOM_SHOW_DATABASES]|=          CF_ALLOW_PROTOCOL_PLUGIN;
659   sql_command_flags[SQLCOM_SHOW_TABLES]|=             CF_ALLOW_PROTOCOL_PLUGIN;
660   sql_command_flags[SQLCOM_SHOW_FIELDS]|=             CF_ALLOW_PROTOCOL_PLUGIN;
661   sql_command_flags[SQLCOM_SHOW_KEYS]|=               CF_ALLOW_PROTOCOL_PLUGIN;
662   sql_command_flags[SQLCOM_SHOW_VARIABLES]|=          CF_ALLOW_PROTOCOL_PLUGIN;
663   sql_command_flags[SQLCOM_SHOW_STATUS]|=             CF_ALLOW_PROTOCOL_PLUGIN;
664   sql_command_flags[SQLCOM_SHOW_ENGINE_LOGS]|=        CF_ALLOW_PROTOCOL_PLUGIN;
665   sql_command_flags[SQLCOM_SHOW_ENGINE_STATUS]|=      CF_ALLOW_PROTOCOL_PLUGIN;
666   sql_command_flags[SQLCOM_SHOW_ENGINE_MUTEX]|=       CF_ALLOW_PROTOCOL_PLUGIN;
667   sql_command_flags[SQLCOM_SHOW_PROCESSLIST]|=        CF_ALLOW_PROTOCOL_PLUGIN;
668   sql_command_flags[SQLCOM_SHOW_MASTER_STAT]|=        CF_ALLOW_PROTOCOL_PLUGIN;
669   sql_command_flags[SQLCOM_SHOW_SLAVE_STAT]|=         CF_ALLOW_PROTOCOL_PLUGIN;
670   sql_command_flags[SQLCOM_SHOW_GRANTS]|=             CF_ALLOW_PROTOCOL_PLUGIN;
671   sql_command_flags[SQLCOM_SHOW_CREATE]|=             CF_ALLOW_PROTOCOL_PLUGIN;
672   sql_command_flags[SQLCOM_SHOW_CHARSETS]|=           CF_ALLOW_PROTOCOL_PLUGIN;
673   sql_command_flags[SQLCOM_SHOW_COLLATIONS]|=         CF_ALLOW_PROTOCOL_PLUGIN;
674   sql_command_flags[SQLCOM_SHOW_CREATE_DB]|=          CF_ALLOW_PROTOCOL_PLUGIN;
675   sql_command_flags[SQLCOM_SHOW_TABLE_STATUS]|=       CF_ALLOW_PROTOCOL_PLUGIN;
676   sql_command_flags[SQLCOM_SHOW_TRIGGERS]|=           CF_ALLOW_PROTOCOL_PLUGIN;
677   sql_command_flags[SQLCOM_LOAD]|=                    CF_ALLOW_PROTOCOL_PLUGIN;
678   sql_command_flags[SQLCOM_SET_OPTION]|=              CF_ALLOW_PROTOCOL_PLUGIN;
679   sql_command_flags[SQLCOM_LOCK_TABLES]|=             CF_ALLOW_PROTOCOL_PLUGIN;
680   sql_command_flags[SQLCOM_UNLOCK_TABLES]|=           CF_ALLOW_PROTOCOL_PLUGIN;
681   sql_command_flags[SQLCOM_GRANT]|=                   CF_ALLOW_PROTOCOL_PLUGIN;
682   sql_command_flags[SQLCOM_CHANGE_DB]|=               CF_ALLOW_PROTOCOL_PLUGIN;
683   sql_command_flags[SQLCOM_CREATE_DB]|=               CF_ALLOW_PROTOCOL_PLUGIN;
684   sql_command_flags[SQLCOM_DROP_DB]|=                 CF_ALLOW_PROTOCOL_PLUGIN;
685   sql_command_flags[SQLCOM_ALTER_DB]|=                CF_ALLOW_PROTOCOL_PLUGIN;
686   sql_command_flags[SQLCOM_REPAIR]|=                  CF_ALLOW_PROTOCOL_PLUGIN;
687   sql_command_flags[SQLCOM_REPLACE]|=                 CF_ALLOW_PROTOCOL_PLUGIN;
688   sql_command_flags[SQLCOM_REPLACE_SELECT]|=          CF_ALLOW_PROTOCOL_PLUGIN;
689   sql_command_flags[SQLCOM_CREATE_FUNCTION]|=         CF_ALLOW_PROTOCOL_PLUGIN;
690   sql_command_flags[SQLCOM_DROP_FUNCTION]|=           CF_ALLOW_PROTOCOL_PLUGIN;
691   sql_command_flags[SQLCOM_REVOKE]|=                  CF_ALLOW_PROTOCOL_PLUGIN;
692   sql_command_flags[SQLCOM_OPTIMIZE]|=                CF_ALLOW_PROTOCOL_PLUGIN;
693   sql_command_flags[SQLCOM_CHECK]|=                   CF_ALLOW_PROTOCOL_PLUGIN;
694   sql_command_flags[SQLCOM_ASSIGN_TO_KEYCACHE]|=      CF_ALLOW_PROTOCOL_PLUGIN;
695   sql_command_flags[SQLCOM_PRELOAD_KEYS]|=            CF_ALLOW_PROTOCOL_PLUGIN;
696   sql_command_flags[SQLCOM_FLUSH]|=                   CF_ALLOW_PROTOCOL_PLUGIN;
697   sql_command_flags[SQLCOM_KILL]|=                    CF_ALLOW_PROTOCOL_PLUGIN;
698   sql_command_flags[SQLCOM_ANALYZE]|=                 CF_ALLOW_PROTOCOL_PLUGIN;
699   sql_command_flags[SQLCOM_ROLLBACK]|=                CF_ALLOW_PROTOCOL_PLUGIN;
700   sql_command_flags[SQLCOM_ROLLBACK_TO_SAVEPOINT]|=   CF_ALLOW_PROTOCOL_PLUGIN;
701   sql_command_flags[SQLCOM_COMMIT]|=                  CF_ALLOW_PROTOCOL_PLUGIN;
702   sql_command_flags[SQLCOM_SAVEPOINT]|=               CF_ALLOW_PROTOCOL_PLUGIN;
703   sql_command_flags[SQLCOM_RELEASE_SAVEPOINT]|=       CF_ALLOW_PROTOCOL_PLUGIN;
704   sql_command_flags[SQLCOM_SLAVE_START]|=             CF_ALLOW_PROTOCOL_PLUGIN;
705   sql_command_flags[SQLCOM_SLAVE_STOP]|=              CF_ALLOW_PROTOCOL_PLUGIN;
706   sql_command_flags[SQLCOM_BEGIN]|=                   CF_ALLOW_PROTOCOL_PLUGIN;
707   sql_command_flags[SQLCOM_CHANGE_MASTER]|=           CF_ALLOW_PROTOCOL_PLUGIN;
708   sql_command_flags[SQLCOM_CHANGE_REPLICATION_FILTER]|= CF_ALLOW_PROTOCOL_PLUGIN;
709   sql_command_flags[SQLCOM_RENAME_TABLE]|=            CF_ALLOW_PROTOCOL_PLUGIN;
710   sql_command_flags[SQLCOM_RESET]|=                   CF_ALLOW_PROTOCOL_PLUGIN;
711   sql_command_flags[SQLCOM_PURGE]|=                   CF_ALLOW_PROTOCOL_PLUGIN;
712   sql_command_flags[SQLCOM_PURGE_BEFORE]|=            CF_ALLOW_PROTOCOL_PLUGIN;
713   sql_command_flags[SQLCOM_SHOW_BINLOGS]|=            CF_ALLOW_PROTOCOL_PLUGIN;
714   sql_command_flags[SQLCOM_SHOW_OPEN_TABLES]|=        CF_ALLOW_PROTOCOL_PLUGIN;
715   sql_command_flags[SQLCOM_HA_OPEN]|=                 CF_ALLOW_PROTOCOL_PLUGIN;
716   sql_command_flags[SQLCOM_HA_CLOSE]|=                CF_ALLOW_PROTOCOL_PLUGIN;
717   sql_command_flags[SQLCOM_HA_READ]|=                 CF_ALLOW_PROTOCOL_PLUGIN;
718   sql_command_flags[SQLCOM_SHOW_SLAVE_HOSTS]|=        CF_ALLOW_PROTOCOL_PLUGIN;
719   sql_command_flags[SQLCOM_DELETE_MULTI]|=            CF_ALLOW_PROTOCOL_PLUGIN;
720   sql_command_flags[SQLCOM_UPDATE_MULTI]|=            CF_ALLOW_PROTOCOL_PLUGIN;
721   sql_command_flags[SQLCOM_SHOW_BINLOG_EVENTS]|=      CF_ALLOW_PROTOCOL_PLUGIN;
722   sql_command_flags[SQLCOM_DO]|=                      CF_ALLOW_PROTOCOL_PLUGIN;
723   sql_command_flags[SQLCOM_SHOW_WARNS]|=              CF_ALLOW_PROTOCOL_PLUGIN;
724   sql_command_flags[SQLCOM_EMPTY_QUERY]|=             CF_ALLOW_PROTOCOL_PLUGIN;
725   sql_command_flags[SQLCOM_SHOW_ERRORS]|=             CF_ALLOW_PROTOCOL_PLUGIN;
726   sql_command_flags[SQLCOM_SHOW_STORAGE_ENGINES]|=    CF_ALLOW_PROTOCOL_PLUGIN;
727   sql_command_flags[SQLCOM_SHOW_PRIVILEGES]|=         CF_ALLOW_PROTOCOL_PLUGIN;
728   sql_command_flags[SQLCOM_HELP]|=                    CF_ALLOW_PROTOCOL_PLUGIN;
729   sql_command_flags[SQLCOM_CREATE_USER]|=             CF_ALLOW_PROTOCOL_PLUGIN;
730   sql_command_flags[SQLCOM_DROP_USER]|=               CF_ALLOW_PROTOCOL_PLUGIN;
731   sql_command_flags[SQLCOM_RENAME_USER]|=             CF_ALLOW_PROTOCOL_PLUGIN;
732   sql_command_flags[SQLCOM_REVOKE_ALL]|=              CF_ALLOW_PROTOCOL_PLUGIN;
733   sql_command_flags[SQLCOM_CHECKSUM]|=                CF_ALLOW_PROTOCOL_PLUGIN;
734   sql_command_flags[SQLCOM_CREATE_PROCEDURE]|=        CF_ALLOW_PROTOCOL_PLUGIN;
735   sql_command_flags[SQLCOM_CREATE_SPFUNCTION]|=       CF_ALLOW_PROTOCOL_PLUGIN;
736   sql_command_flags[SQLCOM_CALL]|=                    CF_ALLOW_PROTOCOL_PLUGIN;
737   sql_command_flags[SQLCOM_DROP_PROCEDURE]|=          CF_ALLOW_PROTOCOL_PLUGIN;
738   sql_command_flags[SQLCOM_ALTER_PROCEDURE]|=         CF_ALLOW_PROTOCOL_PLUGIN;
739   sql_command_flags[SQLCOM_ALTER_FUNCTION]|=          CF_ALLOW_PROTOCOL_PLUGIN;
740   sql_command_flags[SQLCOM_SHOW_CREATE_PROC]|=        CF_ALLOW_PROTOCOL_PLUGIN;
741   sql_command_flags[SQLCOM_SHOW_CREATE_FUNC]|=        CF_ALLOW_PROTOCOL_PLUGIN;
742   sql_command_flags[SQLCOM_SHOW_STATUS_PROC]|=        CF_ALLOW_PROTOCOL_PLUGIN;
743   sql_command_flags[SQLCOM_SHOW_STATUS_FUNC]|=        CF_ALLOW_PROTOCOL_PLUGIN;
744   sql_command_flags[SQLCOM_PREPARE]|=                 CF_ALLOW_PROTOCOL_PLUGIN;
745   sql_command_flags[SQLCOM_EXECUTE]|=                 CF_ALLOW_PROTOCOL_PLUGIN;
746   sql_command_flags[SQLCOM_DEALLOCATE_PREPARE]|=      CF_ALLOW_PROTOCOL_PLUGIN;
747   sql_command_flags[SQLCOM_CREATE_VIEW]|=             CF_ALLOW_PROTOCOL_PLUGIN;
748   sql_command_flags[SQLCOM_DROP_VIEW]|=               CF_ALLOW_PROTOCOL_PLUGIN;
749   sql_command_flags[SQLCOM_CREATE_TRIGGER]|=          CF_ALLOW_PROTOCOL_PLUGIN;
750   sql_command_flags[SQLCOM_DROP_TRIGGER]|=            CF_ALLOW_PROTOCOL_PLUGIN;
751   sql_command_flags[SQLCOM_XA_START]|=                CF_ALLOW_PROTOCOL_PLUGIN;
752   sql_command_flags[SQLCOM_XA_END]|=                  CF_ALLOW_PROTOCOL_PLUGIN;
753   sql_command_flags[SQLCOM_XA_PREPARE]|=              CF_ALLOW_PROTOCOL_PLUGIN;
754   sql_command_flags[SQLCOM_XA_COMMIT]|=               CF_ALLOW_PROTOCOL_PLUGIN;
755   sql_command_flags[SQLCOM_XA_ROLLBACK]|=             CF_ALLOW_PROTOCOL_PLUGIN;
756   sql_command_flags[SQLCOM_XA_RECOVER]|=              CF_ALLOW_PROTOCOL_PLUGIN;
757   sql_command_flags[SQLCOM_SHOW_PROC_CODE]|=          CF_ALLOW_PROTOCOL_PLUGIN;
758   sql_command_flags[SQLCOM_SHOW_FUNC_CODE]|=          CF_ALLOW_PROTOCOL_PLUGIN;
759   sql_command_flags[SQLCOM_ALTER_TABLESPACE]|=        CF_ALLOW_PROTOCOL_PLUGIN;
760   sql_command_flags[SQLCOM_BINLOG_BASE64_EVENT]|=     CF_ALLOW_PROTOCOL_PLUGIN;
761   sql_command_flags[SQLCOM_SHOW_PLUGINS]|=            CF_ALLOW_PROTOCOL_PLUGIN;
762   sql_command_flags[SQLCOM_CREATE_SERVER]|=           CF_ALLOW_PROTOCOL_PLUGIN;
763   sql_command_flags[SQLCOM_DROP_SERVER]|=             CF_ALLOW_PROTOCOL_PLUGIN;
764   sql_command_flags[SQLCOM_ALTER_SERVER]|=            CF_ALLOW_PROTOCOL_PLUGIN;
765   sql_command_flags[SQLCOM_CREATE_EVENT]|=            CF_ALLOW_PROTOCOL_PLUGIN;
766   sql_command_flags[SQLCOM_ALTER_EVENT]|=             CF_ALLOW_PROTOCOL_PLUGIN;
767   sql_command_flags[SQLCOM_DROP_EVENT]|=              CF_ALLOW_PROTOCOL_PLUGIN;
768   sql_command_flags[SQLCOM_SHOW_CREATE_EVENT]|=       CF_ALLOW_PROTOCOL_PLUGIN;
769   sql_command_flags[SQLCOM_SHOW_EVENTS]|=             CF_ALLOW_PROTOCOL_PLUGIN;
770   sql_command_flags[SQLCOM_SHOW_CREATE_TRIGGER]|=     CF_ALLOW_PROTOCOL_PLUGIN;
771   sql_command_flags[SQLCOM_ALTER_DB_UPGRADE]|=        CF_ALLOW_PROTOCOL_PLUGIN;
772   sql_command_flags[SQLCOM_SHOW_PROFILE]|=            CF_ALLOW_PROTOCOL_PLUGIN;
773   sql_command_flags[SQLCOM_SHOW_PROFILES]|=           CF_ALLOW_PROTOCOL_PLUGIN;
774   sql_command_flags[SQLCOM_SIGNAL]|=                  CF_ALLOW_PROTOCOL_PLUGIN;
775   sql_command_flags[SQLCOM_RESIGNAL]|=                CF_ALLOW_PROTOCOL_PLUGIN;
776   sql_command_flags[SQLCOM_SHOW_RELAYLOG_EVENTS]|=    CF_ALLOW_PROTOCOL_PLUGIN;
777   sql_command_flags[SQLCOM_GET_DIAGNOSTICS]|=         CF_ALLOW_PROTOCOL_PLUGIN;
778   sql_command_flags[SQLCOM_ALTER_USER]|=              CF_ALLOW_PROTOCOL_PLUGIN;
779   sql_command_flags[SQLCOM_EXPLAIN_OTHER]|=           CF_ALLOW_PROTOCOL_PLUGIN;
780   sql_command_flags[SQLCOM_SHOW_CREATE_USER]|=        CF_ALLOW_PROTOCOL_PLUGIN;
781   sql_command_flags[SQLCOM_END]|=                     CF_ALLOW_PROTOCOL_PLUGIN;
782 }
783 
sqlcom_can_generate_row_events(enum enum_sql_command command)784 bool sqlcom_can_generate_row_events(enum enum_sql_command command)
785 {
786   return (sql_command_flags[command] & CF_CAN_GENERATE_ROW_EVENTS);
787 }
788 
is_update_query(enum enum_sql_command command)789 bool is_update_query(enum enum_sql_command command)
790 {
791   assert(command >= 0 && command <= SQLCOM_END);
792   return (sql_command_flags[command] & CF_CHANGES_DATA) != 0;
793 }
794 
795 
is_explainable_query(enum enum_sql_command command)796 bool is_explainable_query(enum enum_sql_command command)
797 {
798   assert(command >= 0 && command <= SQLCOM_END);
799   return (sql_command_flags[command] & CF_CAN_BE_EXPLAINED) != 0;
800 }
801 
802 /**
803   Check if a sql command is allowed to write to log tables.
804   @param command The SQL command
805   @return true if writing is allowed
806 */
is_log_table_write_query(enum enum_sql_command command)807 bool is_log_table_write_query(enum enum_sql_command command)
808 {
809   assert(command >= 0 && command <= SQLCOM_END);
810   return (sql_command_flags[command] & CF_WRITE_LOGS_COMMAND) != 0;
811 }
812 
execute_init_command(THD * thd,LEX_STRING * init_command,mysql_rwlock_t * var_lock)813 void execute_init_command(THD *thd, LEX_STRING *init_command,
814                           mysql_rwlock_t *var_lock)
815 {
816   Protocol_classic *protocol= thd->get_protocol_classic();
817   Vio* save_vio;
818   ulong save_client_capabilities;
819   COM_DATA com_data;
820 
821   mysql_rwlock_rdlock(var_lock);
822   if (!init_command->length)
823   {
824     mysql_rwlock_unlock(var_lock);
825     return;
826   }
827 
828   /*
829     copy the value under a lock, and release the lock.
830     init_command has to be executed without a lock held,
831     as it may try to change itself
832   */
833   size_t len= init_command->length;
834   char *buf= thd->strmake(init_command->str, len);
835   mysql_rwlock_unlock(var_lock);
836 
837 #if defined(ENABLED_PROFILING)
838   thd->profiling.start_new_query();
839   thd->profiling.set_query_source(buf, len);
840 #endif
841 
842   THD_STAGE_INFO(thd, stage_execution_of_init_command);
843   save_client_capabilities= protocol->get_client_capabilities();
844   protocol->add_client_capability(CLIENT_MULTI_QUERIES);
845   /*
846     We don't need return result of execution to client side.
847     To forbid this we should set thd->net.vio to 0.
848   */
849   save_vio= protocol->get_vio();
850   protocol->set_vio(NULL);
851   protocol->create_command(&com_data, COM_QUERY, (uchar *) buf, len);
852   dispatch_command(thd, &com_data, COM_QUERY);
853   protocol->set_client_capabilities(save_client_capabilities);
854   protocol->set_vio(save_vio);
855 
856 #if defined(ENABLED_PROFILING)
857   thd->profiling.finish_current_query();
858 #endif
859 }
860 
861 
862 /* This works because items are allocated with sql_alloc() */
863 
free_items(Item * item)864 void free_items(Item *item)
865 {
866   Item *next;
867   DBUG_ENTER("free_items");
868   for (; item ; item=next)
869   {
870     next=item->next;
871     item->delete_self();
872   }
873   DBUG_VOID_RETURN;
874 }
875 
876 /**
877    This works because items are allocated with sql_alloc().
878    @note The function also handles null pointers (empty list).
879 */
cleanup_items(Item * item)880 void cleanup_items(Item *item)
881 {
882   DBUG_ENTER("cleanup_items");
883   for (; item ; item=item->next)
884     item->cleanup();
885   DBUG_VOID_RETURN;
886 }
887 
888 #ifndef EMBEDDED_LIBRARY
889 
890 /**
891   Read one command from connection and execute it (query or simple command).
892   This function is called in loop from thread function.
893 
894   For profiling to work, it must never be called recursively.
895 
896   @retval
897     0  success
898   @retval
899     1  request of thread shutdown (see dispatch_command() description)
900 */
901 
do_command(THD * thd)902 bool do_command(THD *thd)
903 {
904   bool return_value;
905   int rc;
906   const bool classic=
907     (thd->get_protocol()->type() == Protocol::PROTOCOL_TEXT ||
908      thd->get_protocol()->type() == Protocol::PROTOCOL_BINARY);
909 
910   NET *net= NULL;
911   enum enum_server_command command;
912   COM_DATA com_data;
913   DBUG_ENTER("do_command");
914 
915   /*
916     indicator of uninitialized lex => normal flow of errors handling
917     (see my_message_sql)
918   */
919   thd->lex->set_current_select(0);
920 
921   /*
922     XXX: this code is here only to clear possible errors of init_connect.
923     Consider moving to prepare_new_connection_state() instead.
924     That requires making sure the DA is cleared before non-parsing statements
925     such as COM_QUIT.
926   */
927   thd->clear_error();				// Clear error message
928   thd->get_stmt_da()->reset_diagnostics_area();
929 
930   if (classic)
931   {
932     /*
933       This thread will do a blocking read from the client which
934       will be interrupted when the next command is received from
935       the client, the connection is closed or "net_wait_timeout"
936       number of seconds has passed.
937     */
938     net= thd->get_protocol_classic()->get_net();
939     my_net_set_read_timeout(net, thd->variables.net_wait_timeout);
940     net_new_transaction(net);
941   }
942 
943   /*
944     Synchronization point for testing of KILL_CONNECTION.
945     This sync point can wait here, to simulate slow code execution
946     between the last test of thd->killed and blocking in read().
947 
948     The goal of this test is to verify that a connection does not
949     hang, if it is killed at this point of execution.
950     (Bug#37780 - main.kill fails randomly)
951 
952     Note that the sync point wait itself will be terminated by a
953     kill. In this case it consumes a condition broadcast, but does
954     not change anything else. The consumed broadcast should not
955     matter here, because the read/recv() below doesn't use it.
956   */
957   DEBUG_SYNC(thd, "before_do_command_net_read");
958 
959   /*
960     Because of networking layer callbacks in place,
961     this call will maintain the following instrumentation:
962     - IDLE events
963     - SOCKET events
964     - STATEMENT events
965     - STAGE events
966     when reading a new network packet.
967     In particular, a new instrumented statement is started.
968     See init_net_server_extension()
969   */
970   thd->m_server_idle= true;
971   rc= thd->get_protocol()->get_command(&com_data, &command);
972   thd->m_server_idle= false;
973 
974   if (rc)
975   {
976     if (classic)
977     {
978       DBUG_PRINT("info",("Got error %d reading command from socket %s",
979                          net->error,
980                          vio_description(net->vio)));
981     }
982     else
983     {
984       DBUG_PRINT("info",("Got error %d reading command from %s protocol",
985                          rc,
986                          (thd->get_protocol()->type() ==
987                           Protocol::PROTOCOL_LOCAL) ? "local" : "plugin"));
988     }
989     /* Instrument this broken statement as "statement/com/error" */
990     thd->m_statement_psi= MYSQL_REFINE_STATEMENT(thd->m_statement_psi,
991                                                  com_statement_info[COM_END].m_key);
992 
993     /* Check if we can continue without closing the connection */
994 
995     /* The error must be set. */
996     assert(thd->is_error());
997     thd->send_statement_status();
998 
999     /* Mark the statement completed. */
1000     MYSQL_END_STATEMENT(thd->m_statement_psi, thd->get_stmt_da());
1001     thd->m_statement_psi= NULL;
1002     thd->m_digest= NULL;
1003 
1004     if (rc < 0)
1005     {
1006       return_value= TRUE;                       // We have to close it.
1007       goto out;
1008     }
1009     if (classic)
1010       net->error= 0;
1011     return_value= FALSE;
1012     goto out;
1013   }
1014 
1015   DBUG_PRINT("info",("Command on %s = %d (%s)",
1016                      vio_description(net->vio), command,
1017                      command_name[command].str));
1018 
1019   DBUG_PRINT("info", ("packet: '%*.s'; command: %d",
1020              (int)thd->get_protocol_classic()->get_packet_length(),
1021              thd->get_protocol_classic()->get_raw_packet(), command));
1022   if (thd->get_protocol_classic()->bad_packet)
1023     assert(0);                // Should be caught earlier
1024 
1025   // Reclaim some memory
1026   thd->get_protocol_classic()->get_packet()->shrink(
1027       thd->variables.net_buffer_length);
1028   /* Restore read timeout value */
1029   if (classic)
1030     my_net_set_read_timeout(net, thd->variables.net_read_timeout);
1031 
1032   return_value= dispatch_command(thd, &com_data, command);
1033   thd->get_protocol_classic()->get_packet()->shrink(
1034       thd->variables.net_buffer_length);
1035 
1036 out:
1037   /* The statement instrumentation must be closed in all cases. */
1038   assert(thd->m_digest == NULL);
1039   assert(thd->m_statement_psi == NULL);
1040   DBUG_RETURN(return_value);
1041 }
1042 #endif  /* EMBEDDED_LIBRARY */
1043 
1044 
1045 /**
1046   @brief Determine if an attempt to update a non-temporary table while the
1047     read-only option was enabled has been made.
1048 
1049   This is a helper function to mysql_execute_command.
1050 
1051   @note SQLCOM_UPDATE_MULTI is an exception and delt with elsewhere.
1052 
1053   @see mysql_execute_command
1054   @returns Status code
1055     @retval TRUE The statement should be denied.
1056     @retval FALSE The statement isn't updating any relevant tables.
1057 */
deny_updates_if_read_only_option(THD * thd,TABLE_LIST * all_tables)1058 static my_bool deny_updates_if_read_only_option(THD *thd,
1059                                                 TABLE_LIST *all_tables)
1060 {
1061   DBUG_ENTER("deny_updates_if_read_only_option");
1062 
1063   if (!check_readonly(thd, false))
1064     DBUG_RETURN(FALSE);
1065 
1066   LEX *lex = thd->lex;
1067   if (!(sql_command_flags[lex->sql_command] & CF_CHANGES_DATA))
1068     DBUG_RETURN(FALSE);
1069 
1070   /* Multi update is an exception and is dealt with later. */
1071   if (lex->sql_command == SQLCOM_UPDATE_MULTI)
1072     DBUG_RETURN(FALSE);
1073 
1074   const my_bool create_temp_tables=
1075     (lex->sql_command == SQLCOM_CREATE_TABLE) &&
1076     (lex->create_info.options & HA_LEX_CREATE_TMP_TABLE);
1077 
1078    const my_bool create_real_tables=
1079      (lex->sql_command == SQLCOM_CREATE_TABLE) &&
1080      !(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE);
1081 
1082   const my_bool drop_temp_tables=
1083     (lex->sql_command == SQLCOM_DROP_TABLE) &&
1084     lex->drop_temporary;
1085 
1086   const my_bool update_real_tables=
1087     ((create_real_tables ||
1088       some_non_temp_table_to_be_updated(thd, all_tables)) &&
1089      !(create_temp_tables || drop_temp_tables));
1090 
1091   const my_bool create_or_drop_databases=
1092     (lex->sql_command == SQLCOM_CREATE_DB) ||
1093     (lex->sql_command == SQLCOM_DROP_DB);
1094 
1095   if (update_real_tables || create_or_drop_databases)
1096   {
1097       /*
1098         An attempt was made to modify one or more non-temporary tables.
1099       */
1100       DBUG_RETURN(TRUE);
1101   }
1102 
1103 
1104   /* Assuming that only temporary tables are modified. */
1105   DBUG_RETURN(FALSE);
1106 }
1107 
1108 
1109 /**
1110   Check whether max statement time is applicable to statement or not.
1111 
1112 
1113   @param  thd   Thread (session) context.
1114 
1115   @return true  if max statement time is applicable to statement
1116   @return false otherwise.
1117 */
is_timer_applicable_to_statement(THD * thd)1118 static inline bool is_timer_applicable_to_statement(THD *thd)
1119 {
1120   bool timer_value_is_set= (thd->lex->max_execution_time ||
1121                             thd->variables.max_execution_time);
1122 
1123   /**
1124     Following conditions are checked,
1125       - is SELECT statement.
1126       - timer support is implemented and it is initialized.
1127       - statement is not made by the slave threads.
1128       - timer is not set for statement
1129       - timer out value of is set
1130       - SELECT statement is not from any stored programs.
1131   */
1132   return (thd->lex->sql_command == SQLCOM_SELECT &&
1133           (have_statement_timeout == SHOW_OPTION_YES) &&
1134           !thd->slave_thread &&
1135           !thd->timer && timer_value_is_set &&
1136           !thd->sp_runtime_ctx);
1137 }
1138 
1139 
1140 /**
1141   Get the maximum execution time for a statement.
1142 
1143   @return Length of time in milliseconds.
1144 
1145   @remark A zero timeout means that no timeout should be
1146           applied to this particular statement.
1147 
1148 */
get_max_execution_time(THD * thd)1149 static inline ulong get_max_execution_time(THD *thd)
1150 {
1151   return (thd->lex->max_execution_time ? thd->lex->max_execution_time :
1152                                         thd->variables.max_execution_time);
1153 }
1154 
1155 
1156 /**
1157   Set the time until the currently running statement is aborted.
1158 
1159   @param  thd   Thread (session) context.
1160 
1161   @return true if the timer was armed.
1162 */
set_statement_timer(THD * thd)1163 static inline bool set_statement_timer(THD *thd)
1164 {
1165   ulong max_execution_time= get_max_execution_time(thd);
1166 
1167   /**
1168     whether timer can be set for the statement or not should be checked before
1169     calling set_statement_timer function.
1170   */
1171   assert(is_timer_applicable_to_statement(thd) == true);
1172   assert(thd->timer == NULL);
1173 
1174   thd->timer= thd_timer_set(thd, thd->timer_cache, max_execution_time);
1175   thd->timer_cache= NULL;
1176 
1177   if (thd->timer)
1178     thd->status_var.max_execution_time_set++;
1179   else
1180     thd->status_var.max_execution_time_set_failed++;
1181 
1182   return thd->timer;
1183 }
1184 
1185 
1186 /**
1187   Deactivate the timer associated with the statement that was executed.
1188 
1189   @param  thd   Thread (session) context.
1190 */
1191 
reset_statement_timer(THD * thd)1192 void reset_statement_timer(THD *thd)
1193 {
1194   assert(thd->timer);
1195   /* Cache the timer object if it can be reused. */
1196   thd->timer_cache= thd_timer_reset(thd->timer);
1197   thd->timer= NULL;
1198 }
1199 
1200 
1201 /**
1202   Perform one connection-level (COM_XXXX) command.
1203 
1204   @param thd             connection handle
1205   @param command         type of command to perform
1206   @com_data              com_data union to store the generated command
1207 
1208   @todo
1209     set thd->lex->sql_command to SQLCOM_END here.
1210   @todo
1211     The following has to be changed to an 8 byte integer
1212 
1213   @retval
1214     0   ok
1215   @retval
1216     1   request of thread shutdown, i. e. if command is
1217         COM_QUIT/COM_SHUTDOWN
1218 */
dispatch_command(THD * thd,const COM_DATA * com_data,enum enum_server_command command)1219 bool dispatch_command(THD *thd, const COM_DATA *com_data,
1220                       enum enum_server_command command)
1221 {
1222   bool error= 0;
1223   Global_THD_manager *thd_manager= Global_THD_manager::get_instance();
1224   DBUG_ENTER("dispatch_command");
1225   DBUG_PRINT("info", ("command: %d", command));
1226 
1227   /* SHOW PROFILE instrumentation, begin */
1228 #if defined(ENABLED_PROFILING)
1229   thd->profiling.start_new_query();
1230 #endif
1231 
1232   /* DTRACE instrumentation, begin */
1233   MYSQL_COMMAND_START(thd->thread_id(), command,
1234                       (char *) thd->security_context()->priv_user().str,
1235                       (char *) thd->security_context()->host_or_ip().str);
1236 
1237   /* Performance Schema Interface instrumentation, begin */
1238   thd->m_statement_psi= MYSQL_REFINE_STATEMENT(thd->m_statement_psi,
1239                                                com_statement_info[command].m_key);
1240 
1241   thd->set_command(command);
1242   /*
1243     Commands which always take a long time are logged into
1244     the slow log only if opt_log_slow_admin_statements is set.
1245   */
1246   thd->enable_slow_log= TRUE;
1247   thd->lex->sql_command= SQLCOM_END; /* to avoid confusing VIEW detectors */
1248   thd->set_time();
1249   if (thd->is_valid_time() == false)
1250   {
1251     /*
1252       If the time has gone past 2038 we need to shutdown the server. But
1253       there is possibility of getting invalid time value on some platforms.
1254       For example, gettimeofday() might return incorrect value on solaris
1255       platform. Hence validating the current time with 5 iterations before
1256       initiating the normal server shutdown process because of time getting
1257       past 2038.
1258     */
1259     const int max_tries= 5;
1260     sql_print_warning("Current time has got past year 2038. Validating current "
1261                       "time with %d iterations before initiating the normal "
1262                       "server shutdown process.", max_tries);
1263 
1264     int tries= 0;
1265     while (++tries <= max_tries)
1266     {
1267       thd->set_time();
1268       if (thd->is_valid_time() == true)
1269       {
1270         sql_print_warning("Iteration %d: Obtained valid current time from "
1271                            "system", tries);
1272         break;
1273       }
1274       sql_print_warning("Iteration %d: Current time obtained from system is "
1275                         "greater than 2038", tries);
1276     }
1277     if (tries > max_tries)
1278     {
1279       /*
1280         If the time has got past 2038 we need to shut this server down.
1281         We do this by making sure every command is a shutdown and we
1282         have enough privileges to shut the server down
1283 
1284         TODO: remove this when we have full 64 bit my_time_t support
1285       */
1286       sql_print_error("This MySQL server doesn't support dates later than 2038");
1287       ulong master_access= thd->security_context()->master_access();
1288       thd->security_context()->set_master_access(master_access | SHUTDOWN_ACL);
1289       command= COM_SHUTDOWN;
1290     }
1291   }
1292   thd->set_query_id(next_query_id());
1293   thd->reset_rewritten_query();
1294   thd_manager->inc_thread_running();
1295 
1296   if (!(server_command_flags[command] & CF_SKIP_QUESTIONS))
1297     thd->status_var.questions++;
1298 
1299   /**
1300     Clear the set of flags that are expected to be cleared at the
1301     beginning of each command.
1302   */
1303   thd->server_status&= ~SERVER_STATUS_CLEAR_SET;
1304 
1305   if (thd->get_protocol()->type() == Protocol::PROTOCOL_PLUGIN &&
1306       !(server_command_flags[command] & CF_ALLOW_PROTOCOL_PLUGIN))
1307   {
1308     my_error(ER_PLUGGABLE_PROTOCOL_COMMAND_NOT_SUPPORTED, MYF(0));
1309     thd->killed= THD::KILL_CONNECTION;
1310     error= true;
1311     goto done;
1312   }
1313 
1314   /**
1315     Enforce password expiration for all RPC commands, except the
1316     following:
1317 
1318     COM_QUERY does a more fine-grained check later.
1319     COM_STMT_CLOSE and COM_STMT_SEND_LONG_DATA don't return anything.
1320     COM_PING only discloses information that the server is running,
1321        and that's available through other means.
1322     COM_QUIT should work even for expired statements.
1323   */
1324   if (unlikely(thd->security_context()->password_expired() &&
1325                command != COM_QUERY &&
1326                command != COM_STMT_CLOSE &&
1327                command != COM_STMT_SEND_LONG_DATA &&
1328                command != COM_PING &&
1329                command != COM_QUIT))
1330   {
1331     my_error(ER_MUST_CHANGE_PASSWORD, MYF(0));
1332     goto done;
1333   }
1334 
1335 #ifndef EMBEDDED_LIBRARY
1336   if (mysql_audit_notify(thd,
1337                          AUDIT_EVENT(MYSQL_AUDIT_COMMAND_START),
1338                          command, command_name[command].str))
1339   {
1340     goto done;
1341   }
1342 #endif /* !EMBEDDED_LIBRARY */
1343 
1344   switch (command) {
1345   case COM_INIT_DB:
1346   {
1347     LEX_STRING tmp;
1348     thd->status_var.com_stat[SQLCOM_CHANGE_DB]++;
1349     thd->convert_string(&tmp, system_charset_info,
1350                         com_data->com_init_db.db_name,
1351                         com_data->com_init_db.length, thd->charset());
1352 
1353     LEX_CSTRING tmp_cstr= {tmp.str, tmp.length};
1354     if (!mysql_change_db(thd, tmp_cstr, FALSE))
1355     {
1356       query_logger.general_log_write(thd, command,
1357                                      thd->db().str, thd->db().length);
1358       my_ok(thd);
1359     }
1360     break;
1361   }
1362 #ifdef HAVE_REPLICATION
1363   case COM_REGISTER_SLAVE:
1364   {
1365     // TODO: access of protocol_classic should be removed
1366     if (!register_slave(thd,
1367       thd->get_protocol_classic()->get_raw_packet(),
1368       thd->get_protocol_classic()->get_packet_length()))
1369       my_ok(thd);
1370     break;
1371   }
1372 #endif
1373   case COM_RESET_CONNECTION:
1374   {
1375     thd->status_var.com_other++;
1376     thd->cleanup_connection();
1377     my_ok(thd);
1378     break;
1379   }
1380   case COM_CHANGE_USER:
1381   {
1382     int auth_rc;
1383     thd->status_var.com_other++;
1384 
1385     thd->cleanup_connection();
1386     USER_CONN *save_user_connect=
1387       const_cast<USER_CONN*>(thd->get_user_connect());
1388     LEX_CSTRING save_db= thd->db();
1389     Security_context save_security_ctx(*(thd->security_context()));
1390 
1391     auth_rc= acl_authenticate(thd, COM_CHANGE_USER);
1392 #ifndef EMBEDDED_LIBRARY
1393     auth_rc|= mysql_audit_notify(thd,
1394                              AUDIT_EVENT(MYSQL_AUDIT_CONNECTION_CHANGE_USER));
1395 #endif
1396     if (auth_rc)
1397     {
1398       *thd->security_context()= save_security_ctx;
1399       thd->set_user_connect(save_user_connect);
1400       thd->reset_db(save_db);
1401 
1402       my_error(ER_ACCESS_DENIED_CHANGE_USER_ERROR, MYF(0),
1403                thd->security_context()->user().str,
1404                thd->security_context()->host_or_ip().str,
1405                (thd->password ? ER(ER_YES) : ER(ER_NO)));
1406       thd->killed= THD::KILL_CONNECTION;
1407       error=true;
1408     }
1409     else
1410     {
1411 #ifndef NO_EMBEDDED_ACCESS_CHECKS
1412       /* we've authenticated new user */
1413       if (save_user_connect)
1414 	decrease_user_connections(save_user_connect);
1415 #endif /* NO_EMBEDDED_ACCESS_CHECKS */
1416       mysql_mutex_lock(&thd->LOCK_thd_data);
1417       my_free(const_cast<char*>(save_db.str));
1418       save_db= NULL_CSTR;
1419       mysql_mutex_unlock(&thd->LOCK_thd_data);
1420     }
1421     break;
1422   }
1423   case COM_STMT_EXECUTE:
1424   {
1425     mysqld_stmt_execute(thd, com_data->com_stmt_execute.stmt_id,
1426                         com_data->com_stmt_execute.flags,
1427                         com_data->com_stmt_execute.params,
1428                         com_data->com_stmt_execute.params_length);
1429     break;
1430   }
1431   case COM_STMT_FETCH:
1432   {
1433     mysqld_stmt_fetch(thd, com_data->com_stmt_fetch.stmt_id,
1434                       com_data->com_stmt_fetch.num_rows);
1435     break;
1436   }
1437   case COM_STMT_SEND_LONG_DATA:
1438   {
1439     mysql_stmt_get_longdata(thd, com_data->com_stmt_send_long_data.stmt_id,
1440                             com_data->com_stmt_send_long_data.param_number,
1441                             com_data->com_stmt_send_long_data.longdata,
1442                             com_data->com_stmt_send_long_data.length);
1443     break;
1444   }
1445   case COM_STMT_PREPARE:
1446   {
1447     mysqld_stmt_prepare(thd, com_data->com_stmt_prepare.query,
1448                         com_data->com_stmt_prepare.length);
1449     break;
1450   }
1451   case COM_STMT_CLOSE:
1452   {
1453     mysqld_stmt_close(thd, com_data->com_stmt_close.stmt_id);
1454     break;
1455   }
1456   case COM_STMT_RESET:
1457   {
1458     mysqld_stmt_reset(thd, com_data->com_stmt_reset.stmt_id);
1459     break;
1460   }
1461   case COM_QUERY:
1462   {
1463     assert(thd->m_digest == NULL);
1464     thd->m_digest= & thd->m_digest_state;
1465     thd->m_digest->reset(thd->m_token_array, max_digest_length);
1466 
1467     if (alloc_query(thd, com_data->com_query.query,
1468                     com_data->com_query.length))
1469       break;					// fatal error is set
1470     MYSQL_QUERY_START(const_cast<char*>(thd->query().str), thd->thread_id(),
1471                       (char *) (thd->db().str ? thd->db().str : ""),
1472                       (char *) thd->security_context()->priv_user().str,
1473                       (char *) thd->security_context()->host_or_ip().str);
1474 
1475     const char *packet_end= thd->query().str + thd->query().length;
1476 
1477     if (opt_general_log_raw)
1478       query_logger.general_log_write(thd, command, thd->query().str,
1479                                      thd->query().length);
1480 
1481     DBUG_PRINT("query",("%-.4096s", thd->query().str));
1482 
1483 #if defined(ENABLED_PROFILING)
1484     thd->profiling.set_query_source(thd->query().str, thd->query().length);
1485 #endif
1486 
1487     Parser_state parser_state;
1488     if (parser_state.init(thd, thd->query().str, thd->query().length))
1489       break;
1490 
1491     parser_state.m_input.m_has_digest = true;
1492 
1493     mysql_parse(thd, &parser_state);
1494 
1495     while (!thd->killed && (parser_state.m_lip.found_semicolon != NULL) &&
1496            ! thd->is_error())
1497     {
1498       /*
1499         Multiple queries exits, execute them individually
1500       */
1501       const char *beginning_of_next_stmt= parser_state.m_lip.found_semicolon;
1502 
1503       /* Finalize server status flags after executing a statement. */
1504       thd->update_server_status();
1505       thd->send_statement_status();
1506       query_cache.end_of_result(thd);
1507 
1508 #ifndef EMBEDDED_LIBRARY
1509       mysql_audit_notify(thd, AUDIT_EVENT(MYSQL_AUDIT_GENERAL_STATUS),
1510                          thd->get_stmt_da()->is_error() ?
1511                          thd->get_stmt_da()->mysql_errno() : 0,
1512                          command_name[command].str,
1513                          command_name[command].length);
1514 #endif
1515 
1516       size_t length= static_cast<size_t>(packet_end - beginning_of_next_stmt);
1517 
1518       log_slow_statement(thd);
1519 
1520       /* Remove garbage at start of query */
1521       while (length > 0 && my_isspace(thd->charset(), *beginning_of_next_stmt))
1522       {
1523         beginning_of_next_stmt++;
1524         length--;
1525       }
1526 
1527 /* PSI end */
1528       MYSQL_END_STATEMENT(thd->m_statement_psi, thd->get_stmt_da());
1529       thd->m_statement_psi= NULL;
1530       thd->m_digest= NULL;
1531 
1532 /* DTRACE end */
1533       if (MYSQL_QUERY_DONE_ENABLED())
1534       {
1535         MYSQL_QUERY_DONE(thd->is_error());
1536       }
1537 
1538 /* SHOW PROFILE end */
1539 #if defined(ENABLED_PROFILING)
1540       thd->profiling.finish_current_query();
1541 #endif
1542 
1543 /* SHOW PROFILE begin */
1544 #if defined(ENABLED_PROFILING)
1545       thd->profiling.start_new_query("continuing");
1546       thd->profiling.set_query_source(beginning_of_next_stmt, length);
1547 #endif
1548 
1549 /* DTRACE begin */
1550       MYSQL_QUERY_START(const_cast<char*>(beginning_of_next_stmt),
1551                         thd->thread_id(),
1552                         (char *) (thd->db().str ? thd->db().str : ""),
1553                         (char *) thd->security_context()->priv_user().str,
1554                         (char *) thd->security_context()->host_or_ip().str);
1555 
1556 /* PSI begin */
1557       thd->m_digest= & thd->m_digest_state;
1558       thd->m_digest->reset(thd->m_token_array, max_digest_length);
1559 
1560       thd->m_statement_psi= MYSQL_START_STATEMENT(&thd->m_statement_state,
1561                                           com_statement_info[command].m_key,
1562                                           thd->db().str, thd->db().length,
1563                                           thd->charset(), NULL);
1564       THD_STAGE_INFO(thd, stage_starting);
1565 
1566       thd->set_query(beginning_of_next_stmt, length);
1567       thd->set_query_id(next_query_id());
1568       /*
1569         Count each statement from the client.
1570       */
1571       thd->status_var.questions++;
1572       thd->set_time(); /* Reset the query start time. */
1573       parser_state.reset(beginning_of_next_stmt, length);
1574       /* TODO: set thd->lex->sql_command to SQLCOM_END here */
1575       mysql_parse(thd, &parser_state);
1576     }
1577 
1578     /* Need to set error to true for graceful shutdown */
1579     if((thd->lex->sql_command == SQLCOM_SHUTDOWN) && (thd->get_stmt_da()->is_ok()))
1580       error= TRUE;
1581 
1582     DBUG_PRINT("info",("query ready"));
1583     break;
1584   }
1585   case COM_FIELD_LIST:				// This isn't actually needed
1586   {
1587     char *fields;
1588     /* Locked closure of all tables */
1589     TABLE_LIST table_list;
1590     LEX_STRING table_name;
1591     LEX_STRING db;
1592     push_deprecated_warn(thd, "COM_FIELD_LIST",
1593                          "SHOW COLUMNS FROM statement");
1594     /*
1595       SHOW statements should not add the used tables to the list of tables
1596       used in a transaction.
1597     */
1598     MDL_savepoint mdl_savepoint= thd->mdl_context.mdl_savepoint();
1599 
1600     thd->status_var.com_stat[SQLCOM_SHOW_FIELDS]++;
1601     if (thd->copy_db_to(&db.str, &db.length))
1602       break;
1603     thd->convert_string(&table_name, system_charset_info,
1604                         (char *) com_data->com_field_list.table_name,
1605                         com_data->com_field_list.table_name_length,
1606                         thd->charset());
1607     enum_ident_name_check ident_check_status=
1608       check_table_name(table_name.str, table_name.length, FALSE);
1609     if (ident_check_status == IDENT_NAME_WRONG)
1610     {
1611       /* this is OK due to convert_string() null-terminating the string */
1612       my_error(ER_WRONG_TABLE_NAME, MYF(0), table_name.str);
1613       break;
1614     }
1615     else if (ident_check_status == IDENT_NAME_TOO_LONG)
1616     {
1617       my_error(ER_TOO_LONG_IDENT, MYF(0), table_name.str);
1618       break;
1619     }
1620     mysql_reset_thd_for_next_command(thd);
1621     lex_start(thd);
1622     /* Must be before we init the table list. */
1623     if (lower_case_table_names)
1624       table_name.length= my_casedn_str(files_charset_info, table_name.str);
1625     table_list.init_one_table(db.str, db.length, table_name.str,
1626                               table_name.length, table_name.str, TL_READ);
1627     /*
1628       Init TABLE_LIST members necessary when the undelrying
1629       table is view.
1630     */
1631     table_list.select_lex= thd->lex->select_lex;
1632     thd->lex->
1633       select_lex->table_list.link_in_list(&table_list,
1634                                          &table_list.next_local);
1635     thd->lex->add_to_query_tables(&table_list);
1636 
1637     if (is_infoschema_db(table_list.db, table_list.db_length))
1638     {
1639       ST_SCHEMA_TABLE *schema_table= find_schema_table(thd, table_list.alias);
1640       if (schema_table)
1641         table_list.schema_table= schema_table;
1642     }
1643 
1644     if (!(fields=
1645         (char *) thd->memdup(com_data->com_field_list.query,
1646                              com_data->com_field_list.query_length)))
1647       break;
1648     // Don't count end \0
1649     thd->set_query(fields, com_data->com_field_list.query_length - 1);
1650     query_logger.general_log_print(thd, command, "%s %s",
1651                                    table_list.table_name, fields);
1652 
1653     if (open_temporary_tables(thd, &table_list))
1654       break;
1655 
1656     if (check_table_access(thd, SELECT_ACL, &table_list,
1657                            TRUE, UINT_MAX, FALSE))
1658       break;
1659     /*
1660       Turn on an optimization relevant if the underlying table
1661       is a view: do not fill derived tables.
1662     */
1663     thd->lex->sql_command= SQLCOM_SHOW_FIELDS;
1664 
1665     // See comment in opt_trace_disable_if_no_security_context_access()
1666     Opt_trace_start ots(thd, &table_list, thd->lex->sql_command, NULL,
1667                         NULL, 0, NULL, NULL);
1668 
1669     mysqld_list_fields(thd,&table_list,fields);
1670 
1671     thd->lex->unit->cleanup(true);
1672     /* No need to rollback statement transaction, it's not started. */
1673     assert(thd->get_transaction()->is_empty(Transaction_ctx::STMT));
1674     close_thread_tables(thd);
1675     thd->mdl_context.rollback_to_savepoint(mdl_savepoint);
1676 
1677     if (thd->transaction_rollback_request)
1678     {
1679       /*
1680         Transaction rollback was requested since MDL deadlock was
1681         discovered while trying to open tables. Rollback transaction
1682         in all storage engines including binary log and release all
1683         locks.
1684       */
1685       trans_rollback_implicit(thd);
1686       thd->mdl_context.release_transactional_locks();
1687     }
1688 
1689     thd->cleanup_after_query();
1690     break;
1691   }
1692   case COM_QUIT:
1693     /* We don't calculate statistics for this command */
1694     query_logger.general_log_print(thd, command, NullS);
1695     // Don't give 'abort' message
1696     // TODO: access of protocol_classic should be removed
1697     if (thd->is_classic_protocol())
1698       thd->get_protocol_classic()->get_net()->error= 0;
1699     thd->get_stmt_da()->disable_status();       // Don't send anything back
1700     error=TRUE;					// End server
1701     break;
1702 #ifndef EMBEDDED_LIBRARY
1703   case COM_BINLOG_DUMP_GTID:
1704     // TODO: access of protocol_classic should be removed
1705     error=
1706       com_binlog_dump_gtid(thd,
1707         (char *)thd->get_protocol_classic()->get_raw_packet(),
1708         thd->get_protocol_classic()->get_packet_length());
1709     break;
1710   case COM_BINLOG_DUMP:
1711     // TODO: access of protocol_classic should be removed
1712     error=
1713       com_binlog_dump(thd,
1714         (char*)thd->get_protocol_classic()->get_raw_packet(),
1715         thd->get_protocol_classic()->get_packet_length());
1716     break;
1717 #endif
1718   case COM_REFRESH:
1719   {
1720     int not_used;
1721     push_deprecated_warn(thd, "COM_REFRESH", "FLUSH statement");
1722     /*
1723       Initialize thd->lex since it's used in many base functions, such as
1724       open_tables(). Otherwise, it remains uninitialized and may cause crash
1725       during execution of COM_REFRESH.
1726     */
1727     lex_start(thd);
1728 
1729     thd->status_var.com_stat[SQLCOM_FLUSH]++;
1730     ulong options= (ulong) com_data->com_refresh.options;
1731     if (trans_commit_implicit(thd))
1732       break;
1733     thd->mdl_context.release_transactional_locks();
1734     if (check_global_access(thd,RELOAD_ACL))
1735       break;
1736     query_logger.general_log_print(thd, command, NullS);
1737 #ifndef NDEBUG
1738     bool debug_simulate= FALSE;
1739     DBUG_EXECUTE_IF("simulate_detached_thread_refresh", debug_simulate= TRUE;);
1740     if (debug_simulate)
1741     {
1742       /*
1743         Simulate a reload without a attached thread session.
1744         Provides a environment similar to that of when the
1745         server receives a SIGHUP signal and reloads caches
1746         and flushes tables.
1747       */
1748       bool res;
1749       my_thread_set_THR_THD(NULL);
1750       res= reload_acl_and_cache(NULL, options | REFRESH_FAST,
1751                                 NULL, &not_used);
1752       my_thread_set_THR_THD(thd);
1753       if (res)
1754         break;
1755     }
1756     else
1757 #endif
1758     if (reload_acl_and_cache(thd, options, (TABLE_LIST*) 0, &not_used))
1759       break;
1760     if (trans_commit_implicit(thd))
1761       break;
1762     close_thread_tables(thd);
1763     thd->mdl_context.release_transactional_locks();
1764     my_ok(thd);
1765     break;
1766   }
1767 #ifndef EMBEDDED_LIBRARY
1768   case COM_SHUTDOWN:
1769   {
1770     thd->status_var.com_other++;
1771     /*
1772       If the client is < 4.1.3, it is going to send us no argument; then
1773       packet_length is 0, packet[0] is the end 0 of the packet. Note that
1774       SHUTDOWN_DEFAULT is 0. If client is >= 4.1.3, the shutdown level is in
1775       packet[0].
1776     */
1777     enum mysql_enum_shutdown_level level;
1778     if (!thd->is_valid_time())
1779       level= SHUTDOWN_DEFAULT;
1780     else
1781       level= com_data->com_shutdown.level;
1782     if(!shutdown(thd, level, command))
1783       break;
1784     error= TRUE;
1785     break;
1786   }
1787 #endif
1788   case COM_STATISTICS:
1789   {
1790     STATUS_VAR current_global_status_var;
1791     ulong uptime;
1792     size_t length MY_ATTRIBUTE((unused));
1793     ulonglong queries_per_second1000;
1794     char buff[250];
1795     size_t buff_len= sizeof(buff);
1796 
1797     query_logger.general_log_print(thd, command, NullS);
1798     thd->status_var.com_stat[SQLCOM_SHOW_STATUS]++;
1799     mysql_mutex_lock(&LOCK_status);
1800     calc_sum_of_all_status(&current_global_status_var);
1801     mysql_mutex_unlock(&LOCK_status);
1802     if (!(uptime= (ulong) (thd->start_time.tv_sec - server_start_time)))
1803       queries_per_second1000= 0;
1804     else
1805       queries_per_second1000= thd->query_id * 1000LL / uptime;
1806 
1807     length= my_snprintf(buff, buff_len - 1,
1808                         "Uptime: %lu  Threads: %d  Questions: %lu  "
1809                         "Slow queries: %llu  Opens: %llu  Flush tables: %lu  "
1810                         "Open tables: %u  Queries per second avg: %u.%03u",
1811                         uptime,
1812                         (int) thd_manager->get_thd_count(), (ulong) thd->query_id,
1813                         current_global_status_var.long_query_count,
1814                         current_global_status_var.opened_tables,
1815                         refresh_version,
1816                         table_cache_manager.cached_tables(),
1817                         (uint) (queries_per_second1000 / 1000),
1818                         (uint) (queries_per_second1000 % 1000));
1819 #ifdef EMBEDDED_LIBRARY
1820     /* Store the buffer in permanent memory */
1821     my_ok(thd, 0, 0, buff);
1822 #else
1823     // TODO: access of protocol_classic should be removed.
1824     // should be rewritten using store functions
1825     thd->get_protocol_classic()->write((uchar*) buff, length);
1826     thd->get_protocol_classic()->flush_net();
1827     thd->get_stmt_da()->disable_status();
1828 #endif
1829     break;
1830   }
1831   case COM_PING:
1832     thd->status_var.com_other++;
1833     my_ok(thd);				// Tell client we are alive
1834     break;
1835   case COM_PROCESS_INFO:
1836     thd->status_var.com_stat[SQLCOM_SHOW_PROCESSLIST]++;
1837     push_deprecated_warn(thd, "COM_PROCESS_INFO",
1838                          "SHOW PROCESSLIST statement");
1839     if (!thd->security_context()->priv_user().str[0] &&
1840         check_global_access(thd, PROCESS_ACL))
1841       break;
1842     query_logger.general_log_print(thd, command, NullS);
1843     mysqld_list_processes(
1844       thd,
1845       thd->security_context()->check_access(PROCESS_ACL) ?
1846       NullS : thd->security_context()->priv_user().str, 0);
1847     break;
1848   case COM_PROCESS_KILL:
1849   {
1850     push_deprecated_warn(thd, "COM_PROCESS_KILL",
1851                          "KILL CONNECTION/QUERY statement");
1852     if (thd_manager->get_thread_id() & (~0xfffffffful))
1853       my_error(ER_DATA_OUT_OF_RANGE, MYF(0), "thread_id", "mysql_kill()");
1854     else
1855     {
1856     thd->status_var.com_stat[SQLCOM_KILL]++;
1857       sql_kill(thd, com_data->com_kill.id, false);
1858     }
1859     break;
1860   }
1861   case COM_SET_OPTION:
1862   {
1863     thd->status_var.com_stat[SQLCOM_SET_OPTION]++;
1864 
1865     switch (com_data->com_set_option.opt_command) {
1866     case (int) MYSQL_OPTION_MULTI_STATEMENTS_ON:
1867       //TODO: access of protocol_classic should be removed
1868       thd->get_protocol_classic()->add_client_capability(
1869           CLIENT_MULTI_STATEMENTS);
1870       my_eof(thd);
1871       break;
1872     case (int) MYSQL_OPTION_MULTI_STATEMENTS_OFF:
1873       thd->get_protocol_classic()->remove_client_capability(
1874         CLIENT_MULTI_STATEMENTS);
1875       my_eof(thd);
1876       break;
1877     default:
1878       my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
1879       break;
1880     }
1881     break;
1882   }
1883   case COM_DEBUG:
1884     thd->status_var.com_other++;
1885     if (check_global_access(thd, SUPER_ACL))
1886       break;					/* purecov: inspected */
1887     mysql_print_status();
1888     query_logger.general_log_print(thd, command, NullS);
1889     my_eof(thd);
1890     break;
1891   case COM_SLEEP:
1892   case COM_CONNECT:				// Impossible here
1893   case COM_TIME:				// Impossible from client
1894   case COM_DELAYED_INSERT: // INSERT DELAYED has been removed.
1895   case COM_END:
1896   default:
1897     my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
1898     break;
1899   }
1900 
1901 done:
1902   assert(thd->derived_tables == NULL &&
1903          (thd->open_tables == NULL ||
1904           (thd->locked_tables_mode == LTM_LOCK_TABLES)));
1905 
1906   /* Finalize server status flags after executing a command. */
1907   thd->update_server_status();
1908   if (thd->killed)
1909     thd->send_kill_message();
1910   thd->send_statement_status();
1911   thd->rpl_thd_ctx.session_gtids_ctx().notify_after_response_packet(thd);
1912   query_cache.end_of_result(thd);
1913 
1914 #ifndef EMBEDDED_LIBRARY
1915   if (!thd->is_error() && !thd->killed_errno())
1916     mysql_audit_notify(thd,
1917                        AUDIT_EVENT(MYSQL_AUDIT_GENERAL_RESULT), 0, NULL, 0);
1918 
1919   mysql_audit_notify(thd, AUDIT_EVENT(MYSQL_AUDIT_GENERAL_STATUS),
1920                      thd->get_stmt_da()->is_error() ?
1921                      thd->get_stmt_da()->mysql_errno() : 0,
1922                      command_name[command].str,
1923                      command_name[command].length);
1924 
1925   /* command_end is informational only. The plugin cannot abort
1926      execution of the command at thie point. */
1927   mysql_audit_notify(thd, AUDIT_EVENT(MYSQL_AUDIT_COMMAND_END), command,
1928                      command_name[command].str);
1929 #endif
1930 
1931   log_slow_statement(thd);
1932 
1933   THD_STAGE_INFO(thd, stage_cleaning_up);
1934 
1935   thd->reset_query();
1936   thd->set_command(COM_SLEEP);
1937   thd->proc_info= 0;
1938   thd->lex->sql_command= SQLCOM_END;
1939 
1940   /* Performance Schema Interface instrumentation, end */
1941   MYSQL_END_STATEMENT(thd->m_statement_psi, thd->get_stmt_da());
1942   thd->m_statement_psi= NULL;
1943   thd->m_digest= NULL;
1944   thd->reset_query_for_display();
1945 
1946   /* Prevent rewritten query from getting "stuck" in SHOW PROCESSLIST. */
1947   thd->reset_rewritten_query();
1948 
1949   thd_manager->dec_thread_running();
1950   free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC));
1951 
1952   /* DTRACE instrumentation, end */
1953   if (MYSQL_QUERY_DONE_ENABLED() && command == COM_QUERY)
1954   {
1955     MYSQL_QUERY_DONE(thd->is_error());
1956   }
1957   if (MYSQL_COMMAND_DONE_ENABLED())
1958   {
1959     MYSQL_COMMAND_DONE(thd->is_error());
1960   }
1961 
1962   /* SHOW PROFILE instrumentation, end */
1963 #if defined(ENABLED_PROFILING)
1964   thd->profiling.finish_current_query();
1965 #endif
1966 
1967   DBUG_RETURN(error);
1968 }
1969 
1970 /**
1971   Shutdown the mysqld server.
1972 
1973   @param  thd        Thread (session) context.
1974   @param  level      Shutdown level.
1975   @param command     type of command to perform
1976 
1977   @retval
1978     true                 success
1979   @retval
1980     false                When user has insufficient privilege or unsupported shutdown level
1981 
1982 */
1983 #ifndef EMBEDDED_LIBRARY
shutdown(THD * thd,enum mysql_enum_shutdown_level level,enum enum_server_command command)1984 bool shutdown(THD *thd, enum mysql_enum_shutdown_level level, enum enum_server_command command)
1985 {
1986   DBUG_ENTER("shutdown");
1987   bool res= FALSE;
1988   thd->lex->no_write_to_binlog= 1;
1989 
1990   if (check_global_access(thd,SHUTDOWN_ACL))
1991     goto error; /* purecov: inspected */
1992 
1993   if (level == SHUTDOWN_DEFAULT)
1994     level= SHUTDOWN_WAIT_ALL_BUFFERS; // soon default will be configurable
1995   else if (level != SHUTDOWN_WAIT_ALL_BUFFERS)
1996   {
1997     my_error(ER_NOT_SUPPORTED_YET, MYF(0), "this shutdown level");
1998     goto error;;
1999   }
2000 
2001   if(command == COM_SHUTDOWN)
2002     my_eof(thd);
2003   else if(command == COM_QUERY)
2004     my_ok(thd);
2005   else
2006   {
2007     my_error(ER_NOT_SUPPORTED_YET, MYF(0), "shutdown from this server command");
2008     goto error;
2009   }
2010 
2011   DBUG_PRINT("quit",("Got shutdown command for level %u", level));
2012   query_logger.general_log_print(thd, command, NullS);
2013   kill_mysql();
2014   res= TRUE;
2015 
2016   error:
2017   DBUG_RETURN(res);
2018 }
2019 #endif
2020 
2021 /**
2022   Create a TABLE_LIST object for an INFORMATION_SCHEMA table.
2023 
2024     This function is used in the parser to convert a SHOW or DESCRIBE
2025     table_name command to a SELECT from INFORMATION_SCHEMA.
2026     It prepares a SELECT_LEX and a TABLE_LIST object to represent the
2027     given command as a SELECT parse tree.
2028 
2029   @param thd              thread handle
2030   @param lex              current lex
2031   @param table_ident      table alias if it's used
2032   @param schema_table_idx the type of the INFORMATION_SCHEMA table to be
2033                           created
2034 
2035   @note
2036     Due to the way this function works with memory and LEX it cannot
2037     be used outside the parser (parse tree transformations outside
2038     the parser break PS and SP).
2039 
2040   @retval
2041     0                 success
2042   @retval
2043     1                 out of memory or SHOW commands are not allowed
2044                       in this version of the server.
2045 */
2046 
prepare_schema_table(THD * thd,LEX * lex,Table_ident * table_ident,enum enum_schema_tables schema_table_idx)2047 int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
2048                          enum enum_schema_tables schema_table_idx)
2049 {
2050   SELECT_LEX *schema_select_lex= NULL;
2051   DBUG_ENTER("prepare_schema_table");
2052 
2053   switch (schema_table_idx) {
2054   case SCH_SCHEMATA:
2055     break;
2056 
2057   case SCH_TABLE_NAMES:
2058   case SCH_TABLES:
2059   case SCH_VIEWS:
2060   case SCH_TRIGGERS:
2061   case SCH_EVENTS:
2062     {
2063       LEX_STRING db;
2064       size_t dummy;
2065       if (lex->select_lex->db == NULL &&
2066           lex->copy_db_to(&lex->select_lex->db, &dummy))
2067         DBUG_RETURN(1);
2068       if ((schema_select_lex= lex->new_empty_query_block()) == NULL)
2069         DBUG_RETURN(1);      /* purecov: inspected */
2070       db.str= schema_select_lex->db= lex->select_lex->db;
2071       schema_select_lex->table_list.first= NULL;
2072       db.length= strlen(db.str);
2073 
2074       if (check_and_convert_db_name(&db, FALSE) != IDENT_NAME_OK)
2075         DBUG_RETURN(1);
2076       break;
2077     }
2078   case SCH_COLUMNS:
2079   case SCH_STATISTICS:
2080   {
2081     assert(table_ident);
2082     TABLE_LIST **query_tables_last= lex->query_tables_last;
2083     if ((schema_select_lex= lex->new_empty_query_block()) == NULL)
2084       DBUG_RETURN(1);        /* purecov: inspected */
2085     if (!schema_select_lex->add_table_to_list(thd, table_ident, 0, 0, TL_READ,
2086                                               MDL_SHARED_READ))
2087       DBUG_RETURN(1);
2088     lex->query_tables_last= query_tables_last;
2089     break;
2090   }
2091   case SCH_PROFILES:
2092     /*
2093       Mark this current profiling record to be discarded.  We don't
2094       wish to have SHOW commands show up in profiling.
2095     */
2096 #if defined(ENABLED_PROFILING)
2097     thd->profiling.discard_current_query();
2098 #endif
2099     break;
2100   case SCH_OPTIMIZER_TRACE:
2101   case SCH_OPEN_TABLES:
2102   case SCH_VARIABLES:
2103   case SCH_STATUS:
2104   case SCH_PROCEDURES:
2105   case SCH_CHARSETS:
2106   case SCH_ENGINES:
2107   case SCH_COLLATIONS:
2108   case SCH_COLLATION_CHARACTER_SET_APPLICABILITY:
2109   case SCH_USER_PRIVILEGES:
2110   case SCH_SCHEMA_PRIVILEGES:
2111   case SCH_TABLE_PRIVILEGES:
2112   case SCH_COLUMN_PRIVILEGES:
2113   case SCH_TABLE_CONSTRAINTS:
2114   case SCH_KEY_COLUMN_USAGE:
2115   default:
2116     break;
2117   }
2118 
2119   SELECT_LEX *select_lex= lex->current_select();
2120   if (make_schema_select(thd, select_lex, schema_table_idx))
2121   {
2122     DBUG_RETURN(1);
2123   }
2124   TABLE_LIST *table_list= select_lex->table_list.first;
2125   table_list->schema_select_lex= schema_select_lex;
2126   table_list->schema_table_reformed= 1;
2127   DBUG_RETURN(0);
2128 }
2129 
2130 
2131 /**
2132   Read query from packet and store in thd->query.
2133   Used in COM_QUERY and COM_STMT_PREPARE.
2134 
2135     Sets the following THD variables:
2136   - query
2137   - query_length
2138 
2139   @retval
2140     FALSE ok
2141   @retval
2142     TRUE  error;  In this case thd->fatal_error is set
2143 */
2144 
alloc_query(THD * thd,const char * packet,size_t packet_length)2145 bool alloc_query(THD *thd, const char *packet, size_t packet_length)
2146 {
2147   /* Remove garbage at start and end of query */
2148   while (packet_length > 0 && my_isspace(thd->charset(), packet[0]))
2149   {
2150     packet++;
2151     packet_length--;
2152   }
2153   const char *pos= packet + packet_length;     // Point at end null
2154   while (packet_length > 0 &&
2155 	 (pos[-1] == ';' || my_isspace(thd->charset() ,pos[-1])))
2156   {
2157     pos--;
2158     packet_length--;
2159   }
2160 
2161   char *query= static_cast<char*>(thd->alloc(packet_length + 1));
2162   if (!query)
2163     return TRUE;
2164   memcpy(query, packet, packet_length);
2165   query[packet_length]= '\0';
2166 
2167   thd->set_query(query, packet_length);
2168 
2169   /* Reclaim some memory */
2170   if(thd->get_protocol()->type() == Protocol::PROTOCOL_TEXT ||
2171      thd->get_protocol()->type() == Protocol::PROTOCOL_BINARY)
2172 
2173   thd->convert_buffer.shrink(thd->variables.net_buffer_length);
2174 
2175   return FALSE;
2176 }
2177 
2178 static
sp_process_definer(THD * thd)2179 bool sp_process_definer(THD *thd)
2180 {
2181   DBUG_ENTER("sp_process_definer");
2182 
2183   LEX *lex= thd->lex;
2184 
2185   /*
2186     If the definer is not specified, this means that CREATE-statement missed
2187     DEFINER-clause. DEFINER-clause can be missed in two cases:
2188 
2189       - The user submitted a statement w/o the clause. This is a normal
2190         case, we should assign CURRENT_USER as definer.
2191 
2192       - Our slave received an updated from the master, that does not
2193         replicate definer for stored rountines. We should also assign
2194         CURRENT_USER as definer here, but also we should mark this routine
2195         as NON-SUID. This is essential for the sake of backward
2196         compatibility.
2197 
2198         The problem is the slave thread is running under "special" user (@),
2199         that actually does not exist. In the older versions we do not fail
2200         execution of a stored routine if its definer does not exist and
2201         continue the execution under the authorization of the invoker
2202         (BUG#13198). And now if we try to switch to slave-current-user (@),
2203         we will fail.
2204 
2205         Actually, this leads to the inconsistent state of master and
2206         slave (different definers, different SUID behaviour), but it seems,
2207         this is the best we can do.
2208   */
2209 
2210   if (!lex->definer)
2211   {
2212     Prepared_stmt_arena_holder ps_arena_holder(thd);
2213 
2214     lex->definer= create_default_definer(thd);
2215 
2216     /* Error has been already reported. */
2217     if (lex->definer == NULL)
2218       DBUG_RETURN(TRUE);
2219 
2220     if (thd->slave_thread && lex->sphead)
2221       lex->sphead->m_chistics->suid= SP_IS_NOT_SUID;
2222   }
2223   else
2224   {
2225     /*
2226       If the specified definer differs from the current user, we
2227       should check that the current user has SUPER privilege (in order
2228       to create a stored routine under another user one must have
2229       SUPER privilege).
2230     */
2231     if ((strcmp(lex->definer->user.str,
2232                 thd->security_context()->priv_user().str) ||
2233          my_strcasecmp(system_charset_info, lex->definer->host.str,
2234                        thd->security_context()->priv_host().str)) &&
2235         check_global_access(thd, SUPER_ACL))
2236     {
2237       my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER");
2238       DBUG_RETURN(TRUE);
2239     }
2240   }
2241 
2242   /* Check that the specified definer exists. Emit a warning if not. */
2243 
2244 #ifndef NO_EMBEDDED_ACCESS_CHECKS
2245   if (!is_acl_user(lex->definer->host.str, lex->definer->user.str))
2246   {
2247     push_warning_printf(thd,
2248                         Sql_condition::SL_NOTE,
2249                         ER_NO_SUCH_USER,
2250                         ER(ER_NO_SUCH_USER),
2251                         lex->definer->user.str,
2252                         lex->definer->host.str);
2253   }
2254 #endif /* NO_EMBEDDED_ACCESS_CHECKS */
2255 
2256   DBUG_RETURN(FALSE);
2257 }
2258 
2259 
2260 /**
2261   Auxiliary call that opens and locks tables for LOCK TABLES statement
2262   and initializes the list of locked tables.
2263 
2264   @param thd     Thread context.
2265   @param tables  List of tables to be locked.
2266 
2267   @return FALSE in case of success, TRUE in case of error.
2268 */
2269 
lock_tables_open_and_lock_tables(THD * thd,TABLE_LIST * tables)2270 static bool lock_tables_open_and_lock_tables(THD *thd, TABLE_LIST *tables)
2271 {
2272   Lock_tables_prelocking_strategy lock_tables_prelocking_strategy;
2273   MDL_deadlock_and_lock_abort_error_handler deadlock_handler;
2274   MDL_savepoint mdl_savepoint= thd->mdl_context.mdl_savepoint();
2275   uint counter;
2276   TABLE_LIST *table;
2277 
2278   thd->in_lock_tables= 1;
2279 
2280 retry:
2281 
2282   if (open_tables(thd, &tables, &counter, 0, &lock_tables_prelocking_strategy))
2283     goto err;
2284 
2285   deadlock_handler.init();
2286   thd->push_internal_handler(&deadlock_handler);
2287 
2288   for (table= tables; table; table= table->next_global)
2289   {
2290     if (!table->is_placeholder())
2291     {
2292       if (table->table->s->tmp_table)
2293       {
2294         /*
2295           We allow to change temporary tables even if they were locked for read
2296           by LOCK TABLES. To avoid a discrepancy between lock acquired at LOCK
2297           TABLES time and by the statement which is later executed under LOCK
2298           TABLES we ensure that for temporary tables we always request a write
2299           lock (such discrepancy can cause problems for the storage engine).
2300           We don't set TABLE_LIST::lock_type in this case as this might result
2301           in extra warnings from THD::decide_logging_format() even though
2302           binary logging is totally irrelevant for LOCK TABLES.
2303         */
2304         table->table->reginfo.lock_type= TL_WRITE;
2305       }
2306       else if (table->lock_type == TL_READ &&
2307                ! table->prelocking_placeholder &&
2308                table->table->file->ha_table_flags() & HA_NO_READ_LOCAL_LOCK)
2309       {
2310         /*
2311           In case when LOCK TABLE ... READ LOCAL was issued for table with
2312           storage engine which doesn't support READ LOCAL option and doesn't
2313           use THR_LOCK locks we need to upgrade weak SR metadata lock acquired
2314           in open_tables() to stronger SRO metadata lock.
2315           This is not needed for tables used through stored routines or
2316           triggers as we always acquire SRO (or even stronger SNRW) metadata
2317           lock for them.
2318         */
2319         bool result= thd->mdl_context.upgrade_shared_lock(
2320                                         table->table->mdl_ticket,
2321                                         MDL_SHARED_READ_ONLY,
2322                                         thd->variables.lock_wait_timeout);
2323 
2324         if (deadlock_handler.need_reopen())
2325         {
2326           /*
2327             Deadlock occurred during upgrade of metadata lock.
2328             Let us restart acquring and opening tables for LOCK TABLES.
2329           */
2330           thd->pop_internal_handler();
2331           close_tables_for_reopen(thd, &tables, mdl_savepoint);
2332           if (open_temporary_tables(thd, tables))
2333             goto err;
2334           goto retry;
2335         }
2336 
2337         if (result)
2338         {
2339           thd->pop_internal_handler();
2340           goto err;
2341         }
2342       }
2343     }
2344   }
2345 
2346   thd->pop_internal_handler();
2347 
2348   if (lock_tables(thd, tables, counter, 0) ||
2349       thd->locked_tables_list.init_locked_tables(thd))
2350     goto err;
2351 
2352   thd->in_lock_tables= 0;
2353 
2354   return FALSE;
2355 
2356 err:
2357   thd->in_lock_tables= 0;
2358 
2359   trans_rollback_stmt(thd);
2360   /*
2361     Need to end the current transaction, so the storage engine (InnoDB)
2362     can free its locks if LOCK TABLES locked some tables before finding
2363     that it can't lock a table in its list
2364   */
2365   trans_rollback(thd);
2366   /* Close tables and release metadata locks. */
2367   close_thread_tables(thd);
2368   assert(!thd->locked_tables_mode);
2369   thd->mdl_context.release_transactional_locks();
2370   return TRUE;
2371 }
2372 
2373 
2374 /**
2375   This is a wrapper for MYSQL_BIN_LOG::gtid_end_transaction. For normal
2376   statements, the function gtid_end_transaction is called in the commit
2377   handler. However, if the statement is filtered out or not written to
2378   the binary log, the commit handler is not invoked. Therefore, this
2379   wrapper calls gtid_end_transaction in case the current statement is
2380   committing but was not written to the binary log.
2381   (The function gtid_end_transaction ensures that gtid-related
2382   end-of-transaction operations are performed; this includes
2383   generating an empty transaction and calling
2384   Gtid_state::update_gtids_impl.)
2385 
2386   @param thd Thread (session) context.
2387 */
2388 
binlog_gtid_end_transaction(THD * thd)2389 static inline void binlog_gtid_end_transaction(THD *thd)
2390 {
2391   DBUG_ENTER("binlog_gtid_end_transaction");
2392 
2393   /*
2394     This performs end-of-transaction actions needed by GTIDs:
2395     in particular, it generates an empty transaction if
2396     needed (e.g., if the statement was filtered out).
2397 
2398     It is executed at the end of an implicitly or explicitly
2399     committing statement.
2400 
2401     In addition, it is executed after CREATE TEMPORARY TABLE
2402     or DROP TEMPORARY TABLE when they occur outside
2403     transactional context.  When enforce_gtid_consistency is
2404     enabled, these statements cannot occur in transactional
2405     context, and then they behave exactly as implicitly
2406     committing: they are written to the binary log
2407     immediately, not wrapped in BEGIN/COMMIT, and cannot be
2408     rolled back. However, they do not count as implicitly
2409     committing according to stmt_causes_implicit_commit(), so
2410     we need to add special cases in the condition below. Hence
2411     the clauses for SQLCOM_CREATE_TABLE and SQLCOM_DROP_TABLE.
2412 
2413     If enforce_gtid_consistency=off, CREATE TEMPORARY TABLE
2414     and DROP TEMPORARY TABLE can occur in the middle of a
2415     transaction.  Then they do not behave as DDL; they are
2416     written to the binary log inside BEGIN/COMMIT.
2417 
2418     (For base tables, SQLCOM_[CREATE|DROP]_TABLE match both
2419     the stmt_causes_implicit_commit(...) clause and the
2420     thd->lex->sql_command == SQLCOM_* clause; for temporary
2421     tables they match only thd->lex->sql_command == SQLCOM_*.)
2422   */
2423   if ((thd->lex->sql_command == SQLCOM_COMMIT ||
2424        (thd->slave_thread &&
2425         (thd->lex->sql_command == SQLCOM_XA_COMMIT ||
2426          thd->lex->sql_command == SQLCOM_XA_ROLLBACK)) ||
2427        stmt_causes_implicit_commit(thd, CF_IMPLICIT_COMMIT_END) ||
2428        ((thd->lex->sql_command == SQLCOM_CREATE_TABLE ||
2429          thd->lex->sql_command == SQLCOM_DROP_TABLE) &&
2430         !thd->in_multi_stmt_transaction_mode())))
2431     (void) mysql_bin_log.gtid_end_transaction(thd);
2432 
2433   DBUG_VOID_RETURN;
2434 }
2435 
2436 
2437 /**
2438   Execute command saved in thd and lex->sql_command.
2439 
2440   @param thd                       Thread handle
2441 
2442   @todo
2443     - Invalidate the table in the query cache if something changed
2444     after unlocking when changes become visible.
2445     @todo: this is workaround. right way will be move invalidating in
2446     the unlock procedure.
2447     - TODO: use check_change_password()
2448 
2449   @retval
2450     FALSE       OK
2451   @retval
2452     TRUE        Error
2453 */
2454 
2455 int
mysql_execute_command(THD * thd,bool first_level)2456 mysql_execute_command(THD *thd, bool first_level)
2457 {
2458   int res= FALSE;
2459   LEX  *const lex= thd->lex;
2460   /* first SELECT_LEX (have special meaning for many of non-SELECTcommands) */
2461   SELECT_LEX *const select_lex= lex->select_lex;
2462   /* first table of first SELECT_LEX */
2463   TABLE_LIST *const first_table= select_lex->get_table_list();
2464   /* list of all tables in query */
2465   TABLE_LIST *all_tables;
2466   /* most outer SELECT_LEX_UNIT of query */
2467   SELECT_LEX_UNIT *const unit= lex->unit;
2468   // keep GTID violation state in order to roll it back on statement failure
2469   bool gtid_consistency_violation_state = thd->has_gtid_consistency_violation;
2470   assert(select_lex->master_unit() == unit);
2471   DBUG_ENTER("mysql_execute_command");
2472   /* EXPLAIN OTHER isn't explainable command, but can have describe flag. */
2473   assert(!lex->describe || is_explainable_query(lex->sql_command) ||
2474          lex->sql_command == SQLCOM_EXPLAIN_OTHER);
2475 
2476   thd->work_part_info= 0;
2477 
2478   assert(thd->get_transaction()->is_empty(Transaction_ctx::STMT) ||
2479          thd->in_sub_stmt);
2480   /*
2481     Each statement or replication event which might produce deadlock
2482     should handle transaction rollback on its own. So by the start of
2483     the next statement transaction rollback request should be fulfilled
2484     already.
2485   */
2486   assert(! thd->transaction_rollback_request || thd->in_sub_stmt);
2487   /*
2488     In many cases first table of main SELECT_LEX have special meaning =>
2489     check that it is first table in global list and relink it first in
2490     queries_tables list if it is necessary (we need such relinking only
2491     for queries with subqueries in select list, in this case tables of
2492     subqueries will go to global list first)
2493 
2494     all_tables will differ from first_table only if most upper SELECT_LEX
2495     do not contain tables.
2496 
2497     Because of above in place where should be at least one table in most
2498     outer SELECT_LEX we have following check:
2499     assert(first_table == all_tables);
2500     assert(first_table == all_tables && first_table != 0);
2501   */
2502   lex->first_lists_tables_same();
2503   /* should be assigned after making first tables same */
2504   all_tables= lex->query_tables;
2505   /* set context for commands which do not use setup_tables */
2506   select_lex->context.resolve_in_table_list_only(select_lex->get_table_list());
2507 
2508   thd->get_stmt_da()->reset_diagnostics_area();
2509   if ((thd->lex->keep_diagnostics != DA_KEEP_PARSE_ERROR) &&
2510       (thd->lex->keep_diagnostics != DA_KEEP_DIAGNOSTICS))
2511   {
2512     /*
2513       No parse errors, and it's not a diagnostic statement:
2514       remove the sql conditions from the DA!
2515       For diagnostic statements we need to keep the conditions
2516       around so we can inspec them.
2517     */
2518     thd->get_stmt_da()->reset_condition_info(thd);
2519   }
2520 
2521 #ifdef HAVE_REPLICATION
2522   if (unlikely(thd->slave_thread))
2523   {
2524     if (!check_database_filters(thd,
2525                                 thd->db().str,
2526                                 lex->sql_command))
2527     {
2528       binlog_gtid_end_transaction(thd);
2529       DBUG_RETURN(0);
2530     }
2531 
2532     if (lex->sql_command == SQLCOM_DROP_TRIGGER)
2533     {
2534       /*
2535         When dropping a trigger, we need to load its table name
2536         before checking slave filter rules.
2537       */
2538       add_table_for_trigger(thd, lex->spname->m_db,
2539                             lex->spname->m_name, true, &all_tables);
2540 
2541       if (!all_tables)
2542       {
2543         /*
2544           If table name cannot be loaded,
2545           it means the trigger does not exists possibly because
2546           CREATE TRIGGER was previously skipped for this trigger
2547           according to slave filtering rules.
2548           Returning success without producing any errors in this case.
2549         */
2550         binlog_gtid_end_transaction(thd);
2551         DBUG_RETURN(0);
2552       }
2553 
2554       // force searching in slave.cc:tables_ok()
2555       all_tables->updating= 1;
2556     }
2557 
2558     /*
2559       For fix of BUG#37051, the master stores the table map for update
2560       in the Query_log_event, and the value is assigned to
2561       thd->variables.table_map_for_update before executing the update
2562       query.
2563 
2564       If thd->variables.table_map_for_update is set, then we are
2565       replicating from a new master, we can use this value to apply
2566       filter rules without opening all the tables. However If
2567       thd->variables.table_map_for_update is not set, then we are
2568       replicating from an old master, so we just skip this and
2569       continue with the old method. And of course, the bug would still
2570       exist for old masters.
2571     */
2572     if (lex->sql_command == SQLCOM_UPDATE_MULTI &&
2573         thd->table_map_for_update)
2574     {
2575       table_map table_map_for_update= thd->table_map_for_update;
2576       uint nr= 0;
2577       TABLE_LIST *table;
2578       for (table=all_tables; table; table=table->next_global, nr++)
2579       {
2580         if (table_map_for_update & ((table_map)1 << nr))
2581           table->updating= TRUE;
2582         else
2583           table->updating= FALSE;
2584       }
2585 
2586       if (all_tables_not_ok(thd, all_tables))
2587       {
2588         /* we warn the slave SQL thread */
2589         my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
2590         binlog_gtid_end_transaction(thd);
2591         DBUG_RETURN(0);
2592       }
2593 
2594       for (table=all_tables; table; table=table->next_global)
2595         table->updating= TRUE;
2596     }
2597 
2598     /*
2599       Check if statment should be skipped because of slave filtering
2600       rules
2601 
2602       Exceptions are:
2603       - UPDATE MULTI: For this statement, we want to check the filtering
2604         rules later in the code
2605       - SET: we always execute it (Not that many SET commands exists in
2606         the binary log anyway -- only 4.1 masters write SET statements,
2607 	in 5.0 there are no SET statements in the binary log)
2608       - DROP TEMPORARY TABLE IF EXISTS: we always execute it (otherwise we
2609         have stale files on slave caused by exclusion of one tmp table).
2610     */
2611     if (!(lex->sql_command == SQLCOM_UPDATE_MULTI) &&
2612 	!(lex->sql_command == SQLCOM_SET_OPTION) &&
2613 	!(lex->sql_command == SQLCOM_DROP_TABLE &&
2614           lex->drop_temporary && lex->drop_if_exists) &&
2615         all_tables_not_ok(thd, all_tables))
2616     {
2617       /* we warn the slave SQL thread */
2618       my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
2619       binlog_gtid_end_transaction(thd);
2620       DBUG_RETURN(0);
2621     }
2622     /*
2623        Execute deferred events first
2624     */
2625     if (slave_execute_deferred_events(thd))
2626       DBUG_RETURN(-1);
2627   }
2628   else
2629   {
2630 #endif /* HAVE_REPLICATION */
2631     /*
2632       When option readonly is set deny operations which change non-temporary
2633       tables. Except for the replication thread and the 'super' users.
2634     */
2635     if (deny_updates_if_read_only_option(thd, all_tables))
2636     {
2637       err_readonly(thd);
2638       DBUG_RETURN(-1);
2639     }
2640 #ifdef HAVE_REPLICATION
2641   } /* endif unlikely slave */
2642 #endif
2643 
2644   thd->status_var.com_stat[lex->sql_command]++;
2645 
2646   Opt_trace_start ots(thd, all_tables, lex->sql_command, &lex->var_list,
2647                       thd->query().str, thd->query().length, NULL,
2648                       thd->variables.character_set_client);
2649 
2650   Opt_trace_object trace_command(&thd->opt_trace);
2651   Opt_trace_array trace_command_steps(&thd->opt_trace, "steps");
2652 
2653   assert(thd->get_transaction()->cannot_safely_rollback(
2654                                                         Transaction_ctx::STMT) == false);
2655 
2656   switch (gtid_pre_statement_checks(thd))
2657   {
2658   case GTID_STATEMENT_EXECUTE:
2659     break;
2660   case GTID_STATEMENT_CANCEL:
2661     DBUG_RETURN(-1);
2662   case GTID_STATEMENT_SKIP:
2663     my_ok(thd);
2664     binlog_gtid_end_transaction(thd);
2665     DBUG_RETURN(0);
2666   }
2667 
2668   /*
2669     End a active transaction so that this command will have it's
2670     own transaction and will also sync the binary log. If a DDL is
2671     not run in it's own transaction it may simply never appear on
2672     the slave in case the outside transaction rolls back.
2673   */
2674   if (stmt_causes_implicit_commit(thd, CF_IMPLICIT_COMMIT_BEGIN))
2675   {
2676     /*
2677       Note that this should never happen inside of stored functions
2678       or triggers as all such statements prohibited there.
2679     */
2680     assert(! thd->in_sub_stmt);
2681     /* Statement transaction still should not be started. */
2682     assert(thd->get_transaction()->is_empty(Transaction_ctx::STMT));
2683 
2684     /*
2685       Implicit commit is not allowed with an active XA transaction.
2686       In this case we should not release metadata locks as the XA transaction
2687       will not be rolled back. Therefore we simply return here.
2688     */
2689     if (trans_check_state(thd))
2690       DBUG_RETURN(-1);
2691 
2692     /* Commit the normal transaction if one is active. */
2693     if (trans_commit_implicit(thd))
2694       goto error;
2695     /* Release metadata locks acquired in this transaction. */
2696     thd->mdl_context.release_transactional_locks();
2697   }
2698 
2699   DEBUG_SYNC(thd, "after_implicit_pre_commit");
2700 
2701   if (gtid_pre_statement_post_implicit_commit_checks(thd))
2702     DBUG_RETURN(-1);
2703 
2704 #ifndef EMBEDDED_LIBRARY
2705   if (mysql_audit_notify(thd, first_level ?
2706                               MYSQL_AUDIT_QUERY_START :
2707                               MYSQL_AUDIT_QUERY_NESTED_START,
2708                               first_level ?
2709                               "MYSQL_AUDIT_QUERY_START" :
2710                               "MYSQL_AUDIT_QUERY_NESTED_START"))
2711   {
2712     DBUG_RETURN(1);
2713   }
2714 #endif /* !EMBEDDED_LIBRARY */
2715 
2716 #ifndef NDEBUG
2717   if (lex->sql_command != SQLCOM_SET_OPTION)
2718     DEBUG_SYNC(thd,"before_execute_sql_command");
2719 #endif
2720 
2721   /*
2722     Check if we are in a read-only transaction and we're trying to
2723     execute a statement which should always be disallowed in such cases.
2724 
2725     Note that this check is done after any implicit commits.
2726   */
2727   if (thd->tx_read_only &&
2728       (sql_command_flags[lex->sql_command] & CF_DISALLOW_IN_RO_TRANS))
2729   {
2730     my_error(ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION, MYF(0));
2731     goto error;
2732   }
2733 
2734   /*
2735     Close tables open by HANDLERs before executing DDL statement
2736     which is going to affect those tables.
2737 
2738     This should happen before temporary tables are pre-opened as
2739     otherwise we will get errors about attempt to re-open tables
2740     if table to be changed is open through HANDLER.
2741 
2742     Note that even although this is done before any privilege
2743     checks there is no security problem here as closing open
2744     HANDLER doesn't require any privileges anyway.
2745   */
2746   if (sql_command_flags[lex->sql_command] & CF_HA_CLOSE)
2747     mysql_ha_rm_tables(thd, all_tables);
2748 
2749   /*
2750     Check that the command is allowed on the PROTOCOL_PLUGIN
2751   */
2752   if (thd->get_protocol()->type() == Protocol::PROTOCOL_PLUGIN &&
2753       !(sql_command_flags[lex->sql_command] & CF_ALLOW_PROTOCOL_PLUGIN))
2754   {
2755     my_error(ER_PLUGGABLE_PROTOCOL_COMMAND_NOT_SUPPORTED, MYF(0));
2756     goto error;
2757   }
2758 
2759   /*
2760     Pre-open temporary tables to simplify privilege checking
2761     for statements which need this.
2762   */
2763   if (sql_command_flags[lex->sql_command] & CF_PREOPEN_TMP_TABLES)
2764   {
2765     if (open_temporary_tables(thd, all_tables))
2766       goto error;
2767   }
2768 
2769   // Save original info for EXPLAIN FOR CONNECTION
2770   if (!thd->in_sub_stmt)
2771     thd->query_plan.set_query_plan(lex->sql_command, lex,
2772                                    !thd->stmt_arena->is_conventional());
2773 
2774   switch (lex->sql_command) {
2775 
2776   case SQLCOM_SHOW_STATUS:
2777   {
2778     system_status_var old_status_var= thd->status_var;
2779     thd->initial_status_var= &old_status_var;
2780 
2781     if (!(res= select_precheck(thd, lex, all_tables, first_table)))
2782       res= execute_sqlcom_select(thd, all_tables);
2783 
2784     /* Don't log SHOW STATUS commands to slow query log */
2785     thd->server_status&= ~(SERVER_QUERY_NO_INDEX_USED |
2786                            SERVER_QUERY_NO_GOOD_INDEX_USED);
2787     /*
2788       restore status variables, as we don't want 'show status' to cause
2789       changes
2790     */
2791     mysql_mutex_lock(&LOCK_status);
2792     add_diff_to_status(&global_status_var, &thd->status_var,
2793                        &old_status_var);
2794     thd->status_var= old_status_var;
2795     thd->initial_status_var= NULL;
2796     mysql_mutex_unlock(&LOCK_status);
2797     break;
2798   }
2799   case SQLCOM_SHOW_EVENTS:
2800 #ifdef EMBEDDED_LIBRARY
2801     my_error(ER_NOT_SUPPORTED_YET, MYF(0), "embedded server");
2802     break;
2803 #endif
2804   case SQLCOM_SHOW_STATUS_PROC:
2805   case SQLCOM_SHOW_STATUS_FUNC:
2806   case SQLCOM_SHOW_DATABASES:
2807   case SQLCOM_SHOW_TABLES:
2808   case SQLCOM_SHOW_TRIGGERS:
2809   case SQLCOM_SHOW_TABLE_STATUS:
2810   case SQLCOM_SHOW_OPEN_TABLES:
2811   case SQLCOM_SHOW_PLUGINS:
2812   case SQLCOM_SHOW_FIELDS:
2813   case SQLCOM_SHOW_KEYS:
2814   case SQLCOM_SHOW_VARIABLES:
2815   case SQLCOM_SHOW_CHARSETS:
2816   case SQLCOM_SHOW_COLLATIONS:
2817   case SQLCOM_SHOW_STORAGE_ENGINES:
2818   case SQLCOM_SHOW_PROFILE:
2819   case SQLCOM_SELECT:
2820   {
2821     DBUG_EXECUTE_IF("use_attachable_trx",
2822                     thd->begin_attachable_ro_transaction(););
2823 
2824     thd->clear_current_query_costs();
2825 
2826     res= select_precheck(thd, lex, all_tables, first_table);
2827 
2828     if (!res)
2829       res= execute_sqlcom_select(thd, all_tables);
2830 
2831     thd->save_current_query_costs();
2832 
2833     DBUG_EXECUTE_IF("use_attachable_trx",
2834                     thd->end_attachable_transaction(););
2835 
2836     break;
2837   }
2838 case SQLCOM_PREPARE:
2839   {
2840     mysql_sql_stmt_prepare(thd);
2841     break;
2842   }
2843   case SQLCOM_EXECUTE:
2844   {
2845     mysql_sql_stmt_execute(thd);
2846     break;
2847   }
2848   case SQLCOM_DEALLOCATE_PREPARE:
2849   {
2850     mysql_sql_stmt_close(thd);
2851     break;
2852   }
2853   case SQLCOM_DO:
2854     res= mysql_do(thd, lex);
2855     break;
2856 
2857   case SQLCOM_EMPTY_QUERY:
2858     my_ok(thd);
2859     break;
2860 
2861   case SQLCOM_HELP:
2862     res= mysqld_help(thd,lex->help_arg);
2863     break;
2864 
2865 #ifndef EMBEDDED_LIBRARY
2866   case SQLCOM_PURGE:
2867   {
2868     if (check_global_access(thd, SUPER_ACL))
2869       goto error;
2870     /* PURGE MASTER LOGS TO 'file' */
2871     res = purge_master_logs(thd, lex->to_log);
2872     break;
2873   }
2874   case SQLCOM_PURGE_BEFORE:
2875   {
2876     Item *it;
2877 
2878     if (check_global_access(thd, SUPER_ACL))
2879       goto error;
2880     /* PURGE MASTER LOGS BEFORE 'data' */
2881     it= lex->purge_value_list.head();
2882     if ((!it->fixed && it->fix_fields(lex->thd, &it)) ||
2883         it->check_cols(1))
2884     {
2885       my_error(ER_WRONG_ARGUMENTS, MYF(0), "PURGE LOGS BEFORE");
2886       goto error;
2887     }
2888     it= new Item_func_unix_timestamp(it);
2889     /*
2890       it is OK only emulate fix_fieds, because we need only
2891       value of constant
2892     */
2893     it->quick_fix_field();
2894     time_t purge_time= static_cast<time_t>(it->val_int());
2895     if (thd->is_error())
2896       goto error;
2897     res = purge_master_logs_before_date(thd, purge_time);
2898     break;
2899   }
2900 #endif
2901   case SQLCOM_SHOW_WARNS:
2902   {
2903     res= mysqld_show_warnings(thd, (ulong)
2904 			      ((1L << (uint) Sql_condition::SL_NOTE) |
2905 			       (1L << (uint) Sql_condition::SL_WARNING) |
2906 			       (1L << (uint) Sql_condition::SL_ERROR)
2907 			       ));
2908     break;
2909   }
2910   case SQLCOM_SHOW_ERRORS:
2911   {
2912     res= mysqld_show_warnings(thd, (ulong)
2913 			      (1L << (uint) Sql_condition::SL_ERROR));
2914     break;
2915   }
2916   case SQLCOM_SHOW_PROFILES:
2917   {
2918 #if defined(ENABLED_PROFILING)
2919     thd->profiling.discard_current_query();
2920     res= thd->profiling.show_profiles();
2921     if (res)
2922       goto error;
2923 #else
2924     my_error(ER_FEATURE_DISABLED, MYF(0), "SHOW PROFILES", "enable-profiling");
2925     goto error;
2926 #endif
2927     break;
2928   }
2929 
2930 #ifdef HAVE_REPLICATION
2931   case SQLCOM_SHOW_SLAVE_HOSTS:
2932   {
2933     if (check_global_access(thd, REPL_SLAVE_ACL))
2934       goto error;
2935     res= show_slave_hosts(thd);
2936     break;
2937   }
2938   case SQLCOM_SHOW_RELAYLOG_EVENTS:
2939   {
2940     if (check_global_access(thd, REPL_SLAVE_ACL))
2941       goto error;
2942     res = mysql_show_relaylog_events(thd);
2943     break;
2944   }
2945   case SQLCOM_SHOW_BINLOG_EVENTS:
2946   {
2947     if (check_global_access(thd, REPL_SLAVE_ACL))
2948       goto error;
2949     res = mysql_show_binlog_events(thd);
2950     break;
2951   }
2952 #endif
2953 
2954   case SQLCOM_ASSIGN_TO_KEYCACHE:
2955   {
2956     assert(first_table == all_tables && first_table != 0);
2957     if (check_access(thd, INDEX_ACL, first_table->db,
2958                      &first_table->grant.privilege,
2959                      &first_table->grant.m_internal,
2960                      0, 0))
2961       goto error;
2962     res= mysql_assign_to_keycache(thd, first_table, &lex->ident);
2963     break;
2964   }
2965   case SQLCOM_PRELOAD_KEYS:
2966   {
2967     assert(first_table == all_tables && first_table != 0);
2968     if (check_access(thd, INDEX_ACL, first_table->db,
2969                      &first_table->grant.privilege,
2970                      &first_table->grant.m_internal,
2971                      0, 0))
2972       goto error;
2973     res = mysql_preload_keys(thd, first_table);
2974     break;
2975   }
2976 #ifdef HAVE_REPLICATION
2977   case SQLCOM_CHANGE_MASTER:
2978   {
2979 
2980     if (check_global_access(thd, SUPER_ACL))
2981       goto error;
2982     res= change_master_cmd(thd);
2983     break;
2984   }
2985   case SQLCOM_SHOW_SLAVE_STAT:
2986   {
2987     /* Accept one of two privileges */
2988     if (check_global_access(thd, SUPER_ACL | REPL_CLIENT_ACL))
2989       goto error;
2990     res= show_slave_status_cmd(thd);
2991     break;
2992   }
2993   case SQLCOM_SHOW_MASTER_STAT:
2994   {
2995     /* Accept one of two privileges */
2996     if (check_global_access(thd, SUPER_ACL | REPL_CLIENT_ACL))
2997       goto error;
2998     res = show_master_status(thd);
2999     break;
3000   }
3001 
3002 #endif /* HAVE_REPLICATION */
3003   case SQLCOM_SHOW_ENGINE_STATUS:
3004     {
3005       if (check_global_access(thd, PROCESS_ACL))
3006         goto error;
3007       res = ha_show_status(thd, lex->create_info.db_type, HA_ENGINE_STATUS);
3008       break;
3009     }
3010   case SQLCOM_SHOW_ENGINE_MUTEX:
3011     {
3012       if (check_global_access(thd, PROCESS_ACL))
3013         goto error;
3014       res = ha_show_status(thd, lex->create_info.db_type, HA_ENGINE_MUTEX);
3015       break;
3016     }
3017   case SQLCOM_CREATE_TABLE:
3018   {
3019     assert(first_table == all_tables && first_table != 0);
3020     bool link_to_local;
3021     TABLE_LIST *create_table= first_table;
3022     TABLE_LIST *select_tables= lex->create_last_non_select_table->next_global;
3023 
3024     /*
3025       Code below (especially in mysql_create_table() and Query_result_create
3026       methods) may modify HA_CREATE_INFO structure in LEX, so we have to
3027       use a copy of this structure to make execution prepared statement-
3028       safe. A shallow copy is enough as this code won't modify any memory
3029       referenced from this structure.
3030     */
3031     HA_CREATE_INFO create_info(lex->create_info);
3032     /*
3033       We need to copy alter_info for the same reasons of re-execution
3034       safety, only in case of Alter_info we have to do (almost) a deep
3035       copy.
3036     */
3037     Alter_info alter_info(lex->alter_info, thd->mem_root);
3038     if (thd->is_fatal_error)
3039     {
3040       /* If out of memory when creating a copy of alter_info. */
3041       res= 1;
3042       goto end_with_restore_list;
3043     }
3044 
3045     if (((lex->create_info.used_fields & HA_CREATE_USED_DATADIR) != 0 ||
3046          (lex->create_info.used_fields & HA_CREATE_USED_INDEXDIR) != 0) &&
3047         check_access(thd, FILE_ACL, any_db, NULL, NULL, FALSE, FALSE))
3048     {
3049       res= 1;
3050       my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "FILE");
3051       goto end_with_restore_list;
3052     }
3053 
3054     if ((res= create_table_precheck(thd, select_tables, create_table)))
3055       goto end_with_restore_list;
3056 
3057     /* Might have been updated in create_table_precheck */
3058     create_info.alias= create_table->alias;
3059 
3060     /*
3061       Assign target tablespace name to enable locking in lock_table_names().
3062       Reject invalid names.
3063     */
3064     if (create_info.tablespace)
3065     {
3066       if (check_tablespace_name(create_info.tablespace) != IDENT_NAME_OK)
3067         goto end_with_restore_list;
3068 
3069       if (!thd->make_lex_string(&create_table->target_tablespace_name,
3070                                 create_info.tablespace,
3071                                 strlen(create_info.tablespace), false))
3072       {
3073         my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
3074         goto end_with_restore_list;
3075       }
3076     }
3077 
3078     // Reject invalid tablespace names specified for partitions.
3079     if (check_partition_tablespace_names(thd->lex->part_info))
3080       goto end_with_restore_list;
3081 
3082     /* Fix names if symlinked or relocated tables */
3083     if (append_file_to_dir(thd, &create_info.data_file_name,
3084 			   create_table->table_name) ||
3085 	append_file_to_dir(thd, &create_info.index_file_name,
3086 			   create_table->table_name))
3087       goto end_with_restore_list;
3088 
3089     /*
3090       If no engine type was given, work out the default now
3091       rather than at parse-time.
3092     */
3093     if (!(create_info.used_fields & HA_CREATE_USED_ENGINE))
3094       create_info.db_type= create_info.options & HA_LEX_CREATE_TMP_TABLE ?
3095               ha_default_temp_handlerton(thd) : ha_default_handlerton(thd);
3096     /*
3097       If we are using SET CHARSET without DEFAULT, add an implicit
3098       DEFAULT to not confuse old users. (This may change).
3099     */
3100     if ((create_info.used_fields &
3101 	 (HA_CREATE_USED_DEFAULT_CHARSET | HA_CREATE_USED_CHARSET)) ==
3102 	HA_CREATE_USED_CHARSET)
3103     {
3104       create_info.used_fields&= ~HA_CREATE_USED_CHARSET;
3105       create_info.used_fields|= HA_CREATE_USED_DEFAULT_CHARSET;
3106       create_info.default_table_charset= create_info.table_charset;
3107       create_info.table_charset= 0;
3108     }
3109 
3110     {
3111       partition_info *part_info= thd->lex->part_info;
3112       if (part_info != NULL && has_external_data_or_index_dir(*part_info) &&
3113           check_access(thd, FILE_ACL, any_db, NULL, NULL, FALSE, FALSE))
3114       {
3115         res= -1;
3116         goto end_with_restore_list;
3117       }
3118       if (part_info && !(part_info= thd->lex->part_info->get_clone(true)))
3119       {
3120         res= -1;
3121         goto end_with_restore_list;
3122       }
3123       thd->work_part_info= part_info;
3124     }
3125 
3126     if (select_lex->item_list.elements)		// With select
3127     {
3128       Query_result *result;
3129 
3130       /*
3131         CREATE TABLE...IGNORE/REPLACE SELECT... can be unsafe, unless
3132         ORDER BY PRIMARY KEY clause is used in SELECT statement. We therefore
3133         use row based logging if mixed or row based logging is available.
3134         TODO: Check if the order of the output of the select statement is
3135         deterministic. Waiting for BUG#42415
3136       */
3137       if(lex->is_ignore())
3138         lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_CREATE_IGNORE_SELECT);
3139 
3140       if(lex->duplicates == DUP_REPLACE)
3141         lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_CREATE_REPLACE_SELECT);
3142 
3143       /*
3144         If:
3145         a) we inside an SP and there was NAME_CONST substitution,
3146         b) binlogging is on (STMT mode),
3147         c) we log the SP as separate statements
3148         raise a warning, as it may cause problems
3149         (see 'NAME_CONST issues' in 'Binary Logging of Stored Programs')
3150        */
3151       if (thd->query_name_consts &&
3152           mysql_bin_log.is_open() &&
3153           thd->variables.binlog_format == BINLOG_FORMAT_STMT &&
3154           !mysql_bin_log.is_query_in_union(thd, thd->query_id))
3155       {
3156         List_iterator_fast<Item> it(select_lex->item_list);
3157         Item *item;
3158         uint splocal_refs= 0;
3159         /* Count SP local vars in the top-level SELECT list */
3160         while ((item= it++))
3161         {
3162           if (item->is_splocal())
3163             splocal_refs++;
3164         }
3165         /*
3166           If it differs from number of NAME_CONST substitution applied,
3167           we may have a SOME_FUNC(NAME_CONST()) in the SELECT list,
3168           that may cause a problem with binary log (see BUG#35383),
3169           raise a warning.
3170         */
3171         if (splocal_refs != thd->query_name_consts)
3172           push_warning(thd,
3173                        Sql_condition::SL_WARNING,
3174                        ER_UNKNOWN_ERROR,
3175 "Invoked routine ran a statement that may cause problems with "
3176 "binary log, see 'NAME_CONST issues' in 'Binary Logging of Stored Programs' "
3177 "section of the manual.");
3178       }
3179 
3180       unit->set_limit(select_lex);
3181 
3182       /*
3183         Disable non-empty MERGE tables with CREATE...SELECT. Too
3184         complicated. See Bug #26379. Empty MERGE tables are read-only
3185         and don't allow CREATE...SELECT anyway.
3186       */
3187       if (create_info.used_fields & HA_CREATE_USED_UNION)
3188       {
3189         my_error(ER_WRONG_OBJECT, MYF(0), create_table->db,
3190                  create_table->table_name, "BASE TABLE");
3191         res= 1;
3192         goto end_with_restore_list;
3193       }
3194 
3195       if (!(res= open_tables_for_query(thd, all_tables, 0)))
3196       {
3197         /* The table already exists */
3198         if (create_table->table || create_table->is_view())
3199         {
3200           if (create_info.options & HA_LEX_CREATE_IF_NOT_EXISTS)
3201           {
3202             push_warning_printf(thd, Sql_condition::SL_NOTE,
3203                                 ER_TABLE_EXISTS_ERROR,
3204                                 ER(ER_TABLE_EXISTS_ERROR),
3205                                 create_info.alias);
3206             my_ok(thd);
3207           }
3208           else
3209           {
3210             my_error(ER_TABLE_EXISTS_ERROR, MYF(0), create_info.alias);
3211             res= 1;
3212           }
3213           goto end_with_restore_list;
3214         }
3215 
3216         /*
3217           Remove target table from main select and name resolution
3218           context. This can't be done earlier as it will break view merging in
3219           statements like "CREATE TABLE IF NOT EXISTS existing_view SELECT".
3220         */
3221         lex->unlink_first_table(&link_to_local);
3222 
3223         /* Updating any other table is prohibited in CTS statement */
3224         for (TABLE_LIST *table= lex->query_tables; table;
3225              table= table->next_global)
3226           if (table->lock_type >= TL_WRITE_ALLOW_WRITE)
3227           {
3228             lex->link_first_table_back(create_table, link_to_local);
3229 
3230             res= 1;
3231             my_error(ER_CANT_UPDATE_TABLE_IN_CREATE_TABLE_SELECT, MYF(0),
3232                      table->table_name, create_info.alias);
3233             goto end_with_restore_list;
3234           }
3235 
3236         /*
3237           Query_result_create is currently not re-execution friendly and
3238           needs to be created for every execution of a PS/SP.
3239         */
3240         if ((result= new Query_result_create(create_table,
3241                                              &create_info,
3242                                              &alter_info,
3243                                              select_lex->item_list,
3244                                              lex->duplicates,
3245                                              select_tables)))
3246         {
3247           Ignore_error_handler ignore_handler;
3248           Strict_error_handler strict_handler;
3249           if (thd->lex->is_ignore())
3250             thd->push_internal_handler(&ignore_handler);
3251           else if (thd->is_strict_mode())
3252             thd->push_internal_handler(&strict_handler);
3253 
3254           /*
3255             CREATE from SELECT give its SELECT_LEX for SELECT,
3256             and item_list belong to SELECT
3257           */
3258           res= handle_query(thd, lex, result, SELECT_NO_UNLOCK, 0);
3259 
3260           if (thd->lex->is_ignore() || thd->is_strict_mode())
3261             thd->pop_internal_handler();
3262 
3263           delete result;
3264         }
3265 
3266         lex->link_first_table_back(create_table, link_to_local);
3267       }
3268     }
3269     else
3270     {
3271       Strict_error_handler strict_handler;
3272       /* Push Strict_error_handler */
3273       if (!thd->lex->is_ignore() && thd->is_strict_mode())
3274         thd->push_internal_handler(&strict_handler);
3275 
3276       Partition_in_shared_ts_error_handler partition_in_shared_ts_handler;
3277       thd->push_internal_handler(&partition_in_shared_ts_handler);
3278 
3279       /* regular create */
3280       if (create_info.options & HA_LEX_CREATE_TABLE_LIKE)
3281       {
3282         /* CREATE TABLE ... LIKE ... */
3283         res= mysql_create_like_table(thd, create_table, select_tables,
3284                                      &create_info);
3285       }
3286       else
3287       {
3288         /* Regular CREATE TABLE */
3289         res= mysql_create_table(thd, create_table,
3290                                 &create_info, &alter_info);
3291       }
3292 
3293       thd->pop_internal_handler();
3294 
3295       /* Pop Strict_error_handler */
3296       if (!thd->lex->is_ignore() && thd->is_strict_mode())
3297         thd->pop_internal_handler();
3298       if (!res)
3299       {
3300         /* in case of create temp tables if @@session_track_state_change is
3301            ON then send session state notification in OK packet */
3302         if(create_info.options & HA_LEX_CREATE_TMP_TABLE &&
3303            thd->session_tracker.get_tracker(SESSION_STATE_CHANGE_TRACKER)->is_enabled())
3304           thd->session_tracker.get_tracker(SESSION_STATE_CHANGE_TRACKER)->mark_as_changed(thd, NULL);
3305         my_ok(thd);
3306       }
3307     }
3308 
3309 end_with_restore_list:
3310     break;
3311   }
3312   case SQLCOM_CREATE_INDEX:
3313     /* Fall through */
3314   case SQLCOM_DROP_INDEX:
3315   /*
3316     CREATE INDEX and DROP INDEX are implemented by calling ALTER
3317     TABLE with proper arguments.
3318 
3319     In the future ALTER TABLE will notice that the request is to
3320     only add indexes and create these one by one for the existing
3321     table without having to do a full rebuild.
3322   */
3323   {
3324     /* Prepare stack copies to be re-execution safe */
3325     HA_CREATE_INFO create_info;
3326     Alter_info alter_info(lex->alter_info, thd->mem_root);
3327 
3328     if (thd->is_fatal_error) /* out of memory creating a copy of alter_info */
3329       goto error;
3330 
3331     assert(first_table == all_tables && first_table != 0);
3332     if (check_one_table_access(thd, INDEX_ACL, all_tables))
3333       goto error; /* purecov: inspected */
3334     /*
3335       Currently CREATE INDEX or DROP INDEX cause a full table rebuild
3336       and thus classify as slow administrative statements just like
3337       ALTER TABLE.
3338     */
3339     thd->enable_slow_log= opt_log_slow_admin_statements;
3340 
3341     create_info.db_type= 0;
3342     create_info.row_type= ROW_TYPE_NOT_USED;
3343     create_info.default_table_charset= thd->variables.collation_database;
3344 
3345     /* Push Strict_error_handler */
3346     Strict_error_handler strict_handler;
3347     if (thd->is_strict_mode())
3348       thd->push_internal_handler(&strict_handler);
3349     assert(!select_lex->order_list.elements);
3350     res= mysql_alter_table(thd, first_table->db, first_table->table_name,
3351                            &create_info, first_table, &alter_info);
3352     /* Pop Strict_error_handler */
3353     if (thd->is_strict_mode())
3354       thd->pop_internal_handler();
3355     break;
3356   }
3357 #ifdef HAVE_REPLICATION
3358   case SQLCOM_START_GROUP_REPLICATION:
3359   {
3360     if (check_global_access(thd, SUPER_ACL))
3361       goto error;
3362 
3363     /*
3364       If the client thread has locked tables, a deadlock is possible.
3365       Assume that
3366       - the client thread does LOCK TABLE t READ.
3367       - then the client thread does START GROUP_REPLICATION.
3368            -try to make the server in super ready only mode
3369            -acquire MDL lock ownership which will be waiting for
3370             LOCK on table t to be released.
3371       To prevent that, refuse START GROUP_REPLICATION if the
3372       client thread has locked tables
3373     */
3374     if (thd->locked_tables_mode ||
3375         thd->in_active_multi_stmt_transaction() || thd->in_sub_stmt)
3376     {
3377       my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
3378                  ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
3379       goto error;
3380     }
3381 
3382     res= group_replication_start();
3383 
3384     //To reduce server dependency, server errors are not used here
3385     switch (res)
3386     {
3387       case 1: //GROUP_REPLICATION_CONFIGURATION_ERROR
3388         my_message(ER_GROUP_REPLICATION_CONFIGURATION,
3389                    ER(ER_GROUP_REPLICATION_CONFIGURATION), MYF(0));
3390         goto error;
3391       case 2: //GROUP_REPLICATION_ALREADY_RUNNING
3392         my_message(ER_GROUP_REPLICATION_RUNNING,
3393                    ER(ER_GROUP_REPLICATION_RUNNING), MYF(0));
3394         goto error;
3395       case 3: //GROUP_REPLICATION_REPLICATION_APPLIER_INIT_ERROR
3396         my_message(ER_GROUP_REPLICATION_APPLIER_INIT_ERROR,
3397                    ER(ER_GROUP_REPLICATION_APPLIER_INIT_ERROR), MYF(0));
3398         goto error;
3399       case 4: //GROUP_REPLICATION_COMMUNICATION_LAYER_SESSION_ERROR
3400         my_message(ER_GROUP_REPLICATION_COMMUNICATION_LAYER_SESSION_ERROR,
3401                    ER(ER_GROUP_REPLICATION_COMMUNICATION_LAYER_SESSION_ERROR), MYF(0));
3402         goto error;
3403       case 5: //GROUP_REPLICATION_COMMUNICATION_LAYER_JOIN_ERROR
3404         my_message(ER_GROUP_REPLICATION_COMMUNICATION_LAYER_JOIN_ERROR,
3405                    ER(ER_GROUP_REPLICATION_COMMUNICATION_LAYER_JOIN_ERROR), MYF(0));
3406         goto error;
3407       case 7: //GROUP_REPLICATION_MAX_GROUP_SIZE
3408         my_message(ER_GROUP_REPLICATION_MAX_GROUP_SIZE,
3409                    ER(ER_GROUP_REPLICATION_MAX_GROUP_SIZE), MYF(0));
3410         goto error;
3411     }
3412     my_ok(thd);
3413     res= 0;
3414     break;
3415   }
3416 
3417   case SQLCOM_STOP_GROUP_REPLICATION:
3418   {
3419     if (check_global_access(thd, SUPER_ACL))
3420       goto error;
3421 
3422     /*
3423       Please see explanation @SQLCOM_SLAVE_STOP case
3424       to know the reason for thd->locked_tables_mode in
3425       the below if condition.
3426     */
3427     if (thd->locked_tables_mode ||
3428         thd->in_active_multi_stmt_transaction() || thd->in_sub_stmt)
3429     {
3430       my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
3431                  ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
3432       goto error;
3433     }
3434 
3435     res= group_replication_stop();
3436     if (res == 1) //GROUP_REPLICATION_CONFIGURATION_ERROR
3437     {
3438       my_message(ER_GROUP_REPLICATION_CONFIGURATION,
3439                  ER(ER_GROUP_REPLICATION_CONFIGURATION), MYF(0));
3440       goto error;
3441     }
3442     if (res == 6) //GROUP_REPLICATION_APPLIER_THREAD_TIMEOUT
3443     {
3444       my_message(ER_GROUP_REPLICATION_STOP_APPLIER_THREAD_TIMEOUT,
3445                  ER(ER_GROUP_REPLICATION_STOP_APPLIER_THREAD_TIMEOUT), MYF(0));
3446       goto error;
3447     }
3448     my_ok(thd);
3449     res= 0;
3450     break;
3451   }
3452 
3453   case SQLCOM_SLAVE_START:
3454   {
3455     res= start_slave_cmd(thd);
3456     break;
3457   }
3458   case SQLCOM_SLAVE_STOP:
3459   {
3460   /*
3461     If the client thread has locked tables, a deadlock is possible.
3462     Assume that
3463     - the client thread does LOCK TABLE t READ.
3464     - then the master updates t.
3465     - then the SQL slave thread wants to update t,
3466       so it waits for the client thread because t is locked by it.
3467     - then the client thread does SLAVE STOP.
3468       SLAVE STOP waits for the SQL slave thread to terminate its
3469       update t, which waits for the client thread because t is locked by it.
3470     To prevent that, refuse SLAVE STOP if the
3471     client thread has locked tables
3472   */
3473   if (thd->locked_tables_mode ||
3474       thd->in_active_multi_stmt_transaction() || thd->global_read_lock.is_acquired())
3475   {
3476     my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
3477                ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
3478     goto error;
3479   }
3480 
3481   res= stop_slave_cmd(thd);
3482   break;
3483   }
3484 #endif /* HAVE_REPLICATION */
3485 
3486   case SQLCOM_RENAME_TABLE:
3487   {
3488     assert(first_table == all_tables && first_table != 0);
3489     TABLE_LIST *table;
3490     for (table= first_table; table; table= table->next_local->next_local)
3491     {
3492       if (check_access(thd, ALTER_ACL | DROP_ACL, table->db,
3493                        &table->grant.privilege,
3494                        &table->grant.m_internal,
3495                        0, 0) ||
3496           check_access(thd, INSERT_ACL | CREATE_ACL, table->next_local->db,
3497                        &table->next_local->grant.privilege,
3498                        &table->next_local->grant.m_internal,
3499                        0, 0))
3500 	goto error;
3501       TABLE_LIST old_list, new_list;
3502       /*
3503         we do not need initialize old_list and new_list because we will
3504         come table[0] and table->next[0] there
3505       */
3506       old_list= table[0];
3507       new_list= table->next_local[0];
3508       if (check_grant(thd, ALTER_ACL | DROP_ACL, &old_list, FALSE, 1, FALSE) ||
3509          (!test_all_bits(table->next_local->grant.privilege,
3510                          INSERT_ACL | CREATE_ACL) &&
3511           check_grant(thd, INSERT_ACL | CREATE_ACL, &new_list, FALSE, 1,
3512                       FALSE)))
3513         goto error;
3514     }
3515 
3516     if (mysql_rename_tables(thd, first_table, 0))
3517       goto error;
3518     break;
3519   }
3520 #ifndef EMBEDDED_LIBRARY
3521   case SQLCOM_SHOW_BINLOGS:
3522     {
3523       if (check_global_access(thd, SUPER_ACL | REPL_CLIENT_ACL))
3524 	goto error;
3525       res = show_binlogs(thd);
3526       break;
3527     }
3528 #endif /* EMBEDDED_LIBRARY */
3529   case SQLCOM_SHOW_CREATE:
3530     assert(first_table == all_tables && first_table != 0);
3531     {
3532      /*
3533         Access check:
3534         SHOW CREATE TABLE require any privileges on the table level (ie
3535         effecting all columns in the table).
3536         SHOW CREATE VIEW require the SHOW_VIEW and SELECT ACLs on the table
3537         level.
3538         NOTE: SHOW_VIEW ACL is checked when the view is created.
3539       */
3540 
3541       DBUG_PRINT("debug", ("lex->only_view: %d, table: %s.%s",
3542                            lex->only_view,
3543                            first_table->db, first_table->table_name));
3544       if (lex->only_view)
3545       {
3546         if (check_table_access(thd, SELECT_ACL, first_table, FALSE, 1, FALSE))
3547         {
3548           DBUG_PRINT("debug", ("check_table_access failed"));
3549           my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0),
3550                    "SHOW", thd->security_context()->priv_user().str,
3551                    thd->security_context()->host_or_ip().str,
3552                    first_table->alias);
3553           goto error;
3554         }
3555         DBUG_PRINT("debug", ("check_table_access succeeded"));
3556 
3557         /* Ignore temporary tables if this is "SHOW CREATE VIEW" */
3558         first_table->open_type= OT_BASE_ONLY;
3559 
3560       }
3561       else
3562       {
3563         /*
3564           Temporary tables should be opened for SHOW CREATE TABLE, but not
3565           for SHOW CREATE VIEW.
3566         */
3567         if (open_temporary_tables(thd, all_tables))
3568           goto error;
3569 
3570         /*
3571           The fact that check_some_access() returned FALSE does not mean that
3572           access is granted. We need to check if first_table->grant.privilege
3573           contains any table-specific privilege.
3574         */
3575         DBUG_PRINT("debug", ("first_table->grant.privilege: %lx",
3576                              first_table->grant.privilege));
3577         if (check_some_access(thd, SHOW_CREATE_TABLE_ACLS, first_table) ||
3578             (first_table->grant.privilege & SHOW_CREATE_TABLE_ACLS) == 0)
3579         {
3580           my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0),
3581                    "SHOW", thd->security_context()->priv_user().str,
3582                    thd->security_context()->host_or_ip().str,
3583                    first_table->alias);
3584           goto error;
3585         }
3586       }
3587 
3588       /* Access is granted. Execute the command.  */
3589       res= mysqld_show_create(thd, first_table);
3590       break;
3591     }
3592   case SQLCOM_CHECKSUM:
3593   {
3594     assert(first_table == all_tables && first_table != 0);
3595     if (check_table_access(thd, SELECT_ACL, all_tables,
3596                            FALSE, UINT_MAX, FALSE))
3597       goto error; /* purecov: inspected */
3598 
3599     res = mysql_checksum_table(thd, first_table, &lex->check_opt);
3600     break;
3601   }
3602   case SQLCOM_REPLACE:
3603   case SQLCOM_INSERT:
3604   case SQLCOM_REPLACE_SELECT:
3605   case SQLCOM_INSERT_SELECT:
3606   {
3607     assert(first_table == all_tables && first_table != 0);
3608     assert(lex->m_sql_cmd != NULL);
3609     res= lex->m_sql_cmd->execute(thd);
3610     break;
3611   }
3612   case SQLCOM_DELETE:
3613   case SQLCOM_DELETE_MULTI:
3614   case SQLCOM_UPDATE:
3615   case SQLCOM_UPDATE_MULTI:
3616   {
3617     assert(first_table == all_tables && first_table != 0);
3618     assert(lex->m_sql_cmd != NULL);
3619     res= lex->m_sql_cmd->execute(thd);
3620     break;
3621   }
3622   case SQLCOM_DROP_TABLE:
3623   {
3624     assert(first_table == all_tables && first_table != 0);
3625     if (!lex->drop_temporary)
3626     {
3627       if (check_table_access(thd, DROP_ACL, all_tables, FALSE, UINT_MAX, FALSE))
3628 	goto error;				/* purecov: inspected */
3629     }
3630     /* DDL and binlog write order are protected by metadata locks. */
3631     res= mysql_rm_table(thd, first_table, lex->drop_if_exists,
3632 			lex->drop_temporary);
3633     /* when dropping temporary tables if @@session_track_state_change is ON then
3634        send the boolean tracker in the OK packet */
3635     if(!res && lex->drop_temporary)
3636     {
3637       if (thd->session_tracker.get_tracker(SESSION_STATE_CHANGE_TRACKER)->is_enabled())
3638         thd->session_tracker.get_tracker(SESSION_STATE_CHANGE_TRACKER)->mark_as_changed(thd, NULL);
3639     }
3640   }
3641   break;
3642   case SQLCOM_SHOW_PROCESSLIST:
3643     if (!thd->security_context()->priv_user().str[0] &&
3644         check_global_access(thd,PROCESS_ACL))
3645       break;
3646     mysqld_list_processes(
3647       thd,
3648       (thd->security_context()->check_access(PROCESS_ACL) ?
3649          NullS :
3650         thd->security_context()->priv_user().str),
3651       lex->verbose);
3652     break;
3653   case SQLCOM_SHOW_PRIVILEGES:
3654     res= mysqld_show_privileges(thd);
3655     break;
3656   case SQLCOM_SHOW_ENGINE_LOGS:
3657     {
3658       if (check_access(thd, FILE_ACL, any_db, NULL, NULL, 0, 0))
3659 	goto error;
3660       res= ha_show_status(thd, lex->create_info.db_type, HA_ENGINE_LOGS);
3661       break;
3662     }
3663   case SQLCOM_CHANGE_DB:
3664   {
3665     const LEX_CSTRING db_str= { select_lex->db,
3666                                 strlen(select_lex->db) };
3667 
3668     if (!mysql_change_db(thd, db_str, FALSE))
3669       my_ok(thd);
3670 
3671     break;
3672   }
3673 
3674   case SQLCOM_LOAD:
3675   {
3676     assert(first_table == all_tables && first_table != 0);
3677     uint privilege= (lex->duplicates == DUP_REPLACE ?
3678 		     INSERT_ACL | DELETE_ACL : INSERT_ACL) |
3679                     (lex->local_file ? 0 : FILE_ACL);
3680 
3681     if (lex->local_file)
3682     {
3683       if (!thd->get_protocol()->has_client_capability(CLIENT_LOCAL_FILES) ||
3684           !opt_local_infile)
3685       {
3686 	my_message(ER_NOT_ALLOWED_COMMAND, ER(ER_NOT_ALLOWED_COMMAND), MYF(0));
3687 	goto error;
3688       }
3689     }
3690 
3691     if (check_one_table_access(thd, privilege, all_tables))
3692       goto error;
3693 
3694     /* Push strict / ignore error handler */
3695     Ignore_error_handler ignore_handler;
3696     Strict_error_handler strict_handler;
3697     if (thd->lex->is_ignore())
3698       thd->push_internal_handler(&ignore_handler);
3699     else if (thd->is_strict_mode())
3700       thd->push_internal_handler(&strict_handler);
3701 
3702     res= mysql_load(thd, lex->exchange, first_table, lex->load_field_list,
3703                     lex->load_update_list, lex->load_value_list, lex->duplicates,
3704                     lex->local_file);
3705 
3706     /* Pop ignore / strict error handler */
3707     if (thd->lex->is_ignore() || thd->is_strict_mode())
3708       thd->pop_internal_handler();
3709 
3710     break;
3711   }
3712 
3713   case SQLCOM_SET_OPTION:
3714   {
3715     List<set_var_base> *lex_var_list= &lex->var_list;
3716 
3717     if ((check_table_access(thd, SELECT_ACL, all_tables, FALSE, UINT_MAX, FALSE)
3718          || open_and_lock_tables(thd, all_tables, 0)))
3719       goto error;
3720     if (!(res= sql_set_variables(thd, lex_var_list)))
3721       my_ok(thd);
3722     else
3723     {
3724       /*
3725         We encountered some sort of error, but no message was sent.
3726         Send something semi-generic here since we don't know which
3727         assignment in the list caused the error.
3728       */
3729       if (!thd->is_error())
3730         my_error(ER_WRONG_ARGUMENTS,MYF(0),"SET");
3731       goto error;
3732     }
3733 
3734     break;
3735   }
3736 
3737   case SQLCOM_UNLOCK_TABLES:
3738     /*
3739       It is critical for mysqldump --single-transaction --master-data that
3740       UNLOCK TABLES does not implicitely commit a connection which has only
3741       done FLUSH TABLES WITH READ LOCK + BEGIN. If this assumption becomes
3742       false, mysqldump will not work.
3743     */
3744     if (thd->variables.option_bits & OPTION_TABLE_LOCK)
3745     {
3746       /*
3747         Can we commit safely? If not, return to avoid releasing
3748         transactional metadata locks.
3749       */
3750       if (trans_check_state(thd))
3751         DBUG_RETURN(-1);
3752       res= trans_commit_implicit(thd);
3753       thd->locked_tables_list.unlock_locked_tables(thd);
3754       thd->mdl_context.release_transactional_locks();
3755       thd->variables.option_bits&= ~(OPTION_TABLE_LOCK);
3756     }
3757     if (thd->global_read_lock.is_acquired())
3758       thd->global_read_lock.unlock_global_read_lock(thd);
3759     if (res)
3760       goto error;
3761     my_ok(thd);
3762     break;
3763   case SQLCOM_LOCK_TABLES:
3764     /*
3765       Can we commit safely? If not, return to avoid releasing
3766       transactional metadata locks.
3767     */
3768     if (trans_check_state(thd))
3769       DBUG_RETURN(-1);
3770     /* We must end the transaction first, regardless of anything */
3771     res= trans_commit_implicit(thd);
3772     thd->locked_tables_list.unlock_locked_tables(thd);
3773     /* Release transactional metadata locks. */
3774     thd->mdl_context.release_transactional_locks();
3775     if (res)
3776       goto error;
3777 
3778     /*
3779       Here we have to pre-open temporary tables for LOCK TABLES.
3780 
3781       CF_PREOPEN_TMP_TABLES is not set for this SQL statement simply
3782       because LOCK TABLES calls close_thread_tables() as a first thing
3783       (it's called from unlock_locked_tables() above). So even if
3784       CF_PREOPEN_TMP_TABLES was set and the tables would be pre-opened
3785       in a usual way, they would have been closed.
3786     */
3787 
3788     if (open_temporary_tables(thd, all_tables))
3789       goto error;
3790 
3791     if (lock_tables_precheck(thd, all_tables))
3792       goto error;
3793 
3794     thd->variables.option_bits|= OPTION_TABLE_LOCK;
3795 
3796     res= lock_tables_open_and_lock_tables(thd, all_tables);
3797 
3798     if (res)
3799     {
3800       thd->variables.option_bits&= ~(OPTION_TABLE_LOCK);
3801     }
3802     else
3803     {
3804       if (thd->variables.query_cache_wlock_invalidate)
3805         query_cache.invalidate_locked_for_write(first_table);
3806       my_ok(thd);
3807     }
3808     break;
3809   case SQLCOM_CREATE_DB:
3810   {
3811     /*
3812       As mysql_create_db() may modify HA_CREATE_INFO structure passed to
3813       it, we need to use a copy of LEX::create_info to make execution
3814       prepared statement- safe.
3815     */
3816     HA_CREATE_INFO create_info(lex->create_info);
3817     char *alias;
3818     if (!(alias=thd->strmake(lex->name.str, lex->name.length)) ||
3819         (check_and_convert_db_name(&lex->name, FALSE) != IDENT_NAME_OK))
3820       break;
3821     if (check_access(thd, CREATE_ACL, lex->name.str, NULL, NULL, 1, 0))
3822       break;
3823     res= mysql_create_db(thd,(lower_case_table_names == 2 ? alias :
3824                               lex->name.str), &create_info, 0);
3825     break;
3826   }
3827   case SQLCOM_DROP_DB:
3828   {
3829     if (check_and_convert_db_name(&lex->name, FALSE) != IDENT_NAME_OK)
3830       break;
3831     if (check_access(thd, DROP_ACL, lex->name.str, NULL, NULL, 1, 0))
3832       break;
3833     res= mysql_rm_db(thd, to_lex_cstring(lex->name), lex->drop_if_exists, 0);
3834     break;
3835   }
3836   case SQLCOM_ALTER_DB_UPGRADE:
3837   {
3838     LEX_STRING *db= & lex->name;
3839     if (check_and_convert_db_name(db, FALSE) != IDENT_NAME_OK)
3840       break;
3841     if (check_access(thd, ALTER_ACL, db->str, NULL, NULL, 1, 0) ||
3842         check_access(thd, DROP_ACL, db->str, NULL, NULL, 1, 0) ||
3843         check_access(thd, CREATE_ACL, db->str, NULL, NULL, 1, 0))
3844     {
3845       res= 1;
3846       break;
3847     }
3848     LEX_CSTRING db_name= {db->str, db->length};
3849     res= mysql_upgrade_db(thd, db_name);
3850     if (!res)
3851       my_ok(thd);
3852     break;
3853   }
3854   case SQLCOM_ALTER_DB:
3855   {
3856     LEX_STRING *db= &lex->name;
3857     HA_CREATE_INFO create_info(lex->create_info);
3858     if (check_and_convert_db_name(db, FALSE) != IDENT_NAME_OK)
3859       break;
3860     if (check_access(thd, ALTER_ACL, db->str, NULL, NULL, 1, 0))
3861       break;
3862     res= mysql_alter_db(thd, db->str, &create_info);
3863     break;
3864   }
3865   case SQLCOM_SHOW_CREATE_DB:
3866   {
3867     DBUG_EXECUTE_IF("4x_server_emul",
3868                     my_error(ER_UNKNOWN_ERROR, MYF(0)); goto error;);
3869     if (check_and_convert_db_name(&lex->name, TRUE) != IDENT_NAME_OK)
3870       break;
3871     res= mysqld_show_create_db(thd, lex->name.str, &lex->create_info);
3872     break;
3873   }
3874   case SQLCOM_CREATE_EVENT:
3875   case SQLCOM_ALTER_EVENT:
3876   #ifndef EMBEDDED_LIBRARY
3877   do
3878   {
3879     assert(lex->event_parse_data);
3880     if (lex->table_or_sp_used())
3881     {
3882       my_error(ER_NOT_SUPPORTED_YET, MYF(0), "Usage of subqueries or stored "
3883                "function calls as part of this statement");
3884       break;
3885     }
3886 
3887     res= sp_process_definer(thd);
3888     if (res)
3889       break;
3890 
3891     switch (lex->sql_command) {
3892     case SQLCOM_CREATE_EVENT:
3893     {
3894       bool if_not_exists= (lex->create_info.options &
3895                            HA_LEX_CREATE_IF_NOT_EXISTS);
3896       res= Events::create_event(thd, lex->event_parse_data, if_not_exists);
3897       break;
3898     }
3899     case SQLCOM_ALTER_EVENT:
3900     {
3901       LEX_STRING db_lex_str= NULL_STR;
3902       if (lex->spname)
3903       {
3904         db_lex_str.str= const_cast<char*>(lex->spname->m_db.str);
3905         db_lex_str.length= lex->spname->m_db.length;
3906       }
3907 
3908       res= Events::update_event(thd, lex->event_parse_data,
3909                                 lex->spname ? &db_lex_str : NULL,
3910                                 lex->spname ? &lex->spname->m_name : NULL);
3911       break;
3912     }
3913     default:
3914       assert(0);
3915     }
3916     DBUG_PRINT("info",("DDL error code=%d", res));
3917     if (!res)
3918       my_ok(thd);
3919 
3920   } while (0);
3921   /* Don't do it, if we are inside a SP */
3922   if (!thd->sp_runtime_ctx)
3923   {
3924     delete lex->sphead;
3925     lex->sphead= NULL;
3926   }
3927   /* lex->unit->cleanup() is called outside, no need to call it here */
3928   break;
3929   case SQLCOM_SHOW_CREATE_EVENT:
3930   {
3931     LEX_STRING db_lex_str= {const_cast<char*>(lex->spname->m_db.str),
3932                               lex->spname->m_db.length};
3933     res= Events::show_create_event(thd, db_lex_str,
3934                                    lex->spname->m_name);
3935     break;
3936   }
3937   case SQLCOM_DROP_EVENT:
3938   {
3939     LEX_STRING db_lex_str= {const_cast<char*>(lex->spname->m_db.str),
3940                               lex->spname->m_db.length};
3941     if (!(res= Events::drop_event(thd,
3942                                   db_lex_str, lex->spname->m_name,
3943                                   lex->drop_if_exists)))
3944         my_ok(thd);
3945     break;
3946   }
3947 #else
3948     my_error(ER_NOT_SUPPORTED_YET,MYF(0),"embedded server");
3949     break;
3950 #endif
3951   case SQLCOM_CREATE_FUNCTION:                  // UDF function
3952   {
3953     if (check_access(thd, INSERT_ACL, "mysql", NULL, NULL, 1, 0))
3954       break;
3955 #ifdef HAVE_DLOPEN
3956     if (!(res = mysql_create_function(thd, &lex->udf)))
3957       my_ok(thd);
3958 #else
3959     my_error(ER_CANT_OPEN_LIBRARY, MYF(0), lex->udf.dl, 0, "feature disabled");
3960     res= TRUE;
3961 #endif
3962     break;
3963   }
3964 #ifndef NO_EMBEDDED_ACCESS_CHECKS
3965   case SQLCOM_CREATE_USER:
3966   {
3967     if (check_access(thd, INSERT_ACL, "mysql", NULL, NULL, 1, 1) &&
3968         check_global_access(thd,CREATE_USER_ACL))
3969       break;
3970     /* Conditionally writes to binlog */
3971     HA_CREATE_INFO create_info(lex->create_info);
3972     if (!(res = mysql_create_user(thd, lex->users_list, create_info.options & HA_LEX_CREATE_IF_NOT_EXISTS)))
3973       my_ok(thd);
3974     break;
3975   }
3976   case SQLCOM_DROP_USER:
3977   {
3978     if (check_access(thd, DELETE_ACL, "mysql", NULL, NULL, 1, 1) &&
3979         check_global_access(thd,CREATE_USER_ACL))
3980       break;
3981     /* Conditionally writes to binlog */
3982     if (!(res = mysql_drop_user(thd, lex->users_list, lex->drop_if_exists)))
3983       my_ok(thd);
3984     break;
3985   }
3986   case SQLCOM_RENAME_USER:
3987   {
3988     if (check_access(thd, UPDATE_ACL, "mysql", NULL, NULL, 1, 1) &&
3989         check_global_access(thd,CREATE_USER_ACL))
3990       break;
3991     /* Conditionally writes to binlog */
3992     if (!(res= mysql_rename_user(thd, lex->users_list)))
3993       my_ok(thd);
3994     break;
3995   }
3996   case SQLCOM_REVOKE_ALL:
3997   {
3998     if (check_access(thd, UPDATE_ACL, "mysql", NULL, NULL, 1, 1) &&
3999         check_global_access(thd,CREATE_USER_ACL))
4000       break;
4001 
4002     /* Replicate current user as grantor */
4003     thd->binlog_invoker();
4004 
4005     /* Conditionally writes to binlog */
4006     if (!(res = mysql_revoke_all(thd, lex->users_list)))
4007       my_ok(thd);
4008     break;
4009   }
4010   case SQLCOM_REVOKE:
4011   case SQLCOM_GRANT:
4012   {
4013     if (lex->type != TYPE_ENUM_PROXY &&
4014         check_access(thd, lex->grant | lex->grant_tot_col | GRANT_ACL,
4015                      first_table ?  first_table->db : select_lex->db,
4016                      first_table ? &first_table->grant.privilege : NULL,
4017                      first_table ? &first_table->grant.m_internal : NULL,
4018                      first_table ? 0 : 1, 0))
4019       goto error;
4020 
4021     /* Replicate current user as grantor */
4022     thd->binlog_invoker();
4023 
4024     if (thd->security_context()->user().str)            // If not replication
4025     {
4026       LEX_USER *user, *tmp_user;
4027       bool first_user= TRUE;
4028 
4029       List_iterator <LEX_USER> user_list(lex->users_list);
4030       while ((tmp_user= user_list++))
4031       {
4032         if (!(user= get_current_user(thd, tmp_user)))
4033           goto error;
4034         if (specialflag & SPECIAL_NO_RESOLVE &&
4035             hostname_requires_resolving(user->host.str))
4036           push_warning(thd, Sql_condition::SL_WARNING,
4037                        ER_WARN_HOSTNAME_WONT_WORK,
4038                        ER(ER_WARN_HOSTNAME_WONT_WORK));
4039         // Are we trying to change a password of another user
4040         assert(user->host.str != 0);
4041 
4042         /*
4043           GRANT/REVOKE PROXY has the target user as a first entry in the list.
4044          */
4045         if (lex->type == TYPE_ENUM_PROXY && first_user)
4046         {
4047           first_user= FALSE;
4048           if (acl_check_proxy_grant_access (thd, user->host.str, user->user.str,
4049                                         lex->grant & GRANT_ACL))
4050             goto error;
4051         }
4052         else if (is_acl_user(user->host.str, user->user.str) &&
4053                  user->auth.str &&
4054                  check_change_password (thd, user->host.str, user->user.str,
4055                                         user->auth.str,
4056                                         user->auth.length))
4057           goto error;
4058       }
4059     }
4060     if (first_table)
4061     {
4062       if (lex->type == TYPE_ENUM_PROCEDURE ||
4063           lex->type == TYPE_ENUM_FUNCTION)
4064       {
4065         uint grants= lex->all_privileges
4066 		   ? (PROC_ACLS & ~GRANT_ACL) | (lex->grant & GRANT_ACL)
4067 		   : lex->grant;
4068         if (check_grant_routine(thd, grants | GRANT_ACL, all_tables,
4069                                 lex->type == TYPE_ENUM_PROCEDURE, 0))
4070 	  goto error;
4071         /* Conditionally writes to binlog */
4072         res= mysql_routine_grant(thd, all_tables,
4073                                  lex->type == TYPE_ENUM_PROCEDURE,
4074                                  lex->users_list, grants,
4075                                  lex->sql_command == SQLCOM_REVOKE, TRUE);
4076         if (!res)
4077           my_ok(thd);
4078       }
4079       else
4080       {
4081 	if (check_grant(thd,(lex->grant | lex->grant_tot_col | GRANT_ACL),
4082                         all_tables, FALSE, UINT_MAX, FALSE))
4083 	  goto error;
4084         /* Conditionally writes to binlog */
4085         res= mysql_table_grant(thd, all_tables, lex->users_list,
4086 			       lex->columns, lex->grant,
4087 			       lex->sql_command == SQLCOM_REVOKE);
4088       }
4089     }
4090     else
4091     {
4092       if (lex->columns.elements || (lex->type && lex->type != TYPE_ENUM_PROXY))
4093       {
4094 	my_message(ER_ILLEGAL_GRANT_FOR_TABLE, ER(ER_ILLEGAL_GRANT_FOR_TABLE),
4095                    MYF(0));
4096         goto error;
4097       }
4098       else
4099       {
4100         /* Conditionally writes to binlog */
4101         res = mysql_grant(thd, select_lex->db, lex->users_list, lex->grant,
4102                           lex->sql_command == SQLCOM_REVOKE,
4103                           lex->type == TYPE_ENUM_PROXY);
4104       }
4105       if (!res)
4106       {
4107 	if (lex->sql_command == SQLCOM_GRANT)
4108 	{
4109 	  List_iterator <LEX_USER> str_list(lex->users_list);
4110 	  LEX_USER *user, *tmp_user;
4111 	  while ((tmp_user=str_list++))
4112           {
4113             if (!(user= get_current_user(thd, tmp_user)))
4114               goto error;
4115 	    reset_mqh(user, 0);
4116           }
4117 	}
4118       }
4119     }
4120     break;
4121   }
4122 #endif /*!NO_EMBEDDED_ACCESS_CHECKS*/
4123   case SQLCOM_RESET:
4124     /*
4125       RESET commands are never written to the binary log, so we have to
4126       initialize this variable because RESET shares the same code as FLUSH
4127     */
4128     lex->no_write_to_binlog= 1;
4129     // Fall through.
4130   case SQLCOM_FLUSH:
4131   {
4132     int write_to_binlog;
4133     if (check_global_access(thd,RELOAD_ACL))
4134       goto error;
4135 
4136     if (first_table && lex->type & REFRESH_READ_LOCK)
4137     {
4138       /* Check table-level privileges. */
4139       if (check_table_access(thd, LOCK_TABLES_ACL | SELECT_ACL, all_tables,
4140                              FALSE, UINT_MAX, FALSE))
4141         goto error;
4142       if (flush_tables_with_read_lock(thd, all_tables))
4143         goto error;
4144       my_ok(thd);
4145       break;
4146     }
4147     else if (first_table && lex->type & REFRESH_FOR_EXPORT)
4148     {
4149       /* Check table-level privileges. */
4150       if (check_table_access(thd, LOCK_TABLES_ACL | SELECT_ACL, all_tables,
4151                              FALSE, UINT_MAX, FALSE))
4152         goto error;
4153       if (flush_tables_for_export(thd, all_tables))
4154         goto error;
4155       my_ok(thd);
4156       break;
4157     }
4158 
4159     /*
4160       reload_acl_and_cache() will tell us if we are allowed to write to the
4161       binlog or not.
4162     */
4163     if (!reload_acl_and_cache(thd, lex->type, first_table, &write_to_binlog))
4164     {
4165       /*
4166         We WANT to write and we CAN write.
4167         ! we write after unlocking the table.
4168       */
4169       /*
4170         Presumably, RESET and binlog writing doesn't require synchronization
4171       */
4172 
4173       if (write_to_binlog > 0)  // we should write
4174       {
4175         if (!lex->no_write_to_binlog)
4176           res= write_bin_log(thd, false, thd->query().str, thd->query().length);
4177       } else if (write_to_binlog < 0)
4178       {
4179         /*
4180            We should not write, but rather report error because
4181            reload_acl_and_cache binlog interactions failed
4182          */
4183         res= 1;
4184       }
4185 
4186       if (!res)
4187         my_ok(thd);
4188     }
4189 
4190     break;
4191   }
4192   case SQLCOM_KILL:
4193   {
4194     Item *it= lex->kill_value_list.head();
4195 
4196     if (lex->table_or_sp_used())
4197     {
4198       my_error(ER_NOT_SUPPORTED_YET, MYF(0), "Usage of subqueries or stored "
4199                "function calls as part of this statement");
4200       goto error;
4201     }
4202 
4203     if ((!it->fixed && it->fix_fields(lex->thd, &it)) || it->check_cols(1))
4204     {
4205       my_error(ER_SET_CONSTANTS_ONLY, MYF(0));
4206       goto error;
4207     }
4208 
4209     my_thread_id thread_id= static_cast<my_thread_id>(it->val_int());
4210     if (thd->is_error())
4211       goto error;
4212 
4213     sql_kill(thd, thread_id, lex->type & ONLY_KILL_QUERY);
4214     break;
4215   }
4216 #ifndef NO_EMBEDDED_ACCESS_CHECKS
4217   case SQLCOM_SHOW_GRANTS:
4218   {
4219     LEX_USER *grant_user= get_current_user(thd, lex->grant_user);
4220     if (!grant_user)
4221       goto error;
4222     if (!strcmp(thd->security_context()->priv_user().str,
4223                 grant_user->user.str) ||
4224         !check_access(thd, SELECT_ACL, "mysql", NULL, NULL, 1, 0))
4225     {
4226       res = mysql_show_grants(thd, grant_user);
4227     }
4228     break;
4229   }
4230   case SQLCOM_SHOW_CREATE_USER:
4231   {
4232     LEX_USER *show_user= get_current_user(thd, lex->grant_user);
4233     Security_context *sctx= thd->security_context();
4234     bool are_both_users_same= !strcmp(sctx->priv_user().str, show_user->user.str) &&
4235                               !my_strcasecmp(system_charset_info, show_user->host.str,
4236                                              sctx->priv_host().str);
4237     if (are_both_users_same || !check_access(thd, SELECT_ACL, "mysql", NULL, NULL, 1, 0))
4238       res= mysql_show_create_user(thd, show_user, are_both_users_same);
4239     break;
4240   }
4241 #endif
4242   case SQLCOM_BEGIN:
4243     if (trans_begin(thd, lex->start_transaction_opt))
4244       goto error;
4245     my_ok(thd);
4246     break;
4247   case SQLCOM_COMMIT:
4248   {
4249     assert(thd->lock == NULL ||
4250            thd->locked_tables_mode == LTM_LOCK_TABLES);
4251     bool tx_chain= (lex->tx_chain == TVL_YES ||
4252                     (thd->variables.completion_type == 1 &&
4253                      lex->tx_chain != TVL_NO));
4254     bool tx_release= (lex->tx_release == TVL_YES ||
4255                       (thd->variables.completion_type == 2 &&
4256                        lex->tx_release != TVL_NO));
4257     if (trans_commit(thd))
4258       goto error;
4259     thd->mdl_context.release_transactional_locks();
4260     /* Begin transaction with the same isolation level. */
4261     if (tx_chain)
4262     {
4263       if (trans_begin(thd))
4264       goto error;
4265     }
4266     else
4267     {
4268       /* Reset the isolation level and access mode if no chaining transaction.*/
4269       trans_reset_one_shot_chistics(thd);
4270     }
4271     /* Disconnect the current client connection. */
4272     if (tx_release)
4273       thd->killed= THD::KILL_CONNECTION;
4274     my_ok(thd);
4275     break;
4276   }
4277   case SQLCOM_ROLLBACK:
4278   {
4279     assert(thd->lock == NULL ||
4280            thd->locked_tables_mode == LTM_LOCK_TABLES);
4281     bool tx_chain= (lex->tx_chain == TVL_YES ||
4282                     (thd->variables.completion_type == 1 &&
4283                      lex->tx_chain != TVL_NO));
4284     bool tx_release= (lex->tx_release == TVL_YES ||
4285                       (thd->variables.completion_type == 2 &&
4286                        lex->tx_release != TVL_NO));
4287     if (trans_rollback(thd))
4288       goto error;
4289     thd->mdl_context.release_transactional_locks();
4290     /* Begin transaction with the same isolation level. */
4291     if (tx_chain)
4292     {
4293       if (trans_begin(thd))
4294         goto error;
4295     }
4296     else
4297     {
4298       /* Reset the isolation level and access mode if no chaining transaction.*/
4299       trans_reset_one_shot_chistics(thd);
4300     }
4301     /* Disconnect the current client connection. */
4302     if (tx_release)
4303       thd->killed= THD::KILL_CONNECTION;
4304     my_ok(thd);
4305     break;
4306   }
4307   case SQLCOM_RELEASE_SAVEPOINT:
4308     if (trans_release_savepoint(thd, lex->ident))
4309       goto error;
4310     my_ok(thd);
4311     break;
4312   case SQLCOM_ROLLBACK_TO_SAVEPOINT:
4313     if (trans_rollback_to_savepoint(thd, lex->ident))
4314       goto error;
4315     my_ok(thd);
4316     break;
4317   case SQLCOM_SAVEPOINT:
4318     if (trans_savepoint(thd, lex->ident))
4319       goto error;
4320     my_ok(thd);
4321     break;
4322   case SQLCOM_CREATE_PROCEDURE:
4323   case SQLCOM_CREATE_SPFUNCTION:
4324   {
4325     uint namelen;
4326     char *name;
4327 
4328     assert(lex->sphead != 0);
4329     assert(lex->sphead->m_db.str); /* Must be initialized in the parser */
4330     /*
4331       Verify that the database name is allowed, optionally
4332       lowercase it.
4333     */
4334     if (check_and_convert_db_name(&lex->sphead->m_db, FALSE) != IDENT_NAME_OK)
4335       goto error;
4336 
4337     if (check_access(thd, CREATE_PROC_ACL, lex->sphead->m_db.str,
4338                      NULL, NULL, 0, 0))
4339       goto error;
4340 
4341     name= lex->sphead->name(&namelen);
4342 #ifdef HAVE_DLOPEN
4343     if (lex->sphead->m_type == SP_TYPE_FUNCTION)
4344     {
4345       udf_func *udf = find_udf(name, namelen);
4346 
4347       if (udf)
4348       {
4349         my_error(ER_UDF_EXISTS, MYF(0), name);
4350         goto error;
4351       }
4352     }
4353 #endif
4354 
4355     if (sp_process_definer(thd))
4356       goto error;
4357 
4358     /*
4359       Record the CURRENT_USER in binlog. The CURRENT_USER is used on slave to
4360       grant default privileges when sp_automatic_privileges variable is set.
4361     */
4362     thd->binlog_invoker();
4363 
4364     if (! (res= sp_create_routine(thd, lex->sphead)))
4365     {
4366 #ifndef NO_EMBEDDED_ACCESS_CHECKS
4367       /* only add privileges if really neccessary */
4368 
4369       Security_context security_context;
4370       bool restore_backup_context= false;
4371       Security_context *backup= NULL;
4372       /*
4373         We're going to issue an implicit GRANT statement so we close all
4374         open tables. We have to keep metadata locks as this ensures that
4375         this statement is atomic against concurent FLUSH TABLES WITH READ
4376         LOCK. Deadlocks which can arise due to fact that this implicit
4377         statement takes metadata locks should be detected by a deadlock
4378         detector in MDL subsystem and reported as errors.
4379 
4380         No need to commit/rollback statement transaction, it's not started.
4381 
4382         TODO: Long-term we should either ensure that implicit GRANT statement
4383               is written into binary log as a separate statement or make both
4384               creation of routine and implicit GRANT parts of one fully atomic
4385               statement.
4386       */
4387       assert(thd->get_transaction()->is_empty(Transaction_ctx::STMT));
4388       close_thread_tables(thd);
4389       /*
4390         Check if invoker exists on slave, then use invoker privilege to
4391         insert routine privileges to mysql.procs_priv. If invoker is not
4392         available then consider using definer.
4393 
4394         Check if the definer exists on slave,
4395         then use definer privilege to insert routine privileges to mysql.procs_priv.
4396 
4397         For current user of SQL thread has GLOBAL_ACL privilege,
4398         which doesn't any check routine privileges,
4399         so no routine privilege record  will insert into mysql.procs_priv.
4400       */
4401 
4402       if (thd->slave_thread)
4403       {
4404         LEX_CSTRING current_user;
4405         LEX_CSTRING current_host;
4406         if (thd->has_invoker())
4407         {
4408           current_host= thd->get_invoker_host();
4409           current_user= thd->get_invoker_user();
4410         }
4411         else
4412         {
4413           current_host= lex->definer->host;
4414           current_user= lex->definer->user;
4415         }
4416         if (is_acl_user(current_host.str, current_user.str))
4417         {
4418           security_context.change_security_context(thd,
4419                                                    current_user,
4420                                                    current_host,
4421                                                    &thd->lex->sphead->m_db,
4422                                                    &backup);
4423           restore_backup_context= true;
4424         }
4425       }
4426 
4427       if (sp_automatic_privileges && !opt_noacl &&
4428           check_routine_access(thd, DEFAULT_CREATE_PROC_ACLS,
4429                                lex->sphead->m_db.str, name,
4430                                lex->sql_command == SQLCOM_CREATE_PROCEDURE, 1))
4431       {
4432         if (sp_grant_privileges(thd, lex->sphead->m_db.str, name,
4433                                 lex->sql_command == SQLCOM_CREATE_PROCEDURE))
4434           push_warning(thd, Sql_condition::SL_WARNING,
4435                        ER_PROC_AUTO_GRANT_FAIL, ER(ER_PROC_AUTO_GRANT_FAIL));
4436         thd->clear_error();
4437       }
4438 
4439       /*
4440         Restore current user with GLOBAL_ACL privilege of SQL thread
4441       */
4442       if (restore_backup_context)
4443       {
4444         assert(thd->slave_thread == 1);
4445         thd->security_context()->restore_security_context(thd, backup);
4446       }
4447 #endif
4448       my_ok(thd);
4449     }
4450     break; /* break super switch */
4451   } /* end case group bracket */
4452   case SQLCOM_CALL:
4453     {
4454       sp_head *sp;
4455 
4456       /* Here we check for the execute privilege on stored procedure. */
4457       if (check_routine_access(thd, EXECUTE_ACL, lex->spname->m_db.str,
4458                                lex->spname->m_name.str,
4459                                lex->sql_command == SQLCOM_CALL, 0))
4460         goto error;
4461 
4462       /*
4463         This will cache all SP and SF and open and lock all tables
4464         required for execution.
4465       */
4466       if (check_table_access(thd, SELECT_ACL, all_tables, FALSE,
4467                              UINT_MAX, FALSE) ||
4468           open_and_lock_tables(thd, all_tables, 0))
4469        goto error;
4470 
4471       /*
4472         By this moment all needed SPs should be in cache so no need to look
4473         into DB.
4474       */
4475       if (!(sp= sp_find_routine(thd, SP_TYPE_PROCEDURE, lex->spname,
4476                                 &thd->sp_proc_cache, TRUE)))
4477       {
4478 	my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "PROCEDURE",
4479                  lex->spname->m_qname.str);
4480 	goto error;
4481       }
4482       else
4483       {
4484 	ha_rows select_limit;
4485         /* bits that should be cleared in thd->server_status */
4486 	uint bits_to_be_cleared= 0;
4487         /*
4488           Check that the stored procedure doesn't contain Dynamic SQL
4489           and doesn't return result sets: such stored procedures can't
4490           be called from a function or trigger.
4491         */
4492         if (thd->in_sub_stmt)
4493         {
4494           const char *where= (thd->in_sub_stmt & SUB_STMT_TRIGGER ?
4495                               "trigger" : "function");
4496           if (sp->is_not_allowed_in_function(where))
4497             goto error;
4498         }
4499 
4500 #ifndef EMBEDDED_LIBRARY
4501         if (mysql_audit_notify(thd,
4502                               AUDIT_EVENT(MYSQL_AUDIT_STORED_PROGRAM_EXECUTE),
4503                               lex->spname->m_db.str,
4504                               lex->spname->m_name.str,
4505                               NULL))
4506         {
4507           goto error;
4508         }
4509 #endif /* !EMBEDDED_LIBRARY */
4510 
4511 	if (sp->m_flags & sp_head::MULTI_RESULTS)
4512 	{
4513 	  if (!thd->get_protocol()->has_client_capability(CLIENT_MULTI_RESULTS))
4514 	  {
4515             /*
4516               The client does not support multiple result sets being sent
4517               back
4518             */
4519 	    my_error(ER_SP_BADSELECT, MYF(0), sp->m_qname.str);
4520 	    goto error;
4521 	  }
4522           /*
4523             If SERVER_MORE_RESULTS_EXISTS is not set,
4524             then remember that it should be cleared
4525           */
4526 	  bits_to_be_cleared= (~thd->server_status &
4527                                SERVER_MORE_RESULTS_EXISTS);
4528 	  thd->server_status|= SERVER_MORE_RESULTS_EXISTS;
4529 	}
4530 
4531 	if (check_routine_access(thd, EXECUTE_ACL,
4532 				 sp->m_db.str, sp->m_name.str, TRUE, FALSE))
4533 	{
4534 	  goto error;
4535 	}
4536 	select_limit= thd->variables.select_limit;
4537 	thd->variables.select_limit= HA_POS_ERROR;
4538 
4539         /*
4540           We never write CALL statements into binlog:
4541            - If the mode is non-prelocked, each statement will be logged
4542              separately.
4543            - If the mode is prelocked, the invoking statement will care
4544              about writing into binlog.
4545           So just execute the statement.
4546         */
4547 	res= sp->execute_procedure(thd, &lex->call_value_list);
4548 
4549 	thd->variables.select_limit= select_limit;
4550 
4551         thd->server_status&= ~bits_to_be_cleared;
4552 
4553 	if (!res)
4554         {
4555           my_ok(thd, (thd->get_row_count_func() < 0) ? 0 : thd->get_row_count_func());
4556         }
4557 	else
4558         {
4559           assert(thd->is_error() || thd->killed);
4560 	  goto error;		// Substatement should already have sent error
4561         }
4562       }
4563       break;
4564     }
4565   case SQLCOM_ALTER_PROCEDURE:
4566   case SQLCOM_ALTER_FUNCTION:
4567     {
4568       if (check_routine_access(thd, ALTER_PROC_ACL, lex->spname->m_db.str,
4569                                lex->spname->m_name.str,
4570                                lex->sql_command == SQLCOM_ALTER_PROCEDURE,
4571                                false))
4572         goto error;
4573 
4574       enum_sp_type sp_type= (lex->sql_command == SQLCOM_ALTER_PROCEDURE) ?
4575                             SP_TYPE_PROCEDURE : SP_TYPE_FUNCTION;
4576       /*
4577         Note that if you implement the capability of ALTER FUNCTION to
4578         alter the body of the function, this command should be made to
4579         follow the restrictions that log-bin-trust-function-creators=0
4580         already puts on CREATE FUNCTION.
4581       */
4582       /* Conditionally writes to binlog */
4583       int sp_result= sp_update_routine(thd, sp_type, lex->spname,
4584                                        &lex->sp_chistics);
4585       if (thd->killed)
4586         goto error;
4587       switch (sp_result)
4588       {
4589       case SP_OK:
4590 	my_ok(thd);
4591 	break;
4592       case SP_KEY_NOT_FOUND:
4593 	my_error(ER_SP_DOES_NOT_EXIST, MYF(0),
4594                  SP_COM_STRING(lex), lex->spname->m_qname.str);
4595 	goto error;
4596       default:
4597 	my_error(ER_SP_CANT_ALTER, MYF(0),
4598                  SP_COM_STRING(lex), lex->spname->m_qname.str);
4599 	goto error;
4600       }
4601       break;
4602     }
4603   case SQLCOM_DROP_PROCEDURE:
4604   case SQLCOM_DROP_FUNCTION:
4605     {
4606 #ifdef HAVE_DLOPEN
4607       if (lex->sql_command == SQLCOM_DROP_FUNCTION &&
4608           ! lex->spname->m_explicit_name)
4609       {
4610         /* DROP FUNCTION <non qualified name> */
4611         udf_func *udf = find_udf(lex->spname->m_name.str,
4612                                  lex->spname->m_name.length);
4613         if (udf)
4614         {
4615           if (check_access(thd, DELETE_ACL, "mysql", NULL, NULL, 1, 0))
4616             goto error;
4617 
4618           if (!(res = mysql_drop_function(thd, &lex->spname->m_name)))
4619           {
4620             my_ok(thd);
4621             break;
4622           }
4623           my_error(ER_SP_DROP_FAILED, MYF(0),
4624                    "FUNCTION (UDF)", lex->spname->m_name.str);
4625           goto error;
4626         }
4627 
4628         if (lex->spname->m_db.str == NULL)
4629         {
4630           if (lex->drop_if_exists)
4631           {
4632             push_warning_printf(thd, Sql_condition::SL_NOTE,
4633                                 ER_SP_DOES_NOT_EXIST, ER(ER_SP_DOES_NOT_EXIST),
4634                                 "FUNCTION (UDF)", lex->spname->m_name.str);
4635             res= FALSE;
4636             my_ok(thd);
4637             break;
4638           }
4639           my_error(ER_SP_DOES_NOT_EXIST, MYF(0),
4640                    "FUNCTION (UDF)", lex->spname->m_name.str);
4641           goto error;
4642         }
4643         /* Fall thought to test for a stored function */
4644       }
4645 #endif
4646 
4647       const char *db= lex->spname->m_db.str;
4648       char *name= lex->spname->m_name.str;
4649 
4650       if (check_routine_access(thd, ALTER_PROC_ACL, db, name,
4651                                lex->sql_command == SQLCOM_DROP_PROCEDURE,
4652                                false))
4653         goto error;
4654 
4655       enum_sp_type sp_type= (lex->sql_command == SQLCOM_DROP_PROCEDURE) ?
4656                             SP_TYPE_PROCEDURE : SP_TYPE_FUNCTION;
4657 
4658       /* Conditionally writes to binlog */
4659       int sp_result= sp_drop_routine(thd, sp_type, lex->spname);
4660 
4661 #ifndef NO_EMBEDDED_ACCESS_CHECKS
4662       /*
4663         We're going to issue an implicit REVOKE statement so we close all
4664         open tables. We have to keep metadata locks as this ensures that
4665         this statement is atomic against concurent FLUSH TABLES WITH READ
4666         LOCK. Deadlocks which can arise due to fact that this implicit
4667         statement takes metadata locks should be detected by a deadlock
4668         detector in MDL subsystem and reported as errors.
4669 
4670         No need to commit/rollback statement transaction, it's not started.
4671 
4672         TODO: Long-term we should either ensure that implicit REVOKE statement
4673               is written into binary log as a separate statement or make both
4674               dropping of routine and implicit REVOKE parts of one fully atomic
4675               statement.
4676       */
4677       assert(thd->get_transaction()->is_empty(Transaction_ctx::STMT));
4678       close_thread_tables(thd);
4679 
4680       if (sp_result != SP_KEY_NOT_FOUND &&
4681           sp_automatic_privileges && !opt_noacl &&
4682           sp_revoke_privileges(thd, db, name,
4683                                lex->sql_command == SQLCOM_DROP_PROCEDURE))
4684       {
4685         push_warning(thd, Sql_condition::SL_WARNING,
4686                      ER_PROC_AUTO_REVOKE_FAIL,
4687                      ER(ER_PROC_AUTO_REVOKE_FAIL));
4688         /* If this happens, an error should have been reported. */
4689         goto error;
4690       }
4691 #endif
4692 
4693       res= sp_result;
4694       switch (sp_result) {
4695       case SP_OK:
4696 	my_ok(thd);
4697 	break;
4698       case SP_KEY_NOT_FOUND:
4699 	if (lex->drop_if_exists)
4700 	{
4701           res= write_bin_log(thd, true, thd->query().str, thd->query().length);
4702 	  push_warning_printf(thd, Sql_condition::SL_NOTE,
4703 			      ER_SP_DOES_NOT_EXIST, ER(ER_SP_DOES_NOT_EXIST),
4704                               SP_COM_STRING(lex), lex->spname->m_qname.str);
4705           if (!res)
4706             my_ok(thd);
4707 	  break;
4708 	}
4709 	my_error(ER_SP_DOES_NOT_EXIST, MYF(0),
4710                  SP_COM_STRING(lex), lex->spname->m_qname.str);
4711 	goto error;
4712       default:
4713 	my_error(ER_SP_DROP_FAILED, MYF(0),
4714                  SP_COM_STRING(lex), lex->spname->m_qname.str);
4715 	goto error;
4716       }
4717       break;
4718     }
4719   case SQLCOM_SHOW_CREATE_PROC:
4720     {
4721       if (sp_show_create_routine(thd, SP_TYPE_PROCEDURE, lex->spname))
4722         goto error;
4723       break;
4724     }
4725   case SQLCOM_SHOW_CREATE_FUNC:
4726     {
4727       if (sp_show_create_routine(thd, SP_TYPE_FUNCTION, lex->spname))
4728 	goto error;
4729       break;
4730     }
4731   case SQLCOM_SHOW_PROC_CODE:
4732   case SQLCOM_SHOW_FUNC_CODE:
4733     {
4734 #ifndef NDEBUG
4735       sp_head *sp;
4736       enum_sp_type sp_type= (lex->sql_command == SQLCOM_SHOW_PROC_CODE) ?
4737                             SP_TYPE_PROCEDURE : SP_TYPE_FUNCTION;
4738 
4739       if (sp_cache_routine(thd, sp_type, lex->spname, false, &sp))
4740         goto error;
4741       if (!sp || sp->show_routine_code(thd))
4742       {
4743         /* We don't distinguish between errors for now */
4744         my_error(ER_SP_DOES_NOT_EXIST, MYF(0),
4745                  SP_COM_STRING(lex), lex->spname->m_name.str);
4746         goto error;
4747       }
4748       break;
4749 #else
4750       my_error(ER_FEATURE_DISABLED, MYF(0),
4751                "SHOW PROCEDURE|FUNCTION CODE", "--with-debug");
4752       goto error;
4753 #endif // ifndef NDEBUG
4754     }
4755   case SQLCOM_SHOW_CREATE_TRIGGER:
4756     {
4757       if (lex->spname->m_name.length > NAME_LEN)
4758       {
4759         my_error(ER_TOO_LONG_IDENT, MYF(0), lex->spname->m_name.str);
4760         goto error;
4761       }
4762 
4763       if (show_create_trigger(thd, lex->spname))
4764         goto error; /* Error has been already logged. */
4765 
4766       break;
4767     }
4768   case SQLCOM_CREATE_VIEW:
4769     {
4770       /*
4771         Note: SQLCOM_CREATE_VIEW also handles 'ALTER VIEW' commands
4772         as specified through the thd->lex->create_view_mode flag.
4773       */
4774       res= mysql_create_view(thd, first_table, thd->lex->create_view_mode);
4775       break;
4776     }
4777   case SQLCOM_DROP_VIEW:
4778     {
4779       if (check_table_access(thd, DROP_ACL, all_tables, FALSE, UINT_MAX, FALSE))
4780         goto error;
4781       /* Conditionally writes to binlog. */
4782       res= mysql_drop_view(thd, first_table, thd->lex->drop_mode);
4783       break;
4784     }
4785   case SQLCOM_CREATE_TRIGGER:
4786   {
4787     /* Conditionally writes to binlog. */
4788     res= mysql_create_or_drop_trigger(thd, all_tables, 1);
4789 
4790     break;
4791   }
4792   case SQLCOM_DROP_TRIGGER:
4793   {
4794     /* Conditionally writes to binlog. */
4795     res= mysql_create_or_drop_trigger(thd, all_tables, 0);
4796     break;
4797   }
4798   case SQLCOM_ALTER_TABLESPACE:
4799     if (check_global_access(thd, CREATE_TABLESPACE_ACL))
4800       break;
4801     if (!(res= mysql_alter_tablespace(thd, lex->alter_tablespace_info)))
4802       my_ok(thd);
4803     break;
4804   case SQLCOM_BINLOG_BASE64_EVENT:
4805   {
4806 #ifndef EMBEDDED_LIBRARY
4807     mysql_client_binlog_statement(thd);
4808 #else /* EMBEDDED_LIBRARY */
4809     my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "embedded");
4810 #endif /* EMBEDDED_LIBRARY */
4811     break;
4812   }
4813   case SQLCOM_EXPLAIN_OTHER:
4814   {
4815     /* EXPLAIN FOR CONNECTION <id> */
4816     mysql_explain_other(thd);
4817     break;
4818   }
4819   case SQLCOM_ANALYZE:
4820   case SQLCOM_CHECK:
4821   case SQLCOM_OPTIMIZE:
4822   case SQLCOM_REPAIR:
4823   case SQLCOM_TRUNCATE:
4824   case SQLCOM_ALTER_TABLE:
4825   case SQLCOM_HA_OPEN:
4826   case SQLCOM_HA_READ:
4827   case SQLCOM_HA_CLOSE:
4828     assert(first_table == all_tables && first_table != 0);
4829     /* fall through */
4830   case SQLCOM_CREATE_SERVER:
4831   case SQLCOM_ALTER_SERVER:
4832   case SQLCOM_DROP_SERVER:
4833   case SQLCOM_SIGNAL:
4834   case SQLCOM_RESIGNAL:
4835   case SQLCOM_GET_DIAGNOSTICS:
4836   case SQLCOM_CHANGE_REPLICATION_FILTER:
4837   case SQLCOM_XA_START:
4838   case SQLCOM_XA_END:
4839   case SQLCOM_XA_PREPARE:
4840   case SQLCOM_XA_COMMIT:
4841   case SQLCOM_XA_ROLLBACK:
4842   case SQLCOM_XA_RECOVER:
4843   case SQLCOM_INSTALL_PLUGIN:
4844   case SQLCOM_UNINSTALL_PLUGIN:
4845   case SQLCOM_SHUTDOWN:
4846   case SQLCOM_ALTER_INSTANCE:
4847     assert(lex->m_sql_cmd != NULL);
4848     res= lex->m_sql_cmd->execute(thd);
4849     break;
4850 
4851 #ifndef NO_EMBEDDED_ACCESS_CHECKS
4852   case SQLCOM_ALTER_USER:
4853   {
4854     LEX_USER *user, *tmp_user;
4855     bool changing_own_password= false;
4856     bool own_password_expired= thd->security_context()->password_expired();
4857     bool check_permission= true;
4858 
4859     List_iterator <LEX_USER> user_list(lex->users_list);
4860     while ((tmp_user= user_list++))
4861     {
4862       bool update_password_only= FALSE;
4863       bool is_self= false;
4864 
4865       /* If it is an empty lex_user update it with current user */
4866       if (!tmp_user->host.str && !tmp_user->user.str)
4867       {
4868         /* set user information as of the current user */
4869         assert(thd->security_context()->priv_host().str);
4870         tmp_user->host.str= (char *) thd->security_context()->priv_host().str;
4871         tmp_user->host.length= strlen(thd->security_context()->priv_host().str);
4872         assert(thd->security_context()->user().str);
4873         tmp_user->user.str= (char *) thd->security_context()->user().str;
4874         tmp_user->user.length= strlen(thd->security_context()->user().str);
4875       }
4876       if (!(user= get_current_user(thd, tmp_user)))
4877         goto error;
4878 
4879       /* copy password expire attributes to individual lex user */
4880       user->alter_status= thd->lex->alter_password;
4881 
4882       if (user->uses_identified_by_clause &&
4883           !thd->lex->mqh.specified_limits &&
4884           !user->alter_status.update_account_locked_column &&
4885           !user->alter_status.update_password_expired_column &&
4886           !user->alter_status.expire_after_days &&
4887           user->alter_status.use_default_password_lifetime &&
4888           (thd->lex->ssl_type == SSL_TYPE_NOT_SPECIFIED))
4889         update_password_only= TRUE;
4890 
4891       is_self= !strcmp(thd->security_context()->user().length ?
4892                        thd->security_context()->user().str : "",
4893                        user->user.str) &&
4894                !my_strcasecmp(&my_charset_latin1, user->host.str,
4895                               thd->security_context()->priv_host().str);
4896       /*
4897         if user executes ALTER statement to change password only
4898         for himself then skip access check.
4899       */
4900       if (update_password_only && is_self)
4901       {
4902         changing_own_password= true;
4903         continue;
4904       }
4905       else if (check_permission)
4906       {
4907         if (check_access(thd, UPDATE_ACL, "mysql", NULL, NULL, 1, 1) &&
4908             check_global_access(thd, CREATE_USER_ACL))
4909           goto error;
4910 
4911         check_permission= false;
4912       }
4913 
4914       if (is_self &&
4915           (user->uses_identified_by_clause ||
4916            user->uses_identified_with_clause ||
4917            user->uses_authentication_string_clause ||
4918            user->uses_identified_by_password_clause))
4919       {
4920         changing_own_password= true;
4921         break;
4922       }
4923 
4924       if (update_password_only &&
4925           likely((get_server_state() == SERVER_OPERATING)) &&
4926           !strcmp(thd->security_context()->priv_user().str,""))
4927       {
4928         my_message(ER_PASSWORD_ANONYMOUS_USER, ER(ER_PASSWORD_ANONYMOUS_USER),
4929                    MYF(0));
4930         goto error;
4931       }
4932     }
4933 
4934     if (unlikely(own_password_expired && !changing_own_password))
4935     {
4936       my_error(ER_MUST_CHANGE_PASSWORD, MYF(0));
4937       goto error;
4938     }
4939 
4940     /* Conditionally writes to binlog */
4941     if (!(res = mysql_alter_user(thd, lex->users_list, lex->drop_if_exists)))
4942       my_ok(thd);
4943     break;
4944   }
4945 #endif
4946   default:
4947 #ifndef EMBEDDED_LIBRARY
4948     assert(0);                             /* Impossible */
4949 #endif
4950     my_ok(thd);
4951     break;
4952   }
4953   goto finish;
4954 
4955 error:
4956   res= TRUE;
4957 
4958 finish:
4959   THD_STAGE_INFO(thd, stage_query_end);
4960 
4961   if (res && thd->get_reprepare_observer() != NULL &&
4962       thd->get_reprepare_observer()->is_invalidated() &&
4963       thd->get_reprepare_observer()->can_retry()) {
4964     thd->skip_gtid_rollback = true;
4965   }
4966 
4967   // Cleanup EXPLAIN info
4968   if (!thd->in_sub_stmt)
4969   {
4970     if (is_explainable_query(lex->sql_command))
4971     {
4972       DEBUG_SYNC(thd, "before_reset_query_plan");
4973       /*
4974         We want EXPLAIN CONNECTION to work until the explained statement ends,
4975         thus it is only now that we may fully clean up any unit of this statement.
4976       */
4977       lex->unit->assert_not_fully_clean();
4978     }
4979     thd->query_plan.set_query_plan(SQLCOM_END, NULL, false);
4980   }
4981 
4982   assert(!thd->in_active_multi_stmt_transaction() ||
4983          thd->in_multi_stmt_transaction_mode());
4984 
4985   if (! thd->in_sub_stmt)
4986   {
4987 #ifndef EMBEDDED_LIBRARY
4988     mysql_audit_notify(thd,
4989                        first_level ? MYSQL_AUDIT_QUERY_STATUS_END :
4990                                      MYSQL_AUDIT_QUERY_NESTED_STATUS_END,
4991                        first_level ? "MYSQL_AUDIT_QUERY_STATUS_END" :
4992                                      "MYSQL_AUDIT_QUERY_NESTED_STATUS_END");
4993 #endif /* !EMBEDDED_LIBRARY */
4994 
4995     /* report error issued during command execution */
4996     if (thd->killed_errno())
4997       thd->send_kill_message();
4998     if (thd->is_error() || (thd->variables.option_bits & OPTION_MASTER_SQL_ERROR))
4999       trans_rollback_stmt(thd);
5000     else
5001     {
5002       /* If commit fails, we should be able to reset the OK status. */
5003       thd->get_stmt_da()->set_overwrite_status(true);
5004       trans_commit_stmt(thd);
5005       thd->get_stmt_da()->set_overwrite_status(false);
5006     }
5007     if (thd->killed == THD::KILL_QUERY ||
5008         thd->killed == THD::KILL_TIMEOUT ||
5009         thd->killed == THD::KILL_BAD_DATA)
5010     {
5011       thd->killed= THD::NOT_KILLED;
5012       thd->reset_query_for_display();
5013     }
5014   }
5015 
5016   lex->unit->cleanup(true);
5017   /* Free tables */
5018   THD_STAGE_INFO(thd, stage_closing_tables);
5019   close_thread_tables(thd);
5020 
5021 #ifndef NDEBUG
5022   if (lex->sql_command != SQLCOM_SET_OPTION && ! thd->in_sub_stmt)
5023     DEBUG_SYNC(thd, "execute_command_after_close_tables");
5024 #endif
5025 
5026   if (! thd->in_sub_stmt && thd->transaction_rollback_request)
5027   {
5028     /*
5029       We are not in sub-statement and transaction rollback was requested by
5030       one of storage engines (e.g. due to deadlock). Rollback transaction in
5031       all storage engines including binary log.
5032     */
5033     trans_rollback_implicit(thd);
5034     thd->mdl_context.release_transactional_locks();
5035   }
5036   else if (stmt_causes_implicit_commit(thd, CF_IMPLICIT_COMMIT_END))
5037   {
5038     /* No transaction control allowed in sub-statements. */
5039     assert(! thd->in_sub_stmt);
5040     /* If commit fails, we should be able to reset the OK status. */
5041     thd->get_stmt_da()->set_overwrite_status(true);
5042     /* Commit the normal transaction if one is active. */
5043     trans_commit_implicit(thd);
5044     thd->get_stmt_da()->set_overwrite_status(false);
5045     thd->mdl_context.release_transactional_locks();
5046   }
5047   else if (! thd->in_sub_stmt && ! thd->in_multi_stmt_transaction_mode())
5048   {
5049     /*
5050       - If inside a multi-statement transaction,
5051       defer the release of metadata locks until the current
5052       transaction is either committed or rolled back. This prevents
5053       other statements from modifying the table for the entire
5054       duration of this transaction.  This provides commit ordering
5055       and guarantees serializability across multiple transactions.
5056       - If in autocommit mode, or outside a transactional context,
5057       automatically release metadata locks of the current statement.
5058     */
5059     thd->mdl_context.release_transactional_locks();
5060   }
5061   else if (! thd->in_sub_stmt)
5062   {
5063     thd->mdl_context.release_statement_locks();
5064   }
5065 
5066   if (thd->variables.session_track_transaction_info > TX_TRACK_NONE)
5067   {
5068     ((Transaction_state_tracker *)
5069      thd->session_tracker.get_tracker(TRANSACTION_INFO_TRACKER))
5070       ->add_trx_state_from_thd(thd);
5071   }
5072 
5073 #if defined(VALGRIND_DO_QUICK_LEAK_CHECK)
5074   // Get incremental leak reports, for easier leak hunting.
5075   // ./mtr --mem --mysqld='-T 4096' --valgrind-mysqld main.1st
5076   // Note that with multiple connections, the report below may be misleading.
5077   if (test_flags & TEST_DO_QUICK_LEAK_CHECK)
5078   {
5079     static unsigned long total_leaked_bytes= 0;
5080     unsigned long leaked= 0;
5081     unsigned long dubious MY_ATTRIBUTE((unused));
5082     unsigned long reachable MY_ATTRIBUTE((unused));
5083     unsigned long suppressed MY_ATTRIBUTE((unused));
5084     /*
5085       We could possibly use VALGRIND_DO_CHANGED_LEAK_CHECK here,
5086       but that is a fairly new addition to the Valgrind api.
5087       Note: we dont want to check 'reachable' until we have done shutdown,
5088       and that is handled by the final report anyways.
5089       We print some extra information, to tell mtr to ignore this report.
5090     */
5091     sql_print_information("VALGRIND_DO_QUICK_LEAK_CHECK");
5092     VALGRIND_DO_QUICK_LEAK_CHECK;
5093     VALGRIND_COUNT_LEAKS(leaked, dubious, reachable, suppressed);
5094     if (leaked > total_leaked_bytes)
5095     {
5096       sql_print_error("VALGRIND_COUNT_LEAKS reports %lu leaked bytes "
5097                       "for query '%.*s'", leaked - total_leaked_bytes,
5098                       static_cast<int>(thd->query().length), thd->query().str);
5099     }
5100     total_leaked_bytes= leaked;
5101   }
5102 #endif
5103 
5104   if (!res && !thd->is_error()) {      // if statement succeeded
5105     binlog_gtid_end_transaction(thd);  // finalize GTID life-cycle
5106     DEBUG_SYNC(thd, "persist_new_state_after_statement_succeeded");
5107   } else if (!gtid_consistency_violation_state &&    // if the consistency state
5108              thd->has_gtid_consistency_violation) {  // was set by the failing
5109                                                      // statement
5110     gtid_state->end_gtid_violating_transaction(thd);  // just roll it back
5111     DEBUG_SYNC(thd, "restore_previous_state_after_statement_failed");
5112   }
5113 
5114   thd->skip_gtid_rollback = false;
5115 
5116   DBUG_RETURN(res || thd->is_error());
5117 }
5118 
execute_sqlcom_select(THD * thd,TABLE_LIST * all_tables)5119 static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables)
5120 {
5121   LEX	*lex= thd->lex;
5122   bool statement_timer_armed= false;
5123   bool res;
5124 
5125   /* assign global limit variable if limit is not given */
5126   {
5127     SELECT_LEX *param= lex->unit->global_parameters();
5128     if (!param->explicit_limit)
5129       param->select_limit=
5130         new Item_int((ulonglong) thd->variables.select_limit);
5131   }
5132 
5133   //check if timer is applicable to statement, if applicable then set timer.
5134   if (is_timer_applicable_to_statement(thd))
5135     statement_timer_armed= set_statement_timer(thd);
5136 
5137   if (!(res= open_tables_for_query(thd, all_tables, 0)))
5138   {
5139     MYSQL_SELECT_START(const_cast<char*>(thd->query().str));
5140     if (lex->is_explain())
5141     {
5142       /*
5143         We always use Query_result_send for EXPLAIN, even if it's an EXPLAIN
5144         for SELECT ... INTO OUTFILE: a user application should be able
5145         to prepend EXPLAIN to any query and receive output for it,
5146         even if the query itself redirects the output.
5147       */
5148       Query_result *const result= new Query_result_send;
5149       if (!result)
5150         return true; /* purecov: inspected */
5151       res= handle_query(thd, lex, result, 0, 0);
5152     }
5153     else
5154     {
5155       Query_result *result= lex->result;
5156       if (!result && !(result= new Query_result_send()))
5157         return true;                            /* purecov: inspected */
5158       Query_result *save_result= result;
5159       Query_result *analyse_result= NULL;
5160       if (lex->proc_analyse)
5161       {
5162         if ((result= analyse_result=
5163                new Query_result_analyse(result, lex->proc_analyse)) == NULL)
5164           return true;
5165       }
5166       res= handle_query(thd, lex, result, 0, 0);
5167       delete analyse_result;
5168       if (save_result != lex->result)
5169         delete save_result;
5170     }
5171     MYSQL_SELECT_DONE((int) res, (ulong) thd->current_found_rows);
5172   }
5173 
5174   if (statement_timer_armed && thd->timer)
5175     reset_statement_timer(thd);
5176 
5177   DEBUG_SYNC(thd, "after_table_open");
5178   return res;
5179 }
5180 
5181 
5182 /****************************************************************************
5183 	Check stack size; Send error if there isn't enough stack to continue
5184 ****************************************************************************/
5185 
5186 
5187 #if STACK_DIRECTION < 0
5188 #define used_stack(A,B) (long) (A - B)
5189 #else
5190 #define used_stack(A,B) (long) (B - A)
5191 #endif
5192 
5193 #ifndef NDEBUG
5194 long max_stack_used;
5195 #endif
5196 
5197 /**
5198   @note
5199   Note: The 'buf' parameter is necessary, even if it is unused here.
5200   - fix_fields functions has a "dummy" buffer large enough for the
5201     corresponding exec. (Thus we only have to check in fix_fields.)
5202   - Passing to check_stack_overrun() prevents the compiler from removing it.
5203 */
check_stack_overrun(THD * thd,long margin,uchar * buf MY_ATTRIBUTE ((unused)))5204 bool check_stack_overrun(THD *thd, long margin,
5205 			 uchar *buf MY_ATTRIBUTE((unused)))
5206 {
5207   long stack_used;
5208   assert(thd == current_thd);
5209   if ((stack_used=used_stack(thd->thread_stack,(char*) &stack_used)) >=
5210       (long) (my_thread_stack_size - margin))
5211   {
5212     /*
5213       Do not use stack for the message buffer to ensure correct
5214       behaviour in cases we have close to no stack left.
5215     */
5216     char* ebuff= new (std::nothrow) char[MYSQL_ERRMSG_SIZE];
5217     if (ebuff) {
5218       my_snprintf(ebuff, MYSQL_ERRMSG_SIZE, ER(ER_STACK_OVERRUN_NEED_MORE),
5219                   stack_used, my_thread_stack_size, margin);
5220       my_message(ER_STACK_OVERRUN_NEED_MORE, ebuff, MYF(ME_FATALERROR));
5221       delete [] ebuff;
5222     }
5223     return 1;
5224   }
5225 #ifndef NDEBUG
5226   max_stack_used= max(max_stack_used, stack_used);
5227 #endif
5228   return 0;
5229 }
5230 
5231 
5232 #define MY_YACC_INIT 1000			// Start with big alloc
5233 #define MY_YACC_MAX  32000			// Because of 'short'
5234 
my_yyoverflow(short ** yyss,YYSTYPE ** yyvs,YYLTYPE ** yyls,ulong * yystacksize)5235 bool my_yyoverflow(short **yyss, YYSTYPE **yyvs, YYLTYPE **yyls, ulong *yystacksize)
5236 {
5237   Yacc_state *state= & current_thd->m_parser_state->m_yacc;
5238   ulong old_info=0;
5239   assert(state);
5240   if ((uint) *yystacksize >= MY_YACC_MAX)
5241     return 1;
5242   if (!state->yacc_yyvs)
5243     old_info= *yystacksize;
5244   *yystacksize= set_zone((*yystacksize)*2,MY_YACC_INIT,MY_YACC_MAX);
5245   if (!(state->yacc_yyvs= (uchar*)
5246         my_realloc(key_memory_bison_stack,
5247                    state->yacc_yyvs,
5248                    *yystacksize*sizeof(**yyvs),
5249                    MYF(MY_ALLOW_ZERO_PTR | MY_FREE_ON_ERROR))) ||
5250       !(state->yacc_yyss= (uchar*)
5251         my_realloc(key_memory_bison_stack,
5252                    state->yacc_yyss,
5253                    *yystacksize*sizeof(**yyss),
5254                    MYF(MY_ALLOW_ZERO_PTR | MY_FREE_ON_ERROR))) ||
5255       !(state->yacc_yyls= (uchar*)
5256         my_realloc(key_memory_bison_stack,
5257                    state->yacc_yyls,
5258                    *yystacksize*sizeof(**yyls),
5259                    MYF(MY_ALLOW_ZERO_PTR | MY_FREE_ON_ERROR))))
5260     return 1;
5261   if (old_info)
5262   {
5263     /*
5264       Only copy the old stack on the first call to my_yyoverflow(),
5265       when replacing a static stack (YYINITDEPTH) by a dynamic stack.
5266       For subsequent calls, my_realloc already did preserve the old stack.
5267     */
5268     memcpy(state->yacc_yyss, *yyss, old_info*sizeof(**yyss));
5269     memcpy(state->yacc_yyvs, *yyvs, old_info*sizeof(**yyvs));
5270     memcpy(state->yacc_yyls, *yyls, old_info*sizeof(**yyls));
5271   }
5272   *yyss= (short*) state->yacc_yyss;
5273   *yyvs= (YYSTYPE*) state->yacc_yyvs;
5274   *yyls= (YYLTYPE*) state->yacc_yyls;
5275   return 0;
5276 }
5277 
5278 
5279 /**
5280   Reset the part of THD responsible for the state of command
5281   processing.
5282 
5283   This needs to be called before execution of every statement
5284   (prepared or conventional).  It is not called by substatements of
5285   routines.
5286 
5287   @todo Remove mysql_reset_thd_for_next_command and only use the
5288   member function.
5289 
5290   @todo Call it after we use THD for queries, not before.
5291 */
mysql_reset_thd_for_next_command(THD * thd)5292 void mysql_reset_thd_for_next_command(THD *thd)
5293 {
5294   thd->reset_for_next_command();
5295 }
5296 
reset_for_next_command()5297 void THD::reset_for_next_command()
5298 {
5299   // TODO: Why on earth is this here?! We should probably fix this
5300   // function and move it to the proper file. /Matz
5301   THD *thd= this;
5302   DBUG_ENTER("mysql_reset_thd_for_next_command");
5303   assert(!thd->sp_runtime_ctx); /* not for substatements of routines */
5304   assert(! thd->in_sub_stmt);
5305   thd->free_list= 0;
5306   /*
5307     Those two lines below are theoretically unneeded as
5308     THD::cleanup_after_query() should take care of this already.
5309   */
5310   thd->auto_inc_intervals_in_cur_stmt_for_binlog.empty();
5311   thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt= 0;
5312 
5313   thd->query_start_usec_used= 0;
5314   thd->is_fatal_error= thd->time_zone_used= 0;
5315   /*
5316     Clear the status flag that are expected to be cleared at the
5317     beginning of each SQL statement.
5318   */
5319   thd->server_status&= ~SERVER_STATUS_CLEAR_SET;
5320   /*
5321     If in autocommit mode and not in a transaction, reset flag
5322     that identifies if a transaction has done some operations
5323     that cannot be safely rolled back.
5324 
5325     If the flag is set an warning message is printed out in
5326     ha_rollback_trans() saying that some tables couldn't be
5327     rolled back.
5328   */
5329   if (!thd->in_multi_stmt_transaction_mode())
5330   {
5331     thd->get_transaction()->reset_unsafe_rollback_flags(
5332         Transaction_ctx::SESSION);
5333   }
5334   assert(thd->security_context()== &thd->m_main_security_ctx);
5335   thd->thread_specific_used= FALSE;
5336 
5337   if (opt_bin_log)
5338   {
5339     thd->user_var_events.clear();
5340     thd->user_var_events_alloc= thd->mem_root;
5341   }
5342   thd->clear_error();
5343   thd->get_stmt_da()->reset_diagnostics_area();
5344   thd->get_stmt_da()->reset_statement_cond_count();
5345 
5346   thd->rand_used= 0;
5347   thd->m_sent_row_count= thd->m_examined_row_count= 0;
5348 
5349   thd->reset_current_stmt_binlog_format_row();
5350   thd->binlog_unsafe_warning_flags= 0;
5351   thd->binlog_need_explicit_defaults_ts= false;
5352 
5353   thd->commit_error= THD::CE_NONE;
5354   thd->durability_property= HA_REGULAR_DURABILITY;
5355   thd->set_trans_pos(NULL, 0);
5356 
5357   thd->derived_tables_processing= false;
5358 
5359   // Need explicit setting, else demand all privileges to a table.
5360   thd->want_privilege= ~NO_ACCESS;
5361 
5362   thd->gtid_executed_warning_issued= false;
5363 
5364   thd->reset_skip_readonly_check();
5365 
5366   DBUG_PRINT("debug",
5367              ("is_current_stmt_binlog_format_row(): %d",
5368               thd->is_current_stmt_binlog_format_row()));
5369 
5370   DBUG_VOID_RETURN;
5371 }
5372 
5373 
5374 /**
5375   Create a select to return the same output as 'SELECT @@var_name'.
5376 
5377   Used for SHOW COUNT(*) [ WARNINGS | ERROR].
5378 
5379   This will crash with a core dump if the variable doesn't exists.
5380 
5381   @param pc                     Current parse context
5382   @param var_name		Variable name
5383 */
5384 
create_select_for_variable(Parse_context * pc,const char * var_name)5385 void create_select_for_variable(Parse_context *pc, const char *var_name)
5386 {
5387   THD *thd= pc->thd;
5388   LEX *lex;
5389   LEX_STRING tmp, null_lex_string;
5390   Item *var;
5391   char buff[MAX_SYS_VAR_LENGTH*2+4+8], *end;
5392   DBUG_ENTER("create_select_for_variable");
5393 
5394   lex= thd->lex;
5395   lex->sql_command= SQLCOM_SELECT;
5396   tmp.str= (char*) var_name;
5397   tmp.length=strlen(var_name);
5398   memset(&null_lex_string, 0, sizeof(null_lex_string));
5399   /*
5400     We set the name of Item to @@session.var_name because that then is used
5401     as the column name in the output.
5402   */
5403   if ((var= get_system_var(pc, OPT_SESSION, tmp, null_lex_string, false)))
5404   {
5405     end= strxmov(buff, "@@session.", var_name, NullS);
5406     var->item_name.copy(buff, end - buff);
5407     add_item_to_list(thd, var);
5408   }
5409   DBUG_VOID_RETURN;
5410 }
5411 
5412 
mysql_init_multi_delete(LEX * lex)5413 void mysql_init_multi_delete(LEX *lex)
5414 {
5415   lex->select_lex->select_limit= 0;
5416   lex->unit->select_limit_cnt= HA_POS_ERROR;
5417   lex->select_lex->table_list.save_and_clear(&lex->auxiliary_table_list);
5418   lex->query_tables= NULL;
5419   lex->query_tables_last= &lex->query_tables;
5420 }
5421 
5422 /*
5423   When you modify mysql_parse(), you may need to mofify
5424   mysql_test_parse_for_slave() in this same file.
5425 */
5426 
5427 /**
5428   Parse a query.
5429 
5430   @param       thd     Current thread
5431   @param       rawbuf  Begining of the query text
5432   @param       length  Length of the query text
5433   @param[out]  found_semicolon For multi queries, position of the character of
5434                                the next query in the query text.
5435 */
5436 
mysql_parse(THD * thd,Parser_state * parser_state)5437 void mysql_parse(THD *thd, Parser_state *parser_state)
5438 {
5439   int error MY_ATTRIBUTE((unused));
5440   DBUG_ENTER("mysql_parse");
5441   DBUG_PRINT("mysql_parse", ("query: '%s'", thd->query().str));
5442 
5443   DBUG_EXECUTE_IF("parser_debug", turn_parser_debug_on(););
5444 
5445   /*
5446     Warning.
5447     The purpose of query_cache_send_result_to_client() is to lookup the
5448     query in the query cache first, to avoid parsing and executing it.
5449     So, the natural implementation would be to:
5450     - first, call query_cache_send_result_to_client,
5451     - second, if caching failed, initialise the lexical and syntactic parser.
5452     The problem is that the query cache depends on a clean initialization
5453     of (among others) lex->safe_to_cache_query and thd->server_status,
5454     which are reset respectively in
5455     - lex_start()
5456     - mysql_reset_thd_for_next_command()
5457     So, initializing the lexical analyser *before* using the query cache
5458     is required for the cache to work properly.
5459     FIXME: cleanup the dependencies in the code to simplify this.
5460   */
5461   mysql_reset_thd_for_next_command(thd);
5462   lex_start(thd);
5463 
5464   thd->m_parser_state= parser_state;
5465   invoke_pre_parse_rewrite_plugins(thd);
5466   thd->m_parser_state= NULL;
5467 
5468   enable_digest_if_any_plugin_needs_it(thd, parser_state);
5469 
5470   if (query_cache.send_result_to_client(thd, thd->query()) <= 0)
5471   {
5472     LEX *lex= thd->lex;
5473     const char *found_semicolon;
5474 
5475     bool err= thd->get_stmt_da()->is_error();
5476 
5477     if (!err)
5478     {
5479       err= parse_sql(thd, parser_state, NULL);
5480       if (!err)
5481         err= invoke_post_parse_rewrite_plugins(thd, false);
5482 
5483       found_semicolon= parser_state->m_lip.found_semicolon;
5484     }
5485 
5486     DEBUG_SYNC_C("sql_parse_before_rewrite");
5487 
5488     if (!err)
5489     {
5490       /*
5491         Rewrite the query for logging and for the Performance Schema
5492         statement tables. (Raw logging happened earlier.)
5493 
5494         Query-cache only handles SELECT, which we don't rewrite, so it's no
5495         concern of ours.
5496 
5497         Sub-routines of mysql_rewrite_query() should try to only rewrite when
5498         necessary (e.g. not do password obfuscation when query contains no
5499         password).
5500 
5501         If rewriting does not happen here, thd->m_rewritten_query is still
5502         empty from being reset in alloc_query().
5503       */
5504 
5505       if (thd->rewritten_query().length() == 0)
5506         mysql_rewrite_query(thd);
5507 
5508       if (thd->rewritten_query().length())
5509       {
5510         lex->safe_to_cache_query= false; // see comments below
5511 
5512         thd->set_query_for_display(thd->rewritten_query().ptr(),
5513                                    thd->rewritten_query().length());
5514       } else if (thd->slave_thread) {
5515         /*
5516           In the slave, we add the information to pfs.events_statements_history,
5517           but not to pfs.threads, as that is what the test suite expects.
5518         */
5519         MYSQL_SET_STATEMENT_TEXT(thd->m_statement_psi,
5520                                  thd->query().str,
5521                                  thd->query().length);
5522       } else {
5523         thd->set_query_for_display(thd->query().str, thd->query().length);
5524       }
5525 
5526       if (!(opt_general_log_raw || thd->slave_thread))
5527       {
5528         if (thd->rewritten_query().length())
5529           query_logger.general_log_write(thd, COM_QUERY,
5530                                          thd->rewritten_query().ptr(),
5531                                          thd->rewritten_query().length());
5532         else
5533         {
5534           size_t qlen= found_semicolon
5535             ? (found_semicolon - thd->query().str)
5536             : thd->query().length;
5537 
5538           query_logger.general_log_write(thd, COM_QUERY,
5539                                          thd->query().str, qlen);
5540         }
5541       }
5542     }
5543 
5544     DEBUG_SYNC_C("sql_parse_after_rewrite");
5545 
5546     if (!err)
5547     {
5548       thd->m_statement_psi= MYSQL_REFINE_STATEMENT(thd->m_statement_psi,
5549                                                    sql_statement_info[thd->lex->sql_command].m_key);
5550 
5551 #ifndef NO_EMBEDDED_ACCESS_CHECKS
5552       if (mqh_used && thd->get_user_connect() &&
5553           check_mqh(thd, lex->sql_command))
5554       {
5555         if (thd->is_classic_protocol())
5556           thd->get_protocol_classic()->get_net()->error = 0;
5557       }
5558       else
5559 #endif
5560       {
5561         if (! thd->is_error())
5562         {
5563           /*
5564             Binlog logs a string starting from thd->query and having length
5565             thd->query_length; so we set thd->query_length correctly (to not
5566             log several statements in one event, when we executed only first).
5567             We set it to not see the ';' (otherwise it would get into binlog
5568             and Query_log_event::print() would give ';;' output).
5569             This also helps display only the current query in SHOW
5570             PROCESSLIST.
5571           */
5572           if (found_semicolon && (ulong) (found_semicolon - thd->query().str))
5573             thd->set_query(thd->query().str,
5574                            static_cast<size_t>(found_semicolon -
5575                                                thd->query().str - 1));
5576           /* Actually execute the query */
5577           if (found_semicolon)
5578           {
5579             lex->safe_to_cache_query= 0;
5580             thd->server_status|= SERVER_MORE_RESULTS_EXISTS;
5581           }
5582           lex->set_trg_event_type_for_tables();
5583           MYSQL_QUERY_EXEC_START(
5584             const_cast<char*>(thd->query().str),
5585             thd->thread_id(),
5586             (char *) (thd->db().str ? thd->db().str : ""),
5587             (char *) thd->security_context()->priv_user().str,
5588             (char *) thd->security_context()->host_or_ip().str,
5589             0);
5590           if (unlikely(thd->security_context()->password_expired() &&
5591                        !lex->is_set_password_sql &&
5592                        lex->sql_command != SQLCOM_SET_OPTION &&
5593                        lex->sql_command != SQLCOM_ALTER_USER))
5594           {
5595             my_error(ER_MUST_CHANGE_PASSWORD, MYF(0));
5596             error= 1;
5597           }
5598           else
5599             error= mysql_execute_command(thd, true);
5600 
5601           MYSQL_QUERY_EXEC_DONE(error);
5602         }
5603       }
5604     }
5605     else
5606     {
5607       /*
5608         Log the failed raw query in the Performance Schema. This statement did not
5609         parse, so there is no way to tell if it may contain a password of not.
5610 
5611         The tradeoff is:
5612           a) If we do log the query, a user typing by accident a broken query
5613              containing a password will have the password exposed. This is very
5614              unlikely, and this behavior can be documented. Remediation is to use
5615              a new password when retyping the corrected query.
5616 
5617           b) If we do not log the query, finding broken queries in the client
5618              application will be much more difficult. This is much more likely.
5619 
5620         Considering that broken queries can typically be generated by attempts at
5621         SQL injection, finding the source of the SQL injection is critical, so the
5622         design choice is to log the query text of broken queries (a).
5623       */
5624       thd->set_query_for_display(thd->query().str, thd->query().length);
5625 
5626       /* Instrument this broken statement as "statement/sql/error" */
5627       thd->m_statement_psi= MYSQL_REFINE_STATEMENT(thd->m_statement_psi,
5628                                           sql_statement_info[SQLCOM_END].m_key);
5629 
5630       assert(thd->is_error());
5631       DBUG_PRINT("info",("Command aborted. Fatal_error: %d",
5632                  thd->is_fatal_error));
5633 
5634       query_cache.abort(&thd->query_cache_tls);
5635     }
5636 
5637     THD_STAGE_INFO(thd, stage_freeing_items);
5638     sp_cache_enforce_limit(thd->sp_proc_cache, stored_program_cache_size);
5639     sp_cache_enforce_limit(thd->sp_func_cache, stored_program_cache_size);
5640     thd->end_statement();
5641     thd->cleanup_after_query();
5642     assert(thd->change_list.is_empty());
5643   }
5644   else
5645   {
5646     /*
5647       Query cache hit. We need to write the general log here if
5648       we haven't already logged the statement earlier due to --log-raw.
5649       Right now, we only cache SELECT results; if the cache ever
5650       becomes more generic, we should also cache the rewritten
5651       query-string together with the original query-string (which
5652       we'd still use for the matching) when we first execute the
5653       query, and then use the obfuscated query-string for logging
5654       here when the query is given again.
5655     */
5656     if (!opt_general_log_raw)
5657       query_logger.general_log_write(thd, COM_QUERY, thd->query().str,
5658                                      thd->query().length);
5659     parser_state->m_lip.found_semicolon= NULL;
5660   }
5661 
5662   DEBUG_SYNC(thd, "query_rewritten");
5663 
5664   DBUG_VOID_RETURN;
5665 }
5666 
5667 
5668 #ifdef HAVE_REPLICATION
5669 /**
5670   Usable by the replication SQL thread only: just parse a query to know if it
5671   can be ignored because of replicate-*-table rules.
5672 
5673   @retval
5674     0	cannot be ignored
5675   @retval
5676     1	can be ignored
5677 */
5678 
mysql_test_parse_for_slave(THD * thd)5679 bool mysql_test_parse_for_slave(THD *thd)
5680 {
5681   LEX *lex= thd->lex;
5682   bool ignorable= false;
5683   sql_digest_state *parent_digest= thd->m_digest;
5684   PSI_statement_locker *parent_locker= thd->m_statement_psi;
5685   DBUG_ENTER("mysql_test_parse_for_slave");
5686 
5687   assert(thd->slave_thread);
5688 
5689   Parser_state parser_state;
5690   if (parser_state.init(thd, thd->query().str, thd->query().length) == 0)
5691   {
5692     lex_start(thd);
5693     mysql_reset_thd_for_next_command(thd);
5694 
5695     thd->m_digest= NULL;
5696     thd->m_statement_psi= NULL;
5697     if (parse_sql(thd, & parser_state, NULL) == 0)
5698     {
5699       if (all_tables_not_ok(thd, lex->select_lex->table_list.first))
5700         ignorable= true;
5701       else if (!check_database_filters(thd,
5702                                        thd->db().str,
5703                                        lex->sql_command))
5704         ignorable= true;
5705     }
5706     thd->m_digest= parent_digest;
5707     thd->m_statement_psi= parent_locker;
5708     thd->end_statement();
5709   }
5710   thd->cleanup_after_query();
5711   DBUG_RETURN(ignorable);
5712 }
5713 #endif
5714 
5715 
5716 
5717 /**
5718   Store field definition for create.
5719 
5720   @return
5721     Return 0 if ok
5722 */
5723 
add_field_to_list(THD * thd,LEX_STRING * field_name,enum_field_types type,char * length,char * decimals,uint type_modifier,Item * default_value,Item * on_update_value,LEX_STRING * comment,char * change,List<String> * interval_list,const CHARSET_INFO * cs,uint uint_geom_type,Generated_column * gcol_info)5724 bool add_field_to_list(THD *thd, LEX_STRING *field_name, enum_field_types type,
5725 		       char *length, char *decimals,
5726 		       uint type_modifier,
5727 		       Item *default_value, Item *on_update_value,
5728                        LEX_STRING *comment,
5729 		       char *change,
5730                        List<String> *interval_list, const CHARSET_INFO *cs,
5731 		       uint uint_geom_type,
5732                        Generated_column *gcol_info)
5733 {
5734   Create_field *new_field;
5735   LEX  *lex= thd->lex;
5736   uint8 datetime_precision= decimals ? atoi(decimals) : 0;
5737   DBUG_ENTER("add_field_to_list");
5738 
5739   LEX_CSTRING field_name_cstr= {field_name->str, field_name->length};
5740 
5741   if (check_string_char_length(field_name_cstr, "", NAME_CHAR_LEN,
5742                                system_charset_info, 1))
5743   {
5744     my_error(ER_TOO_LONG_IDENT, MYF(0), field_name->str); /* purecov: inspected */
5745     DBUG_RETURN(1);				/* purecov: inspected */
5746   }
5747   if (type_modifier & PRI_KEY_FLAG)
5748   {
5749     Key *key;
5750     lex->col_list.push_back(new Key_part_spec(*field_name, 0));
5751     key= new Key(KEYTYPE_PRIMARY, null_lex_str,
5752                       &default_key_create_info,
5753                       0, lex->col_list);
5754     lex->alter_info.key_list.push_back(key);
5755     lex->col_list.empty();
5756   }
5757   if (type_modifier & (UNIQUE_FLAG | UNIQUE_KEY_FLAG))
5758   {
5759     Key *key;
5760     lex->col_list.push_back(new Key_part_spec(*field_name, 0));
5761     key= new Key(KEYTYPE_UNIQUE, null_lex_str,
5762                  &default_key_create_info, 0,
5763                  lex->col_list);
5764     lex->alter_info.key_list.push_back(key);
5765     lex->col_list.empty();
5766   }
5767 
5768   if (default_value)
5769   {
5770     /*
5771       Default value should be literal => basic constants =>
5772       no need fix_fields()
5773 
5774       We allow only CURRENT_TIMESTAMP as function default for the TIMESTAMP or
5775       DATETIME types.
5776     */
5777     if (default_value->type() == Item::FUNC_ITEM &&
5778         (static_cast<Item_func*>(default_value)->functype() !=
5779          Item_func::NOW_FUNC ||
5780          (!real_type_with_now_as_default(type)) ||
5781          default_value->decimals != datetime_precision))
5782     {
5783       my_error(ER_INVALID_DEFAULT, MYF(0), field_name->str);
5784       DBUG_RETURN(1);
5785     }
5786     else if (default_value->type() == Item::NULL_ITEM)
5787     {
5788       default_value= 0;
5789       if ((type_modifier & (NOT_NULL_FLAG | AUTO_INCREMENT_FLAG)) ==
5790 	  NOT_NULL_FLAG)
5791       {
5792 	my_error(ER_INVALID_DEFAULT, MYF(0), field_name->str);
5793 	DBUG_RETURN(1);
5794       }
5795     }
5796     else if (type_modifier & AUTO_INCREMENT_FLAG)
5797     {
5798       my_error(ER_INVALID_DEFAULT, MYF(0), field_name->str);
5799       DBUG_RETURN(1);
5800     }
5801   }
5802 
5803   if (on_update_value &&
5804       (!real_type_with_now_on_update(type) ||
5805        on_update_value->decimals != datetime_precision))
5806   {
5807     my_error(ER_INVALID_ON_UPDATE, MYF(0), field_name->str);
5808     DBUG_RETURN(1);
5809   }
5810 
5811   if (!(new_field= new Create_field()) ||
5812       new_field->init(thd, field_name->str, type, length, decimals, type_modifier,
5813                       default_value, on_update_value, comment, change,
5814                       interval_list, cs, uint_geom_type, gcol_info))
5815     DBUG_RETURN(1);
5816 
5817   lex->alter_info.create_list.push_back(new_field);
5818   lex->last_field=new_field;
5819   DBUG_RETURN(0);
5820 }
5821 
5822 
5823 /** Store position for column in ALTER TABLE .. ADD column. */
5824 
store_position_for_column(const char * name)5825 void store_position_for_column(const char *name)
5826 {
5827   current_thd->lex->last_field->after=(char*) (name);
5828 }
5829 
5830 
5831 /**
5832   save order by and tables in own lists.
5833 */
5834 
add_to_list(SQL_I_List<ORDER> & list,ORDER * order)5835 void add_to_list(SQL_I_List<ORDER> &list, ORDER *order)
5836 {
5837   DBUG_ENTER("add_to_list");
5838   order->item= &order->item_ptr;
5839   order->used_alias= false;
5840   order->used=0;
5841   list.link_in_list(order, &order->next);
5842   DBUG_VOID_RETURN;
5843 }
5844 
5845 
5846 /**
5847   Add a table to list of used tables.
5848 
5849   @param table		Table to add
5850   @param alias		alias for table (or null if no alias)
5851   @param table_options	A set of the following bits:
5852                          - TL_OPTION_UPDATING : Table will be updated
5853                          - TL_OPTION_FORCE_INDEX : Force usage of index
5854                          - TL_OPTION_ALIAS : an alias in multi table DELETE
5855   @param lock_type	How table should be locked
5856   @param mdl_type       Type of metadata lock to acquire on the table.
5857   @param use_index	List of indexed used in USE INDEX
5858   @param ignore_index	List of indexed used in IGNORE INDEX
5859 
5860   @retval
5861       0		Error
5862   @retval
5863     \#	Pointer to TABLE_LIST element added to the total table list
5864 */
5865 
add_table_to_list(THD * thd,Table_ident * table,LEX_STRING * alias,ulong table_options,thr_lock_type lock_type,enum_mdl_type mdl_type,List<Index_hint> * index_hints_arg,List<String> * partition_names,LEX_STRING * option)5866 TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
5867 					     Table_ident *table,
5868 					     LEX_STRING *alias,
5869 					     ulong table_options,
5870 					     thr_lock_type lock_type,
5871 					     enum_mdl_type mdl_type,
5872 					     List<Index_hint> *index_hints_arg,
5873                                              List<String> *partition_names,
5874                                              LEX_STRING *option)
5875 {
5876   TABLE_LIST *ptr;
5877   TABLE_LIST *previous_table_ref= NULL; /* The table preceding the current one. */
5878   const char *alias_str;
5879   LEX *lex= thd->lex;
5880   DBUG_ENTER("add_table_to_list");
5881 
5882   if (!table)
5883     DBUG_RETURN(0);				// End of memory
5884   alias_str= alias ? alias->str : table->table.str;
5885   if (!MY_TEST(table_options & TL_OPTION_ALIAS))
5886   {
5887     enum_ident_name_check ident_check_status=
5888       check_table_name(table->table.str, table->table.length, FALSE);
5889     if (ident_check_status == IDENT_NAME_WRONG)
5890     {
5891       my_error(ER_WRONG_TABLE_NAME, MYF(0), table->table.str);
5892       DBUG_RETURN(0);
5893     }
5894     else if (ident_check_status == IDENT_NAME_TOO_LONG)
5895     {
5896       my_error(ER_TOO_LONG_IDENT, MYF(0), table->table.str);
5897       DBUG_RETURN(0);
5898     }
5899   }
5900   LEX_STRING db= to_lex_string(table->db);
5901   if (table->is_derived_table() == FALSE && table->db.str &&
5902       (check_and_convert_db_name(&db, FALSE) != IDENT_NAME_OK))
5903     DBUG_RETURN(0);
5904 
5905   if (!alias)					/* Alias is case sensitive */
5906   {
5907     if (table->sel)
5908     {
5909       my_message(ER_DERIVED_MUST_HAVE_ALIAS,
5910                  ER(ER_DERIVED_MUST_HAVE_ALIAS), MYF(0));
5911       DBUG_RETURN(0);
5912     }
5913     if (!(alias_str= (char*) thd->memdup(alias_str,table->table.length+1)))
5914       DBUG_RETURN(0);
5915   }
5916   if (!(ptr = (TABLE_LIST *) thd->mem_calloc(sizeof(TABLE_LIST))))
5917     DBUG_RETURN(0);				/* purecov: inspected */
5918   if (table->db.str)
5919   {
5920     ptr->is_fqtn= TRUE;
5921     ptr->db= const_cast<char*>(table->db.str);
5922     ptr->db_length= table->db.length;
5923   }
5924   else if (lex->copy_db_to((char**)&ptr->db, &ptr->db_length))
5925     DBUG_RETURN(0);
5926   else
5927     ptr->is_fqtn= FALSE;
5928 
5929   ptr->alias= const_cast<char*>(alias_str);
5930   ptr->is_alias= alias ? TRUE : FALSE;
5931   if (lower_case_table_names && table->table.length)
5932     table->table.length= my_casedn_str(files_charset_info,
5933                                        const_cast<char*>(table->table.str));
5934   ptr->table_name= const_cast<char*>(table->table.str);
5935   ptr->table_name_length= table->table.length;
5936   ptr->set_tableno(0);
5937   ptr->lock_type=   lock_type;
5938   ptr->updating=    MY_TEST(table_options & TL_OPTION_UPDATING);
5939   /* TODO: remove TL_OPTION_FORCE_INDEX as it looks like it's not used */
5940   ptr->force_index= MY_TEST(table_options & TL_OPTION_FORCE_INDEX);
5941   ptr->ignore_leaves= MY_TEST(table_options & TL_OPTION_IGNORE_LEAVES);
5942   ptr->set_derived_unit(table->sel);
5943   if (!ptr->is_derived() && is_infoschema_db(ptr->db, ptr->db_length))
5944   {
5945     ST_SCHEMA_TABLE *schema_table;
5946     if (ptr->updating &&
5947         /* Special cases which are processed by commands itself */
5948         lex->sql_command != SQLCOM_CHECK &&
5949         lex->sql_command != SQLCOM_CHECKSUM)
5950     {
5951       my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
5952                thd->security_context()->priv_user().str,
5953                thd->security_context()->priv_host().str,
5954                INFORMATION_SCHEMA_NAME.str);
5955       DBUG_RETURN(0);
5956     }
5957     schema_table= find_schema_table(thd, ptr->table_name);
5958     if (!schema_table ||
5959         (schema_table->hidden &&
5960          ((sql_command_flags[lex->sql_command] & CF_STATUS_COMMAND) == 0 ||
5961           /*
5962             this check is used for show columns|keys from I_S hidden table
5963           */
5964           lex->sql_command == SQLCOM_SHOW_FIELDS ||
5965           lex->sql_command == SQLCOM_SHOW_KEYS)))
5966     {
5967       my_error(ER_UNKNOWN_TABLE, MYF(0),
5968                ptr->table_name, INFORMATION_SCHEMA_NAME.str);
5969       DBUG_RETURN(0);
5970     }
5971     ptr->schema_table_name= const_cast<char*>(ptr->table_name);
5972     ptr->schema_table= schema_table;
5973   }
5974   ptr->select_lex= this;
5975   ptr->cacheable_table= 1;
5976   ptr->index_hints= index_hints_arg;
5977   ptr->option= option ? option->str : 0;
5978   /* check that used name is unique */
5979   if (lock_type != TL_IGNORE)
5980   {
5981     TABLE_LIST *first_table= table_list.first;
5982     if (lex->sql_command == SQLCOM_CREATE_VIEW)
5983       first_table= first_table ? first_table->next_local : NULL;
5984     for (TABLE_LIST *tables= first_table ;
5985 	 tables ;
5986 	 tables=tables->next_local)
5987     {
5988       if (!my_strcasecmp(table_alias_charset, alias_str, tables->alias) &&
5989 	  !strcmp(ptr->db, tables->db))
5990       {
5991 	my_error(ER_NONUNIQ_TABLE, MYF(0), alias_str); /* purecov: tested */
5992 	DBUG_RETURN(0);				/* purecov: tested */
5993       }
5994     }
5995   }
5996   /* Store the table reference preceding the current one. */
5997   if (table_list.elements > 0)
5998   {
5999     /*
6000       table_list.next points to the last inserted TABLE_LIST->next_local'
6001       element
6002       We don't use the offsetof() macro here to avoid warnings from gcc
6003     */
6004     previous_table_ref= (TABLE_LIST*) ((char*) table_list.next -
6005                                        ((char*) &(ptr->next_local) -
6006                                         (char*) ptr));
6007     /*
6008       Set next_name_resolution_table of the previous table reference to point
6009       to the current table reference. In effect the list
6010       TABLE_LIST::next_name_resolution_table coincides with
6011       TABLE_LIST::next_local. Later this may be changed in
6012       store_top_level_join_columns() for NATURAL/USING joins.
6013     */
6014     previous_table_ref->next_name_resolution_table= ptr;
6015   }
6016 
6017   /*
6018     Link the current table reference in a local list (list for current select).
6019     Notice that as a side effect here we set the next_local field of the
6020     previous table reference to 'ptr'. Here we also add one element to the
6021     list 'table_list'.
6022   */
6023   table_list.link_in_list(ptr, &ptr->next_local);
6024   ptr->next_name_resolution_table= NULL;
6025   ptr->partition_names= partition_names;
6026   /* Link table in global list (all used tables) */
6027   lex->add_to_query_tables(ptr);
6028 
6029   // Pure table aliases do not need to be locked:
6030   if (!MY_TEST(table_options & TL_OPTION_ALIAS))
6031   {
6032     MDL_REQUEST_INIT(& ptr->mdl_request,
6033                      MDL_key::TABLE, ptr->db, ptr->table_name, mdl_type,
6034                      MDL_TRANSACTION);
6035   }
6036   if (table->is_derived_table())
6037   {
6038     ptr->derived_key_list.empty();
6039     derived_table_count++;
6040   }
6041   DBUG_RETURN(ptr);
6042 }
6043 
6044 
6045 /**
6046   Initialize a new table list for a nested join.
6047 
6048     The function initializes a structure of the TABLE_LIST type
6049     for a nested join. It sets up its nested join list as empty.
6050     The created structure is added to the front of the current
6051     join list in the st_select_lex object. Then the function
6052     changes the current nest level for joins to refer to the newly
6053     created empty list after having saved the info on the old level
6054     in the initialized structure.
6055 
6056   @param thd         current thread
6057 
6058   @retval
6059     0   if success
6060   @retval
6061     1   otherwise
6062 */
6063 
init_nested_join(THD * thd)6064 bool st_select_lex::init_nested_join(THD *thd)
6065 {
6066   DBUG_ENTER("init_nested_join");
6067 
6068   TABLE_LIST *const ptr=
6069     TABLE_LIST::new_nested_join(thd->mem_root, "(nested_join)",
6070                                 embedding, join_list, this);
6071   if (ptr == NULL)
6072     DBUG_RETURN(true);
6073 
6074   join_list->push_front(ptr);
6075   embedding= ptr;
6076   join_list= &ptr->nested_join->join_list;
6077 
6078   DBUG_RETURN(false);
6079 }
6080 
6081 
6082 /**
6083   End a nested join table list.
6084 
6085     The function returns to the previous join nest level.
6086     If the current level contains only one member, the function
6087     moves it one level up, eliminating the nest.
6088 
6089   @param thd         current thread
6090 
6091   @return
6092     - Pointer to TABLE_LIST element added to the total table list, if success
6093     - 0, otherwise
6094 */
6095 
end_nested_join(THD * thd)6096 TABLE_LIST *st_select_lex::end_nested_join(THD *thd)
6097 {
6098   TABLE_LIST *ptr;
6099   NESTED_JOIN *nested_join;
6100   DBUG_ENTER("end_nested_join");
6101 
6102   assert(embedding);
6103   ptr= embedding;
6104   join_list= ptr->join_list;
6105   embedding= ptr->embedding;
6106   nested_join= ptr->nested_join;
6107   if (nested_join->join_list.elements == 1)
6108   {
6109     TABLE_LIST *embedded= nested_join->join_list.head();
6110     join_list->pop();
6111     embedded->join_list= join_list;
6112     embedded->embedding= embedding;
6113     join_list->push_front(embedded);
6114     ptr= embedded;
6115   }
6116   else if (nested_join->join_list.elements == 0)
6117   {
6118     join_list->pop();
6119     ptr= 0;                                     // return value
6120   }
6121   DBUG_RETURN(ptr);
6122 }
6123 
6124 
6125 /**
6126   Nest last join operation.
6127 
6128     The function nest last join operation as if it was enclosed in braces.
6129 
6130   @param thd         current thread
6131 
6132   @retval
6133     0  Error
6134   @retval
6135     \#  Pointer to TABLE_LIST element created for the new nested join
6136 */
6137 
nest_last_join(THD * thd)6138 TABLE_LIST *st_select_lex::nest_last_join(THD *thd)
6139 {
6140   DBUG_ENTER("nest_last_join");
6141 
6142   TABLE_LIST *const ptr=
6143     TABLE_LIST::new_nested_join(thd->mem_root, "(nest_last_join)",
6144                                 embedding, join_list, this);
6145   if (ptr == NULL)
6146     DBUG_RETURN(NULL);
6147 
6148   List<TABLE_LIST> *const embedded_list= &ptr->nested_join->join_list;
6149 
6150   for (uint i=0; i < 2; i++)
6151   {
6152     TABLE_LIST *table= join_list->pop();
6153     table->join_list= embedded_list;
6154     table->embedding= ptr;
6155     embedded_list->push_back(table);
6156     if (table->natural_join)
6157     {
6158       ptr->is_natural_join= TRUE;
6159       /*
6160         If this is a JOIN ... USING, move the list of joined fields to the
6161         table reference that describes the join.
6162       */
6163       if (prev_join_using)
6164         ptr->join_using_fields= prev_join_using;
6165     }
6166   }
6167   join_list->push_front(ptr);
6168 
6169   DBUG_RETURN(ptr);
6170 }
6171 
6172 
6173 /**
6174   Add a table to the current join list.
6175 
6176     The function puts a table in front of the current join list
6177     of st_select_lex object.
6178     Thus, joined tables are put into this list in the reverse order
6179     (the most outer join operation follows first).
6180 
6181   @param table       the table to add
6182 
6183   @return
6184     None
6185 */
6186 
add_joined_table(TABLE_LIST * table)6187 void st_select_lex::add_joined_table(TABLE_LIST *table)
6188 {
6189   DBUG_ENTER("add_joined_table");
6190   join_list->push_front(table);
6191   table->join_list= join_list;
6192   table->embedding= embedding;
6193   DBUG_VOID_RETURN;
6194 }
6195 
6196 
6197 /**
6198   Convert a right join into equivalent left join.
6199 
6200     The function takes the current join list t[0],t[1] ... and
6201     effectively converts it into the list t[1],t[0] ...
6202     Although the outer_join flag for the new nested table contains
6203     JOIN_TYPE_RIGHT, it will be handled as the inner table of a left join
6204     operation.
6205 
6206   EXAMPLES
6207   @verbatim
6208     SELECT * FROM t1 RIGHT JOIN t2 ON on_expr =>
6209       SELECT * FROM t2 LEFT JOIN t1 ON on_expr
6210 
6211     SELECT * FROM t1,t2 RIGHT JOIN t3 ON on_expr =>
6212       SELECT * FROM t1,t3 LEFT JOIN t2 ON on_expr
6213 
6214     SELECT * FROM t1,t2 RIGHT JOIN (t3,t4) ON on_expr =>
6215       SELECT * FROM t1,(t3,t4) LEFT JOIN t2 ON on_expr
6216 
6217     SELECT * FROM t1 LEFT JOIN t2 ON on_expr1 RIGHT JOIN t3  ON on_expr2 =>
6218       SELECT * FROM t3 LEFT JOIN (t1 LEFT JOIN t2 ON on_expr2) ON on_expr1
6219    @endverbatim
6220 
6221   @param thd         current thread
6222 
6223   @return
6224     - Pointer to the table representing the inner table, if success
6225     - 0, otherwise
6226 */
6227 
convert_right_join()6228 TABLE_LIST *st_select_lex::convert_right_join()
6229 {
6230   TABLE_LIST *tab2= join_list->pop();
6231   TABLE_LIST *tab1= join_list->pop();
6232   DBUG_ENTER("convert_right_join");
6233 
6234   join_list->push_front(tab2);
6235   join_list->push_front(tab1);
6236   tab1->outer_join|= JOIN_TYPE_RIGHT;
6237 
6238   DBUG_RETURN(tab1);
6239 }
6240 
6241 /**
6242   Set lock for all tables in current select level.
6243 
6244   @param lock_type			Lock to set for tables
6245 
6246   @note
6247     If lock is a write lock, then tables->updating is set 1
6248     This is to get tables_ok to know that the table is updated by the
6249     query
6250     Set type of metadata lock to request according to lock_type.
6251 */
6252 
set_lock_for_tables(thr_lock_type lock_type)6253 void st_select_lex::set_lock_for_tables(thr_lock_type lock_type)
6254 {
6255   bool for_update= lock_type >= TL_READ_NO_INSERT;
6256   enum_mdl_type mdl_type= mdl_type_for_dml(lock_type);
6257   DBUG_ENTER("set_lock_for_tables");
6258   DBUG_PRINT("enter", ("lock_type: %d  for_update: %d", lock_type,
6259 		       for_update));
6260   for (TABLE_LIST *tables= table_list.first;
6261        tables;
6262        tables= tables->next_local)
6263   {
6264     tables->lock_type= lock_type;
6265     tables->updating=  for_update;
6266     tables->mdl_request.set_type(mdl_type);
6267   }
6268   DBUG_VOID_RETURN;
6269 }
6270 
6271 
6272 /**
6273   Create a fake SELECT_LEX for a unit.
6274 
6275     The method create a fake SELECT_LEX object for a unit.
6276     This object is created for any union construct containing a union
6277     operation and also for any single select union construct of the form
6278     @verbatim
6279     (SELECT ... ORDER BY order_list [LIMIT n]) ORDER BY ...
6280     @endvarbatim
6281     or of the form
6282     @varbatim
6283     (SELECT ... ORDER BY LIMIT n) ORDER BY ...
6284     @endvarbatim
6285 
6286   @param thd_arg       thread handle
6287 
6288   @note
6289     The object is used to retrieve rows from the temporary table
6290     where the result on the union is obtained.
6291 
6292   @retval
6293     1     on failure to create the object
6294   @retval
6295     0     on success
6296 */
6297 
add_fake_select_lex(THD * thd_arg)6298 bool st_select_lex_unit::add_fake_select_lex(THD *thd_arg)
6299 {
6300   SELECT_LEX *first_sl= first_select();
6301   DBUG_ENTER("add_fake_select_lex");
6302   assert(!fake_select_lex);
6303   assert(thd_arg == thd);
6304 
6305   if (!(fake_select_lex= thd_arg->lex->new_empty_query_block()))
6306     DBUG_RETURN(true);       /* purecov: inspected */
6307   fake_select_lex->include_standalone(this, &fake_select_lex);
6308   fake_select_lex->select_number= INT_MAX;
6309   fake_select_lex->linkage= GLOBAL_OPTIONS_TYPE;
6310   fake_select_lex->select_limit= 0;
6311 
6312   fake_select_lex->set_context(first_sl->context.outer_context);
6313 
6314   /* allow item list resolving in fake select for ORDER BY */
6315   fake_select_lex->context.resolve_in_select_list= TRUE;
6316 
6317   if (!is_union())
6318   {
6319     /*
6320       This works only for
6321       (SELECT ... ORDER BY list [LIMIT n]) ORDER BY order_list [LIMIT m],
6322       (SELECT ... LIMIT n) ORDER BY order_list [LIMIT m]
6323       just before the parser starts processing order_list
6324     */
6325     fake_select_lex->no_table_names_allowed= 1;
6326   }
6327   thd->lex->pop_context();
6328   DBUG_RETURN(false);
6329 }
6330 
6331 
6332 /**
6333   Push a new name resolution context for a JOIN ... ON clause to the
6334   context stack of a query block.
6335 
6336     Create a new name resolution context for a JOIN ... ON clause,
6337     set the first and last leaves of the list of table references
6338     to be used for name resolution, and push the newly created
6339     context to the stack of contexts of the query.
6340 
6341   @param pc        current parse context
6342   @param left_op   left  operand of the JOIN
6343   @param right_op  rigth operand of the JOIN
6344 
6345   @todo Research if we should set the "outer_context" member of the new ON
6346   context.
6347 
6348   @retval
6349     FALSE  if all is OK
6350   @retval
6351     TRUE   if a memory allocation error occured
6352 */
6353 
6354 bool
push_new_name_resolution_context(Parse_context * pc,TABLE_LIST * left_op,TABLE_LIST * right_op)6355 push_new_name_resolution_context(Parse_context *pc,
6356                                  TABLE_LIST *left_op, TABLE_LIST *right_op)
6357 {
6358   THD *thd= pc->thd;
6359   Name_resolution_context *on_context;
6360   if (!(on_context= new (thd->mem_root) Name_resolution_context))
6361     return TRUE;
6362   on_context->init();
6363   on_context->first_name_resolution_table=
6364     left_op->first_leaf_for_name_resolution();
6365   on_context->last_name_resolution_table=
6366     right_op->last_leaf_for_name_resolution();
6367   on_context->select_lex= pc->select;
6368   on_context->next_context= pc->select->first_context;
6369   pc->select->first_context= on_context;
6370 
6371   return thd->lex->push_context(on_context);
6372 }
6373 
6374 
6375 /**
6376   Add an ON condition to the second operand of a JOIN ... ON.
6377 
6378     Add an ON condition to the right operand of a JOIN ... ON clause.
6379 
6380   @param b     the second operand of a JOIN ... ON
6381   @param expr  the condition to be added to the ON clause
6382 */
6383 
add_join_on(TABLE_LIST * b,Item * expr)6384 void add_join_on(TABLE_LIST *b, Item *expr)
6385 {
6386   if (expr)
6387   {
6388     b->set_join_cond_optim((Item*)1); // m_join_cond_optim is not ready
6389     if (!b->join_cond())
6390       b->set_join_cond(expr);
6391     else
6392     {
6393       /*
6394         If called from the parser, this happens if you have both a
6395         right and left join. If called later, it happens if we add more
6396         than one condition to the ON clause.
6397       */
6398       b->set_join_cond(new Item_cond_and(b->join_cond(), expr));
6399     }
6400     b->join_cond()->top_level_item();
6401   }
6402 }
6403 
6404 
6405 /**
6406   Mark that there is a NATURAL JOIN or JOIN ... USING between two
6407   tables.
6408 
6409     This function marks that table b should be joined with a either via
6410     a NATURAL JOIN or via JOIN ... USING. Both join types are special
6411     cases of each other, so we treat them together. The function
6412     setup_conds() creates a list of equal condition between all fields
6413     of the same name for NATURAL JOIN or the fields in 'using_fields'
6414     for JOIN ... USING. The list of equality conditions is stored
6415     either in b->join_cond(), or in JOIN::conds, depending on whether there
6416     was an outer join.
6417 
6418   EXAMPLE
6419   @verbatim
6420     SELECT * FROM t1 NATURAL LEFT JOIN t2
6421      <=>
6422     SELECT * FROM t1 LEFT JOIN t2 ON (t1.i=t2.i and t1.j=t2.j ... )
6423 
6424     SELECT * FROM t1 NATURAL JOIN t2 WHERE <some_cond>
6425      <=>
6426     SELECT * FROM t1, t2 WHERE (t1.i=t2.i and t1.j=t2.j and <some_cond>)
6427 
6428     SELECT * FROM t1 JOIN t2 USING(j) WHERE <some_cond>
6429      <=>
6430     SELECT * FROM t1, t2 WHERE (t1.j=t2.j and <some_cond>)
6431    @endverbatim
6432 
6433   @param a		  Left join argument
6434   @param b		  Right join argument
6435   @param using_fields    Field names from USING clause
6436 */
6437 
add_join_natural(TABLE_LIST * a,TABLE_LIST * b,List<String> * using_fields,SELECT_LEX * lex)6438 void add_join_natural(TABLE_LIST *a, TABLE_LIST *b, List<String> *using_fields,
6439                       SELECT_LEX *lex)
6440 {
6441   b->natural_join= a;
6442   lex->prev_join_using= using_fields;
6443 }
6444 
6445 
6446 /**
6447   kill on thread.
6448 
6449   @param thd			Thread class
6450   @param id			Thread id
6451   @param only_kill_query        Should it kill the query or the connection
6452 
6453   @note
6454     This is written such that we have a short lock on LOCK_thd_list
6455 */
6456 
6457 
kill_one_thread(THD * thd,my_thread_id id,bool only_kill_query)6458 static uint kill_one_thread(THD *thd, my_thread_id id, bool only_kill_query)
6459 {
6460   THD *tmp= NULL;
6461   uint error=ER_NO_SUCH_THREAD;
6462   Find_thd_with_id find_thd_with_id(id);
6463 
6464   DBUG_ENTER("kill_one_thread");
6465   DBUG_PRINT("enter", ("id=%u only_kill=%d", id, only_kill_query));
6466   tmp= Global_THD_manager::get_instance()->find_thd(&find_thd_with_id);
6467   if (tmp)
6468   {
6469     /*
6470       If we're SUPER, we can KILL anything, including system-threads.
6471       No further checks.
6472 
6473       KILLer: thd->m_security_ctx->user could in theory be NULL while
6474       we're still in "unauthenticated" state. This is a theoretical
6475       case (the code suggests this could happen, so we play it safe).
6476 
6477       KILLee: tmp->m_security_ctx->user will be NULL for system threads.
6478       We need to check so Jane Random User doesn't crash the server
6479       when trying to kill a) system threads or b) unauthenticated users'
6480       threads (Bug#43748).
6481 
6482       If user of both killer and killee are non-NULL, proceed with
6483       slayage if both are string-equal.
6484     */
6485 
6486     if ((thd->security_context()->check_access(SUPER_ACL)) ||
6487         thd->security_context()->user_matches(tmp->security_context()))
6488     {
6489       /* process the kill only if thread is not already undergoing any kill
6490          connection.
6491       */
6492       if (tmp->killed != THD::KILL_CONNECTION)
6493       {
6494         tmp->awake(only_kill_query ? THD::KILL_QUERY : THD::KILL_CONNECTION);
6495       }
6496       error= 0;
6497     }
6498     else
6499       error=ER_KILL_DENIED_ERROR;
6500     mysql_mutex_unlock(&tmp->LOCK_thd_data);
6501   }
6502   DEBUG_SYNC(thd, "kill_thd_end");
6503   DBUG_PRINT("exit", ("%d", error));
6504   DBUG_RETURN(error);
6505 }
6506 
6507 
6508 /*
6509   kills a thread and sends response
6510 
6511   SYNOPSIS
6512     sql_kill()
6513     thd			Thread class
6514     id			Thread id
6515     only_kill_query     Should it kill the query or the connection
6516 */
6517 
6518 static
sql_kill(THD * thd,my_thread_id id,bool only_kill_query)6519 void sql_kill(THD *thd, my_thread_id id, bool only_kill_query)
6520 {
6521   uint error;
6522   if (!(error= kill_one_thread(thd, id, only_kill_query)))
6523   {
6524     if (! thd->killed)
6525       my_ok(thd);
6526   }
6527   else
6528     my_error(error, MYF(0), id);
6529 }
6530 
6531 /**
6532   This class implements callback function used by killall_non_super_threads
6533   to kill all threads that do not have the SUPER privilege
6534 */
6535 
6536 class Kill_non_super_conn : public Do_THD_Impl
6537 {
6538 private:
6539   /* THD of connected client. */
6540   THD *m_client_thd;
6541 
6542 public:
Kill_non_super_conn(THD * thd)6543   Kill_non_super_conn(THD *thd) :
6544 	    m_client_thd(thd)
6545   {
6546     assert(m_client_thd->security_context()->check_access(SUPER_ACL));
6547   }
6548 
operator ()(THD * thd_to_kill)6549   virtual void operator()(THD *thd_to_kill)
6550   {
6551     mysql_mutex_lock(&thd_to_kill->LOCK_thd_data);
6552 
6553     /* Kill only if non super thread and non slave thread.
6554        If an account has not yet been assigned to the security context of the
6555        thread we cannot tell if the account is super user or not. In this case
6556        we cannot kill that thread. In offline mode, after the account is
6557        assigned to this thread and it turns out it is not super user thread,
6558        the authentication for this thread will fail and the thread will be
6559        terminated.
6560     */
6561     if (thd_to_kill->security_context()->has_account_assigned()
6562   && !(thd_to_kill->security_context()->check_access(SUPER_ACL))
6563 	&& thd_to_kill->killed != THD::KILL_CONNECTION
6564 	&& !thd_to_kill->slave_thread)
6565       thd_to_kill->awake(THD::KILL_CONNECTION);
6566 
6567     mysql_mutex_unlock(&thd_to_kill->LOCK_thd_data);
6568   }
6569 };
6570 
6571 /*
6572   kills all the threads that do not have the
6573   SUPER privilege.
6574 
6575   SYNOPSIS
6576     killall_non_super_threads()
6577     thd                 Thread class
6578 */
6579 
killall_non_super_threads(THD * thd)6580 void killall_non_super_threads(THD *thd)
6581 {
6582   Kill_non_super_conn kill_non_super_conn(thd);
6583   Global_THD_manager *thd_manager= Global_THD_manager::get_instance();
6584   thd_manager->do_for_all_thd(&kill_non_super_conn);
6585 }
6586 
6587 /** If pointer is not a null pointer, append filename to it. */
6588 
append_file_to_dir(THD * thd,const char ** filename_ptr,const char * table_name)6589 bool append_file_to_dir(THD *thd, const char **filename_ptr,
6590                         const char *table_name)
6591 {
6592   char buff[FN_REFLEN],*ptr, *end;
6593   if (!*filename_ptr)
6594     return 0;					// nothing to do
6595 
6596   /* Check that the filename is not too long and it's a hard path */
6597   if (strlen(*filename_ptr)+strlen(table_name) >= FN_REFLEN-1 ||
6598       !test_if_hard_path(*filename_ptr))
6599   {
6600     my_error(ER_WRONG_TABLE_NAME, MYF(0), *filename_ptr);
6601     return 1;
6602   }
6603   /* Fix is using unix filename format on dos */
6604   my_stpcpy(buff,*filename_ptr);
6605   end=convert_dirname(buff, *filename_ptr, NullS);
6606   if (!(ptr= (char*) thd->alloc((size_t) (end-buff) + strlen(table_name)+1)))
6607     return 1;					// End of memory
6608   *filename_ptr=ptr;
6609   strxmov(ptr,buff,table_name,NullS);
6610   return 0;
6611 }
6612 
6613 
comp_eq_creator(bool invert)6614 Comp_creator *comp_eq_creator(bool invert)
6615 {
6616   return invert?(Comp_creator *)&ne_creator:(Comp_creator *)&eq_creator;
6617 }
6618 
comp_equal_creator(bool invert)6619 Comp_creator *comp_equal_creator(bool invert)
6620 {
6621   assert(!invert); // Function never called with true.
6622   return &equal_creator;
6623 }
6624 
6625 
comp_ge_creator(bool invert)6626 Comp_creator *comp_ge_creator(bool invert)
6627 {
6628   return invert?(Comp_creator *)&lt_creator:(Comp_creator *)&ge_creator;
6629 }
6630 
6631 
comp_gt_creator(bool invert)6632 Comp_creator *comp_gt_creator(bool invert)
6633 {
6634   return invert?(Comp_creator *)&le_creator:(Comp_creator *)&gt_creator;
6635 }
6636 
6637 
comp_le_creator(bool invert)6638 Comp_creator *comp_le_creator(bool invert)
6639 {
6640   return invert?(Comp_creator *)&gt_creator:(Comp_creator *)&le_creator;
6641 }
6642 
6643 
comp_lt_creator(bool invert)6644 Comp_creator *comp_lt_creator(bool invert)
6645 {
6646   return invert?(Comp_creator *)&ge_creator:(Comp_creator *)&lt_creator;
6647 }
6648 
6649 
comp_ne_creator(bool invert)6650 Comp_creator *comp_ne_creator(bool invert)
6651 {
6652   return invert?(Comp_creator *)&eq_creator:(Comp_creator *)&ne_creator;
6653 }
6654 
6655 
6656 /**
6657   Construct ALL/ANY/SOME subquery Item.
6658 
6659   @param left_expr   pointer to left expression
6660   @param cmp         compare function creator
6661   @param all         true if we create ALL subquery
6662   @param select_lex  pointer on parsed subquery structure
6663 
6664   @return
6665     constructed Item (or 0 if out of memory)
6666 */
all_any_subquery_creator(Item * left_expr,chooser_compare_func_creator cmp,bool all,SELECT_LEX * select_lex)6667 Item * all_any_subquery_creator(Item *left_expr,
6668 				chooser_compare_func_creator cmp,
6669 				bool all,
6670 				SELECT_LEX *select_lex)
6671 {
6672   if ((cmp == &comp_eq_creator) && !all)       //  = ANY <=> IN
6673     return new Item_in_subselect(left_expr, select_lex);
6674 
6675   if ((cmp == &comp_ne_creator) && all)        // <> ALL <=> NOT IN
6676     return new Item_func_not(new Item_in_subselect(left_expr, select_lex));
6677 
6678   Item_allany_subselect *it=
6679     new Item_allany_subselect(left_expr, cmp, select_lex, all);
6680   if (all)
6681     return it->upper_item= new Item_func_not_all(it);	/* ALL */
6682 
6683   return it->upper_item= new Item_func_nop_all(it);      /* ANY/SOME */
6684 }
6685 
6686 
6687 /**
6688    Set proper open mode and table type for element representing target table
6689    of CREATE TABLE statement, also adjust statement table list if necessary.
6690 */
6691 
create_table_set_open_action_and_adjust_tables(LEX * lex)6692 void create_table_set_open_action_and_adjust_tables(LEX *lex)
6693 {
6694   TABLE_LIST *create_table= lex->query_tables;
6695 
6696   if (lex->create_info.options & HA_LEX_CREATE_TMP_TABLE)
6697     create_table->open_type= OT_TEMPORARY_ONLY;
6698   else
6699     create_table->open_type= OT_BASE_ONLY;
6700 
6701   if (!lex->select_lex->item_list.elements)
6702   {
6703     /*
6704       Avoid opening and locking target table for ordinary CREATE TABLE
6705       or CREATE TABLE LIKE for write (unlike in CREATE ... SELECT we
6706       won't do any insertions in it anyway). Not doing this causes
6707       problems when running CREATE TABLE IF NOT EXISTS for already
6708       existing log table.
6709     */
6710     create_table->lock_type= TL_READ;
6711   }
6712 }
6713 
6714 
6715 /**
6716   negate given expression.
6717 
6718   @param pc   current parse context
6719   @param expr expression for negation
6720 
6721   @return
6722     negated expression
6723 */
6724 
negate_expression(Parse_context * pc,Item * expr)6725 Item *negate_expression(Parse_context *pc, Item *expr)
6726 {
6727   Item *negated;
6728   if (expr->type() == Item::FUNC_ITEM &&
6729       ((Item_func *) expr)->functype() == Item_func::NOT_FUNC)
6730   {
6731     /* it is NOT(NOT( ... )) */
6732     Item *arg= ((Item_func *) expr)->arguments()[0];
6733     enum_parsing_context place= pc->select->parsing_place;
6734     if (arg->is_bool_func() || place == CTX_WHERE || place == CTX_HAVING)
6735       return arg;
6736     /*
6737       if it is not boolean function then we have to emulate value of
6738       not(not(a)), it will be a != 0
6739     */
6740     return new Item_func_ne(arg, new Item_int_0());
6741   }
6742 
6743   if ((negated= expr->neg_transformer(pc->thd)) != 0)
6744     return negated;
6745   return new Item_func_not(expr);
6746 }
6747 
6748 /**
6749   Set the specified definer to the default value, which is the
6750   current user in the thread.
6751 
6752   @param[in]  thd       thread handler
6753   @param[out] definer   definer
6754 */
6755 
get_default_definer(THD * thd,LEX_USER * definer)6756 void get_default_definer(THD *thd, LEX_USER *definer)
6757 {
6758   const Security_context *sctx= thd->security_context();
6759 
6760   definer->user.str= (char *) sctx->priv_user().str;
6761   definer->user.length= strlen(definer->user.str);
6762 
6763   definer->host.str= (char *) sctx->priv_host().str;
6764   definer->host.length= strlen(definer->host.str);
6765 
6766   definer->plugin= EMPTY_CSTR;
6767   definer->auth= NULL_CSTR;
6768   definer->uses_identified_with_clause= false;
6769   definer->uses_identified_by_clause= false;
6770   definer->uses_authentication_string_clause= false;
6771   definer->uses_identified_by_password_clause= false;
6772   definer->alter_status.update_password_expired_column= false;
6773   definer->alter_status.use_default_password_lifetime= true;
6774   definer->alter_status.expire_after_days= 0;
6775   definer->alter_status.update_account_locked_column= false;
6776   definer->alter_status.account_locked= false;
6777 }
6778 
6779 
6780 /**
6781   Create default definer for the specified THD.
6782 
6783   @param[in] thd         thread handler
6784 
6785   @return
6786     - On success, return a valid pointer to the created and initialized
6787     LEX_USER, which contains definer information.
6788     - On error, return 0.
6789 */
6790 
create_default_definer(THD * thd)6791 LEX_USER *create_default_definer(THD *thd)
6792 {
6793   LEX_USER *definer;
6794 
6795   if (! (definer= (LEX_USER*) thd->alloc(sizeof(LEX_USER))))
6796     return 0;
6797 
6798   thd->get_definer(definer);
6799 
6800   return definer;
6801 }
6802 
6803 
6804 /**
6805   Retuns information about user or current user.
6806 
6807   @param[in] thd          thread handler
6808   @param[in] user         user
6809 
6810   @return
6811     - On success, return a valid pointer to initialized
6812     LEX_USER, which contains user information.
6813     - On error, return 0.
6814 */
6815 
get_current_user(THD * thd,LEX_USER * user)6816 LEX_USER *get_current_user(THD *thd, LEX_USER *user)
6817 {
6818   if (!user->user.str)  // current_user
6819   {
6820     LEX_USER *default_definer= create_default_definer(thd);
6821     if (default_definer)
6822     {
6823       /*
6824         Inherit parser semantics from the statement in which the user parameter
6825         was used.
6826         This is needed because a st_lex_user is both used as a component in an
6827         AST and as a specifier for a particular user in the ACL subsystem.
6828       */
6829       default_definer->uses_authentication_string_clause=
6830         user->uses_authentication_string_clause;
6831       default_definer->uses_identified_by_clause=
6832         user->uses_identified_by_clause;
6833       default_definer->uses_identified_by_password_clause=
6834         user->uses_identified_by_password_clause;
6835       default_definer->uses_identified_with_clause=
6836         user->uses_identified_with_clause;
6837       default_definer->plugin.str= user->plugin.str;
6838       default_definer->plugin.length= user->plugin.length;
6839       default_definer->auth.str= user->auth.str;
6840       default_definer->auth.length= user->auth.length;
6841       default_definer->alter_status= user->alter_status;
6842 
6843       return default_definer;
6844     }
6845   }
6846 
6847   return user;
6848 }
6849 
6850 
6851 /**
6852   Check that byte length of a string does not exceed some limit.
6853 
6854   @param str         string to be checked
6855   @param err_msg     error message to be displayed if the string is too long
6856   @param max_length  max length
6857 
6858   @retval
6859     FALSE   the passed string is not longer than max_length
6860   @retval
6861     TRUE    the passed string is longer than max_length
6862 
6863   NOTE
6864     The function is not used in existing code but can be useful later?
6865 */
6866 
check_string_byte_length(const LEX_CSTRING & str,const char * err_msg,size_t max_byte_length)6867 static bool check_string_byte_length(const LEX_CSTRING &str,
6868                                      const char *err_msg,
6869                                      size_t max_byte_length)
6870 {
6871   if (str.length <= max_byte_length)
6872     return FALSE;
6873 
6874   my_error(ER_WRONG_STRING_LENGTH, MYF(0), str.str, err_msg, max_byte_length);
6875 
6876   return TRUE;
6877 }
6878 
6879 
6880 /*
6881   Check that char length of a string does not exceed some limit.
6882 
6883   SYNOPSIS
6884   check_string_char_length()
6885       str              string to be checked
6886       err_msg          error message to be displayed if the string is too long
6887       max_char_length  max length in symbols
6888       cs               string charset
6889 
6890   RETURN
6891     FALSE   the passed string is not longer than max_char_length
6892     TRUE    the passed string is longer than max_char_length
6893 */
6894 
6895 
check_string_char_length(const LEX_CSTRING & str,const char * err_msg,size_t max_char_length,const CHARSET_INFO * cs,bool no_error)6896 bool check_string_char_length(const LEX_CSTRING &str, const char *err_msg,
6897                               size_t max_char_length, const CHARSET_INFO *cs,
6898                               bool no_error)
6899 {
6900   int well_formed_error;
6901   size_t res= cs->cset->well_formed_len(cs, str.str, str.str + str.length,
6902                                         max_char_length, &well_formed_error);
6903 
6904   if (!well_formed_error &&  str.length == res)
6905     return FALSE;
6906 
6907   if (!no_error)
6908   {
6909     ErrConvString err(str.str, str.length, cs);
6910     my_error(ER_WRONG_STRING_LENGTH, MYF(0), err.ptr(), err_msg, max_char_length);
6911   }
6912   return TRUE;
6913 }
6914 
6915 
6916 /*
6917   Check if path does not contain mysql data home directory
6918   SYNOPSIS
6919     test_if_data_home_dir()
6920     dir                     directory
6921     conv_home_dir           converted data home directory
6922     home_dir_len            converted data home directory length
6923 
6924   RETURN VALUES
6925     0	ok
6926     1	error
6927 */
6928 C_MODE_START
6929 
test_if_data_home_dir(const char * dir)6930 int test_if_data_home_dir(const char *dir)
6931 {
6932   char path[FN_REFLEN];
6933   size_t dir_len;
6934   DBUG_ENTER("test_if_data_home_dir");
6935 
6936   if (!dir)
6937     DBUG_RETURN(0);
6938 
6939   (void) fn_format(path, dir, "", "",
6940                    (MY_RETURN_REAL_PATH|MY_RESOLVE_SYMLINKS));
6941   dir_len= strlen(path);
6942   if (mysql_unpacked_real_data_home_len<= dir_len)
6943   {
6944     if (dir_len > mysql_unpacked_real_data_home_len &&
6945         path[mysql_unpacked_real_data_home_len] != FN_LIBCHAR)
6946       DBUG_RETURN(0);
6947 
6948     if (lower_case_file_system)
6949     {
6950       if (!my_strnncoll(default_charset_info, (const uchar*) path,
6951                         mysql_unpacked_real_data_home_len,
6952                         (const uchar*) mysql_unpacked_real_data_home,
6953                         mysql_unpacked_real_data_home_len))
6954         DBUG_RETURN(1);
6955     }
6956     else if (!memcmp(path, mysql_unpacked_real_data_home,
6957                      mysql_unpacked_real_data_home_len))
6958       DBUG_RETURN(1);
6959   }
6960   DBUG_RETURN(0);
6961 }
6962 
6963 C_MODE_END
6964 
6965 
6966 /**
6967   Check that host name string is valid.
6968 
6969   @param[in] str string to be checked
6970 
6971   @return             Operation status
6972     @retval  FALSE    host name is ok
6973     @retval  TRUE     host name string is longer than max_length or
6974                       has invalid symbols
6975 */
6976 
check_host_name(const LEX_CSTRING & str)6977 bool check_host_name(const LEX_CSTRING &str)
6978 {
6979   const char *name= str.str;
6980   const char *end= str.str + str.length;
6981   if (check_string_byte_length(str, ER(ER_HOSTNAME), HOSTNAME_LENGTH))
6982     return TRUE;
6983 
6984   while (name != end)
6985   {
6986     if (*name == '@')
6987     {
6988       my_printf_error(ER_UNKNOWN_ERROR,
6989                       "Malformed hostname (illegal symbol: '%c')", MYF(0),
6990                       *name);
6991       return TRUE;
6992     }
6993     name++;
6994   }
6995   return FALSE;
6996 }
6997 
6998 
6999 class Parser_oom_handler : public Internal_error_handler
7000 {
7001 public:
Parser_oom_handler()7002   Parser_oom_handler()
7003     : m_has_errors(false), m_is_mem_error(false)
7004   {}
handle_condition(THD * thd,uint sql_errno,const char * sqlstate,Sql_condition::enum_severity_level * level,const char * msg)7005   virtual bool handle_condition(THD *thd,
7006                                 uint sql_errno,
7007                                 const char* sqlstate,
7008                                 Sql_condition::enum_severity_level *level,
7009                                 const char* msg)
7010   {
7011     if (*level == Sql_condition::SL_ERROR)
7012     {
7013       m_has_errors= true;
7014       /* Out of memory error is reported only once. Return as handled */
7015       if (m_is_mem_error && sql_errno == EE_CAPACITY_EXCEEDED)
7016         return true;
7017       if (sql_errno == EE_CAPACITY_EXCEEDED)
7018       {
7019         m_is_mem_error= true;
7020         my_error(ER_CAPACITY_EXCEEDED, MYF(0),
7021                  static_cast<ulonglong>(thd->variables.parser_max_mem_size),
7022                  "parser_max_mem_size",
7023                  ER_THD(thd, ER_CAPACITY_EXCEEDED_IN_PARSER));
7024         return true;
7025       }
7026     }
7027     return false;
7028   }
7029 private:
7030   bool m_has_errors;
7031   bool m_is_mem_error;
7032 };
7033 
7034 
7035 extern int MYSQLparse(class THD *thd); // from sql_yacc.cc
7036 
7037 
7038 /**
7039   This is a wrapper of MYSQLparse(). All the code should call parse_sql()
7040   instead of MYSQLparse().
7041 
7042   As a by product of parsing, the parser can also generate a query digest.
7043   To compute a digest, invoke this function as follows.
7044 
7045   @verbatim
7046     THD *thd = ...;
7047     const char *query_text = ...;
7048     uint query_length = ...;
7049     Object_creation_ctx *ctx = ...;
7050     bool rc;
7051 
7052     Parser_state parser_state;
7053     if (parser_state.init(thd, query_text, query_length)
7054     {
7055       ... handle error
7056     }
7057 
7058     parser_state.m_input.m_has_digest= true;
7059     parser_state.m_input.m_compute_digest= true;
7060 
7061     rc= parse_sql(the, &parser_state, ctx);
7062     if (! rc)
7063     {
7064       unsigned char md5[MD5_HASH_SIZE];
7065       char digest_text[1024];
7066       bool truncated;
7067       const sql_digest_storage *digest= & thd->m_digest->m_digest_storage;
7068 
7069       compute_digest_md5(digest, & md5[0]);
7070       compute_digest_text(digest, & digest_text[0], sizeof(digest_text), & truncated);
7071     }
7072   @endverbatim
7073 
7074   @param thd Thread context.
7075   @param parser_state Parser state.
7076   @param creation_ctx Object creation context.
7077 
7078   @return Error status.
7079     @retval FALSE on success.
7080     @retval TRUE on parsing error.
7081 */
7082 
parse_sql(THD * thd,Parser_state * parser_state,Object_creation_ctx * creation_ctx)7083 bool parse_sql(THD *thd,
7084                Parser_state *parser_state,
7085                Object_creation_ctx *creation_ctx)
7086 {
7087   DBUG_ENTER("parse_sql");
7088   bool ret_value;
7089   assert(thd->m_parser_state == NULL);
7090   // TODO fix to allow parsing gcol exprs after main query.
7091 //  assert(thd->lex->m_sql_cmd == NULL);
7092 
7093   MYSQL_QUERY_PARSE_START(const_cast<char*>(thd->query().str));
7094   /* Backup creation context. */
7095 
7096   Object_creation_ctx *backup_ctx= NULL;
7097 
7098   if (creation_ctx)
7099     backup_ctx= creation_ctx->set_n_backup(thd);
7100 
7101   /* Set parser state. */
7102 
7103   thd->m_parser_state= parser_state;
7104 
7105   parser_state->m_digest_psi= NULL;
7106   parser_state->m_lip.m_digest= NULL;
7107 
7108   /*
7109     Only consider statements that are supposed to have a digest,
7110     like top level queries.
7111   */
7112   if (parser_state->m_input.m_has_digest) {
7113     /*
7114       For these statements,
7115       see if the digest computation is required.
7116     */
7117     if (thd->m_digest != NULL)
7118     {
7119       /* Start Digest */
7120       parser_state->m_digest_psi= MYSQL_DIGEST_START(thd->m_statement_psi);
7121 
7122       if (parser_state->m_input.m_compute_digest ||
7123          (parser_state->m_digest_psi != NULL))
7124       {
7125         /*
7126           If either:
7127           - the caller wants to compute a digest
7128           - the performance schema wants to compute a digest
7129           set the digest listener in the lexer.
7130         */
7131         parser_state->m_lip.m_digest= thd->m_digest;
7132         parser_state->m_lip.m_digest->m_digest_storage.m_charset_number= thd->charset()->number;
7133       }
7134     }
7135   }
7136 
7137   /* Parse the query. */
7138 
7139   /*
7140     Use a temporary DA while parsing. We don't know until after parsing
7141     whether the current command is a diagnostic statement, in which case
7142     we'll need to have the previous DA around to answer questions about it.
7143   */
7144   Diagnostics_area *parser_da= thd->get_parser_da();
7145   Diagnostics_area *da=        thd->get_stmt_da();
7146 
7147   Parser_oom_handler poomh;
7148   // Note that we may be called recursively here, on INFORMATION_SCHEMA queries.
7149 
7150   set_memroot_max_capacity(thd->mem_root, thd->variables.parser_max_mem_size);
7151   set_memroot_error_reporting(thd->mem_root, true);
7152   thd->push_internal_handler(&poomh);
7153 
7154   thd->push_diagnostics_area(parser_da, false);
7155 
7156   bool mysql_parse_status= MYSQLparse(thd) != 0;
7157 
7158   thd->pop_internal_handler();
7159   set_memroot_max_capacity(thd->mem_root, 0);
7160   set_memroot_error_reporting(thd->mem_root, false);
7161   /*
7162     Unwind diagnostics area.
7163 
7164     If any issues occurred during parsing, they will become
7165     the sole conditions for the current statement.
7166 
7167     Otherwise, if we have a diagnostic statement on our hands,
7168     we'll preserve the previous diagnostics area here so we
7169     can answer questions about it.  This specifically means
7170     that repeatedly asking about a DA won't clear it.
7171 
7172     Otherwise, it's a regular command with no issues during
7173     parsing, so we'll just clear the DA in preparation for
7174     the processing of this command.
7175   */
7176 
7177   if (parser_da->current_statement_cond_count() != 0)
7178   {
7179     /*
7180       Error/warning during parsing: top DA should contain parse error(s)!  Any
7181       pre-existing conditions will be replaced. The exception is diagnostics
7182       statements, in which case we wish to keep the errors so they can be sent
7183       to the client.
7184     */
7185     if (thd->lex->sql_command != SQLCOM_SHOW_WARNS &&
7186         thd->lex->sql_command != SQLCOM_GET_DIAGNOSTICS)
7187       da->reset_condition_info(thd);
7188 
7189     /*
7190       We need to put any errors in the DA as well as the condition list.
7191     */
7192     if (parser_da->is_error() && !da->is_error())
7193     {
7194       da->set_error_status(parser_da->mysql_errno(),
7195                            parser_da->message_text(),
7196                            parser_da->returned_sqlstate());
7197     }
7198 
7199     da->copy_sql_conditions_from_da(thd, parser_da);
7200 
7201     parser_da->reset_diagnostics_area();
7202     parser_da->reset_condition_info(thd);
7203 
7204     /*
7205       Do not clear the condition list when starting execution as it
7206       now contains not the results of the previous executions, but
7207       a non-zero number of errors/warnings thrown during parsing!
7208     */
7209     thd->lex->keep_diagnostics= DA_KEEP_PARSE_ERROR;
7210   }
7211 
7212   thd->pop_diagnostics_area();
7213 
7214   /*
7215     Check that if MYSQLparse() failed either thd->is_error() is set, or an
7216     internal error handler is set.
7217 
7218     The assert will not catch a situation where parsing fails without an
7219     error reported if an error handler exists. The problem is that the
7220     error handler might have intercepted the error, so thd->is_error() is
7221     not set. However, there is no way to be 100% sure here (the error
7222     handler might be for other errors than parsing one).
7223   */
7224 
7225   assert(!mysql_parse_status ||
7226          (mysql_parse_status && thd->is_error()) ||
7227          (mysql_parse_status && thd->get_internal_handler()));
7228 
7229   /* Reset parser state. */
7230 
7231   thd->m_parser_state= NULL;
7232 
7233   /* Restore creation context. */
7234 
7235   if (creation_ctx)
7236     creation_ctx->restore_env(thd, backup_ctx);
7237 
7238   /* That's it. */
7239 
7240   ret_value= mysql_parse_status || thd->is_fatal_error;
7241 
7242   if ((ret_value == 0) &&
7243       (parser_state->m_digest_psi != NULL))
7244   {
7245     /*
7246       On parsing success, record the digest in the performance schema.
7247     */
7248     assert(thd->m_digest != NULL);
7249     MYSQL_DIGEST_END(parser_state->m_digest_psi,
7250                      & thd->m_digest->m_digest_storage);
7251   }
7252 
7253   MYSQL_QUERY_PARSE_DONE(ret_value);
7254   DBUG_RETURN(ret_value);
7255 }
7256 
7257 /**
7258   @} (end of group Runtime_Environment)
7259 */
7260 
7261 
7262 
7263 /**
7264   Check and merge "CHARACTER SET cs [ COLLATE cl ]" clause
7265 
7266   @param cs character set pointer.
7267   @param cl collation pointer.
7268 
7269   Check if collation "cl" is applicable to character set "cs".
7270 
7271   If "cl" is NULL (e.g. when COLLATE clause is not specified),
7272   then simply "cs" is returned.
7273 
7274   @return Error status.
7275     @retval NULL, if "cl" is not applicable to "cs".
7276     @retval pointer to merged CHARSET_INFO on success.
7277 */
7278 
7279 
7280 const CHARSET_INFO*
merge_charset_and_collation(const CHARSET_INFO * cs,const CHARSET_INFO * cl)7281 merge_charset_and_collation(const CHARSET_INFO *cs, const CHARSET_INFO *cl)
7282 {
7283   if (cl)
7284   {
7285     if (!my_charset_same(cs, cl))
7286     {
7287       my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0), cl->name, cs->csname);
7288       return NULL;
7289     }
7290     return cl;
7291   }
7292   return cs;
7293 }
7294