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