summaryrefslogtreecommitdiff
path: root/sql/sql_parse.cc
diff options
context:
space:
mode:
authorSergey Petrunya <psergey@askmonty.org>2013-10-15 11:51:41 +0400
committerSergey Petrunya <psergey@askmonty.org>2013-10-15 11:51:41 +0400
commit1e36cbfa391ac80297958a4cc72d676e15eb1b37 (patch)
tree2304f70f5fd0d810ae7690360c65283015f08b5c /sql/sql_parse.cc
parenteb2c6f451392396ef2ca74f1dba761fc4459d171 (diff)
parent25d0175fde2bff7397628d91c30aac8ba9d56301 (diff)
downloadmariadb-git-1e36cbfa391ac80297958a4cc72d676e15eb1b37.tar.gz
MDEV-3798: [SHOW] EXPLAIN UPDATE/DELETE
- Merge with 10.0-base
Diffstat (limited to 'sql/sql_parse.cc')
-rw-r--r--sql/sql_parse.cc115
1 files changed, 80 insertions, 35 deletions
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index da245c2d508..d7d2358e5d5 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -598,6 +598,7 @@ static void handle_bootstrap_impl(THD *thd)
#if defined(ENABLED_PROFILING)
thd->profiling.finish_current_query();
#endif
+ delete_explain_query(thd->lex);
if (bootstrap_error)
break;
@@ -807,7 +808,9 @@ bool do_command(THD *thd)
my_net_set_read_timeout(net, thd->variables.net_read_timeout);
DBUG_ASSERT(packet_length);
+ DBUG_ASSERT(!thd->apc_target.is_enabled());
return_value= dispatch_command(command, thd, packet+1, (uint) (packet_length-1));
+ DBUG_ASSERT(!thd->apc_target.is_enabled());
out:
DBUG_RETURN(return_value);
@@ -1117,6 +1120,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
ulong length= (ulong)(packet_end - beginning_of_next_stmt);
log_slow_statement(thd);
+ DBUG_ASSERT(!thd->apc_target.is_enabled());
/* Remove garbage at start of query */
while (length > 0 && my_isspace(thd->charset(), *beginning_of_next_stmt))
@@ -1520,10 +1524,15 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
}
+/*
+ @note
+ This function must call delete_explain_query().
+*/
void log_slow_statement(THD *thd)
{
DBUG_ENTER("log_slow_statement");
+
/*
The following should never be true with our current code base,
but better to keep this here so we don't accidently try to log a
@@ -1532,11 +1541,15 @@ void log_slow_statement(THD *thd)
if (unlikely(thd->in_sub_stmt))
DBUG_VOID_RETURN; // Don't set time for sub stmt
+
/* Follow the slow log filter configuration. */
if (!thd->enable_slow_log ||
(thd->variables.log_slow_filter
&& !(thd->variables.log_slow_filter & thd->query_plan_flags)))
+ {
+ delete_explain_query(thd->lex);
DBUG_VOID_RETURN;
+ }
if (((thd->server_status & SERVER_QUERY_WAS_SLOW) ||
((thd->server_status &
@@ -1559,6 +1572,8 @@ void log_slow_statement(THD *thd)
thd->utime_after_query);
thd_proc_info(thd, 0);
}
+
+ delete_explain_query(thd->lex);
DBUG_VOID_RETURN;
}
@@ -2185,6 +2200,8 @@ mysql_execute_command(THD *thd)
/* Release metadata locks acquired in this transaction. */
thd->mdl_context.release_transactional_locks();
}
+
+ create_explain_query(thd->lex, thd->mem_root);
#ifndef DBUG_OFF
if (lex->sql_command != SQLCOM_SET_OPTION)
@@ -3156,6 +3173,7 @@ end_with_restore_list:
case SQLCOM_INSERT_SELECT:
{
select_result *sel_result;
+ bool explain= test(lex->describe);
DBUG_ASSERT(first_table == all_tables && first_table != 0);
if ((res= insert_precheck(thd, all_tables)))
break;
@@ -3225,6 +3243,10 @@ end_with_restore_list:
}
delete sel_result;
}
+
+ if (!res && explain)
+ res= thd->lex->explain->send_explain(thd);
+
/* revert changes for SP */
MYSQL_INSERT_SELECT_DONE(res, (ulong) thd->get_row_count_func());
select_lex->table_list.first= first_table;
@@ -3265,7 +3287,8 @@ end_with_restore_list:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
TABLE_LIST *aux_tables= thd->lex->auxiliary_table_list.first;
- multi_delete *del_result;
+ bool explain= test(lex->describe);
+ select_result *result;
if ((res= multi_delete_precheck(thd, all_tables)))
break;
@@ -3287,25 +3310,34 @@ end_with_restore_list:
goto error;
}
- if (!thd->is_fatal_error &&
- (del_result= new multi_delete(aux_tables, lex->table_count)))
- {
- res= mysql_select(thd, &select_lex->ref_pointer_array,
- select_lex->get_table_list(),
- select_lex->with_wild,
- select_lex->item_list,
- select_lex->where,
- 0, (ORDER *)NULL, (ORDER *)NULL, (Item *)NULL,
- (ORDER *)NULL,
- (select_lex->options | thd->variables.option_bits |
- SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK |
- OPTION_SETUP_TABLES_DONE) & ~OPTION_BUFFER_RESULT,
- del_result, unit, select_lex);
- res|= thd->is_error();
- MYSQL_MULTI_DELETE_DONE(res, del_result->num_deleted());
- if (res)
- del_result->abort_result_set();
- delete del_result;
+ if (!thd->is_fatal_error)
+ {
+ result= new multi_delete(aux_tables, lex->table_count);
+ if (result)
+ {
+ res= mysql_select(thd, &select_lex->ref_pointer_array,
+ select_lex->get_table_list(),
+ select_lex->with_wild,
+ select_lex->item_list,
+ select_lex->where,
+ 0, (ORDER *)NULL, (ORDER *)NULL, (Item *)NULL,
+ (ORDER *)NULL,
+ (select_lex->options | thd->variables.option_bits |
+ SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK |
+ OPTION_SETUP_TABLES_DONE) & ~OPTION_BUFFER_RESULT,
+ result, unit, select_lex);
+ res|= thd->is_error();
+
+ MYSQL_MULTI_DELETE_DONE(res, del_result->num_deleted());
+ if (res)
+ result->abort_result_set(); /* for both DELETE and EXPLAIN DELETE */
+ else
+ {
+ if (explain)
+ res= thd->lex->explain->send_explain(thd);
+ }
+ delete result;
+ }
}
else
{
@@ -4743,8 +4775,8 @@ finish:
ha_maria::implicit_commit(thd, FALSE);
#endif
}
-
lex->unit.cleanup();
+
/* Free tables */
thd_proc_info(thd, "closing tables");
close_thread_tables(thd);
@@ -4819,24 +4851,37 @@ static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables)
if (!(result= new select_send()))
return 1; /* purecov: inspected */
thd->send_explain_fields(result);
- res= mysql_explain_union(thd, &thd->lex->unit, result);
+
/*
- The code which prints the extended description is not robust
- against malformed queries, so skip it if we have an error.
+ This will call optimize() for all parts of query. The query plan is
+ printed out below.
*/
- if (!res && (lex->describe & DESCRIBE_EXTENDED))
+ res= mysql_explain_union(thd, &thd->lex->unit, result);
+
+ /* Print EXPLAIN only if we don't have an error */
+ if (!res)
{
- char buff[1024];
- String str(buff,(uint32) sizeof(buff), system_charset_info);
- str.length(0);
- /*
- The warnings system requires input in utf8, @see
- mysqld_show_warnings().
- */
- thd->lex->unit.print(&str, QT_TO_SYSTEM_CHARSET);
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
- ER_YES, str.c_ptr_safe());
+ /*
+ Do like the original select_describe did: remove OFFSET from the
+ top-level LIMIT
+ */
+ result->reset_offset_limit();
+ thd->lex->explain->print_explain(result, thd->lex->describe);
+ if (lex->describe & DESCRIBE_EXTENDED)
+ {
+ char buff[1024];
+ String str(buff,(uint32) sizeof(buff), system_charset_info);
+ str.length(0);
+ /*
+ The warnings system requires input in utf8, @see
+ mysqld_show_warnings().
+ */
+ thd->lex->unit.print(&str, QT_TO_SYSTEM_CHARSET);
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ER_YES, str.c_ptr_safe());
+ }
}
+
if (res)
result->abort_result_set();
else