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); ...@@ -10,11 +10,11 @@ alter table t1 add key(a), add key(b);
show explain for 2*1000*1000*1000; show explain for 2*1000*1000*1000;
ERROR HY000: Unknown thread id: 2000000000 ERROR HY000: Unknown thread id: 2000000000
show explain for (select max(a) from t0); 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; 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; 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 @show_explain_probe_select_id=1;
set debug_dbug='d,show_explain_probe_join_exec_start'; set debug_dbug='d,show_explain_probe_join_exec_start';
select count(*) from t1 where a < 100000; select count(*) from t1 where a < 100000;
...@@ -153,7 +153,7 @@ set @show_explain_probe_select_id=1; ...@@ -153,7 +153,7 @@ set @show_explain_probe_select_id=1;
set debug_dbug='d,show_explain_probe_join_exec_end'; 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; select a, (select max(a) from t0 b where b.a+a.a<10) from t0 a where a<1;
show explain for $thr2; 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) a (select max(a) from t0 b where b.a+a.a<10)
0 9 0 9
# Try to do SHOW EXPLAIN for a query that runs a SET command: # Try to do SHOW EXPLAIN for a query that runs a SET command:
...@@ -163,7 +163,7 @@ set @show_explain_probe_select_id=2; ...@@ -163,7 +163,7 @@ set @show_explain_probe_select_id=2;
set debug_dbug='d,show_explain_probe_join_exec_start'; set debug_dbug='d,show_explain_probe_join_exec_start';
set @foo= (select max(a) from t0 where sin(a) >0); set @foo= (select max(a) from t0 where sin(a) >0);
show explain for $thr2; 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 # Attempt SHOW EXPLAIN for an UPDATE
# #
...@@ -172,9 +172,9 @@ set @show_explain_probe_select_id=2; ...@@ -172,9 +172,9 @@ set @show_explain_probe_select_id=2;
set debug_dbug='d,show_explain_probe_join_exec_start'; 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 ; update t2 set dummy=0 where (select max(a) from t0 where t2.a + t0.a <3) >3 ;
show explain for $thr2; 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; 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; drop table t2;
# #
# Attempt SHOW EXPLAIN for a DELETE # Attempt SHOW EXPLAIN for a DELETE
...@@ -184,9 +184,9 @@ set @show_explain_probe_select_id=2; ...@@ -184,9 +184,9 @@ set @show_explain_probe_select_id=2;
set debug_dbug='d,show_explain_probe_join_exec_start'; 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 ; delete from t2 where (select max(a) from t0 where t2.a + t0.a <3) >3 ;
show explain for $thr2; 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; 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; drop table t2;
# #
# Multiple SHOW EXPLAIN calls for one select # 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; ...@@ -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: # FIXED by "conservative assumptions about when QEP is available" fix:
# NOTE: current code will not show "Using join buffer": # NOTE: current code will not show "Using join buffer":
show explain for $thr2; 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
1 1
2 2
...@@ -361,7 +361,7 @@ set @show_explain_probe_select_id=2; ...@@ -361,7 +361,7 @@ set @show_explain_probe_select_id=2;
set debug_dbug='d,show_explain_probe_join_exec_end'; set debug_dbug='d,show_explain_probe_join_exec_end';
SELECT * FROM v1, t2; SELECT * FROM v1, t2;
show explain for $thr2; 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 a b
8 4 8 4
8 5 8 5
...@@ -393,7 +393,7 @@ set @show_explain_probe_select_id=1; ...@@ -393,7 +393,7 @@ set @show_explain_probe_select_id=1;
set debug_dbug='d,show_explain_probe_join_exec_end'; set debug_dbug='d,show_explain_probe_join_exec_end';
select * from t0 where 1>10; select * from t0 where 1>10;
show explain for $thr2; 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=''; set debug_dbug='';
# #
...@@ -405,7 +405,7 @@ set @show_explain_probe_select_id=1; ...@@ -405,7 +405,7 @@ set @show_explain_probe_select_id=1;
set debug_dbug='d,show_explain_probe_join_exec_end'; set debug_dbug='d,show_explain_probe_join_exec_end';
select * from t0,t3 where t3.a=112233; select * from t0,t3 where t3.a=112233;
show explain for $thr2; 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 a a
set debug_dbug=''; set debug_dbug='';
drop table t3; drop table t3;
...@@ -510,7 +510,7 @@ set @show_explain_probe_select_id=1; ...@@ -510,7 +510,7 @@ set @show_explain_probe_select_id=1;
set debug_dbug='d,show_explain_probe_join_exec_end'; 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`); SELECT * FROM t2 WHERE (5, 78) IN (SELECT `a1`, MAX(`a1`) FROM t2 GROUP BY `a1`);
show explain for $thr2; 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 pk a1
set debug_dbug=''; set debug_dbug='';
DROP TABLE t2; DROP TABLE t2;
...@@ -732,6 +732,7 @@ drop table t1,t3,t4; ...@@ -732,6 +732,7 @@ drop table t1,t3,t4;
# ---------- SHOW EXPLAIN and permissions ----------------- # ---------- SHOW EXPLAIN and permissions -----------------
# #
grant ALL on test.* to test2@localhost; 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 # First, make sure that user 'test2' cannot do SHOW EXPLAIN on us
# #
...@@ -739,7 +740,7 @@ set @show_explain_probe_select_id=1; ...@@ -739,7 +740,7 @@ set @show_explain_probe_select_id=1;
set debug_dbug='d,show_explain_probe_join_exec_start'; set debug_dbug='d,show_explain_probe_join_exec_start';
select * from t0 where a < 3; select * from t0 where a < 3;
show explain for $thr2; 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; show explain for $thr2;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t0 ALL NULL NULL NULL NULL 10 Using where 1 SIMPLE t0 ALL NULL NULL NULL NULL 10 Using where
...@@ -751,11 +752,20 @@ a ...@@ -751,11 +752,20 @@ a
2 2
set debug_dbug=''; set debug_dbug='';
# #
# Unfortunately, our test setup doesn't allow to check that test2 # Check that user test2 can do SHOW EXPLAIN on its own queries
# 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
# #
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 # 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); ...@@ -45,7 +45,7 @@ alter table t1 add key(a), add key(b);
--error ER_NO_SUCH_THREAD --error ER_NO_SUCH_THREAD
show explain for 2*1000*1000*1000; 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); show explain for (select max(a) from t0);
# #
...@@ -58,11 +58,11 @@ let $thr2=`select connection_id()`; ...@@ -58,11 +58,11 @@ let $thr2=`select connection_id()`;
connection default; connection default;
# SHOW EXPLAIN FOR <idle thread> # SHOW EXPLAIN FOR <idle thread>
--error ER_ERROR_WHEN_EXECUTING_COMMAND --error ER_TARGET_NOT_EXPLAINABLE
evalp show explain for $thr2; evalp show explain for $thr2;
# SHOW EXPLAIN FOR <ourselves> # SHOW EXPLAIN FOR <ourselves>
--error ER_ERROR_WHEN_EXECUTING_COMMAND --error ER_TARGET_NOT_EXPLAINABLE
evalp show explain for $thr1; evalp show explain for $thr1;
let $wait_condition= select State='show_explain_trap' from information_schema.processlist where id=$thr2; 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'; ...@@ -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; send select a, (select max(a) from t0 b where b.a+a.a<10) from t0 a where a<1;
connection default; connection default;
--source include/wait_condition.inc --source include/wait_condition.inc
--error ER_ERROR_WHEN_EXECUTING_COMMAND --error ER_TARGET_NOT_EXPLAINABLE
evalp show explain for $thr2; evalp show explain for $thr2;
connection con1; connection con1;
reap; reap;
...@@ -212,7 +212,7 @@ set debug_dbug='d,show_explain_probe_join_exec_start'; ...@@ -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); send set @foo= (select max(a) from t0 where sin(a) >0);
connection default; connection default;
--source include/wait_condition.inc --source include/wait_condition.inc
--error ER_ERROR_WHEN_EXECUTING_COMMAND --error ER_TARGET_NOT_EXPLAINABLE
evalp show explain for $thr2; evalp show explain for $thr2;
connection con1; connection con1;
reap; reap;
...@@ -226,9 +226,9 @@ set debug_dbug='d,show_explain_probe_join_exec_start'; ...@@ -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 ; send update t2 set dummy=0 where (select max(a) from t0 where t2.a + t0.a <3) >3 ;
connection default; connection default;
--source include/wait_condition.inc --source include/wait_condition.inc
--error ER_ERROR_WHEN_EXECUTING_COMMAND --error ER_TARGET_NOT_EXPLAINABLE
evalp show explain for $thr2; evalp show explain for $thr2;
--error ER_ERROR_WHEN_EXECUTING_COMMAND --error ER_TARGET_NOT_EXPLAINABLE
evalp show explain for $thr2; evalp show explain for $thr2;
connection con1; connection con1;
reap; reap;
...@@ -243,9 +243,9 @@ set debug_dbug='d,show_explain_probe_join_exec_start'; ...@@ -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 ; send delete from t2 where (select max(a) from t0 where t2.a + t0.a <3) >3 ;
connection default; connection default;
--source include/wait_condition.inc --source include/wait_condition.inc
--error ER_ERROR_WHEN_EXECUTING_COMMAND --error ER_TARGET_NOT_EXPLAINABLE
evalp show explain for $thr2; evalp show explain for $thr2;
--error ER_ERROR_WHEN_EXECUTING_COMMAND --error ER_TARGET_NOT_EXPLAINABLE
evalp show explain for $thr2; evalp show explain for $thr2;
connection con1; connection con1;
reap; reap;
...@@ -329,7 +329,7 @@ connection default; ...@@ -329,7 +329,7 @@ connection default;
--source include/wait_condition.inc --source include/wait_condition.inc
--echo # FIXED by "conservative assumptions about when QEP is available" fix: --echo # FIXED by "conservative assumptions about when QEP is available" fix:
--echo # NOTE: current code will not show "Using join buffer": --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; evalp show explain for $thr2;
connection con1; connection con1;
reap; reap;
...@@ -378,7 +378,7 @@ send SELECT * FROM v1, t2; ...@@ -378,7 +378,7 @@ send SELECT * FROM v1, t2;
connection default; connection default;
--source include/wait_condition.inc --source include/wait_condition.inc
--error ER_ERROR_WHEN_EXECUTING_COMMAND --error ER_TARGET_NOT_EXPLAINABLE
evalp show explain for $thr2; evalp show explain for $thr2;
connection con1; connection con1;
reap; reap;
...@@ -408,7 +408,7 @@ set debug_dbug='d,show_explain_probe_join_exec_end'; ...@@ -408,7 +408,7 @@ set debug_dbug='d,show_explain_probe_join_exec_end';
send select * from t0 where 1>10; send select * from t0 where 1>10;
connection default; connection default;
--source include/wait_condition.inc --source include/wait_condition.inc
--error ER_ERROR_WHEN_EXECUTING_COMMAND --error ER_TARGET_NOT_EXPLAINABLE
evalp show explain for $thr2; evalp show explain for $thr2;
connection con1; connection con1;
reap; reap;
...@@ -424,7 +424,7 @@ set debug_dbug='d,show_explain_probe_join_exec_end'; ...@@ -424,7 +424,7 @@ set debug_dbug='d,show_explain_probe_join_exec_end';
send select * from t0,t3 where t3.a=112233; send select * from t0,t3 where t3.a=112233;
connection default; connection default;
--source include/wait_condition.inc --source include/wait_condition.inc
--error ER_ERROR_WHEN_EXECUTING_COMMAND --error ER_TARGET_NOT_EXPLAINABLE
evalp show explain for $thr2; evalp show explain for $thr2;
connection con1; connection con1;
reap; reap;
...@@ -520,7 +520,7 @@ send ...@@ -520,7 +520,7 @@ send
SELECT * FROM t2 WHERE (5, 78) IN (SELECT `a1`, MAX(`a1`) FROM t2 GROUP BY `a1`); SELECT * FROM t2 WHERE (5, 78) IN (SELECT `a1`, MAX(`a1`) FROM t2 GROUP BY `a1`);
connection default; connection default;
--source include/wait_condition.inc --source include/wait_condition.inc
--error ER_ERROR_WHEN_EXECUTING_COMMAND --error ER_TARGET_NOT_EXPLAINABLE
evalp show explain for $thr2; evalp show explain for $thr2;
connection con1; connection con1;
reap; reap;
...@@ -734,6 +734,8 @@ drop table t1,t3,t4; ...@@ -734,6 +734,8 @@ drop table t1,t3,t4;
--echo # --echo #
grant ALL on test.* to test2@localhost; 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,,); connect (con2, localhost, test2,,);
connection con1; connection con1;
...@@ -760,12 +762,32 @@ reap; ...@@ -760,12 +762,32 @@ reap;
set debug_dbug=''; set debug_dbug='';
--echo # --echo #
--echo # Unfortunately, our test setup doesn't allow to check that test2 --echo # Check that user test2 can do SHOW EXPLAIN on its own queries
--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 # --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 #
--echo # Now, grant test2 a PROCESSLIST permission, and see that he's able to observe us --echo # Now, grant test2 a PROCESSLIST permission, and see that he's able to observe us
--echo # --echo #
......
...@@ -24,35 +24,6 @@ ...@@ -24,35 +24,6 @@
/* For standalone testing of APC system, see unittest/sql/my_apc-t.cc */ /* 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. Initialize the target.
...@@ -266,9 +237,6 @@ bool Apc_target::make_apc_call(THD *caller_thd, Apc_call *call, ...@@ -266,9 +237,6 @@ bool Apc_target::make_apc_call(THD *caller_thd, Apc_call *call,
void Apc_target::process_apc_requests() void Apc_target::process_apc_requests()
{ {
if (!get_first_in_queue())
return;
while (1) while (1)
{ {
Call_request *request; Call_request *request;
......
#ifndef INCLUDES_MY_APC_H
#define INCLUDES_MY_APC_H
/* /*
Copyright (c) 2011 - 2012, Monty Program Ab Copyright (c) 2011 - 2012, Monty Program Ab
...@@ -93,7 +95,7 @@ class Apc_target ...@@ -93,7 +95,7 @@ class Apc_target
We use this structure, because we We use this structure, because we
- process requests sequentially: requests are added at the end of the - process requests sequentially: requests are added at the end of the
list and removed from the front. With circular list, we can keep one 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 - 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 cancel the request, which means we need a fast request-removal
operation. operation.
...@@ -132,3 +134,5 @@ class Apc_target ...@@ -132,3 +134,5 @@ class Apc_target
void init_show_explain_psi_keys(void); void init_show_explain_psi_keys(void);
#endif #endif
#endif //INCLUDES_MY_APC_H
...@@ -3909,8 +3909,8 @@ static int init_thread_environment() ...@@ -3909,8 +3909,8 @@ static int init_thread_environment()
sp_cache_init(); sp_cache_init();
#ifdef HAVE_EVENT_SCHEDULER #ifdef HAVE_EVENT_SCHEDULER
Events::init_mutexes(); Events::init_mutexes();
init_show_explain_psi_keys();
#endif #endif
init_show_explain_psi_keys();
/* Parameter for threads created for connections */ /* Parameter for threads created for connections */
(void) pthread_attr_init(&connection_attrib); (void) pthread_attr_init(&connection_attrib);
(void) pthread_attr_setdetachstate(&connection_attrib, (void) pthread_attr_setdetachstate(&connection_attrib,
......
...@@ -4345,13 +4345,13 @@ ER_TOO_MANY_USER_CONNECTIONS 42000 ...@@ -4345,13 +4345,13 @@ ER_TOO_MANY_USER_CONNECTIONS 42000
ER_SET_CONSTANTS_ONLY ER_SET_CONSTANTS_ONLY
dan "Du må kun bruge konstantudtryk med SET" dan "Du må kun bruge konstantudtryk med SET"
nla "U mag alleen constante expressies gebruiken bij 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" est "Ainult konstantsed suurused on lubatud SET klauslis"
fre "Seules les expressions constantes sont autorisées avec SET" 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" ita "Si possono usare solo espressioni costanti con SET"
por "Você pode usar apenas expressões constantes com SET" por "Você pode usar apenas expressões constantes com SET"
rus "Вы можете использовать в SET только константные выражения" rus "С этой командой вы можете использовать только константные выражения"
serbian "Možete upotrebiti samo konstantan iskaz sa komandom 'SET'" serbian "Možete upotrebiti samo konstantan iskaz sa komandom 'SET'"
spa "Tu solo debes usar expresiones constantes con SET" spa "Tu solo debes usar expresiones constantes con SET"
swe "Man kan endast använda konstantuttryck med SET" swe "Man kan endast använda konstantuttryck med SET"
...@@ -6582,3 +6582,5 @@ ER_STORED_FUNCTION_PREVENTS_SWITCH_SKIP_REPLICATION ...@@ -6582,3 +6582,5 @@ ER_STORED_FUNCTION_PREVENTS_SWITCH_SKIP_REPLICATION
eng "Cannot modify @@session.skip_replication inside a stored function or trigger" eng "Cannot modify @@session.skip_replication inside a stored function or trigger"
ER_QUERY_EXCEEDED_ROWS_EXAMINED_LIMIT 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." 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) ...@@ -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() bool select_send::send_eof()
{ {
/* /*
...@@ -3233,43 +3224,6 @@ void THD::restore_active_arena(Query_arena *set, Query_arena *backup) ...@@ -3233,43 +3224,6 @@ void THD::restore_active_arena(Query_arena *set, Query_arena *backup)
DBUG_VOID_RETURN; 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() Statement::~Statement()
{ {
} }
...@@ -3832,6 +3786,7 @@ void THD::restore_backup_open_tables_state(Open_tables_backup *backup) ...@@ -3832,6 +3786,7 @@ void THD::restore_backup_open_tables_state(Open_tables_backup *backup)
@retval 1 the user thread has been killed @retval 1 the user thread has been killed
This is used to signal a storage engine if it should be 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) extern "C" int thd_killed(const MYSQL_THD thd)
...@@ -3839,6 +3794,10 @@ extern "C" int thd_killed(const MYSQL_THD thd) ...@@ -3839,6 +3794,10 @@ extern "C" int thd_killed(const MYSQL_THD thd)
if (!thd) if (!thd)
thd= current_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)) if (!(thd->killed & KILL_HARD_BIT))
return 0; return 0;
return thd->killed; return thd->killed;
......
...@@ -1520,39 +1520,7 @@ class Global_read_lock ...@@ -1520,39 +1520,7 @@ class Global_read_lock
extern "C" void my_message_sql(uint error, const char *str, myf MyFlags); 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; class THD;
void mysqld_show_explain(THD *thd, const char *calling_user, ulong thread_id);
#ifndef DBUG_OFF #ifndef DBUG_OFF
void dbug_serve_apcs(THD *thd, int n_calls); void dbug_serve_apcs(THD *thd, int n_calls);
#endif #endif
...@@ -2222,6 +2190,7 @@ class THD :public Statement, ...@@ -2222,6 +2190,7 @@ class THD :public Statement,
*/ */
killed_state volatile killed; killed_state volatile killed;
/* See also thd_killed() */
inline bool check_killed() inline bool check_killed()
{ {
if (killed) if (killed)
...@@ -2438,7 +2407,8 @@ class THD :public Statement, ...@@ -2438,7 +2407,8 @@ class THD :public Statement,
Allows this thread to serve as a target for others to schedule Async Allows this thread to serve as a target for others to schedule Async
Procedure Calls on. 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. Show_explain_request uses this.
*/ */
Apc_target apc_target; Apc_target apc_target;
......
...@@ -2155,9 +2155,9 @@ mysql_execute_command(THD *thd) ...@@ -2155,9 +2155,9 @@ mysql_execute_command(THD *thd)
*/ */
if (lex->sroutines.records || lex->query_tables->next_global) if (lex->sroutines.records || lex->query_tables->next_global)
{ {
my_error(ER_NOT_SUPPORTED_YET, MYF(0), "Usage of subqueries or stored " my_message(ER_SET_CONSTANTS_ONLY, ER(ER_SET_CONSTANTS_ONLY),
"function calls as part of this statement"); MYF(0));
break; goto error;
} }
Item **it= &(lex->show_explain_for_thread); Item **it= &(lex->show_explain_for_thread);
......
...@@ -1999,8 +1999,50 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) ...@@ -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. Store the SHOW EXPLAIN output in the temporary table.
...@@ -2048,7 +2090,7 @@ int fill_show_explain(THD *thd, TABLE_LIST *table, COND *cond) ...@@ -2048,7 +2090,7 @@ int fill_show_explain(THD *thd, TABLE_LIST *table, COND *cond)
if (calling_user && (!tmp_sctx->user || strcmp(calling_user, if (calling_user && (!tmp_sctx->user || strcmp(calling_user,
tmp_sctx->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); mysql_mutex_unlock(&tmp->LOCK_thd_data);
DBUG_RETURN(1); DBUG_RETURN(1);
} }
...@@ -2056,8 +2098,7 @@ int fill_show_explain(THD *thd, TABLE_LIST *table, COND *cond) ...@@ -2056,8 +2098,7 @@ int fill_show_explain(THD *thd, TABLE_LIST *table, COND *cond)
if (tmp == thd) if (tmp == thd)
{ {
mysql_mutex_unlock(&tmp->LOCK_thd_data); mysql_mutex_unlock(&tmp->LOCK_thd_data);
my_error(ER_ERROR_WHEN_EXECUTING_COMMAND, MYF(0), "SHOW EXPLAIN", my_error(ER_TARGET_NOT_EXPLAINABLE, MYF(0));
target_not_explainable_cmd);
DBUG_RETURN(1); DBUG_RETURN(1);
} }
...@@ -2084,21 +2125,12 @@ int fill_show_explain(THD *thd, TABLE_LIST *table, COND *cond) ...@@ -2084,21 +2125,12 @@ int fill_show_explain(THD *thd, TABLE_LIST *table, COND *cond)
if (bres || explain_req.failed_to_produce) if (bres || explain_req.failed_to_produce)
{ {
if (thd->killed) if (thd->killed)
{
thd->send_kill_message(); thd->send_kill_message();
} else if (timed_out)
else my_error(ER_LOCK_WAIT_TIMEOUT, MYF(0));
if (timed_out)
{
my_error(ER_ERROR_WHEN_EXECUTING_COMMAND, MYF(0),
"SHOW EXPLAIN",
"Timeout");
}
else else
{ my_error(ER_TARGET_NOT_EXPLAINABLE, MYF(0));
my_error(ER_ERROR_WHEN_EXECUTING_COMMAND, MYF(0),
"SHOW EXPLAIN", target_not_explainable_cmd);
}
bres= TRUE; bres= TRUE;
} }
else else
...@@ -8427,7 +8459,32 @@ ST_FIELD_INFO keycache_fields_info[]= ...@@ -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 Description of ST_FIELD_INFO in table.h
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "sql_list.h" /* List */ #include "sql_list.h" /* List */
#include "handler.h" /* enum_schema_tables */ #include "handler.h" /* enum_schema_tables */
#include "table.h" /* enum_schema_table_state */ #include "table.h" /* enum_schema_table_state */
#include "my_apc.h"
/* Forward declarations */ /* Forward declarations */
class JOIN; class JOIN;
...@@ -132,4 +133,28 @@ enum enum_schema_tables get_schema_table_idx(ST_SCHEMA_TABLE *schema_table); ...@@ -132,4 +133,28 @@ enum enum_schema_tables get_schema_table_idx(ST_SCHEMA_TABLE *schema_table);
/* These functions were under INNODB_COMPATIBILITY_HOOKS */ /* These functions were under INNODB_COMPATIBILITY_HOOKS */
int get_quote_char_for_identifier(THD *thd, const char *name, uint length); 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 */ #endif /* SQL_SHOW_H */
...@@ -90,7 +90,7 @@ void *test_apc_service_thread(void *ptr) ...@@ -90,7 +90,7 @@ void *test_apc_service_thread(void *ptr)
apc_target.init(&target_mutex); apc_target.init(&target_mutex);
apc_target.enable(); apc_target.enable();
started= TRUE; started= TRUE;
fprintf(stderr, "# test_apc_service_thread started\n"); diag("test_apc_service_thread started");
while (!service_should_exit) while (!service_should_exit)
{ {
//apc_target.disable(); //apc_target.disable();
...@@ -137,7 +137,7 @@ class Apc_order : public Apc_target::Apc_call ...@@ -137,7 +137,7 @@ class Apc_order : public Apc_target::Apc_call
void *test_apc_requestor_thread(void *ptr) void *test_apc_requestor_thread(void *ptr)
{ {
my_thread_init(); my_thread_init();
fprintf(stderr, "# test_apc_requestor_thread started\n"); diag("test_apc_requestor_thread started");
THD my_thd; THD my_thd;
while (!requestors_should_exit) while (!requestors_should_exit)
...@@ -159,7 +159,7 @@ void *test_apc_requestor_thread(void *ptr) ...@@ -159,7 +159,7 @@ void *test_apc_requestor_thread(void *ptr)
if (dst_value != 0) 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; have_errors= true;
} }
} }
...@@ -167,13 +167,13 @@ void *test_apc_requestor_thread(void *ptr) ...@@ -167,13 +167,13 @@ void *test_apc_requestor_thread(void *ptr)
{ {
if (dst_value != src_value) 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; have_errors= true;
} }
} }
//my_sleep(300); //my_sleep(300);
} }
fprintf(stderr, "# test_apc_requestor_thread exiting\n"); diag("test_apc_requestor_thread exiting");
my_thread_end(); my_thread_end();
return NULL; return NULL;
} }
...@@ -204,20 +204,20 @@ int main(int args, char **argv) ...@@ -204,20 +204,20 @@ int main(int args, char **argv)
for (i = 0; i < 15; i++) for (i = 0; i < 15; i++)
{ {
my_sleep(500*1000); 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; requestors_should_exit= TRUE;
for (i = 0; i < N_THREADS; i++) for (i = 0; i < N_THREADS; i++)
pthread_join(request_thr[i], NULL); pthread_join(request_thr[i], NULL);
fprintf(stderr, "# Shutting down service\n"); diag("Shutting down service");
service_should_exit= TRUE; service_should_exit= TRUE;
pthread_join(service_thr, NULL); pthread_join(service_thr, NULL);
mysql_mutex_destroy(&apc_counters_mutex); mysql_mutex_destroy(&apc_counters_mutex);
fprintf(stderr, "# Done.\n"); diag("Done");
my_thread_end(); my_thread_end();
my_thread_global_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