Commit 2368f889 authored by Sergey Petrunya's avatar Sergey Petrunya

MWL#182: Explain running statements

- Address feedback from the second code review.
parent a49b4c97
......@@ -10,11 +10,11 @@ alter table t1 add key(a), add key(b);
show explain for 2*1000*1000*1000;
ERROR HY000: Unknown thread id: 2000000000
show explain for (select max(a) from t0);
ERROR 42000: This version of MariaDB doesn't yet support 'Usage of subqueries or stored function calls as part of this statement'
ERROR HY000: You may only use constant expressions in this statement
show explain for $thr2;
ERROR HY000: Error when executing command SHOW EXPLAIN: Target is not running EXPLAINable command
ERROR HY000: Target is not running an EXPLAINable command
show explain for $thr1;
ERROR HY000: Error when executing command SHOW EXPLAIN: Target is not running EXPLAINable command
ERROR HY000: Target is not running an EXPLAINable command
set @show_explain_probe_select_id=1;
set debug_dbug='d,show_explain_probe_join_exec_start';
select count(*) from t1 where a < 100000;
......@@ -153,7 +153,7 @@ set @show_explain_probe_select_id=1;
set debug_dbug='d,show_explain_probe_join_exec_end';
select a, (select max(a) from t0 b where b.a+a.a<10) from t0 a where a<1;
show explain for $thr2;
ERROR HY000: Error when executing command SHOW EXPLAIN: Target is not running EXPLAINable command
ERROR HY000: Target is not running an EXPLAINable command
a (select max(a) from t0 b where b.a+a.a<10)
0 9
# Try to do SHOW EXPLAIN for a query that runs a SET command:
......@@ -163,7 +163,7 @@ set @show_explain_probe_select_id=2;
set debug_dbug='d,show_explain_probe_join_exec_start';
set @foo= (select max(a) from t0 where sin(a) >0);
show explain for $thr2;
ERROR HY000: Error when executing command SHOW EXPLAIN: Target is not running EXPLAINable command
ERROR HY000: Target is not running an EXPLAINable command
#
# Attempt SHOW EXPLAIN for an UPDATE
#
......@@ -172,9 +172,9 @@ set @show_explain_probe_select_id=2;
set debug_dbug='d,show_explain_probe_join_exec_start';
update t2 set dummy=0 where (select max(a) from t0 where t2.a + t0.a <3) >3 ;
show explain for $thr2;
ERROR HY000: Error when executing command SHOW EXPLAIN: Target is not running EXPLAINable command
ERROR HY000: Target is not running an EXPLAINable command
show explain for $thr2;
ERROR HY000: Error when executing command SHOW EXPLAIN: Target is not running EXPLAINable command
ERROR HY000: Target is not running an EXPLAINable command
drop table t2;
#
# Attempt SHOW EXPLAIN for a DELETE
......@@ -184,9 +184,9 @@ set @show_explain_probe_select_id=2;
set debug_dbug='d,show_explain_probe_join_exec_start';
delete from t2 where (select max(a) from t0 where t2.a + t0.a <3) >3 ;
show explain for $thr2;
ERROR HY000: Error when executing command SHOW EXPLAIN: Target is not running EXPLAINable command
ERROR HY000: Target is not running an EXPLAINable command
show explain for $thr2;
ERROR HY000: Error when executing command SHOW EXPLAIN: Target is not running EXPLAINable command
ERROR HY000: Target is not running an EXPLAINable command
drop table t2;
#
# Multiple SHOW EXPLAIN calls for one select
......@@ -308,7 +308,7 @@ SELECT alias.a FROM t2, ( SELECT * FROM t2 ) AS alias GROUP BY alias.a;
# FIXED by "conservative assumptions about when QEP is available" fix:
# NOTE: current code will not show "Using join buffer":
show explain for $thr2;
ERROR HY000: Error when executing command SHOW EXPLAIN: Target is not running EXPLAINable command
ERROR HY000: Target is not running an EXPLAINable command
a
1
2
......@@ -361,7 +361,7 @@ set @show_explain_probe_select_id=2;
set debug_dbug='d,show_explain_probe_join_exec_end';
SELECT * FROM v1, t2;
show explain for $thr2;
ERROR HY000: Error when executing command SHOW EXPLAIN: Target is not running EXPLAINable command
ERROR HY000: Target is not running an EXPLAINable command
a b
8 4
8 5
......@@ -393,7 +393,7 @@ set @show_explain_probe_select_id=1;
set debug_dbug='d,show_explain_probe_join_exec_end';
select * from t0 where 1>10;
show explain for $thr2;
ERROR HY000: Error when executing command SHOW EXPLAIN: Target is not running EXPLAINable command
ERROR HY000: Target is not running an EXPLAINable command
a
set debug_dbug='';
#
......@@ -405,7 +405,7 @@ set @show_explain_probe_select_id=1;
set debug_dbug='d,show_explain_probe_join_exec_end';
select * from t0,t3 where t3.a=112233;
show explain for $thr2;
ERROR HY000: Error when executing command SHOW EXPLAIN: Target is not running EXPLAINable command
ERROR HY000: Target is not running an EXPLAINable command
a a
set debug_dbug='';
drop table t3;
......@@ -510,7 +510,7 @@ set @show_explain_probe_select_id=1;
set debug_dbug='d,show_explain_probe_join_exec_end';
SELECT * FROM t2 WHERE (5, 78) IN (SELECT `a1`, MAX(`a1`) FROM t2 GROUP BY `a1`);
show explain for $thr2;
ERROR HY000: Error when executing command SHOW EXPLAIN: Target is not running EXPLAINable command
ERROR HY000: Target is not running an EXPLAINable command
pk a1
set debug_dbug='';
DROP TABLE t2;
......@@ -732,6 +732,7 @@ drop table t1,t3,t4;
# ---------- SHOW EXPLAIN and permissions -----------------
#
grant ALL on test.* to test2@localhost;
grant super on *.* to test2@localhost;
#
# First, make sure that user 'test2' cannot do SHOW EXPLAIN on us
#
......@@ -739,7 +740,7 @@ set @show_explain_probe_select_id=1;
set debug_dbug='d,show_explain_probe_join_exec_start';
select * from t0 where a < 3;
show explain for $thr2;
ERROR 42000: Access denied; you need (at least one of) the PROCESSLIST privilege(s) for this operation
ERROR 42000: Access denied; you need (at least one of) the PROCESS privilege(s) for this operation
show explain for $thr2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t0 ALL NULL NULL NULL NULL 10 Using where
......@@ -751,11 +752,20 @@ a
2
set debug_dbug='';
#
# Unfortunately, our test setup doesn't allow to check that test2
# can do SHOW EXPLAIN on his own queries. This is because SET debug_dbug
# requires SUPER privilege. Giving SUPER to test2 will make the test
# meaningless
# Check that user test2 can do SHOW EXPLAIN on its own queries
#
set @show_explain_probe_select_id=1;
set debug_dbug='d,show_explain_probe_join_exec_start';
select * from t0 where a < 3;
show explain for $thr_con2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t0 ALL NULL NULL NULL NULL 10 Using where
Warnings:
Note 1003 select * from t0 where a < 3
a
0
1
2
#
# Now, grant test2 a PROCESSLIST permission, and see that he's able to observe us
#
......
......@@ -45,7 +45,7 @@ alter table t1 add key(a), add key(b);
--error ER_NO_SUCH_THREAD
show explain for 2*1000*1000*1000;
--error ER_NOT_SUPPORTED_YET
--error ER_SET_CONSTANTS_ONLY
show explain for (select max(a) from t0);
#
......@@ -58,11 +58,11 @@ let $thr2=`select connection_id()`;
connection default;
# SHOW EXPLAIN FOR <idle thread>
--error ER_ERROR_WHEN_EXECUTING_COMMAND
--error ER_TARGET_NOT_EXPLAINABLE
evalp show explain for $thr2;
# SHOW EXPLAIN FOR <ourselves>
--error ER_ERROR_WHEN_EXECUTING_COMMAND
--error ER_TARGET_NOT_EXPLAINABLE
evalp show explain for $thr1;
let $wait_condition= select State='show_explain_trap' from information_schema.processlist where id=$thr2;
......@@ -192,7 +192,7 @@ set debug_dbug='d,show_explain_probe_join_exec_end';
send select a, (select max(a) from t0 b where b.a+a.a<10) from t0 a where a<1;
connection default;
--source include/wait_condition.inc
--error ER_ERROR_WHEN_EXECUTING_COMMAND
--error ER_TARGET_NOT_EXPLAINABLE
evalp show explain for $thr2;
connection con1;
reap;
......@@ -212,7 +212,7 @@ set debug_dbug='d,show_explain_probe_join_exec_start';
send set @foo= (select max(a) from t0 where sin(a) >0);
connection default;
--source include/wait_condition.inc
--error ER_ERROR_WHEN_EXECUTING_COMMAND
--error ER_TARGET_NOT_EXPLAINABLE
evalp show explain for $thr2;
connection con1;
reap;
......@@ -226,9 +226,9 @@ set debug_dbug='d,show_explain_probe_join_exec_start';
send update t2 set dummy=0 where (select max(a) from t0 where t2.a + t0.a <3) >3 ;
connection default;
--source include/wait_condition.inc
--error ER_ERROR_WHEN_EXECUTING_COMMAND
--error ER_TARGET_NOT_EXPLAINABLE
evalp show explain for $thr2;
--error ER_ERROR_WHEN_EXECUTING_COMMAND
--error ER_TARGET_NOT_EXPLAINABLE
evalp show explain for $thr2;
connection con1;
reap;
......@@ -243,9 +243,9 @@ set debug_dbug='d,show_explain_probe_join_exec_start';
send delete from t2 where (select max(a) from t0 where t2.a + t0.a <3) >3 ;
connection default;
--source include/wait_condition.inc
--error ER_ERROR_WHEN_EXECUTING_COMMAND
--error ER_TARGET_NOT_EXPLAINABLE
evalp show explain for $thr2;
--error ER_ERROR_WHEN_EXECUTING_COMMAND
--error ER_TARGET_NOT_EXPLAINABLE
evalp show explain for $thr2;
connection con1;
reap;
......@@ -329,7 +329,7 @@ connection default;
--source include/wait_condition.inc
--echo # FIXED by "conservative assumptions about when QEP is available" fix:
--echo # NOTE: current code will not show "Using join buffer":
--error ER_ERROR_WHEN_EXECUTING_COMMAND
--error ER_TARGET_NOT_EXPLAINABLE
evalp show explain for $thr2;
connection con1;
reap;
......@@ -378,7 +378,7 @@ send SELECT * FROM v1, t2;
connection default;
--source include/wait_condition.inc
--error ER_ERROR_WHEN_EXECUTING_COMMAND
--error ER_TARGET_NOT_EXPLAINABLE
evalp show explain for $thr2;
connection con1;
reap;
......@@ -408,7 +408,7 @@ set debug_dbug='d,show_explain_probe_join_exec_end';
send select * from t0 where 1>10;
connection default;
--source include/wait_condition.inc
--error ER_ERROR_WHEN_EXECUTING_COMMAND
--error ER_TARGET_NOT_EXPLAINABLE
evalp show explain for $thr2;
connection con1;
reap;
......@@ -424,7 +424,7 @@ set debug_dbug='d,show_explain_probe_join_exec_end';
send select * from t0,t3 where t3.a=112233;
connection default;
--source include/wait_condition.inc
--error ER_ERROR_WHEN_EXECUTING_COMMAND
--error ER_TARGET_NOT_EXPLAINABLE
evalp show explain for $thr2;
connection con1;
reap;
......@@ -520,7 +520,7 @@ send
SELECT * FROM t2 WHERE (5, 78) IN (SELECT `a1`, MAX(`a1`) FROM t2 GROUP BY `a1`);
connection default;
--source include/wait_condition.inc
--error ER_ERROR_WHEN_EXECUTING_COMMAND
--error ER_TARGET_NOT_EXPLAINABLE
evalp show explain for $thr2;
connection con1;
reap;
......@@ -734,6 +734,8 @@ drop table t1,t3,t4;
--echo #
grant ALL on test.* to test2@localhost;
# Give the user SUPER privilege so it can set debug_dbug variable.
grant super on *.* to test2@localhost;
connect (con2, localhost, test2,,);
connection con1;
......@@ -760,12 +762,32 @@ reap;
set debug_dbug='';
--echo #
--echo # Unfortunately, our test setup doesn't allow to check that test2
--echo # can do SHOW EXPLAIN on his own queries. This is because SET debug_dbug
--echo # requires SUPER privilege. Giving SUPER to test2 will make the test
--echo # meaningless
--echo # Check that user test2 can do SHOW EXPLAIN on its own queries
--echo #
connect (con3, localhost, test2,,);
connection con2;
let $thr_con2=`select connection_id()`;
set @show_explain_probe_select_id=1;
set debug_dbug='d,show_explain_probe_join_exec_start';
send
select * from t0 where a < 3;
connection con1;
let $save_wait_condition= $wait_condition;
let $wait_condition= select State='show_explain_trap' from information_schema.processlist where id=$thr_con2;
--source include/wait_condition.inc
connection con3;
evalp show explain for $thr_con2;
connection con2;
reap;
connection con1;
disconnect con3;
let $wait_condition= $save_wait_condition;
--echo #
--echo # Now, grant test2 a PROCESSLIST permission, and see that he's able to observe us
--echo #
......
......@@ -24,35 +24,6 @@
/* For standalone testing of APC system, see unittest/sql/my_apc-t.cc */
#ifndef MY_APC_STANDALONE
ST_FIELD_INFO show_explain_fields_info[]=
{
/* field_name, length, type, value, field_flags, old_name*/
{"id", 3, MYSQL_TYPE_LONGLONG, 0 /*value*/, MY_I_S_MAYBE_NULL, "id",
SKIP_OPEN_TABLE},
{"select_type", 19, MYSQL_TYPE_STRING, 0 /*value*/, 0, "select_type",
SKIP_OPEN_TABLE},
{"table", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0 /*value*/, MY_I_S_MAYBE_NULL,
"table", SKIP_OPEN_TABLE},
{"type", 10, MYSQL_TYPE_STRING, 0, MY_I_S_MAYBE_NULL, "type", SKIP_OPEN_TABLE},
{"possible_keys", NAME_CHAR_LEN*MAX_KEY, MYSQL_TYPE_STRING, 0/*value*/,
MY_I_S_MAYBE_NULL, "possible_keys", SKIP_OPEN_TABLE},
{"key", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0/*value*/, MY_I_S_MAYBE_NULL,
"key", SKIP_OPEN_TABLE},
{"key_len", NAME_CHAR_LEN*MAX_KEY, MYSQL_TYPE_STRING, 0/*value*/,
MY_I_S_MAYBE_NULL, "key_len", SKIP_OPEN_TABLE},
{"ref", NAME_CHAR_LEN*MAX_REF_PARTS, MYSQL_TYPE_STRING, 0/*value*/,
MY_I_S_MAYBE_NULL, "ref", SKIP_OPEN_TABLE},
{"rows", 10, MYSQL_TYPE_LONGLONG, 0/*value*/, MY_I_S_MAYBE_NULL, "rows",
SKIP_OPEN_TABLE},
{"Extra", 255, MYSQL_TYPE_STRING, 0/*value*/, 0 /*flags*/, "Extra",
SKIP_OPEN_TABLE},
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
};
#endif
/*
Initialize the target.
......@@ -266,9 +237,6 @@ bool Apc_target::make_apc_call(THD *caller_thd, Apc_call *call,
void Apc_target::process_apc_requests()
{
if (!get_first_in_queue())
return;
while (1)
{
Call_request *request;
......
#ifndef INCLUDES_MY_APC_H
#define INCLUDES_MY_APC_H
/*
Copyright (c) 2011 - 2012, Monty Program Ab
......@@ -93,7 +95,7 @@ class Apc_target
We use this structure, because we
- process requests sequentially: requests are added at the end of the
list and removed from the front. With circular list, we can keep one
pointer.
pointer, and access both front an back of the list with it.
- a thread that has posted a request may time out (or be KILLed) and
cancel the request, which means we need a fast request-removal
operation.
......@@ -132,3 +134,5 @@ class Apc_target
void init_show_explain_psi_keys(void);
#endif
#endif //INCLUDES_MY_APC_H
......@@ -3909,8 +3909,8 @@ static int init_thread_environment()
sp_cache_init();
#ifdef HAVE_EVENT_SCHEDULER
Events::init_mutexes();
init_show_explain_psi_keys();
#endif
init_show_explain_psi_keys();
/* Parameter for threads created for connections */
(void) pthread_attr_init(&connection_attrib);
(void) pthread_attr_setdetachstate(&connection_attrib,
......
......@@ -4345,13 +4345,13 @@ ER_TOO_MANY_USER_CONNECTIONS 42000
ER_SET_CONSTANTS_ONLY
dan "Du må kun bruge konstantudtryk med SET"
nla "U mag alleen constante expressies gebruiken bij SET"
eng "You may only use constant expressions with SET"
eng "You may only use constant expressions in this statement"
est "Ainult konstantsed suurused on lubatud SET klauslis"
fre "Seules les expressions constantes sont autorisées avec SET"
ger "Bei SET dürfen nur konstante Ausdrücke verwendet werden"
ger "Bei diesem Befehl dürfen nur konstante Ausdrücke verwendet werden"
ita "Si possono usare solo espressioni costanti con SET"
por "Você pode usar apenas expressões constantes com SET"
rus "Вы можете использовать в SET только константные выражения"
rus "С этой командой вы можете использовать только константные выражения"
serbian "Možete upotrebiti samo konstantan iskaz sa komandom 'SET'"
spa "Tu solo debes usar expresiones constantes con SET"
swe "Man kan endast använda konstantuttryck med SET"
......@@ -6582,3 +6582,5 @@ ER_STORED_FUNCTION_PREVENTS_SWITCH_SKIP_REPLICATION
eng "Cannot modify @@session.skip_replication inside a stored function or trigger"
ER_QUERY_EXCEEDED_ROWS_EXAMINED_LIMIT
eng "Query execution was interrupted. The query examined at least %llu rows, which exceeds LIMIT ROWS EXAMINED (%llu). The query result may be incomplete."
ER_TARGET_NOT_EXPLAINABLE
eng "Target is not running an EXPLAINable command"
......@@ -2295,15 +2295,6 @@ int select_send::send_data(List<Item> &items)
}
int select_result_explain_buffer::send_data(List<Item> &items)
{
fill_record(thd, dst_table->field, items, TRUE, FALSE);
if ((dst_table->file->ha_write_tmp_row(dst_table->record[0])))
return 1;
return 0;
}
bool select_send::send_eof()
{
/*
......@@ -3233,43 +3224,6 @@ void THD::restore_active_arena(Query_arena *set, Query_arena *backup)
DBUG_VOID_RETURN;
}
/*
Produce EXPLAIN data.
This function is APC-scheduled to be run in the context of the thread that
we're producing EXPLAIN for.
*/
void Show_explain_request::call_in_target_thread()
{
Query_arena backup_arena;
bool printed_anything= FALSE;
/*
Change the arena because JOIN::print_explain and co. are going to allocate
items. Let them allocate them on our arena.
*/
target_thd->set_n_backup_active_arena((Query_arena*)request_thd,
&backup_arena);
query_str.copy(target_thd->query(),
target_thd->query_length(),
&my_charset_bin);
if (target_thd->lex->unit.print_explain(explain_buf, 0 /* explain flags*/,
&printed_anything))
{
failed_to_produce= TRUE;
}
if (!printed_anything)
failed_to_produce= TRUE;
target_thd->restore_active_arena((Query_arena*)request_thd, &backup_arena);
}
Statement::~Statement()
{
}
......@@ -3832,6 +3786,7 @@ void THD::restore_backup_open_tables_state(Open_tables_backup *backup)
@retval 1 the user thread has been killed
This is used to signal a storage engine if it should be killed.
See also THD::check_killed().
*/
extern "C" int thd_killed(const MYSQL_THD thd)
......@@ -3839,6 +3794,10 @@ extern "C" int thd_killed(const MYSQL_THD thd)
if (!thd)
thd= current_thd;
Apc_target *apc_target= (Apc_target*)&thd->apc_target;
if (apc_target->have_apc_requests())
apc_target->process_apc_requests();
if (!(thd->killed & KILL_HARD_BIT))
return 0;
return thd->killed;
......
......@@ -1520,39 +1520,7 @@ class Global_read_lock
extern "C" void my_message_sql(uint error, const char *str, myf MyFlags);
class select_result_explain_buffer;
/*
SHOW EXPLAIN request object.
The thread that runs SHOW EXPLAIN statement creates a Show_explain_request
object R, and then schedules APC call of
Show_explain_request::call((void*)&R).
*/
class Show_explain_request : public Apc_target::Apc_call
{
public:
THD *target_thd; /* thd that we're running SHOW EXPLAIN for */
THD *request_thd; /* thd that run SHOW EXPLAIN command */
/* If true, there was some error when producing EXPLAIN output. */
bool failed_to_produce;
/* SHOW EXPLAIN will be stored here */
select_result_explain_buffer *explain_buf;
/* Query that we've got SHOW EXPLAIN for */
String query_str;
/* Overloaded virtual function */
void call_in_target_thread();
};
class THD;
void mysqld_show_explain(THD *thd, const char *calling_user, ulong thread_id);
#ifndef DBUG_OFF
void dbug_serve_apcs(THD *thd, int n_calls);
#endif
......@@ -2222,6 +2190,7 @@ class THD :public Statement,
*/
killed_state volatile killed;
/* See also thd_killed() */
inline bool check_killed()
{
if (killed)
......@@ -2438,7 +2407,8 @@ class THD :public Statement,
Allows this thread to serve as a target for others to schedule Async
Procedure Calls on.
It's possible to schedule arbitrary C++ function calls. Currently, only
It's possible to schedule any code to be executed this way, by
inheriting from the Apc_call object. Currently, only
Show_explain_request uses this.
*/
Apc_target apc_target;
......
......@@ -2155,9 +2155,9 @@ mysql_execute_command(THD *thd)
*/
if (lex->sroutines.records || lex->query_tables->next_global)
{
my_error(ER_NOT_SUPPORTED_YET, MYF(0), "Usage of subqueries or stored "
"function calls as part of this statement");
break;
my_message(ER_SET_CONSTANTS_ONLY, ER(ER_SET_CONSTANTS_ONLY),
MYF(0));
goto error;
}
Item **it= &(lex->show_explain_for_thread);
......
......@@ -1999,8 +1999,50 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose)
}
static
const char *target_not_explainable_cmd="Target is not running EXPLAINable command";
/*
Produce EXPLAIN data.
This function is APC-scheduled to be run in the context of the thread that
we're producing EXPLAIN for.
*/
void Show_explain_request::call_in_target_thread()
{
Query_arena backup_arena;
bool printed_anything= FALSE;
/*
Change the arena because JOIN::print_explain and co. are going to allocate
items. Let them allocate them on our arena.
*/
target_thd->set_n_backup_active_arena((Query_arena*)request_thd,
&backup_arena);
query_str.copy(target_thd->query(),
target_thd->query_length(),
&my_charset_bin);
if (target_thd->lex->unit.print_explain(explain_buf, 0 /* explain flags*/,
&printed_anything))
{
failed_to_produce= TRUE;
}
if (!printed_anything)
failed_to_produce= TRUE;
target_thd->restore_active_arena((Query_arena*)request_thd, &backup_arena);
}
int select_result_explain_buffer::send_data(List<Item> &items)
{
fill_record(thd, dst_table->field, items, TRUE, FALSE);
if ((dst_table->file->ha_write_tmp_row(dst_table->record[0])))
return 1;
return 0;
}
/*
Store the SHOW EXPLAIN output in the temporary table.
......@@ -2048,7 +2090,7 @@ int fill_show_explain(THD *thd, TABLE_LIST *table, COND *cond)
if (calling_user && (!tmp_sctx->user || strcmp(calling_user,
tmp_sctx->user)))
{
my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "PROCESSLIST");
my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "PROCESS");
mysql_mutex_unlock(&tmp->LOCK_thd_data);
DBUG_RETURN(1);
}
......@@ -2056,8 +2098,7 @@ int fill_show_explain(THD *thd, TABLE_LIST *table, COND *cond)
if (tmp == thd)
{
mysql_mutex_unlock(&tmp->LOCK_thd_data);
my_error(ER_ERROR_WHEN_EXECUTING_COMMAND, MYF(0), "SHOW EXPLAIN",
target_not_explainable_cmd);
my_error(ER_TARGET_NOT_EXPLAINABLE, MYF(0));
DBUG_RETURN(1);
}
......@@ -2084,21 +2125,12 @@ int fill_show_explain(THD *thd, TABLE_LIST *table, COND *cond)
if (bres || explain_req.failed_to_produce)
{
if (thd->killed)
{
thd->send_kill_message();
}
else
if (timed_out)
{
my_error(ER_ERROR_WHEN_EXECUTING_COMMAND, MYF(0),
"SHOW EXPLAIN",
"Timeout");
}
else if (timed_out)
my_error(ER_LOCK_WAIT_TIMEOUT, MYF(0));
else
{
my_error(ER_ERROR_WHEN_EXECUTING_COMMAND, MYF(0),
"SHOW EXPLAIN", target_not_explainable_cmd);
}
my_error(ER_TARGET_NOT_EXPLAINABLE, MYF(0));
bres= TRUE;
}
else
......@@ -8427,7 +8459,32 @@ ST_FIELD_INFO keycache_fields_info[]=
};
extern ST_FIELD_INFO show_explain_fields_info[];
ST_FIELD_INFO show_explain_fields_info[]=
{
/* field_name, length, type, value, field_flags, old_name*/
{"id", 3, MYSQL_TYPE_LONGLONG, 0 /*value*/, MY_I_S_MAYBE_NULL, "id",
SKIP_OPEN_TABLE},
{"select_type", 19, MYSQL_TYPE_STRING, 0 /*value*/, 0, "select_type",
SKIP_OPEN_TABLE},
{"table", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0 /*value*/, MY_I_S_MAYBE_NULL,
"table", SKIP_OPEN_TABLE},
{"type", 10, MYSQL_TYPE_STRING, 0, MY_I_S_MAYBE_NULL, "type", SKIP_OPEN_TABLE},
{"possible_keys", NAME_CHAR_LEN*MAX_KEY, MYSQL_TYPE_STRING, 0/*value*/,
MY_I_S_MAYBE_NULL, "possible_keys", SKIP_OPEN_TABLE},
{"key", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0/*value*/, MY_I_S_MAYBE_NULL,
"key", SKIP_OPEN_TABLE},
{"key_len", NAME_CHAR_LEN*MAX_KEY, MYSQL_TYPE_STRING, 0/*value*/,
MY_I_S_MAYBE_NULL, "key_len", SKIP_OPEN_TABLE},
{"ref", NAME_CHAR_LEN*MAX_REF_PARTS, MYSQL_TYPE_STRING, 0/*value*/,
MY_I_S_MAYBE_NULL, "ref", SKIP_OPEN_TABLE},
{"rows", 10, MYSQL_TYPE_LONGLONG, 0/*value*/, MY_I_S_MAYBE_NULL, "rows",
SKIP_OPEN_TABLE},
{"Extra", 255, MYSQL_TYPE_STRING, 0/*value*/, 0 /*flags*/, "Extra",
SKIP_OPEN_TABLE},
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
};
/*
Description of ST_FIELD_INFO in table.h
......
......@@ -19,6 +19,7 @@
#include "sql_list.h" /* List */
#include "handler.h" /* enum_schema_tables */
#include "table.h" /* enum_schema_table_state */
#include "my_apc.h"
/* Forward declarations */
class JOIN;
......@@ -132,4 +133,28 @@ enum enum_schema_tables get_schema_table_idx(ST_SCHEMA_TABLE *schema_table);
/* These functions were under INNODB_COMPATIBILITY_HOOKS */
int get_quote_char_for_identifier(THD *thd, const char *name, uint length);
class select_result_explain_buffer;
/*
SHOW EXPLAIN request object.
*/
class Show_explain_request : public Apc_target::Apc_call
{
public:
THD *target_thd; /* thd that we're running SHOW EXPLAIN for */
THD *request_thd; /* thd that run SHOW EXPLAIN command */
/* If true, there was some error when producing EXPLAIN output. */
bool failed_to_produce;
/* SHOW EXPLAIN will be stored here */
select_result_explain_buffer *explain_buf;
/* Query that we've got SHOW EXPLAIN for */
String query_str;
/* Overloaded virtual function */
void call_in_target_thread();
};
#endif /* SQL_SHOW_H */
......@@ -90,7 +90,7 @@ void *test_apc_service_thread(void *ptr)
apc_target.init(&target_mutex);
apc_target.enable();
started= TRUE;
fprintf(stderr, "# test_apc_service_thread started\n");
diag("test_apc_service_thread started");
while (!service_should_exit)
{
//apc_target.disable();
......@@ -137,7 +137,7 @@ class Apc_order : public Apc_target::Apc_call
void *test_apc_requestor_thread(void *ptr)
{
my_thread_init();
fprintf(stderr, "# test_apc_requestor_thread started\n");
diag("test_apc_requestor_thread started");
THD my_thd;
while (!requestors_should_exit)
......@@ -159,7 +159,7 @@ void *test_apc_requestor_thread(void *ptr)
if (dst_value != 0)
{
fprintf(stderr, "APC was done even though return value says it wasnt!\n");
diag("APC was done even though return value says it wasnt!");
have_errors= true;
}
}
......@@ -167,13 +167,13 @@ void *test_apc_requestor_thread(void *ptr)
{
if (dst_value != src_value)
{
fprintf(stderr, "APC was not done even though return value says it was!\n");
diag("APC was not done even though return value says it was!");
have_errors= true;
}
}
//my_sleep(300);
}
fprintf(stderr, "# test_apc_requestor_thread exiting\n");
diag("test_apc_requestor_thread exiting");
my_thread_end();
return NULL;
}
......@@ -204,20 +204,20 @@ int main(int args, char **argv)
for (i = 0; i < 15; i++)
{
my_sleep(500*1000);
fprintf(stderr, "# %d APCs served %d missed\n", apcs_served, apcs_missed);
diag("%d APCs served %d missed", apcs_served, apcs_missed);
}
fprintf(stderr, "# Shutting down requestors\n");
diag("Shutting down requestors");
requestors_should_exit= TRUE;
for (i = 0; i < N_THREADS; i++)
pthread_join(request_thr[i], NULL);
fprintf(stderr, "# Shutting down service\n");
diag("Shutting down service");
service_should_exit= TRUE;
pthread_join(service_thr, NULL);
mysql_mutex_destroy(&apc_counters_mutex);
fprintf(stderr, "# Done.\n");
diag("Done");
my_thread_end();
my_thread_global_end();
......
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