Commit e0cd6f4b authored by Igor Babaev's avatar Igor Babaev

Fixed bugs: mdev-13780 CTE not found, mdev-14184 recursive CTE not found

The support of embedded CTEs was not correct in the cases when
embedded CTEs were used multiple times. The problems occurred with
both non-recursive (bug mdev-13780) and recursive (bug mdev-14184)
embedded CTEs.
parent 8f2e8cf0
...@@ -1079,3 +1079,52 @@ id select_type table type possible_keys key key_len ref rows Extra ...@@ -1079,3 +1079,52 @@ id select_type table type possible_keys key key_len ref rows Extra
3 DERIVED t2 ALL NULL NULL NULL NULL 3 Using where; Using join buffer (flat, BNL join) 3 DERIVED t2 ALL NULL NULL NULL NULL 3 Using where; Using join buffer (flat, BNL join)
NULL UNION RESULT <union1,4> ALL NULL NULL NULL NULL NULL NULL UNION RESULT <union1,4> ALL NULL NULL NULL NULL NULL
DROP TABLE t1,t2; DROP TABLE t1,t2;
#
# MDEV-13780: tower of embedding CTEs with multiple usage of them
#
create table t1 (a int);
insert into t1 values (3), (2), (4), (7), (1), (2), (5);
with cte_e as
(
with cte_o as
(
with cte_i as (select * from t1 where a < 7)
select * from cte_i where a > 1
)
select * from cte_o as cto_o1 where a < 3
union
select * from cte_o as cto_o2 where a > 4
)
select * from cte_e as cte_e1 where a > 1
union
select * from cte_e as cte_e2;
a
2
5
explain extended with cte_e as
(
with cte_o as
(
with cte_i as (select * from t1 where a < 7)
select * from cte_i where a > 1
)
select * from cte_o as cto_o1 where a < 3
union
select * from cte_o as cto_o2 where a > 4
)
select * from cte_e as cte_e1 where a > 1
union
select * from cte_e as cte_e2;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 14 100.00 Using where
2 DERIVED t1 ALL NULL NULL NULL NULL 7 100.00 Using where
5 UNION t1 ALL NULL NULL NULL NULL 7 100.00 Using where
NULL UNION RESULT <union2,5> ALL NULL NULL NULL NULL NULL NULL
6 UNION <derived9> ALL NULL NULL NULL NULL 14 100.00
9 DERIVED t1 ALL NULL NULL NULL NULL 7 100.00 Using where
12 UNION t1 ALL NULL NULL NULL NULL 7 100.00 Using where
NULL UNION RESULT <union9,12> ALL NULL NULL NULL NULL NULL NULL
NULL UNION RESULT <union1,6> ALL NULL NULL NULL NULL NULL NULL
Warnings:
Note 1003 with cte_e as (with cte_o as (with cte_i as (select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` < 7)select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` > 1)select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` < 3 and `test`.`t1`.`a` > 1 and `test`.`t1`.`a` < 7 and `test`.`t1`.`a` > 1 union select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` > 4 and `test`.`t1`.`a` > 1 and `test`.`t1`.`a` < 7 and `test`.`t1`.`a` > 1)select `cte_e1`.`a` AS `a` from `cte_e` `cte_e1` where `cte_e1`.`a` > 1 union select `cte_e2`.`a` AS `a` from `cte_e` `cte_e2`
drop table t1;
...@@ -2875,3 +2875,25 @@ f ...@@ -2875,3 +2875,25 @@ f
2 2
set standard_compliant_cte=default; set standard_compliant_cte=default;
DROP TABLE t; DROP TABLE t;
#
# mdev-14184: recursive CTE embedded into CTE with multiple references
#
WITH
cte1 AS (
SELECT n FROM (
WITH RECURSIVE rec_cte(n) AS (
SELECT 1 as n1
UNION ALL
SELECT n+1 as n2 FROM rec_cte WHERE n < 3
) SELECT n FROM rec_cte
) AS X
),
cte2 as (
SELECT 2 FROM cte1
)
SELECT *
FROM cte1;
n
1
2
3
...@@ -743,3 +743,31 @@ eval $q; ...@@ -743,3 +743,31 @@ eval $q;
eval explain $q; eval explain $q;
DROP TABLE t1,t2; DROP TABLE t1,t2;
--echo #
--echo # MDEV-13780: tower of embedding CTEs with multiple usage of them
--echo #
create table t1 (a int);
insert into t1 values (3), (2), (4), (7), (1), (2), (5);
let $q=
with cte_e as
(
with cte_o as
(
with cte_i as (select * from t1 where a < 7)
select * from cte_i where a > 1
)
select * from cte_o as cto_o1 where a < 3
union
select * from cte_o as cto_o2 where a > 4
)
select * from cte_e as cte_e1 where a > 1
union
select * from cte_e as cte_e2;
eval $q;
eval explain extended $q;
drop table t1;
...@@ -1928,3 +1928,22 @@ set standard_compliant_cte=default; ...@@ -1928,3 +1928,22 @@ set standard_compliant_cte=default;
DROP TABLE t; DROP TABLE t;
--echo #
--echo # mdev-14184: recursive CTE embedded into CTE with multiple references
--echo #
WITH
cte1 AS (
SELECT n FROM (
WITH RECURSIVE rec_cte(n) AS (
SELECT 1 as n1
UNION ALL
SELECT n+1 as n2 FROM rec_cte WHERE n < 3
) SELECT n FROM rec_cte
) AS X
),
cte2 as (
SELECT 2 FROM cte1
)
SELECT *
FROM cte1;
...@@ -349,7 +349,10 @@ void With_element::check_dependencies_in_select(st_select_lex *sl, ...@@ -349,7 +349,10 @@ void With_element::check_dependencies_in_select(st_select_lex *sl,
/* Now look for the dependencies in the subqueries of sl */ /* Now look for the dependencies in the subqueries of sl */
st_select_lex_unit *inner_unit= sl->first_inner_unit(); st_select_lex_unit *inner_unit= sl->first_inner_unit();
for (; inner_unit; inner_unit= inner_unit->next_unit()) for (; inner_unit; inner_unit= inner_unit->next_unit())
{
if (!inner_unit->with_element)
check_dependencies_in_unit(inner_unit, ctxt, in_subq, dep_map); check_dependencies_in_unit(inner_unit, ctxt, in_subq, dep_map);
}
} }
...@@ -838,7 +841,6 @@ st_select_lex_unit *With_element::clone_parsed_spec(THD *thd, ...@@ -838,7 +841,6 @@ st_select_lex_unit *With_element::clone_parsed_spec(THD *thd,
with_table->next_global= spec_tables; with_table->next_global= spec_tables;
} }
res= &lex->unit; res= &lex->unit;
res->set_with_clause(owner);
lex->unit.include_down(with_table->select_lex); lex->unit.include_down(with_table->select_lex);
lex->unit.set_slave(with_select); lex->unit.set_slave(with_select);
...@@ -847,6 +849,8 @@ st_select_lex_unit *With_element::clone_parsed_spec(THD *thd, ...@@ -847,6 +849,8 @@ st_select_lex_unit *With_element::clone_parsed_spec(THD *thd,
insert_chain_before( insert_chain_before(
(st_select_lex_node **) &(old_lex->all_selects_list), (st_select_lex_node **) &(old_lex->all_selects_list),
with_select)); with_select));
if (check_dependencies_in_with_clauses(lex->with_clauses_list))
res= NULL;
lex_end(lex); lex_end(lex);
err: err:
if (arena) if (arena)
...@@ -990,14 +994,18 @@ With_element *st_select_lex::find_table_def_in_with_clauses(TABLE_LIST *table) ...@@ -990,14 +994,18 @@ With_element *st_select_lex::find_table_def_in_with_clauses(TABLE_LIST *table)
and it was unsuccesful. Yet for units cloned from the spec it has not and it was unsuccesful. Yet for units cloned from the spec it has not
been done yet. been done yet.
*/ */
if (with_elem && sl->master_unit() == with_elem->spec) With_clause *attached_with_clause=sl->get_with_clause();
if (attached_with_clause &&
(found= attached_with_clause->find_table_def(table, NULL)))
break; break;
With_clause *with_clause=sl->get_with_clause(); if (with_elem)
if (with_clause)
{ {
With_element *barrier= with_clause->with_recursive ? NULL : with_elem; With_clause *containing_with_clause= with_elem->get_owner();
if ((found= with_clause->find_table_def(table, barrier))) With_element *barrier= containing_with_clause->with_recursive ?
NULL : with_elem;
if ((found= containing_with_clause->find_table_def(table, barrier)))
break; break;
sl= sl->master_unit()->outer_select();
} }
master_unit= sl->master_unit(); master_unit= sl->master_unit();
/* Do not look for the table's definition beyond the scope of the view */ /* Do not look for the table's definition beyond the scope of the view */
......
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