Commit 32692140 authored by Sergei Petrunia's avatar Sergei Petrunia

MDEV-27306: SET STATEMENT optimizer_trace=1 Doesn't save the trace

In mysql_execute_command(), move optimizer trace initialization to be
after run_set_statement_if_requested() call.

Unfortunately, mysql_execute_command() code uses "goto error" a lot, and
this means optimizer trace code cannot use RAII objects. Work this around
by:
- Make Opt_trace_start a non-RAII object, add init() method.
- Move the code that writes the top-level object and array into
  Opt_trace_start::init().
parent 946dafb2
...@@ -9248,5 +9248,22 @@ json_detailed(json_extract(trace, '$**.best_join_order')) ...@@ -9248,5 +9248,22 @@ json_detailed(json_extract(trace, '$**.best_join_order'))
] ]
] ]
DROP TABLE t1; DROP TABLE t1;
#
# MDEV-27306: SET STATEMENT optimizer_trace=1 Doesn't save the trace
#
set optimizer_trace=0;
set statement optimizer_trace=1 for select * from seq_1_to_10 where seq<2;
seq
1
# The trace must not be empty:
select left(trace, 100) from information_schema.optimizer_trace;
left(trace, 100)
{
"steps": [
{
"join_preparation": {
"select_id": 1,
"steps": [
# End of 10.6 tests # End of 10.6 tests
set optimizer_trace='enabled=off'; set optimizer_trace='enabled=off';
...@@ -865,5 +865,13 @@ select json_detailed(json_extract(trace, '$**.best_join_order')) ...@@ -865,5 +865,13 @@ select json_detailed(json_extract(trace, '$**.best_join_order'))
from information_schema.OPTIMIZER_TRACE; from information_schema.OPTIMIZER_TRACE;
DROP TABLE t1; DROP TABLE t1;
--echo #
--echo # MDEV-27306: SET STATEMENT optimizer_trace=1 Doesn't save the trace
--echo #
set optimizer_trace=0;
set statement optimizer_trace=1 for select * from seq_1_to_10 where seq<2;
--echo # The trace must not be empty:
select left(trace, 100) from information_schema.optimizer_trace;
--echo # End of 10.6 tests --echo # End of 10.6 tests
set optimizer_trace='enabled=off'; set optimizer_trace='enabled=off';
...@@ -471,12 +471,14 @@ void Opt_trace_context::end() ...@@ -471,12 +471,14 @@ void Opt_trace_context::end()
current_trace= NULL; current_trace= NULL;
} }
Opt_trace_start::Opt_trace_start(THD *thd, TABLE_LIST *tbl,
void Opt_trace_start::init(THD *thd,
TABLE_LIST *tbl,
enum enum_sql_command sql_command, enum enum_sql_command sql_command,
List<set_var_base> *set_vars, List<set_var_base> *set_vars,
const char *query, const char *query,
size_t query_length, size_t query_length,
const CHARSET_INFO *query_charset):ctx(&thd->opt_trace) const CHARSET_INFO *query_charset)
{ {
/* /*
if optimizer trace is enabled and the statment we have is traceable, if optimizer trace is enabled and the statment we have is traceable,
...@@ -496,6 +498,9 @@ Opt_trace_start::Opt_trace_start(THD *thd, TABLE_LIST *tbl, ...@@ -496,6 +498,9 @@ Opt_trace_start::Opt_trace_start(THD *thd, TABLE_LIST *tbl,
ctx->set_query(query, query_length, query_charset); ctx->set_query(query, query_length, query_charset);
traceable= TRUE; traceable= TRUE;
opt_trace_disable_if_no_tables_access(thd, tbl); opt_trace_disable_if_no_tables_access(thd, tbl);
Json_writer *w= ctx->get_current_json();
w->start_object();
w->add_member("steps").start_array();
} }
} }
...@@ -503,6 +508,9 @@ Opt_trace_start::~Opt_trace_start() ...@@ -503,6 +508,9 @@ Opt_trace_start::~Opt_trace_start()
{ {
if (traceable) if (traceable)
{ {
Json_writer *w= ctx->get_current_json();
w->end_array();
w->end_object();
ctx->end(); ctx->end();
traceable= FALSE; traceable= FALSE;
} }
......
...@@ -72,14 +72,18 @@ struct Opt_trace_info ...@@ -72,14 +72,18 @@ struct Opt_trace_info
*/ */
class Opt_trace_start { class Opt_trace_start
{
public: public:
Opt_trace_start(THD *thd_arg, TABLE_LIST *tbl, Opt_trace_start(THD *thd_arg): ctx(&thd_arg->opt_trace), traceable(false) {}
void init(THD *thd, TABLE_LIST *tbl,
enum enum_sql_command sql_command, enum enum_sql_command sql_command,
List<set_var_base> *set_vars, List<set_var_base> *set_vars,
const char *query, const char *query,
size_t query_length, size_t query_length,
const CHARSET_INFO *query_charset); const CHARSET_INFO *query_charset);
~Opt_trace_start(); ~Opt_trace_start();
private: private:
......
...@@ -3489,10 +3489,9 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp, ...@@ -3489,10 +3489,9 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp,
thd->lex->safe_to_cache_query= 0; thd->lex->safe_to_cache_query= 0;
#endif #endif
Opt_trace_start ots(thd, m_lex->query_tables, Opt_trace_start ots(thd);
SQLCOM_SELECT, &m_lex->var_list, ots.init(thd, m_lex->query_tables, SQLCOM_SELECT, &m_lex->var_list,
NULL, 0, NULL, 0, thd->variables.character_set_client);
thd->variables.character_set_client);
Json_writer_object trace_command(thd); Json_writer_object trace_command(thd);
Json_writer_array trace_command_steps(thd, "steps"); Json_writer_array trace_command_steps(thd, "steps");
......
...@@ -3644,12 +3644,7 @@ mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt) ...@@ -3644,12 +3644,7 @@ mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt)
#ifdef HAVE_REPLICATION #ifdef HAVE_REPLICATION
} /* endif unlikely slave */ } /* endif unlikely slave */
#endif #endif
Opt_trace_start ots(thd, all_tables, lex->sql_command, &lex->var_list, Opt_trace_start ots(thd);
thd->query(), thd->query_length(),
thd->variables.character_set_client);
Json_writer_object trace_command(thd);
Json_writer_array trace_command_steps(thd, "steps");
/* store old value of binlog format */ /* store old value of binlog format */
enum_binlog_format orig_binlog_format,orig_current_stmt_binlog_format; enum_binlog_format orig_binlog_format,orig_current_stmt_binlog_format;
...@@ -3715,6 +3710,10 @@ mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt) ...@@ -3715,6 +3710,10 @@ mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt)
if (run_set_statement_if_requested(thd, lex)) if (run_set_statement_if_requested(thd, lex))
goto error; goto error;
/* After SET STATEMENT is done, we can initialize the Optimizer Trace: */
ots.init(thd, all_tables, lex->sql_command, &lex->var_list, thd->query(),
thd->query_length(), thd->variables.character_set_client);
if (thd->lex->mi.connection_name.str == NULL) if (thd->lex->mi.connection_name.str == NULL)
thd->lex->mi.connection_name= thd->variables.default_master_connection; thd->lex->mi.connection_name= thd->variables.default_master_connection;
......
...@@ -2437,9 +2437,9 @@ static bool check_prepared_statement(Prepared_statement *stmt) ...@@ -2437,9 +2437,9 @@ static bool check_prepared_statement(Prepared_statement *stmt)
For the optimizer trace, this is the symmetric, for statement preparation, For the optimizer trace, this is the symmetric, for statement preparation,
of what is done at statement execution (in mysql_execute_command()). of what is done at statement execution (in mysql_execute_command()).
*/ */
Opt_trace_start ots(thd, tables, lex->sql_command, &lex->var_list, Opt_trace_start ots(thd);
thd->query(), thd->query_length(), ots.init(thd, tables, lex->sql_command, &lex->var_list, thd->query(),
thd->variables.character_set_client); thd->query_length(), thd->variables.character_set_client);
Json_writer_object trace_command(thd); Json_writer_object trace_command(thd);
Json_writer_array trace_command_steps(thd, "steps"); Json_writer_array trace_command_steps(thd, "steps");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment