Merge of recent changes in MWL#182 in 5.3 with {Merge of MWL#182 with 5.5}
This commit is contained in:
commit
34e9a4c1e2
@ -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;
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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= ¤t_thd->killed;
|
||||
/* volatile killed_state *killed= ¤t_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= ¬_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 */
|
||||
}
|
||||
|
@ -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())))
|
||||
|
@ -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);
|
||||
|
||||
|
63
sql/my_apc.h
63
sql/my_apc.h
@ -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;
|
||||
}
|
||||
};
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user