summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergei Petrunia <psergey@askmonty.org>2021-12-19 17:19:02 +0300
committerSergei Petrunia <psergey@askmonty.org>2021-12-19 17:19:02 +0300
commit32692140e1a4f9aa87359f3ef6efe4a615119e71 (patch)
tree3db2fc477fa84e4b39ad67f63ecad57235b39539
parent946dafb260fc5683e1ec1410a801f2235ba2313a (diff)
downloadmariadb-git-bb-10.6-mdev27306.tar.gz
MDEV-27306: SET STATEMENT optimizer_trace=1 Doesn't save the tracebb-10.6-mdev27306
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().
-rw-r--r--mysql-test/main/opt_trace.result17
-rw-r--r--mysql-test/main/opt_trace.test8
-rw-r--r--sql/opt_trace.cc20
-rw-r--r--sql/opt_trace.h18
-rw-r--r--sql/sp_head.cc7
-rw-r--r--sql/sql_parse.cc11
-rw-r--r--sql/sql_prepare.cc6
7 files changed, 61 insertions, 26 deletions
diff --git a/mysql-test/main/opt_trace.result b/mysql-test/main/opt_trace.result
index b0c2a9ca4d9..477c1f31095 100644
--- a/mysql-test/main/opt_trace.result
+++ b/mysql-test/main/opt_trace.result
@@ -9248,5 +9248,22 @@ json_detailed(json_extract(trace, '$**.best_join_order'))
]
]
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
set optimizer_trace='enabled=off';
diff --git a/mysql-test/main/opt_trace.test b/mysql-test/main/opt_trace.test
index 402caf2a165..9a7aa017cd4 100644
--- a/mysql-test/main/opt_trace.test
+++ b/mysql-test/main/opt_trace.test
@@ -865,5 +865,13 @@ select json_detailed(json_extract(trace, '$**.best_join_order'))
from information_schema.OPTIMIZER_TRACE;
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
set optimizer_trace='enabled=off';
diff --git a/sql/opt_trace.cc b/sql/opt_trace.cc
index ba9220cac44..4bc493940fb 100644
--- a/sql/opt_trace.cc
+++ b/sql/opt_trace.cc
@@ -471,12 +471,14 @@ void Opt_trace_context::end()
current_trace= NULL;
}
-Opt_trace_start::Opt_trace_start(THD *thd, TABLE_LIST *tbl,
- enum enum_sql_command sql_command,
- List<set_var_base> *set_vars,
- const char *query,
- size_t query_length,
- const CHARSET_INFO *query_charset):ctx(&thd->opt_trace)
+
+void Opt_trace_start::init(THD *thd,
+ TABLE_LIST *tbl,
+ enum enum_sql_command sql_command,
+ List<set_var_base> *set_vars,
+ const char *query,
+ size_t query_length,
+ const CHARSET_INFO *query_charset)
{
/*
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,
ctx->set_query(query, query_length, query_charset);
traceable= TRUE;
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()
{
if (traceable)
{
+ Json_writer *w= ctx->get_current_json();
+ w->end_array();
+ w->end_object();
ctx->end();
traceable= FALSE;
}
diff --git a/sql/opt_trace.h b/sql/opt_trace.h
index 101fb5f707e..1ee23a33591 100644
--- a/sql/opt_trace.h
+++ b/sql/opt_trace.h
@@ -72,14 +72,18 @@ struct Opt_trace_info
*/
-class Opt_trace_start {
+class Opt_trace_start
+{
public:
- Opt_trace_start(THD *thd_arg, TABLE_LIST *tbl,
- enum enum_sql_command sql_command,
- List<set_var_base> *set_vars,
- const char *query,
- size_t query_length,
- const CHARSET_INFO *query_charset);
+ 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,
+ List<set_var_base> *set_vars,
+ const char *query,
+ size_t query_length,
+ const CHARSET_INFO *query_charset);
+
~Opt_trace_start();
private:
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 641c88de826..97905f6a5b4 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -3489,10 +3489,9 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp,
thd->lex->safe_to_cache_query= 0;
#endif
- Opt_trace_start ots(thd, m_lex->query_tables,
- SQLCOM_SELECT, &m_lex->var_list,
- NULL, 0,
- thd->variables.character_set_client);
+ Opt_trace_start ots(thd);
+ ots.init(thd, m_lex->query_tables, SQLCOM_SELECT, &m_lex->var_list,
+ NULL, 0, thd->variables.character_set_client);
Json_writer_object trace_command(thd);
Json_writer_array trace_command_steps(thd, "steps");
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 2a48c8fb1ce..0886fc85151 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -3644,12 +3644,7 @@ mysql_execute_command(THD *thd, bool is_called_from_prepared_stmt)
#ifdef HAVE_REPLICATION
} /* endif unlikely slave */
#endif
- Opt_trace_start ots(thd, all_tables, lex->sql_command, &lex->var_list,
- thd->query(), thd->query_length(),
- thd->variables.character_set_client);
-
- Json_writer_object trace_command(thd);
- Json_writer_array trace_command_steps(thd, "steps");
+ Opt_trace_start ots(thd);
/* store old value of 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)
if (run_set_statement_if_requested(thd, lex))
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)
thd->lex->mi.connection_name= thd->variables.default_master_connection;
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 4ead77c225f..67032142591 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -2437,9 +2437,9 @@ static bool check_prepared_statement(Prepared_statement *stmt)
For the optimizer trace, this is the symmetric, for statement preparation,
of what is done at statement execution (in mysql_execute_command()).
*/
- Opt_trace_start ots(thd, tables, lex->sql_command, &lex->var_list,
- thd->query(), thd->query_length(),
- thd->variables.character_set_client);
+ Opt_trace_start ots(thd);
+ ots.init(thd, tables, lex->sql_command, &lex->var_list, thd->query(),
+ thd->query_length(), thd->variables.character_set_client);
Json_writer_object trace_command(thd);
Json_writer_array trace_command_steps(thd, "steps");