Commit e1c92a6c authored by Igor Babaev's avatar Igor Babaev

Fixed a problem with unreferenced CTE:

explain for the query containing WITH clause
with an unreferenced CTE caused a crash.
Added a test covered this case.

Also added a test for usage CTE in different parts of union.
parent 247632e6
...@@ -309,6 +309,41 @@ c c ...@@ -309,6 +309,41 @@ c c
1 1 1 1
4 4 4 4
4 4 4 4
# t two references of t used in different parts of a union
with t as (select a from t1 where b >= 'c')
select * from t where a < 2
union
select * from t where a >= 4;
a
1
4
select * from (select a from t1 where b >= 'c') as t
where t.a < 2
union
select * from (select a from t1 where b >= 'c') as t
where t.a >= 4;
a
1
4
explain
with t as (select a from t1 where b >= 'c')
select * from t where a < 2
union
select * from t where a >= 4;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where
3 UNION t1 ALL NULL NULL NULL NULL 8 Using where
NULL UNION RESULT <union1,3> ALL NULL NULL NULL NULL NULL
explain
select * from (select a from t1 where b >= 'c') as t
where t.a < 2
union
select * from (select a from t1 where b >= 'c') as t
where t.a >= 4;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where
3 UNION t1 ALL NULL NULL NULL NULL 8 Using where
NULL UNION RESULT <union1,3> ALL NULL NULL NULL NULL NULL
# specification of t contains union # specification of t contains union
with t as (select a from t1 where b >= 'f' with t as (select a from t1 where b >= 'f'
union union
...@@ -749,6 +784,19 @@ ERROR HY000: WITH column list and SELECT field list have different column counts ...@@ -749,6 +784,19 @@ ERROR HY000: WITH column list and SELECT field list have different column counts
with t(f1,f1) as (select * from t1 where b >= 'c') with t(f1,f1) as (select * from t1 where b >= 'c')
select t1.b from t2,t1 where t1.a = t2.c; select t1.b from t2,t1 where t1.a = t2.c;
ERROR 42S21: Duplicate column name 'f1' ERROR 42S21: Duplicate column name 'f1'
# explain for query with unreferenced with table
explain
with t as (select a from t1 where b >= 'c')
select t1.b from t2,t1 where t1.a = t2.c;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 4
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join)
explain
with t as (select a, count(*) from t1 where b >= 'c' group by a)
select t1.b from t2,t1 where t1.a = t2.c;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 4
1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where; Using join buffer (flat, BNL join)
drop table t1,t2; drop table t1,t2;
# #
# Bug mdev-9937: View used in the specification of with table # Bug mdev-9937: View used in the specification of with table
......
...@@ -152,6 +152,28 @@ select * from (select * from t1 where b >= 'c') as r1, ...@@ -152,6 +152,28 @@ select * from (select * from t1 where b >= 'c') as r1,
with t(c) as (select a from t1 where b >= 'c') with t(c) as (select a from t1 where b >= 'c')
select * from t r1, t r2 where r1.c=r2.c; select * from t r1, t r2 where r1.c=r2.c;
--echo # t two references of t used in different parts of a union
with t as (select a from t1 where b >= 'c')
select * from t where a < 2
union
select * from t where a >= 4;
select * from (select a from t1 where b >= 'c') as t
where t.a < 2
union
select * from (select a from t1 where b >= 'c') as t
where t.a >= 4;
explain
with t as (select a from t1 where b >= 'c')
select * from t where a < 2
union
select * from t where a >= 4;
explain
select * from (select a from t1 where b >= 'c') as t
where t.a < 2
union
select * from (select a from t1 where b >= 'c') as t
where t.a >= 4;
--echo # specification of t contains union --echo # specification of t contains union
with t as (select a from t1 where b >= 'f' with t as (select a from t1 where b >= 'f'
union union
...@@ -437,6 +459,16 @@ with t(f) as (select * from t1 where b >= 'c') ...@@ -437,6 +459,16 @@ with t(f) as (select * from t1 where b >= 'c')
with t(f1,f1) as (select * from t1 where b >= 'c') with t(f1,f1) as (select * from t1 where b >= 'c')
select t1.b from t2,t1 where t1.a = t2.c; select t1.b from t2,t1 where t1.a = t2.c;
--echo # explain for query with unreferenced with table
explain
with t as (select a from t1 where b >= 'c')
select t1.b from t2,t1 where t1.a = t2.c;
explain
with t as (select a, count(*) from t1 where b >= 'c' group by a)
select t1.b from t2,t1 where t1.a = t2.c;
drop table t1,t2; drop table t1,t2;
--echo # --echo #
......
...@@ -24402,11 +24402,14 @@ int JOIN::save_explain_data_intern(Explain_query *output, ...@@ -24402,11 +24402,14 @@ int JOIN::save_explain_data_intern(Explain_query *output,
(1) they are not parts of ON clauses that were eliminated by table (1) they are not parts of ON clauses that were eliminated by table
elimination. elimination.
(2) they are not merged derived tables (2) they are not merged derived tables
(3) they are not unreferenced CTE
*/ */
if (!(tmp_unit->item && tmp_unit->item->eliminated) && // (1) if (!(tmp_unit->item && tmp_unit->item->eliminated) && // (1)
(!tmp_unit->derived || (!tmp_unit->derived ||
tmp_unit->derived->is_materialized_derived())) // (2) tmp_unit->derived->is_materialized_derived()) && // (2)
{ !(tmp_unit->with_element &&
!tmp_unit->with_element->is_referenced())) // (3)
{
explain->add_child(tmp_unit->first_select()->select_number); explain->add_child(tmp_unit->first_select()->select_number);
} }
} }
...@@ -24466,9 +24469,11 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, ...@@ -24466,9 +24469,11 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
Save plans for child subqueries, when Save plans for child subqueries, when
(1) they are not parts of eliminated WHERE/ON clauses. (1) they are not parts of eliminated WHERE/ON clauses.
(2) they are not VIEWs that were "merged for INSERT". (2) they are not VIEWs that were "merged for INSERT".
(3) they are not unreferenced CTE.
*/ */
if (!(unit->item && unit->item->eliminated) && // (1) if (!(unit->item && unit->item->eliminated) && // (1)
!(unit->derived && unit->derived->merged_for_insert)) // (2) !(unit->derived && unit->derived->merged_for_insert) && // (2)
!(unit->with_element && !unit->with_element->is_referenced())) // (3)
{ {
if (mysql_explain_union(thd, unit, result)) if (mysql_explain_union(thd, unit, result))
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
......
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