Merge of recent changes in MWL#182 in 5.3 with {Merge of MWL#182 with 5.5}

This commit is contained in:
Sergey Petrunya 2012-05-17 00:59:03 +04:00
commit 34e9a4c1e2
15 changed files with 942 additions and 125 deletions

View File

@ -1,4 +1,5 @@
drop table if exists t0, t1;
drop table if exists t0, t1, t2, t3, t4;
drop view if exists v1;
create table t0 (a int);
insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
create table t1 (a int);
@ -20,12 +21,16 @@ select count(*) from t1 where a < 100000;
show explain for $thr2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index a a 5 NULL 1000 Using where; Using index
Warnings:
Note 1003 select count(*) from t1 where a < 100000
count(*)
1000
select max(c) from t1 where a < 10;
show explain for $thr2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range a a 5 NULL 10 Using index condition
Warnings:
Note 1003 select max(c) from t1 where a < 10
max(c)
9
# We can catch EXPLAIN, too.
@ -35,6 +40,8 @@ explain select max(c) from t1 where a < 10;
show explain for $thr2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range a a 5 NULL 10 Using index condition; Rowid-ordered scan
Warnings:
Note 1003 explain select max(c) from t1 where a < 10
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range a a 5 NULL 10 Using index condition; Rowid-ordered scan
set optimizer_switch= @show_expl_tmp;
@ -47,6 +54,8 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY A ALL NULL NULL NULL NULL 10
2 UNION B ALL NULL NULL NULL NULL 10
NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL
Warnings:
Note 1003 explain select a from t0 A union select a+1 from t0 B
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY A ALL NULL NULL NULL NULL 10
2 UNION B ALL NULL NULL NULL NULL 10
@ -60,6 +69,8 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY A ALL NULL NULL NULL NULL 10
2 UNION B ALL NULL NULL NULL NULL 10
NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL
Warnings:
Note 1003 explain select a from t0 A union select a+1 from t0 B
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY A ALL NULL NULL NULL NULL 10
2 UNION B ALL NULL NULL NULL NULL 10
@ -72,6 +83,8 @@ show explain for $thr2;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY A ALL NULL NULL NULL NULL 10 Using where
2 SUBQUERY B ALL NULL NULL NULL NULL 10
Warnings:
Note 1003 select a, (select max(a) from t0 B) from t0 A where a<1
a (select max(a) from t0 B)
0 9
# Uncorrelated subquery, explain
@ -82,6 +95,8 @@ show explain for $thr2;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY A ALL NULL NULL NULL NULL 10 Using where
2 SUBQUERY B ALL NULL NULL NULL NULL 10
Warnings:
Note 1003 explain select a, (select max(a) from t0 B) from t0 A where a<1
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY A ALL NULL NULL NULL NULL 10 Using where
2 SUBQUERY B ALL NULL NULL NULL NULL 10
@ -93,6 +108,8 @@ show explain for $thr2;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY a ALL NULL NULL NULL NULL 10 Using where
2 DEPENDENT SUBQUERY b ALL NULL NULL NULL NULL 10 Using where
Warnings:
Note 1003 select a, (select max(a) from t0 b where b.a+a.a<10) from t0 a where a<1
a (select max(a) from t0 b where b.a+a.a<10)
0 9
# correlated subquery, explain
@ -103,6 +120,8 @@ show explain for $thr2;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY a ALL NULL NULL NULL NULL 10 Using where
2 DEPENDENT SUBQUERY b ALL NULL NULL NULL NULL 10 Using where
Warnings:
Note 1003 select a, (select max(a) from t0 b where b.a+a.a<10) from t0 a where a<1
a (select max(a) from t0 b where b.a+a.a<10)
0 9
# correlated subquery, select, while inside the subquery
@ -113,6 +132,8 @@ show explain for $thr2;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY a ALL NULL NULL NULL NULL 10 Using where
2 DEPENDENT SUBQUERY b ALL NULL NULL NULL NULL 10 Using where
Warnings:
Note 1003 select a, (select max(a) from t0 b where b.a+a.a<10) from t0 a where a<1
a (select max(a) from t0 b where b.a+a.a<10)
0 9
# correlated subquery, explain, while inside the subquery
@ -123,6 +144,8 @@ show explain for $thr2;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY a ALL NULL NULL NULL NULL 10 Using where
2 DEPENDENT SUBQUERY b ALL NULL NULL NULL NULL 10 Using where
Warnings:
Note 1003 select a, (select max(a) from t0 b where b.a+a.a<10) from t0 a where a<1
a (select max(a) from t0 b where b.a+a.a<10)
0 9
# correlated subquery, explain, while inside the subquery
@ -131,7 +154,365 @@ 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;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Query plan already deleted
1 PRIMARY a ALL NULL NULL NULL NULL 10
2 DEPENDENT SUBQUERY b ALL NULL NULL NULL NULL 10
Warnings:
Note 1003 select a, (select max(a) from t0 b where b.a+a.a<10) from t0 a where a<1
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:
# I've found experimentally that select_id==2 here...
#
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
#
# Attempt SHOW EXPLAIN for an UPDATE
#
create table t2 as select a as a, a as dummy from t0 limit 2;
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
show explain for $thr2;
ERROR HY000: Error when executing command SHOW EXPLAIN: Target is not running EXPLAINable command
drop table t2;
#
# Attempt SHOW EXPLAIN for a DELETE
#
create table t2 as select a as a, a as dummy from t0 limit 2;
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
show explain for $thr2;
ERROR HY000: Error when executing command SHOW EXPLAIN: Target is not running EXPLAINable command
drop table t2;
#
# Multiple SHOW EXPLAIN calls for one select
#
create table t2 as select a as a, a as dummy from t0 limit 3;
set @show_explain_probe_select_id=2;
set debug_dbug='d,show_explain_probe_join_exec_start';
select t2.a, ((select max(a) from t0 where t2.a + t0.a <3) >3) as SUBQ from t2;
show explain for $thr2;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 3
2 DEPENDENT SUBQUERY t0 ALL NULL NULL NULL NULL 10 Using where
Warnings:
Note 1003 select t2.a, ((select max(a) from t0 where t2.a + t0.a <3) >3) as SUBQ from t2
show explain for $thr2;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 3
2 DEPENDENT SUBQUERY t0 ALL NULL NULL NULL NULL 10 Using where
Warnings:
Note 1003 select t2.a, ((select max(a) from t0 where t2.a + t0.a <3) >3) as SUBQ from t2
show explain for $thr2;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 3
2 DEPENDENT SUBQUERY t0 ALL NULL NULL NULL NULL 10 Using where
Warnings:
Note 1003 select t2.a, ((select max(a) from t0 where t2.a + t0.a <3) >3) as SUBQ from t2
a SUBQ
0 0
1 0
2 0
drop table t2;
#
# SHOW EXPLAIN for SELECT ... ORDER BY with "Using filesort"
#
explain select * from t0 order by a;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t0 ALL NULL NULL NULL NULL 10 Using filesort
set debug_dbug='d,show_explain_probe_join_exec_start';
set @show_explain_probe_select_id=1;
select * from t0 order by a;
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 filesort
Warnings:
Note 1003 select * from t0 order by a
a
0
1
2
3
4
5
6
7
8
9
#
# SHOW EXPLAIN for SELECT ... with "Using temporary"
#
explain select distinct a from t0;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t0 ALL NULL NULL NULL NULL 10 Using temporary
set debug_dbug='d,show_explain_probe_join_exec_start';
set @show_explain_probe_select_id=1;
select distinct a from t0;
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 temporary
Warnings:
Note 1003 select distinct a from t0
a
0
1
2
3
4
5
6
7
8
9
#
# SHOW EXPLAIN for SELECT ... with "Using temporary; Using filesort"
#
explain select distinct a from t0;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t0 ALL NULL NULL NULL NULL 10 Using temporary
set debug_dbug='d,show_explain_probe_join_exec_start';
set @show_explain_probe_select_id=1;
select distinct a from t0;
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 temporary
Warnings:
Note 1003 select distinct a from t0
a
0
1
2
3
4
5
6
7
8
9
set debug_dbug='';
#
# MDEV-238: SHOW EXPLAIN: Server crashes in JOIN::print_explain with FROM subquery and GROUP BY
#
CREATE TABLE t2 ( a INT );
INSERT INTO t2 VALUES (1),(2),(1),(4),(2);
explain SELECT alias.a FROM t2, ( SELECT * FROM t2 ) AS alias GROUP BY alias.a;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ALL NULL NULL NULL NULL 5 Using temporary; Using filesort
1 SIMPLE t2 ALL NULL NULL NULL NULL 5 Using join buffer (flat, BNL join)
set debug_dbug='d,show_explain_in_find_all_keys';
SELECT alias.a FROM t2, ( SELECT * FROM t2 ) AS alias GROUP BY alias.a;
# NOTE: current code will not show "Using join buffer":
show explain for $thr2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ALL NULL NULL NULL NULL 5 Using temporary; Using filesort
1 SIMPLE t2 ALL NULL NULL NULL NULL 5
Warnings:
Note 1003 SELECT alias.a FROM t2, ( SELECT * FROM t2 ) AS alias GROUP BY alias.a
a
1
2
4
set debug_dbug='';
DROP TABLE t2;
#
# MDEV-239: Assertion `field_types == 0 ... ' failed in Protocol_text::store(double, uint32, String*) with
# SHOW EXPLAIN over EXPLAIN EXTENDED
#
CREATE TABLE t2 (a INT);
INSERT INTO t2 VALUES (1),(2),(1),(4),(2);
EXPLAIN EXTENDED SELECT alias.a FROM t2, ( SELECT * FROM t2 ) AS alias GROUP BY alias.a ;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t2 ALL NULL NULL NULL NULL 5 100.00 Using temporary; Using filesort
1 SIMPLE t2 ALL NULL NULL NULL NULL 5 100.00 Using join buffer (flat, BNL join)
Warnings:
Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` join `test`.`t2` group by `test`.`t2`.`a`
set @show_explain_probe_select_id=1;
set debug_dbug='d,show_explain_probe_join_exec_end';
EXPLAIN EXTENDED SELECT alias.a FROM t2, ( SELECT * FROM t2 ) AS alias GROUP BY alias.a ;
show explain for $thr2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ALL NULL NULL NULL NULL 5 Using temporary; Using filesort
1 SIMPLE t2 ALL NULL NULL NULL NULL 5 Using join buffer (flat, BNL join)
Warnings:
Note 1003 EXPLAIN EXTENDED SELECT alias.a FROM t2, ( SELECT * FROM t2 ) AS alias GROUP BY alias.a
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t2 ALL NULL NULL NULL NULL 5 100.00 Using temporary; Using filesort
1 SIMPLE t2 ALL NULL NULL NULL NULL 5 100.00 Using join buffer (flat, BNL join)
Warnings:
Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` join `test`.`t2` group by `test`.`t2`.`a`
set debug_dbug='';
DROP TABLE t2;
#
# MDEV-240: SHOW EXPLAIN: Assertion `this->optimized == 2' failed in
# JOIN::print_explain on query with a JOIN, TEMPTABLE view,
#
CREATE TABLE t3 (a INT);
CREATE ALGORITHM=TEMPTABLE VIEW v1 AS SELECT * FROM t3;
INSERT INTO t3 VALUES (8);
CREATE TABLE t2 (b INT);
INSERT INTO t2 VALUES (4),(5),(6),(7),(8),(9);
explain SELECT * FROM v1, t2;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 1
1 PRIMARY t2 ALL NULL NULL NULL NULL 6
2 DERIVED t3 system NULL NULL NULL NULL 1
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;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Not yet optimized
Warnings:
Note 1003 SELECT * FROM v1, t2
a b
8 4
8 5
8 6
8 7
8 8
8 9
set debug_dbug='';
DROP VIEW v1;
DROP TABLE t2, t3;
#
# MDEV-267: SHOW EXPLAIN: Server crashes in JOIN::print_explain on most of queries
#
set @show_explain_probe_select_id=1;
set debug_dbug='d,show_explain_probe_join_exec_end';
select sleep(1);
show explain for $thr2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 select sleep(1)
sleep(1)
0
set debug_dbug='';
#
# Same as above, but try another reason for JOIN to be degenerate
#
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;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
Warnings:
Note 1003 select * from t0 where 1>10
a
set debug_dbug='';
#
# Same as above, but try another reason for JOIN to be degenerate (2)
#
create table t3(a int primary key);
insert into t3 select a from t0;
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;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL no matching row in const table
Warnings:
Note 1003 select * from t0,t3 where t3.a=112233
a a
set debug_dbug='';
drop table t3;
#
# MDEV-270: SHOW EXPLAIN: server crashes in JOIN::print_explain on a query with
# select tables optimized away
#
CREATE TABLE t2 (pk INT PRIMARY KEY, a INT ) ENGINE=MyISAM;
INSERT INTO t2 VALUES
(1,4),(2,62),(3,7),(4,1),(5,0),(6,7),(7,7),(8,1),(9,7),(10,1),
(11,5),(12,2),(13,0),(14,1),(15,8),(16,1),(17,1),(18,9),(19,1),(20,5) ;
explain SELECT * FROM t2 WHERE a =
(SELECT MAX(a) FROM t2
WHERE pk= (SELECT MAX(pk) FROM t2 WHERE pk = 3)
);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 20 Using where
2 SUBQUERY t2 const PRIMARY PRIMARY 4 const 1 Using where
3 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
set @show_explain_probe_select_id=2;
set debug_dbug='d,show_explain_probe_do_select';
SELECT * FROM t2 WHERE a =
(SELECT MAX(a) FROM t2
WHERE pk= (SELECT MAX(pk) FROM t2 WHERE pk = 3)
);
show explain for $thr2;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 20 Using where
2 SUBQUERY t2 const PRIMARY PRIMARY 4 1 Using where
3 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
Warnings:
Note 1003 SELECT * FROM t2 WHERE a =
(SELECT MAX(a) FROM t2
WHERE pk= (SELECT MAX(pk) FROM t2 WHERE pk = 3)
)
pk a
3 7
6 7
7 7
9 7
set debug_dbug='';
drop table t2;
#
# MDEV-273: SHOW EXPLAIN: server crashes in JOIN::print_explain on a query with impossible WHERE
#
CREATE TABLE t2 (a1 INT, KEY(a1)) ENGINE=MyISAM;
INSERT INTO t2 VALUES
(4),(6),(7),(1),(0),(7),(7),(1),(7),(1),
(5),(2),(0),(1),(8),(1),(1),(9),(1),(5);
CREATE TABLE t3 (b1 INT) ENGINE=MyISAM;
INSERT INTO t3 VALUES
(4),(5),(8),(4),(8),(2),(9),(6),(4),(8),
(3),(5),(9),(6),(8),(3),(2),(6),(3),(1),
(4),(3),(1),(7),(0),(0),(9),(5),(9),(0),
(2),(2),(5),(9),(1),(4),(8),(6),(5),(5),
(1),(7),(2),(8),(9),(3),(2),(6),(6),(5),
(4),(3),(2),(7),(4),(6),(0),(8),(5),(8),
(2),(9),(7),(5),(7),(0),(4),(3),(1),(0),
(6),(2),(8),(3),(7),(3),(5),(5),(1),(2),
(1),(7),(1),(9),(9),(8),(3);
CREATE TABLE t4 (c1 INT) ENGINE=MyISAM;
EXPLAIN
SELECT count(*) FROM t2, t3
WHERE a1 < ALL (
SELECT a1 FROM t2
WHERE a1 IN ( SELECT a1 FROM t2, t4 )
);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 index NULL a1 5 NULL 20 Using where; Using index
1 PRIMARY t3 ALL NULL NULL NULL NULL 87 Using join buffer (flat, BNL join)
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
set @show_explain_probe_select_id=1;
set debug_dbug='d,show_explain_probe_do_select';
SELECT count(*) FROM t2, t3
WHERE a1 < ALL (
SELECT a1 FROM t2
WHERE a1 IN ( SELECT a1 FROM t2, t4 )
);
show explain for $thr2;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 index NULL a1 5 NULL 20 Using where; Using index
1 PRIMARY t3 ALL NULL NULL NULL NULL 87 Using join buffer (flat, BNL join)
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL no matching row in const table
Warnings:
Note 1003 SELECT count(*) FROM t2, t3
WHERE a1 < ALL (
SELECT a1 FROM t2
WHERE a1 IN ( SELECT a1 FROM t2, t4 )
)
count(*)
1740
set debug_dbug='';
drop table t2, t3, t4;
drop table t0,t1;

View File

@ -4,7 +4,8 @@
--source include/have_debug.inc
--disable_warnings
drop table if exists t0, t1;
drop table if exists t0, t1, t2, t3, t4;
drop view if exists v1;
--enable_warnings
#
@ -196,12 +197,308 @@ reap;
# TODO: explain in the parent subuqery when the un-correlated child has been
# run (and have done irreversible cleanups)
# ^^ Is this at all possible after 5.3?
# Maybe, for 5.3 try this:
# - run before/after the parent has invoked child's optimization
# - run after materialization
# TODO: hit JOIN::optimize for non-select commands: UPDATE/DELETE, SET.
--echo # Try to do SHOW EXPLAIN for a query that runs a SET command:
--echo # I've found experimentally that select_id==2 here...
--echo #
set @show_explain_probe_select_id=2;
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
evalp show explain for $thr2;
connection con1;
reap;
--echo #
--echo # Attempt SHOW EXPLAIN for an UPDATE
--echo #
create table t2 as select a as a, a as dummy from t0 limit 2;
set @show_explain_probe_select_id=2;
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
evalp show explain for $thr2;
--error ER_ERROR_WHEN_EXECUTING_COMMAND
evalp show explain for $thr2;
connection con1;
reap;
drop table t2;
--echo #
--echo # Attempt SHOW EXPLAIN for a DELETE
--echo #
create table t2 as select a as a, a as dummy from t0 limit 2;
set @show_explain_probe_select_id=2;
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
evalp show explain for $thr2;
--error ER_ERROR_WHEN_EXECUTING_COMMAND
evalp show explain for $thr2;
connection con1;
reap;
drop table t2;
## TODO: Test this: multiple SHOW EXPLAIN calls in course of running of one select
##
--echo #
--echo # Multiple SHOW EXPLAIN calls for one select
--echo #
create table t2 as select a as a, a as dummy from t0 limit 3;
set @show_explain_probe_select_id=2;
set debug_dbug='d,show_explain_probe_join_exec_start';
send select t2.a, ((select max(a) from t0 where t2.a + t0.a <3) >3) as SUBQ from t2;
connection default;
--source include/wait_condition.inc
evalp show explain for $thr2;
evalp show explain for $thr2;
evalp show explain for $thr2;
connection con1;
reap;
drop table t2;
--echo #
--echo # SHOW EXPLAIN for SELECT ... ORDER BY with "Using filesort"
--echo #
explain select * from t0 order by a;
set debug_dbug='d,show_explain_probe_join_exec_start';
set @show_explain_probe_select_id=1;
send select * from t0 order by a;
connection default;
--source include/wait_condition.inc
evalp show explain for $thr2;
connection con1;
reap;
--echo #
--echo # SHOW EXPLAIN for SELECT ... with "Using temporary"
--echo #
connection default;
explain select distinct a from t0;
connection con1;
set debug_dbug='d,show_explain_probe_join_exec_start';
set @show_explain_probe_select_id=1;
send select distinct a from t0;
connection default;
--source include/wait_condition.inc
evalp show explain for $thr2;
connection con1;
reap;
--echo #
--echo # SHOW EXPLAIN for SELECT ... with "Using temporary; Using filesort"
--echo #
connection default;
explain select distinct a from t0;
connection con1;
set debug_dbug='d,show_explain_probe_join_exec_start';
set @show_explain_probe_select_id=1;
send select distinct a from t0;
connection default;
--source include/wait_condition.inc
evalp show explain for $thr2;
connection con1;
reap;
set debug_dbug='';
--echo #
--echo # MDEV-238: SHOW EXPLAIN: Server crashes in JOIN::print_explain with FROM subquery and GROUP BY
--echo #
CREATE TABLE t2 ( a INT );
INSERT INTO t2 VALUES (1),(2),(1),(4),(2);
explain SELECT alias.a FROM t2, ( SELECT * FROM t2 ) AS alias GROUP BY alias.a;
set debug_dbug='d,show_explain_in_find_all_keys';
send SELECT alias.a FROM t2, ( SELECT * FROM t2 ) AS alias GROUP BY alias.a;
connection default;
--source include/wait_condition.inc
--echo # NOTE: current code will not show "Using join buffer":
evalp show explain for $thr2;
connection con1;
reap;
set debug_dbug='';
DROP TABLE t2;
--echo #
--echo # MDEV-239: Assertion `field_types == 0 ... ' failed in Protocol_text::store(double, uint32, String*) with
--echo # SHOW EXPLAIN over EXPLAIN EXTENDED
--echo #
CREATE TABLE t2 (a INT);
INSERT INTO t2 VALUES (1),(2),(1),(4),(2);
EXPLAIN EXTENDED SELECT alias.a FROM t2, ( SELECT * FROM t2 ) AS alias GROUP BY alias.a ;
set @show_explain_probe_select_id=1;
set debug_dbug='d,show_explain_probe_join_exec_end';
send EXPLAIN EXTENDED SELECT alias.a FROM t2, ( SELECT * FROM t2 ) AS alias GROUP BY alias.a ;
connection default;
--source include/wait_condition.inc
evalp show explain for $thr2;
connection con1;
reap;
set debug_dbug='';
DROP TABLE t2;
--echo #
--echo # MDEV-240: SHOW EXPLAIN: Assertion `this->optimized == 2' failed in
--echo # JOIN::print_explain on query with a JOIN, TEMPTABLE view,
--echo #
CREATE TABLE t3 (a INT);
CREATE ALGORITHM=TEMPTABLE VIEW v1 AS SELECT * FROM t3;
INSERT INTO t3 VALUES (8);
CREATE TABLE t2 (b INT);
INSERT INTO t2 VALUES (4),(5),(6),(7),(8),(9);
explain SELECT * FROM v1, t2;
set @show_explain_probe_select_id=2;
set debug_dbug='d,show_explain_probe_join_exec_end';
send SELECT * FROM v1, t2;
connection default;
--source include/wait_condition.inc
evalp show explain for $thr2;
connection con1;
reap;
set debug_dbug='';
DROP VIEW v1;
DROP TABLE t2, t3;
--echo #
--echo # MDEV-267: SHOW EXPLAIN: Server crashes in JOIN::print_explain on most of queries
--echo #
set @show_explain_probe_select_id=1;
set debug_dbug='d,show_explain_probe_join_exec_end';
send select sleep(1);
connection default;
--source include/wait_condition.inc
evalp show explain for $thr2;
connection con1;
reap;
set debug_dbug='';
--echo #
--echo # Same as above, but try another reason for JOIN to be degenerate
--echo #
set @show_explain_probe_select_id=1;
set debug_dbug='d,show_explain_probe_join_exec_end';
send select * from t0 where 1>10;
connection default;
--source include/wait_condition.inc
evalp show explain for $thr2;
connection con1;
reap;
set debug_dbug='';
--echo #
--echo # Same as above, but try another reason for JOIN to be degenerate (2)
--echo #
create table t3(a int primary key);
insert into t3 select a from t0;
set @show_explain_probe_select_id=1;
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
evalp show explain for $thr2;
connection con1;
reap;
set debug_dbug='';
drop table t3;
--echo #
--echo # MDEV-270: SHOW EXPLAIN: server crashes in JOIN::print_explain on a query with
--echo # select tables optimized away
--echo #
CREATE TABLE t2 (pk INT PRIMARY KEY, a INT ) ENGINE=MyISAM;
INSERT INTO t2 VALUES
(1,4),(2,62),(3,7),(4,1),(5,0),(6,7),(7,7),(8,1),(9,7),(10,1),
(11,5),(12,2),(13,0),(14,1),(15,8),(16,1),(17,1),(18,9),(19,1),(20,5) ;
explain SELECT * FROM t2 WHERE a =
(SELECT MAX(a) FROM t2
WHERE pk= (SELECT MAX(pk) FROM t2 WHERE pk = 3)
);
set @show_explain_probe_select_id=2;
set debug_dbug='d,show_explain_probe_do_select';
send SELECT * FROM t2 WHERE a =
(SELECT MAX(a) FROM t2
WHERE pk= (SELECT MAX(pk) FROM t2 WHERE pk = 3)
);
connection default;
--source include/wait_condition.inc
evalp show explain for $thr2;
connection con1;
reap;
set debug_dbug='';
drop table t2;
--echo #
--echo # MDEV-273: SHOW EXPLAIN: server crashes in JOIN::print_explain on a query with impossible WHERE
--echo #
CREATE TABLE t2 (a1 INT, KEY(a1)) ENGINE=MyISAM;
INSERT INTO t2 VALUES
(4),(6),(7),(1),(0),(7),(7),(1),(7),(1),
(5),(2),(0),(1),(8),(1),(1),(9),(1),(5);
CREATE TABLE t3 (b1 INT) ENGINE=MyISAM;
INSERT INTO t3 VALUES
(4),(5),(8),(4),(8),(2),(9),(6),(4),(8),
(3),(5),(9),(6),(8),(3),(2),(6),(3),(1),
(4),(3),(1),(7),(0),(0),(9),(5),(9),(0),
(2),(2),(5),(9),(1),(4),(8),(6),(5),(5),
(1),(7),(2),(8),(9),(3),(2),(6),(6),(5),
(4),(3),(2),(7),(4),(6),(0),(8),(5),(8),
(2),(9),(7),(5),(7),(0),(4),(3),(1),(0),
(6),(2),(8),(3),(7),(3),(5),(5),(1),(2),
(1),(7),(1),(9),(9),(8),(3);
CREATE TABLE t4 (c1 INT) ENGINE=MyISAM;
EXPLAIN
SELECT count(*) FROM t2, t3
WHERE a1 < ALL (
SELECT a1 FROM t2
WHERE a1 IN ( SELECT a1 FROM t2, t4 )
);
set @show_explain_probe_select_id=1;
set debug_dbug='d,show_explain_probe_do_select';
send
SELECT count(*) FROM t2, t3
WHERE a1 < ALL (
SELECT a1 FROM t2
WHERE a1 IN ( SELECT a1 FROM t2, t4 )
);
connection default;
--source include/wait_condition.inc
evalp show explain for $thr2;
connection con1;
reap;
set debug_dbug='';
drop table t2, t3, t4;
## TODO: Test this: have several SHOW EXPLAIN requests be queued up for a
## thread and served together.

View File

@ -502,7 +502,7 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
my_off_t record;
TABLE *sort_form;
THD *thd= current_thd;
volatile killed_state *killed= &thd->killed;
//volatile killed_state *killed= &thd->killed;
handler *file;
MY_BITMAP *save_read_set, *save_write_set, *save_vcol_set;
uchar *next_sort_key= sort_keys_buf;
@ -523,6 +523,11 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
if (flag)
ref_pos= &file->ref[0];
next_pos=ref_pos;
DBUG_EXECUTE_IF("show_explain_in_find_all_keys",
dbug_serve_apcs(thd, 1);
);
if (!quick_select)
{
next_pos=(uchar*) 0; /* Find records in sequence */
@ -586,7 +591,7 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
break;
}
if (*killed)
if (thd->check_killed())
{
DBUG_PRINT("info",("Sort killed by user"));
if (!quick_select)
@ -1231,18 +1236,20 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
void *first_cmp_arg;
element_count dupl_count= 0;
uchar *src;
killed_state not_killable;
/* killed_state not_killable; */
uchar *unique_buff= param->unique_buff;
volatile killed_state *killed= &current_thd->killed;
/* volatile killed_state *killed= &current_thd->killed; */
const bool killable= !param->not_killable;
THD* const thd=current_thd;
DBUG_ENTER("merge_buffers");
status_var_increment(current_thd->status_var.filesort_merge_passes);
current_thd->query_plan_fsort_passes++;
if (param->not_killable)
status_var_increment(thd->status_var.filesort_merge_passes);
thd->query_plan_fsort_passes++;
/*if (param->not_killable)
{
killed= &not_killable;
not_killable= NOT_KILLED;
}
}*/
error=0;
rec_length= param->rec_length;
@ -1320,7 +1327,7 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
while (queue.elements > 1)
{
if (*killed)
if (killable && thd->check_killed())
{
error= 1; goto err; /* purecov: inspected */
}

View File

@ -4725,6 +4725,7 @@ int subselect_hash_sj_engine::exec()
thd->lex->current_select= materialize_engine->select_lex;
/* The subquery should be optimized, and materialized only once. */
DBUG_ASSERT(materialize_join->optimized && !is_materialized);
materialize_join->exec();
if ((res= test(materialize_join->error || thd->is_fatal_error ||
thd->is_error())))

View File

@ -25,6 +25,14 @@
*/
/*
Initialize the target.
@note
Initialization must be done prior to enabling/disabling the target, or making
any call requests to it.
Initial state after initialization is 'disabled'.
*/
void Apc_target::init()
{
// todo: should use my_pthread_... functions instead?
@ -37,6 +45,9 @@ void Apc_target::init()
}
/*
Destroy the target. The target must be disabled when this call is made.
*/
void Apc_target::destroy()
{
DBUG_ASSERT(!enabled);
@ -44,6 +55,9 @@ void Apc_target::destroy()
}
/*
Enter ther state where the target is available for serving APC requests
*/
void Apc_target::enable()
{
pthread_mutex_lock(&LOCK_apc_queue);
@ -52,6 +66,13 @@ void Apc_target::enable()
}
/*
Make the target unavailable for serving APC requests.
@note
This call will serve all requests that were already enqueued
*/
void Apc_target::disable()
{
bool process= FALSE;
@ -63,6 +84,9 @@ void Apc_target::disable()
process_apc_requests();
}
/* (internal) Put request into the request list */
void Apc_target::enqueue_request(Call_request *qe)
{
//call_queue_size++;
@ -82,6 +106,13 @@ void Apc_target::enqueue_request(Call_request *qe)
}
}
/*
(internal) Remove given request from the request queue.
The request is not necessarily first in the queue.
*/
void Apc_target::dequeue_request(Call_request *qe)
{
//call_queue_size--;
@ -100,8 +131,10 @@ void Apc_target::dequeue_request(Call_request *qe)
/*
Make an apc call in another thread. The caller is responsible so
that we're not calling to ourselves.
Make an APC (Async Procedure Call) in another thread.
The caller is responsible for making sure he's not calling an Apc_target
that is serviced by the same thread it is called from.
psergey-todo: Should waits here be KILLable? (it seems one needs
to use thd->enter_cond() calls to be killable)
@ -120,7 +153,7 @@ bool Apc_target::make_apc_call(apc_func_t func, void *func_arg,
Call_request apc_request;
apc_request.func= func;
apc_request.func_arg= func_arg;
apc_request.done= FALSE;
apc_request.processed= FALSE;
(void)pthread_cond_init(&apc_request.COND_request, NULL);
(void)pthread_mutex_init(&apc_request.LOCK_request, MY_MUTEX_INIT_SLOW);
pthread_mutex_lock(&apc_request.LOCK_request);
@ -134,19 +167,19 @@ bool Apc_target::make_apc_call(apc_func_t func, void *func_arg,
int wait_res= 0;
/* todo: how about processing other errors here? */
while (!apc_request.done && (wait_res != ETIMEDOUT))
while (!apc_request.processed && (wait_res != ETIMEDOUT))
{
wait_res= pthread_cond_timedwait(&apc_request.COND_request,
&apc_request.LOCK_request, &abstime);
}
if (!apc_request.done)
if (!apc_request.processed)
{
/* We timed out */
apc_request.done= TRUE;
/* The wait has timed out. Remove the request from the queue */
apc_request.processed= TRUE;
*timed_out= TRUE;
pthread_mutex_unlock(&apc_request.LOCK_request);
//psergey-todo: "Whoa rare event" refers to this part, right? put a comment.
pthread_mutex_lock(&LOCK_apc_queue);
dequeue_request(&apc_request);
pthread_mutex_unlock(&LOCK_apc_queue);
@ -172,7 +205,8 @@ bool Apc_target::make_apc_call(apc_func_t func, void *func_arg,
/*
Process all APC requests
Process all APC requests.
This should be called periodically by the APC target thread.
*/
void Apc_target::process_apc_requests()
@ -191,7 +225,7 @@ void Apc_target::process_apc_requests()
request->what="seen by process_apc_requests";
pthread_mutex_lock(&request->LOCK_request);
if (request->done)
if (request->processed)
{
/*
We can get here when
@ -215,7 +249,7 @@ void Apc_target::process_apc_requests()
*/
request->what="dequeued by process_apc_requests";
dequeue_request(request);
request->done= TRUE;
request->processed= TRUE;
pthread_mutex_unlock(&LOCK_apc_queue);

View File

@ -3,9 +3,18 @@
*/
/*
Design
- Mutex-guarded request queue (it belongs to the target), which can be enabled/
disabled (when empty).
Interface
~~~~~~~~~
(
- This is an APC request queue
- We assume there is a particular owner thread which periodically calls
process_apc_requests() to serve the call requests.
- Other threads can post call requests, and block until they are exectued.
)
Implementation
~~~~~~~~~~~~~~
- The target has a mutex-guarded request queue.
- After the request has been put into queue, the requestor waits for request
to be satisfied. The worker satisifes the request and signals the
@ -21,31 +30,11 @@ public:
Apc_target() : enabled(0), apc_calls(NULL) /*, call_queue_size(0)*/ {}
~Apc_target() { DBUG_ASSERT(!enabled && !apc_calls);}
/*
Initialize the target. This must be called before anything else. Right
after initialization, the target is disabled.
*/
void init();
/*
Destroy the target. The target must be disabled when this call is made.
*/
void destroy();
/*
Enter into state where this target will be serving APC requests
*/
void enable();
/*
Leave the state where we could serve APC requests (will serve all already
enqueued requests)
*/
void disable();
/*
This should be called periodically to serve observation requests.
*/
void process_apc_requests();
typedef void (*apc_func_t)(void *arg);
@ -68,18 +57,32 @@ public:
#endif
private:
class Call_request;
/*
Non-zero value means we're enabled. It's an int, not bool, because one can
call enable() N times (and then needs to call disable() N times before the
target is really disabled)
*/
int enabled;
/*
Circular, double-linked list of all enqueued call requests.
We use this structure, because we
- process requests sequentially
- a thread that has posted a request may time out (or be KILLed) and
cancel the request, which means we'll need to remove its request at
arbitrary point in time.
*/
Call_request *apc_calls;
pthread_mutex_t LOCK_apc_queue;
pthread_mutex_t LOCK_apc_queue;
class Call_request
{
public:
apc_func_t func;
void *func_arg;
bool done;
apc_func_t func; /* Function to call */
void *func_arg; /* Argument to pass it */
bool processed;
pthread_mutex_t LOCK_request;
pthread_cond_t COND_request;
@ -87,13 +90,15 @@ private:
Call_request *next;
Call_request *prev;
const char *what;
const char *what; /* State of the request */
};
void enqueue_request(Call_request *qe);
void dequeue_request(Call_request *qe);
/* return the first call request in queue, or NULL if there are none enqueued */
Call_request *get_first_in_queue()
{
{
return apc_calls;
}
};

View File

@ -2015,6 +2015,11 @@ int THD::send_explain_fields(select_result *result)
}
/*
Populate the provided field_list with EXPLAIN output columns.
this->lex->describe has the EXPLAIN flags
*/
void THD::make_explain_field_list(List<Item> &field_list)
{
Item *item;
@ -3280,13 +3285,20 @@ void Show_explain_request::get_explain_data(void *arg)
//TODO: change mem_root to point to request_thd->mem_root.
// Actually, change the ARENA, because we're going to allocate items!
Query_arena backup_arena;
req->target_thd->set_n_backup_active_arena((Query_arena*)req->request_thd,
&backup_arena);
THD *target_thd= req->target_thd;
req->target_thd->lex->unit.print_explain(req->explain_buf);
req->target_thd->restore_active_arena((Query_arena*)req->request_thd,
target_thd->set_n_backup_active_arena((Query_arena*)req->request_thd,
&backup_arena);
req->query_str.copy(target_thd->query(),
target_thd->query_length(),
&my_charset_bin);
if (target_thd->lex->unit.print_explain(req->explain_buf, 0 /* explain flags */))
req->failed_to_produce= TRUE;
target_thd->restore_active_arena((Query_arena*)req->request_thd,
&backup_arena);
}

View File

@ -1528,8 +1528,12 @@ public:
THD *target_thd;
THD *request_thd;
bool failed_to_produce;
select_result_explain_buffer *explain_buf;
String query_str;
static void get_explain_data(void *arg);
};

View File

@ -2236,7 +2236,7 @@ enum_nested_loop_state JOIN_CACHE::join_matching_records(bool skip_last)
while (!(error= join_tab_scan->next()))
{
if (join->thd->killed)
if (join->thd->check_killed())
{
/* The user has aborted the execution of the query */
join->thd->send_kill_message();
@ -2506,7 +2506,7 @@ enum_nested_loop_state JOIN_CACHE::join_null_complements(bool skip_last)
for ( ; cnt; cnt--)
{
if (join->thd->killed)
if (join->thd->check_killed())
{
/* The user has aborted the execution of the query */
join->thd->send_kill_message();
@ -3356,7 +3356,7 @@ int JOIN_TAB_SCAN::next()
update_virtual_fields(thd, table);
while (!err && select && (skip_rc= select->skip_record(thd)) <= 0)
{
if (thd->killed || skip_rc < 0)
if (thd->check_killed() || skip_rc < 0)
return 1;
/*
Move to the next record if the last retrieved record does not

View File

@ -3831,6 +3831,7 @@ void SELECT_LEX::update_used_tables()
/**
Set the EXPLAIN type for this subquery.
psergey-todo: comments about
*/
void st_select_lex::set_explain_type(bool on_the_fly)
@ -4072,16 +4073,32 @@ int print_explain_message_line(select_result_sink *result,
const char *message);
int st_select_lex::print_explain(select_result_sink *output)
int st_select_lex::print_explain(select_result_sink *output,
uint8 explain_flags)
{
int res;
if (join && join->have_query_plan == JOIN::QEP_AVAILABLE)
{
res= join->print_explain(output, TRUE,
FALSE, // need_tmp_table,
FALSE, // bool need_order,
FALSE, // bool distinct,
NULL); //const char *message
/*
There is a number of reasons join can be marked as degenerate, so all
three conditions below can happen simultaneously, or individually:
*/
if (!join->table_count || !join->tables_list || join->zero_result_cause)
{
/* It's a degenerate join */
const char *cause= join->zero_result_cause ? join-> zero_result_cause :
"No tables used";
res= join->print_explain(output, explain_flags, TRUE, FALSE, FALSE,
FALSE, cause);
}
else
{
res= join->print_explain(output, explain_flags, TRUE,
join->need_tmp, // need_tmp_table
(join->order != 0 && !join->skip_sort_order), // bool need_order
join->select_distinct, // bool distinct
NULL); //const char *message
}
if (res)
goto err;
@ -4095,7 +4112,7 @@ int st_select_lex::print_explain(select_result_sink *output)
*/
if (!(unit->item && unit->item->eliminated))
{
unit->print_explain(output);
unit->print_explain(output, explain_flags);
}
}
}
@ -4119,14 +4136,24 @@ err:
}
int st_select_lex_unit::print_explain(select_result_sink *output)
int st_select_lex_unit::print_explain(select_result_sink *output,
uint8 explain_flags)
{
int res= 0;
SELECT_LEX *first= first_select();
if (first && !first->next_select() && !first->join)
{
/*
If there is only one child, 'first', and it has join==NULL, emit "not in
EXPLAIN state" error.
*/
return 1;
}
for (SELECT_LEX *sl= first; sl; sl= sl->next_select())
{
if ((res= sl->print_explain(output)))
if ((res= sl->print_explain(output, explain_flags)))
break;
}
@ -4136,7 +4163,7 @@ int st_select_lex_unit::print_explain(select_result_sink *output)
if (fake_select_lex && !fake_select_lex->join)
{
res= print_fake_select_lex_join(output, TRUE /* on the fly */,
fake_select_lex, 0 /* flags */);
fake_select_lex, explain_flags);
}
return res;
}

View File

@ -718,7 +718,7 @@ public:
friend int subselect_union_engine::exec();
List<Item> *get_unit_column_types();
int print_explain(select_result_sink *output);
int print_explain(select_result_sink *output, uint8 explain_flags);
};
typedef class st_select_lex_unit SELECT_LEX_UNIT;
@ -1039,7 +1039,7 @@ public:
bool save_prep_leaf_tables(THD *thd);
bool is_merged_child_of(st_select_lex *ancestor);
int print_explain(select_result_sink *output);
int print_explain(select_result_sink *output, uint8 explain_flags);
/*
For MODE_ONLY_FULL_GROUP_BY we need to maintain two flags:
- Non-aggregated fields are used in this select.

View File

@ -7281,28 +7281,36 @@ prev_record_reads(POSITION *positions, uint idx, table_map found_ref)
return found;
}
enum enum_exec_or_opt {WALK_OPTIMIZATION_TABS , WALK_EXECUTION_TABS};
/*
Enumerate join tabs in breadth-first fashion, including const tables.
*/
JOIN_TAB *first_breadth_first_tab(JOIN *join)
JOIN_TAB *first_breadth_first_tab(JOIN *join, enum enum_exec_or_opt tabs_kind)
{
return join->join_tab; /* There's always one (i.e. first) table */
/* There's always one (i.e. first) table */
return (tabs_kind == WALK_EXECUTION_TABS)? join->join_tab:
join->table_access_tabs;
}
JOIN_TAB *next_breadth_first_tab(JOIN *join, JOIN_TAB *tab)
JOIN_TAB *next_breadth_first_tab(JOIN *join, enum enum_exec_or_opt tabs_kind,
JOIN_TAB *tab)
{
JOIN_TAB* const first_top_tab= first_breadth_first_tab(join, tabs_kind);
const uint n_top_tabs_count= (tabs_kind == WALK_EXECUTION_TABS)?
join->top_join_tab_count:
join->top_table_access_tabs_count;
if (!tab->bush_root_tab)
{
/* We're at top level. Get the next top-level tab */
tab++;
if (tab < join->join_tab + join->top_join_tab_count)
if (tab < first_top_tab + n_top_tabs_count)
return tab;
/* No more top-level tabs. Switch to enumerating SJM nest children */
tab= join->join_tab;
tab= first_top_tab;
}
else
{
@ -7326,7 +7334,7 @@ JOIN_TAB *next_breadth_first_tab(JOIN *join, JOIN_TAB *tab)
Ok, "tab" points to a top-level table, and we need to find the next SJM
nest and enter it.
*/
for (; tab < join->join_tab + join->top_join_tab_count; tab++)
for (; tab < first_top_tab + n_top_tabs_count; tab++)
{
if (tab->bush_children)
return tab->bush_children->start;
@ -7350,7 +7358,7 @@ JOIN_TAB *first_top_level_tab(JOIN *join, enum enum_with_const_tables with_const
JOIN_TAB *next_top_level_tab(JOIN *join, JOIN_TAB *tab)
{
tab= next_breadth_first_tab(join, tab);
tab= next_breadth_first_tab(join, WALK_EXECUTION_TABS, tab);
if (tab && tab->bush_root_tab)
tab= NULL;
return tab;
@ -7650,6 +7658,13 @@ get_best_combination(JOIN *join)
join->top_join_tab_count= join->join_tab_ranges.head()->end -
join->join_tab_ranges.head()->start;
/*
Save pointers to select join tabs for SHOW EXPLAIN
*/
join->table_access_tabs= join->join_tab;
join->top_table_access_tabs_count= join->top_join_tab_count;
update_depend_map(join);
DBUG_RETURN(0);
}
@ -8079,6 +8094,7 @@ JOIN::make_simple_join(JOIN *parent, TABLE *temp_table)
!(parent->join_tab_reexec= (JOIN_TAB*) thd->alloc(sizeof(JOIN_TAB))))
DBUG_RETURN(TRUE); /* purecov: inspected */
// psergey-todo: here, save the pointer for original join_tabs.
join_tab= parent->join_tab_reexec;
table= &parent->table_reexec[0]; parent->table_reexec[0]= temp_table;
table_count= top_join_tab_count= 1;
@ -10239,7 +10255,12 @@ void JOIN_TAB::cleanup()
if (cache)
{
cache->free();
cache= 0;
cache= 0; // psergey: this is why we don't see "Using join cache" in SHOW EXPLAIN
// when it is run for "Using temporary+filesort" queries while they
// are at reading-from-tmp-table phase.
//
// TODO ask igor if this can be just moved to later phase
// (JOIN_CACHE objects themselves are not big, arent they)
}
limit= 0;
if (table)
@ -10546,7 +10567,10 @@ void JOIN::cleanup(bool full)
DBUG_ENTER("JOIN::cleanup");
DBUG_PRINT("enter", ("full %u", (uint) full));
have_query_plan= QEP_DELETED;
/*
psergey: let's try without this first:
have_query_plan= QEP_DELETED;
*/
if (table)
{
JOIN_TAB *tab;
@ -21200,7 +21224,7 @@ int print_explain_message_line(select_result_sink *result,
int print_fake_select_lex_join(select_result_sink *result, bool on_the_fly,
SELECT_LEX *select_lex, uint8 select_options)
SELECT_LEX *select_lex, uint8 explain_flags)
{
const CHARSET_INFO *cs= system_charset_info;
Item *item_null= new Item_null();
@ -21246,7 +21270,7 @@ int print_fake_select_lex_join(select_result_sink *result, bool on_the_fly,
item_list.push_back(new Item_string(table_name_buffer, len, cs));
}
/* partitions */
if (/*join->thd->lex->describe*/ select_options & DESCRIBE_PARTITIONS)
if (explain_flags & DESCRIBE_PARTITIONS)
item_list.push_back(item_null);
/* type */
item_list.push_back(new Item_string(join_type_str[JT_ALL],
@ -21261,7 +21285,7 @@ int print_fake_select_lex_join(select_result_sink *result, bool on_the_fly,
/* ref */
item_list.push_back(item_null);
/* in_rows */
if (select_options & DESCRIBE_EXTENDED)
if (explain_flags & DESCRIBE_EXTENDED)
item_list.push_back(item_null);
/* rows */
item_list.push_back(item_null);
@ -21287,7 +21311,8 @@ int print_fake_select_lex_join(select_result_sink *result, bool on_the_fly,
modifications to any select's data structures
*/
int JOIN::print_explain(select_result_sink *result, bool on_the_fly,
int JOIN::print_explain(select_result_sink *result, uint8 explain_flags,
bool on_the_fly,
bool need_tmp_table, bool need_order,
bool distinct, const char *message)
{
@ -21303,7 +21328,7 @@ int JOIN::print_explain(select_result_sink *result, bool on_the_fly,
DBUG_PRINT("info", ("Select 0x%lx, type %s, message %s",
(ulong)join->select_lex, join->select_lex->type,
message ? message : "NULL"));
DBUG_ASSERT(this->have_query_plan == QEP_AVAILABLE);
DBUG_ASSERT(have_query_plan == QEP_AVAILABLE);
/* Don't log this into the slow query log */
if (!on_the_fly)
@ -21318,35 +21343,16 @@ int JOIN::print_explain(select_result_sink *result, bool on_the_fly,
*/
if (message)
{
// join->thd->lex->describe <- as options
#if 0
item_list.push_bace(new Item_int((int32)
join->select_lex->select_number));
item_list.push_back(new Item_string(join->select_lex->type,
strlen(join->select_lex->type), cs));
for (uint i=0 ; i < 7; i++)
item_list.push_back(item_null);
if (join->thd->lex->describe & DESCRIBE_PARTITIONS)
item_list.push_back(item_null);
if (join->thd->lex->describe & DESCRIBE_EXTENDED)
item_list.push_back(item_null);
item_list.push_back(new Item_string(message,strlen(message),cs));
if (result->send_data(item_list))
error= 1;
#endif
//psergey-todo: is passing join->thd->lex->describe correct for SHOW EXPLAIN?
if (print_explain_message_line(result, join->select_lex, on_the_fly,
join->thd->lex->describe, message))
explain_flags, message))
error= 1;
}
else if (join->select_lex == join->unit->fake_select_lex)
{
//psergey-todo: is passing join->thd->lex->describe correct for SHOW EXPLAIN?
if (print_fake_select_lex_join(result, on_the_fly,
join->select_lex,
join->thd->lex->describe))
explain_flags))
error= 1;
}
else if (!join->select_lex->master_unit()->derived ||
@ -21359,9 +21365,10 @@ int JOIN::print_explain(select_result_sink *result, bool on_the_fly,
bool printing_materialize_nest= FALSE;
uint select_id= join->select_lex->select_number;
JOIN_TAB* const first_top_tab= first_breadth_first_tab(join, WALK_OPTIMIZATION_TABS);
for (JOIN_TAB *tab= first_breadth_first_tab(join); tab;
tab= next_breadth_first_tab(join, tab))
for (JOIN_TAB *tab= first_breadth_first_tab(join, WALK_OPTIMIZATION_TABS); tab;
tab= next_breadth_first_tab(join, WALK_OPTIMIZATION_TABS, tab))
{
if (tab->bush_root_tab)
{
@ -21450,7 +21457,7 @@ int JOIN::print_explain(select_result_sink *result, bool on_the_fly,
cs));
}
/* "partitions" column */
if (join->thd->lex->describe & DESCRIBE_PARTITIONS)
if (explain_flags & DESCRIBE_PARTITIONS)
{
#ifdef WITH_PARTITION_STORAGE_ENGINE
partition_info *part_info;
@ -21598,7 +21605,7 @@ int JOIN::print_explain(select_result_sink *result, bool on_the_fly,
table_list->schema_table)
{
/* in_rows */
if (join->thd->lex->describe & DESCRIBE_EXTENDED)
if (explain_flags & DESCRIBE_EXTENDED)
item_list.push_back(item_null);
/* rows */
item_list.push_back(item_null);
@ -21635,7 +21642,7 @@ int JOIN::print_explain(select_result_sink *result, bool on_the_fly,
MY_INT64_NUM_DECIMAL_DIGITS));
/* Add "filtered" field to item_list. */
if (join->thd->lex->describe & DESCRIBE_EXTENDED)
if (explain_flags & DESCRIBE_EXTENDED)
{
float f= 0.0;
if (examined_rows)
@ -21719,7 +21726,7 @@ int JOIN::print_explain(select_result_sink *result, bool on_the_fly,
{
extra.append(STRING_WITH_LEN("; Using where with pushed "
"condition"));
if (thd->lex->describe & DESCRIBE_EXTENDED)
if (explain_flags & DESCRIBE_EXTENDED)
{
extra.append(STRING_WITH_LEN(": "));
((COND *)pushed_cond)->print(&extra, QT_ORDINARY);
@ -21812,7 +21819,7 @@ int JOIN::print_explain(select_result_sink *result, bool on_the_fly,
extra.append(STRING_WITH_LEN("; End temporary"));
else if (tab->do_firstmatch)
{
if (tab->do_firstmatch == join->join_tab - 1)
if (tab->do_firstmatch == /*join->join_tab*/ first_top_tab - 1)
extra.append(STRING_WITH_LEN("; FirstMatch"));
else
{
@ -21879,7 +21886,8 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
THD *thd=join->thd;
select_result *result=join->result;
DBUG_ENTER("select_describe");
join->error= join->print_explain(result, FALSE, /* Not on-the-fly */
join->error= join->print_explain(result, thd->lex->describe,
FALSE, /* Not on-the-fly */
need_tmp_table, need_order, distinct,
message);

View File

@ -896,6 +896,20 @@ protected:
public:
JOIN_TAB *join_tab, **best_ref;
/*
For "Using temporary+Using filesort" queries, JOIN::join_tab can point to
either:
1. array of join tabs describing how to run the select, or
2. array of single join tab describing read from the temporary table.
SHOW EXPLAIN code needs to read/show #1. This is why two next members are
there for saving it.
*/
JOIN_TAB *table_access_tabs;
uint top_table_access_tabs_count;
JOIN_TAB **map2table; ///< mapping between table indexes and JOIN_TABs
JOIN_TAB *join_tab_save; ///< saved join_tab for subquery reexecution
@ -1161,7 +1175,11 @@ public:
const char *zero_result_cause; ///< not 0 if exec must return zero result
bool union_part; ///< this subselect is part of union
bool optimized; ///< flag to avoid double optimization in EXPLAIN
enum join_optimization_state { NOT_OPTIMIZED=0,
OPTIMIZATION_IN_PROGRESS=1,
OPTIMIZATION_DONE=2};
bool optimized; ///< flag to avoid double optimization in EXPLAIN
bool initialized; ///< flag to avoid double init_execution calls
enum { QEP_NOT_PRESENT_YET, QEP_AVAILABLE, QEP_DELETED} have_query_plan;
@ -1393,7 +1411,8 @@ public:
return (unit->item && unit->item->is_in_predicate());
}
int print_explain(select_result_sink *result, bool on_the_fly,
int print_explain(select_result_sink *result, uint8 explain_flags,
bool on_the_fly,
bool need_tmp_table, bool need_order,
bool distinct,const char *message);
private:

View File

@ -2062,16 +2062,33 @@ void mysqld_show_explain(THD *thd, ulong thread_id)
explain_req.explain_buf= explain_buf;
explain_req.target_thd= tmp;
explain_req.request_thd= thd;
explain_req.failed_to_produce= FALSE;
bres= tmp->apc_target.make_apc_call(Show_explain_request::get_explain_data,
(void*)&explain_req,
timeout_sec, &timed_out);
if (bres)
if (bres || explain_req.failed_to_produce)
{
/* TODO not enabled or time out */
my_error(ER_ERROR_WHEN_EXECUTING_COMMAND, MYF(0),
"SHOW EXPLAIN",
"Target is not running EXPLAINable command");
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 is not running EXPLAINable command");
}
bres= TRUE;
}
else
{
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_YES, explain_req.query_str.c_ptr_safe());
}
mysql_mutex_unlock(&tmp->LOCK_thd_data);
if (!bres)

View File

@ -1106,7 +1106,12 @@ public:
See TABLE_LIST::process_index_hints().
*/
bool force_index_group;
bool distinct,const_table,no_rows, used_for_duplicate_elimination;
/*
TRUE<=> this table was created with create_tmp_table(... distinct=TRUE..)
call
*/
bool distinct;
bool const_table,no_rows, used_for_duplicate_elimination;
/**
If set, the optimizer has found that row retrieval should access index