Commit 6bce3366 authored by Sergey Petrunya's avatar Sergey Petrunya

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
parent 6fae4447
drop table if exists t0, t1, t2; drop table if exists t0, t1, t2;
drop view if exists v1;
create table t0 (a int); create table t0 (a int);
insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
create table t1 (a int); create table t1 (a int);
...@@ -337,4 +338,36 @@ Warnings: ...@@ -337,4 +338,36 @@ Warnings:
Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` join `test`.`t2` group by `test`.`t2`.`a` Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` join `test`.`t2` group by `test`.`t2`.`a`
set debug=''; set debug='';
DROP TABLE t2; 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; drop table t0,t1;
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
--disable_warnings --disable_warnings
drop table if exists t0, t1, t2; drop table if exists t0, t1, t2;
drop view if exists v1;
--enable_warnings --enable_warnings
# #
...@@ -346,6 +347,30 @@ set debug=''; ...@@ -346,6 +347,30 @@ set debug='';
DROP TABLE t2; 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 ## TODO: Test this: have several SHOW EXPLAIN requests be queued up for a
## thread and served together. ## thread and served together.
......
...@@ -2910,7 +2910,7 @@ int subselect_single_select_engine::exec() ...@@ -2910,7 +2910,7 @@ int subselect_single_select_engine::exec()
SELECT_LEX *save_select= thd->lex->current_select; SELECT_LEX *save_select= thd->lex->current_select;
thd->lex->current_select= select_lex; thd->lex->current_select= select_lex;
if (!join->optimized) if (join->optimized != JOIN::OPTIMIZATION_DONE)
{ {
SELECT_LEX_UNIT *unit= select_lex->master_unit(); SELECT_LEX_UNIT *unit= select_lex->master_unit();
...@@ -4647,7 +4647,9 @@ int subselect_hash_sj_engine::exec() ...@@ -4647,7 +4647,9 @@ int subselect_hash_sj_engine::exec()
*/ */
thd->lex->current_select= materialize_engine->select_lex; thd->lex->current_select= materialize_engine->select_lex;
/* The subquery should be optimized, and materialized only once. */ /* 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(); materialize_join->exec();
if ((res= test(materialize_join->error || thd->is_fatal_error || if ((res= test(materialize_join->error || thd->is_fatal_error ||
thd->is_error()))) thd->is_error())))
......
...@@ -3750,7 +3750,7 @@ int st_select_lex::print_explain(select_result_sink *output, ...@@ -3750,7 +3750,7 @@ int st_select_lex::print_explain(select_result_sink *output,
uint8 explain_flags) uint8 explain_flags)
{ {
int res; int res;
if (join && join->optimized == 2) if (join && join->optimized == JOIN::OPTIMIZATION_DONE)
{ {
res= join->print_explain(output, explain_flags, TRUE, res= join->print_explain(output, explain_flags, TRUE,
join->need_tmp, // need_tmp_table join->need_tmp, // need_tmp_table
......
...@@ -608,7 +608,7 @@ JOIN::prepare(Item ***rref_pointer_array, ...@@ -608,7 +608,7 @@ JOIN::prepare(Item ***rref_pointer_array,
DBUG_ENTER("JOIN::prepare"); DBUG_ENTER("JOIN::prepare");
// to prevent double initialization on EXPLAIN // to prevent double initialization on EXPLAIN
if (optimized) if (optimized != JOIN::NOT_OPTIMIZED)
DBUG_RETURN(0); DBUG_RETURN(0);
conds= conds_init; conds= conds_init;
...@@ -936,7 +936,7 @@ err: ...@@ -936,7 +936,7 @@ err:
int JOIN::optimize() int JOIN::optimize()
{ {
int res= optimize_inner(); int res= optimize_inner();
optimized= 2; optimized= JOIN::OPTIMIZATION_DONE;
return res; return res;
} }
/** /**
...@@ -960,9 +960,9 @@ JOIN::optimize_inner() ...@@ -960,9 +960,9 @@ JOIN::optimize_inner()
DBUG_ENTER("JOIN::optimize"); DBUG_ENTER("JOIN::optimize");
do_send_rows = (unit->select_limit_cnt) ? 1 : 0; do_send_rows = (unit->select_limit_cnt) ? 1 : 0;
// to prevent double initialization on EXPLAIN // to prevent double initialization on EXPLAIN
if (optimized) if (optimized != JOIN::NOT_OPTIMIZED)
DBUG_RETURN(0); DBUG_RETURN(0);
optimized= 1; optimized= JOIN::OPTIMIZATION_IN_PROGRESS;
thd_proc_info(thd, "optimizing"); thd_proc_info(thd, "optimizing");
set_allowed_join_cache_types(); set_allowed_join_cache_types();
...@@ -1731,7 +1731,7 @@ int JOIN::init_execution() ...@@ -1731,7 +1731,7 @@ int JOIN::init_execution()
{ {
DBUG_ENTER("JOIN::init_execution"); DBUG_ENTER("JOIN::init_execution");
DBUG_ASSERT(optimized); DBUG_ASSERT(optimized == JOIN::OPTIMIZATION_DONE);
DBUG_ASSERT(!(select_options & SELECT_DESCRIBE)); DBUG_ASSERT(!(select_options & SELECT_DESCRIBE));
initialized= true; initialized= true;
...@@ -21187,7 +21187,7 @@ int JOIN::print_explain(select_result_sink *result, uint8 explain_flags, ...@@ -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", DBUG_PRINT("info", ("Select 0x%lx, type %s, message %s",
(ulong)join->select_lex, join->select_lex->type, (ulong)join->select_lex, join->select_lex->type,
message ? message : "NULL")); message ? message : "NULL"));
DBUG_ASSERT(this->optimized == 2);
/* Don't log this into the slow query log */ /* Don't log this into the slow query log */
if (!on_the_fly) if (!on_the_fly)
...@@ -21204,6 +21204,10 @@ int JOIN::print_explain(select_result_sink *result, uint8 explain_flags, ...@@ -21204,6 +21204,10 @@ int JOIN::print_explain(select_result_sink *result, uint8 explain_flags,
{ {
item_list.push_back(new Item_int((int32) item_list.push_back(new Item_int((int32)
join->select_lex->select_number)); 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, item_list.push_back(new Item_string(join->select_lex->type,
strlen(join->select_lex->type), cs)); strlen(join->select_lex->type), cs));
for (uint i=0 ; i < 7; i++) for (uint i=0 ; i < 7; i++)
...@@ -21227,6 +21231,7 @@ int JOIN::print_explain(select_result_sink *result, uint8 explain_flags, ...@@ -21227,6 +21231,7 @@ int JOIN::print_explain(select_result_sink *result, uint8 explain_flags,
else if (!join->select_lex->master_unit()->derived || else if (!join->select_lex->master_unit()->derived ||
join->select_lex->master_unit()->derived->is_materialized_derived()) join->select_lex->master_unit()->derived->is_materialized_derived())
{ {
DBUG_ASSERT(optimized == JOIN::OPTIMIZATION_DONE);
table_map used_tables=0; table_map used_tables=0;
//if (!join->select_lex->type) //if (!join->select_lex->type)
if (on_the_fly) if (on_the_fly)
......
...@@ -1178,7 +1178,11 @@ public: ...@@ -1178,7 +1178,11 @@ public:
const char *zero_result_cause; ///< not 0 if exec must return zero result const char *zero_result_cause; ///< not 0 if exec must return zero result
bool union_part; ///< this subselect is part of union 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 bool initialized; ///< flag to avoid double init_execution calls
/* /*
...@@ -1261,7 +1265,7 @@ public: ...@@ -1261,7 +1265,7 @@ public:
ref_pointer_array= items0= items1= items2= items3= 0; ref_pointer_array= items0= items1= items2= items3= 0;
ref_pointer_array_size= 0; ref_pointer_array_size= 0;
zero_result_cause= 0; zero_result_cause= 0;
optimized= 0; optimized= JOIN::NOT_OPTIMIZED;
initialized= 0; initialized= 0;
cond_equal= 0; cond_equal= 0;
having_equal= 0; having_equal= 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment