summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Petrunya <psergey@askmonty.org>2012-05-11 18:13:06 +0400
committerSergey Petrunya <psergey@askmonty.org>2012-05-11 18:13:06 +0400
commit6bce336624e84f5ec377926b105ec2002b38c96b (patch)
tree403415304e99e5f25617e4b75f401938aaae7d83
parent6fae4447f0873c159d94d1a3d8deafbd224d8100 (diff)
downloadmariadb-git-6bce336624e84f5ec377926b105ec2002b38c96b.tar.gz
MDEV-240: SHOW EXPLAIN: Assertion `this->optimized == 2' failed
- Fix the bug: SHOW EXPLAIN may hit a case where a join is partially optimized. - Change JOIN::optimized to use enum instead of numeric constants
-rw-r--r--mysql-test/r/show_explain.result33
-rw-r--r--mysql-test/t/show_explain.test25
-rw-r--r--sql/item_subselect.cc6
-rw-r--r--sql/sql_lex.cc2
-rw-r--r--sql/sql_select.cc17
-rw-r--r--sql/sql_select.h8
6 files changed, 80 insertions, 11 deletions
diff --git a/mysql-test/r/show_explain.result b/mysql-test/r/show_explain.result
index 4f0e89975ff..2051a409178 100644
--- a/mysql-test/r/show_explain.result
+++ b/mysql-test/r/show_explain.result
@@ -1,4 +1,5 @@
drop table if exists t0, t1, t2;
+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);
@@ -337,4 +338,36 @@ Warnings:
Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` join `test`.`t2` group by `test`.`t2`.`a`
set debug='';
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='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='';
+DROP VIEW v1;
+DROP TABLE t2, t3;
drop table t0,t1;
diff --git a/mysql-test/t/show_explain.test b/mysql-test/t/show_explain.test
index 02850efedd8..36c34c8df5c 100644
--- a/mysql-test/t/show_explain.test
+++ b/mysql-test/t/show_explain.test
@@ -5,6 +5,7 @@
--disable_warnings
drop table if exists t0, t1, t2;
+drop view if exists v1;
--enable_warnings
#
@@ -346,6 +347,30 @@ set debug='';
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='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='';
+DROP VIEW v1;
+DROP TABLE t2, t3;
+
## TODO: Test this: have several SHOW EXPLAIN requests be queued up for a
## thread and served together.
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 8b720b350a5..1780953bd7e 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -2910,7 +2910,7 @@ int subselect_single_select_engine::exec()
SELECT_LEX *save_select= thd->lex->current_select;
thd->lex->current_select= select_lex;
- if (!join->optimized)
+ if (join->optimized != JOIN::OPTIMIZATION_DONE)
{
SELECT_LEX_UNIT *unit= select_lex->master_unit();
@@ -4647,7 +4647,9 @@ 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);
+ DBUG_ASSERT(materialize_join->optimized == JOIN::OPTIMIZATION_DONE &&
+ !is_materialized);
+
materialize_join->exec();
if ((res= test(materialize_join->error || thd->is_fatal_error ||
thd->is_error())))
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 69bb822f05a..29d0a9e9888 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -3750,7 +3750,7 @@ int st_select_lex::print_explain(select_result_sink *output,
uint8 explain_flags)
{
int res;
- if (join && join->optimized == 2)
+ if (join && join->optimized == JOIN::OPTIMIZATION_DONE)
{
res= join->print_explain(output, explain_flags, TRUE,
join->need_tmp, // need_tmp_table
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index f48f180d1dd..af7a06e424d 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -608,7 +608,7 @@ JOIN::prepare(Item ***rref_pointer_array,
DBUG_ENTER("JOIN::prepare");
// to prevent double initialization on EXPLAIN
- if (optimized)
+ if (optimized != JOIN::NOT_OPTIMIZED)
DBUG_RETURN(0);
conds= conds_init;
@@ -936,7 +936,7 @@ err:
int JOIN::optimize()
{
int res= optimize_inner();
- optimized= 2;
+ optimized= JOIN::OPTIMIZATION_DONE;
return res;
}
/**
@@ -960,9 +960,9 @@ JOIN::optimize_inner()
DBUG_ENTER("JOIN::optimize");
do_send_rows = (unit->select_limit_cnt) ? 1 : 0;
// to prevent double initialization on EXPLAIN
- if (optimized)
+ if (optimized != JOIN::NOT_OPTIMIZED)
DBUG_RETURN(0);
- optimized= 1;
+ optimized= JOIN::OPTIMIZATION_IN_PROGRESS;
thd_proc_info(thd, "optimizing");
set_allowed_join_cache_types();
@@ -1731,7 +1731,7 @@ int JOIN::init_execution()
{
DBUG_ENTER("JOIN::init_execution");
- DBUG_ASSERT(optimized);
+ DBUG_ASSERT(optimized == JOIN::OPTIMIZATION_DONE);
DBUG_ASSERT(!(select_options & SELECT_DESCRIBE));
initialized= true;
@@ -21187,7 +21187,7 @@ int JOIN::print_explain(select_result_sink *result, uint8 explain_flags,
DBUG_PRINT("info", ("Select 0x%lx, type %s, message %s",
(ulong)join->select_lex, join->select_lex->type,
message ? message : "NULL"));
- DBUG_ASSERT(this->optimized == 2);
+
/* Don't log this into the slow query log */
if (!on_the_fly)
@@ -21204,6 +21204,10 @@ int JOIN::print_explain(select_result_sink *result, uint8 explain_flags,
{
item_list.push_back(new Item_int((int32)
join->select_lex->select_number));
+
+ if (on_the_fly)
+ join->select_lex->set_explain_type(on_the_fly);
+
item_list.push_back(new Item_string(join->select_lex->type,
strlen(join->select_lex->type), cs));
for (uint i=0 ; i < 7; i++)
@@ -21227,6 +21231,7 @@ int JOIN::print_explain(select_result_sink *result, uint8 explain_flags,
else if (!join->select_lex->master_unit()->derived ||
join->select_lex->master_unit()->derived->is_materialized_derived())
{
+ DBUG_ASSERT(optimized == JOIN::OPTIMIZATION_DONE);
table_map used_tables=0;
//if (!join->select_lex->type)
if (on_the_fly)
diff --git a/sql/sql_select.h b/sql/sql_select.h
index a15720b4b30..3bb007f0d93 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -1178,7 +1178,11 @@ public:
const char *zero_result_cause; ///< not 0 if exec must return zero result
bool union_part; ///< this subselect is part of union
- int optimized; ///< flag to avoid double optimization in EXPLAIN
+
+ enum join_optimization_state { NOT_OPTIMIZED=0,
+ OPTIMIZATION_IN_PROGRESS=1,
+ OPTIMIZATION_DONE=2};
+ join_optimization_state optimized; ///< flag to avoid double optimization in EXPLAIN
bool initialized; ///< flag to avoid double init_execution calls
/*
@@ -1261,7 +1265,7 @@ public:
ref_pointer_array= items0= items1= items2= items3= 0;
ref_pointer_array_size= 0;
zero_result_cause= 0;
- optimized= 0;
+ optimized= JOIN::NOT_OPTIMIZED;
initialized= 0;
cond_equal= 0;
having_equal= 0;