diff options
author | Sergey Petrunya <psergey@askmonty.org> | 2012-05-16 12:49:22 +0400 |
---|---|---|
committer | Sergey Petrunya <psergey@askmonty.org> | 2012-05-16 12:49:22 +0400 |
commit | 533e1d28459ab5aa0604560bf8885ae18e553295 (patch) | |
tree | be0474de18ca22b5768245061a7118cb6860f80e | |
parent | 382e81ca84a51fded86df6f21e0b4e003fc94388 (diff) | |
download | mariadb-git-533e1d28459ab5aa0604560bf8885ae18e553295.tar.gz |
MDEV-273: SHOW EXPLAIN: server crashes in JOIN::print_explain on a query with impossible WHERE
- It turns out, there is a case where the join is degenerate, but
join->table_count!= && join->tables_list!=NULL. Need to also check
if join->zero_result_cause!=NULL, too.
- There is a slight problem: The code sets
zero_result_cause= "no matching row in const table"
when NOT running EXPLAIN. The result is that SHOW EXPLAIN will show this line while
regular EXPLAIN will not.
-rw-r--r-- | mysql-test/r/show_explain.result | 56 | ||||
-rw-r--r-- | mysql-test/t/show_explain.test | 45 | ||||
-rw-r--r-- | sql/sql_lex.cc | 6 |
3 files changed, 101 insertions, 6 deletions
diff --git a/mysql-test/r/show_explain.result b/mysql-test/r/show_explain.result index 1b1c30b56df..d19a6f29539 100644 --- a/mysql-test/r/show_explain.result +++ b/mysql-test/r/show_explain.result @@ -1,4 +1,4 @@ -drop table if exists t0, t1, t2; +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); @@ -407,8 +407,7 @@ set debug='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 t3 const PRIMARY PRIMARY 4 0 unique row not found -1 SIMPLE t0 ALL NULL NULL NULL NULL 10 +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 @@ -453,4 +452,55 @@ pk a 9 7 set debug=''; 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='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=''; +drop table t2, t3, t4; drop table t0,t1; diff --git a/mysql-test/t/show_explain.test b/mysql-test/t/show_explain.test index d813956a1fe..35694e97111 100644 --- a/mysql-test/t/show_explain.test +++ b/mysql-test/t/show_explain.test @@ -4,7 +4,7 @@ --source include/have_debug.inc --disable_warnings -drop table if exists t0, t1, t2; +drop table if exists t0, t1, t2, t3, t4; drop view if exists v1; --enable_warnings @@ -444,9 +444,50 @@ set debug=''; 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='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=''; +drop table t2, t3, t4; ## TODO: Test this: have several SHOW EXPLAIN requests be queued up for a ## thread and served together. diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 556077220de..13972d56605 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -3752,7 +3752,11 @@ int st_select_lex::print_explain(select_result_sink *output, int res; if (join && join->optimized == JOIN::OPTIMIZATION_DONE) { - if (!join->table_count || !join->tables_list) + /* + 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 : |