28 #include "sql_parse.h"
31 #ifdef OPTIMIZER_TRACE
35 const char I_S_table_name[]=
"OPTIMIZER_TRACE";
47 bool list_has_optimizer_trace_table(
const TABLE_LIST *tbl)
49 for( ; tbl ; tbl= tbl->next_global)
51 if (tbl->schema_table &&
52 0 == strcmp(tbl->schema_table->table_name, I_S_table_name))
63 inline bool sql_command_can_be_traced(
enum enum_sql_command sql_command)
91 bool sets_var_optimizer_trace(
enum enum_sql_command sql_command,
94 if (sql_command == SQLCOM_SET_OPTION)
105 void opt_trace_disable_if_no_tables_access(THD *thd,
TABLE_LIST *tbl);
110 Opt_trace_start::Opt_trace_start(THD *thd,
TABLE_LIST *tbl,
111 enum enum_sql_command sql_command,
113 const char *
query,
size_t query_length,
116 : ctx(&thd->opt_trace)
118 DBUG_ENTER(
"opt_trace_start");
126 const ulonglong var= thd->variables.optimizer_trace;
127 bool support_I_S=
false, support_dbug_or_missing_priv=
false;
130 DBUG_EXECUTE(
"opt", support_dbug_or_missing_priv=
true;);
133 if (unlikely(var & Opt_trace_context::FLAG_ENABLED))
135 if (sql_command_can_be_traced(sql_command) &&
136 !sets_var_optimizer_trace(sql_command, set_vars) &&
137 !list_has_optimizer_trace_table(tbl) &&
194 support_dbug_or_missing_priv=
true;
197 error= ctx->start(support_I_S, support_dbug_or_missing_priv,
198 thd->variables.end_markers_in_json,
199 (var & Opt_trace_context::FLAG_ONE_LINE),
200 thd->variables.optimizer_trace_offset,
201 thd->variables.optimizer_trace_limit,
202 thd->variables.optimizer_trace_max_mem_size,
203 thd->variables.optimizer_trace_features);
207 if (unlikely(support_I_S) && ctx->is_started())
212 buffer.set_charset(system_charset_info);
213 instr->print(&buffer);
214 ctx->set_query(buffer.ptr(), buffer.length(), query_charset);
217 ctx->set_query(query, query_length, query_charset);
220 opt_trace_disable_if_no_tables_access(thd, tbl);
225 Opt_trace_start::~Opt_trace_start()
227 DBUG_ENTER(
"~opt_trace_start");
234 void opt_trace_print_expanded_query(THD *thd, st_select_lex *select_lex,
249 if (likely(!trace->support_I_S()))
252 String str(buff,(uint32)
sizeof(buff), system_charset_info);
260 select_lex->print(thd, &str, enum_query_type(QT_TO_SYSTEM_CHARSET |
261 QT_SHOW_SELECT_NUMBER |
263 trace_object->add_utf8(
"expanded_query", str.ptr(), str.length());
267 void opt_trace_disable_if_no_security_context_access(THD *thd)
269 #ifndef NO_EMBEDDED_ACCESS_CHECKS
270 DBUG_ENTER(
"opt_trace_check_disable_if_no_security_context_access");
271 if (likely(!(thd->variables.optimizer_trace &
272 Opt_trace_context::FLAG_ENABLED)) ||
290 if (!trace->is_started())
322 trace->disable_I_S_for_this_and_children();
330 if (!(test_all_bits(thd->main_security_ctx.master_access,
331 (GLOBAL_ACLS & ~GRANT_ACL))) &&
332 (0 != strcmp(thd->main_security_ctx.priv_user,
333 thd->security_ctx->priv_user) ||
334 0 != my_strcasecmp(system_charset_info,
335 thd->main_security_ctx.priv_host,
336 thd->security_ctx->priv_host)))
337 trace->missing_privilege();
343 void opt_trace_disable_if_no_stored_proc_func_access(THD *thd,
sp_head *sp)
345 #ifndef NO_EMBEDDED_ACCESS_CHECKS
346 DBUG_ENTER(
"opt_trace_disable_if_no_stored_proc_func_access");
347 if (likely(!(thd->variables.optimizer_trace &
348 Opt_trace_context::FLAG_ENABLED)) || thd->system_thread)
351 if (!trace->is_started())
354 trace->disable_I_S_for_this_and_children();
358 Security_context *
const backup_thd_sctx= thd->security_ctx;
359 DBUG_PRINT(
"opt", (
"routine: '%s'", sp->m_name.str));
360 thd->security_ctx= &thd->main_security_ctx;
363 thd->security_ctx= backup_thd_sctx;
365 trace->missing_privilege();
371 void opt_trace_disable_if_no_view_access(THD *thd,
TABLE_LIST *
view,
374 #ifndef NO_EMBEDDED_ACCESS_CHECKS
375 DBUG_ENTER(
"opt_trace_disable_if_no_view_access");
376 if (likely(!(thd->variables.optimizer_trace &
377 Opt_trace_context::FLAG_ENABLED)) || thd->system_thread)
380 if (!trace->is_started())
383 trace->disable_I_S_for_this_and_children();
386 DBUG_PRINT(
"opt", (
"view: '%s'", view->table_name));
387 Security_context *
const backup_table_sctx= view->security_ctx;
388 Security_context *
const backup_thd_sctx= thd->security_ctx;
389 const GRANT_INFO backup_grant_info= view->grant;
391 view->security_ctx= NULL;
392 thd->security_ctx= &thd->main_security_ctx;
395 view->security_ctx= backup_table_sctx;
396 thd->security_ctx= backup_thd_sctx;
397 view->grant= backup_grant_info;
401 trace->missing_privilege();
410 opt_trace_disable_if_no_tables_access(thd, underlying_tables);
433 void opt_trace_disable_if_no_tables_access(THD *thd,
TABLE_LIST *tbl)
435 #ifndef NO_EMBEDDED_ACCESS_CHECKS
436 DBUG_ENTER(
"opt_trace_disable_if_no_tables_access");
437 if (likely(!(thd->variables.optimizer_trace &
438 Opt_trace_context::FLAG_ENABLED)) || thd->system_thread)
441 if (!trace->is_started())
444 trace->disable_I_S_for_this_and_children();
447 Security_context *
const backup_thd_sctx= thd->security_ctx;
448 thd->security_ctx= &thd->main_security_ctx;
450 thd->lex->first_not_own_table();
452 t != NULL && t != first_not_own_table;
455 DBUG_PRINT(
"opt", (
"table: '%s'", t->table_name));
460 if (!t->is_anonymous_derived_table())
463 Security_context *
const backup_table_sctx= t->security_ctx;
464 t->security_ctx= NULL;
474 ((t->grant.privilege & SELECT_ACL) == 0);
485 t->security_ctx= backup_table_sctx;
486 t->grant= backup_grant_info;
489 trace->missing_privilege();
494 thd->security_ctx= backup_thd_sctx;
502 int fill_optimizer_trace_info(THD *thd,
TABLE_LIST *tables,
Item *cond)
524 if (!test_all_bits(thd->security_ctx->master_access,
525 (GLOBAL_ACLS & ~GRANT_ACL)) &&
526 (0 != strcmp(thd->main_security_ctx.priv_user,
527 thd->security_ctx->priv_user) ||
528 0 != my_strcasecmp(system_charset_info,
529 thd->main_security_ctx.priv_host,
530 thd->security_ctx->priv_host)))
536 for (Opt_trace_iterator it(&thd->opt_trace) ; !it.at_end() ; it.next())
539 restore_record(table, s->default_values);
546 table->field[0]->store(info.query_ptr,
547 static_cast<uint>(info.query_length),
549 table->field[1]->store(info.trace_ptr,
550 static_cast<uint>(info.trace_length),
551 system_charset_info);
552 table->field[2]->store(info.missing_bytes,
true);
553 table->field[3]->store(info.missing_priv,
true);
554 if (schema_table_store_record(thd, table))
561 #endif // OPTIMIZER_TRACE
566 {
"QUERY", 65535, MYSQL_TYPE_STRING, 0,
false, NULL, SKIP_OPEN_TABLE},
567 {
"TRACE", 65535, MYSQL_TYPE_STRING, 0,
false, NULL, SKIP_OPEN_TABLE},
568 {
"MISSING_BYTES_BEYOND_MAX_MEM_SIZE", 20, MYSQL_TYPE_LONG,
569 0,
false, NULL, SKIP_OPEN_TABLE},
570 {
"INSUFFICIENT_PRIVILEGES", 1, MYSQL_TYPE_TINY,
571 0,
false, NULL, SKIP_OPEN_TABLE},
572 {NULL, 0, MYSQL_TYPE_STRING, 0,
true, NULL, 0}