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