mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 03:52:35 +01:00
MWL#182: Explain running statements
- Address feedback from the second code review.
This commit is contained in:
parent
a49b4c970f
commit
2368f8895d
12 changed files with 201 additions and 184 deletions
|
@ -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;
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#ifndef INCLUDES_MY_APC_H
|
||||
#define INCLUDES_MY_APC_H
|
||||
/*
|
||||
Copyright (c) 2011 - 2012, Monty Program Ab
|
||||
|
||||
|
@ -93,7 +95,7 @@ private:
|
|||
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 @@ private:
|
|||
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 @@ private:
|
|||
|
||||
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 @@ public:
|
|||
*/
|
||||
killed_state volatile killed;
|
||||
|
||||
/* See also thd_killed() */
|
||||
inline bool check_killed()
|
||||
{
|
||||
if (killed)
|
||||
|
@ -2438,7 +2407,8 @@ public:
|
|||
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_LOCK_WAIT_TIMEOUT, MYF(0));
|
||||
else
|
||||
if (timed_out)
|
||||
{
|
||||
my_error(ER_ERROR_WHEN_EXECUTING_COMMAND, MYF(0),
|
||||
"SHOW EXPLAIN",
|
||||
"Timeout");
|
||||
}
|
||||
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 @@ public:
|
|||
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();
|
||||
|
||||
|
|
Loading…
Reference in a new issue