summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorSergey Petrunya <psergey@askmonty.org>2012-07-05 22:04:13 +0400
committerSergey Petrunya <psergey@askmonty.org>2012-07-05 22:04:13 +0400
commit3e90dc1f77dc3fa51d542bf82a336753310f7776 (patch)
treed0c14418aa1ab3d3af27a98cd9a27d603d753fac /sql
parentb97678f066dd9dfb32409c61028080ac14efb1eb (diff)
downloadmariadb-git-3e90dc1f77dc3fa51d542bf82a336753310f7776.tar.gz
MWL#182: Explain running statements
- Make SHOW EXPLAIN command be KILLable with KILL QUERY.
Diffstat (limited to 'sql')
-rw-r--r--sql/my_apc.cc21
-rw-r--r--sql/my_apc.h4
-rw-r--r--sql/sql_show.cc8
3 files changed, 25 insertions, 8 deletions
diff --git a/sql/my_apc.cc b/sql/my_apc.cc
index 1cc13f41566..dd15daf48a2 100644
--- a/sql/my_apc.cc
+++ b/sql/my_apc.cc
@@ -145,8 +145,8 @@ void Apc_target::dequeue_request(Call_request *qe)
to use thd->enter_cond() calls to be killable)
*/
-bool Apc_target::make_apc_call(Apc_call *call, int timeout_sec,
- bool *timed_out)
+bool Apc_target::make_apc_call(THD *caller_thd, Apc_call *call,
+ int timeout_sec, bool *timed_out)
{
bool res= TRUE;
*timed_out= FALSE;
@@ -166,6 +166,9 @@ bool Apc_target::make_apc_call(Apc_call *call, int timeout_sec,
set_timespec(abstime, timeout);
int wait_res= 0;
+ const char *old_msg;
+ old_msg= caller_thd->enter_cond(&apc_request.COND_request,
+ LOCK_thd_data_ptr, "show_explain");
/* todo: how about processing other errors here? */
while (!apc_request.processed && (wait_res != ETIMEDOUT))
{
@@ -173,13 +176,18 @@ bool Apc_target::make_apc_call(Apc_call *call, int timeout_sec,
wait_res= mysql_cond_timedwait(&apc_request.COND_request,
LOCK_thd_data_ptr, &abstime);
// &apc_request.LOCK_request, &abstime);
+ if (caller_thd->killed)
+ {
+ break;
+ }
}
if (!apc_request.processed)
{
/*
- The wait has timed out. Remove the request from the queue (ok to do
- because we own LOCK_thd_data_ptr.
+ The wait has timed out, or this thread was KILLed.
+ Remove the request from the queue (ok to do because we own
+ LOCK_thd_data_ptr)
*/
apc_request.processed= TRUE;
dequeue_request(&apc_request);
@@ -191,7 +199,10 @@ bool Apc_target::make_apc_call(Apc_call *call, int timeout_sec,
/* Request was successfully executed and dequeued by the target thread */
res= FALSE;
}
- mysql_mutex_unlock(LOCK_thd_data_ptr);
+ /*
+ exit_cond() will call mysql_mutex_unlock(LOCK_thd_data_ptr) for us:
+ */
+ caller_thd->exit_cond(old_msg);
/* Destroy all APC request data */
mysql_cond_destroy(&apc_request.COND_request);
diff --git a/sql/my_apc.h b/sql/my_apc.h
index 93b934c9df1..84819b9beea 100644
--- a/sql/my_apc.h
+++ b/sql/my_apc.h
@@ -33,6 +33,8 @@
requestor.
*/
+class THD;
+
/*
Target for asynchronous procedure calls (APCs).
- A target is running in some particular thread,
@@ -62,7 +64,7 @@ public:
};
/* Make a call in the target thread (see function definition for details) */
- bool make_apc_call(Apc_call *call, int timeout_sec, bool *timed_out);
+ bool make_apc_call(THD *caller_thd, Apc_call *call, int timeout_sec, bool *timed_out);
#ifndef DBUG_OFF
int n_calls_processed; /* Number of calls served by this target */
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index d26c8f18340..6c407f0cec3 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -2084,11 +2084,15 @@ void mysqld_show_explain(THD *thd, const char *calling_user, ulong thread_id)
explain_req.failed_to_produce= FALSE;
/* Ok, we have a lock on target->LOCK_thd_data, can call: */
- bres= tmp->apc_target.make_apc_call(&explain_req, timeout_sec, &timed_out);
+ bres= tmp->apc_target.make_apc_call(thd, &explain_req, timeout_sec, &timed_out);
if (bres || explain_req.failed_to_produce)
{
- /* TODO not enabled or time out */
+ if (thd->killed)
+ {
+ thd->send_kill_message();
+ }
+ else
if (timed_out)
{
my_error(ER_ERROR_WHEN_EXECUTING_COMMAND, MYF(0),