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
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
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
2
set standard_compliant_cte=default;
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;
eval explain $q;
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;
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,
/* Now look for the dependencies in the subqueries of sl */
st_select_lex_unit *inner_unit= sl->first_inner_unit();
for (; inner_unit; inner_unit= inner_unit->next_unit())
check_dependencies_in_unit(inner_unit, ctxt, in_subq, dep_map);
{
if (!inner_unit->with_element)
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,
with_table->next_global= spec_tables;
}
res= &lex->unit;
res->set_with_clause(owner);
lex->unit.include_down(with_table->select_lex);
lex->unit.set_slave(with_select);
......@@ -847,6 +849,8 @@ st_select_lex_unit *With_element::clone_parsed_spec(THD *thd,
insert_chain_before(
(st_select_lex_node **) &(old_lex->all_selects_list),
with_select));
if (check_dependencies_in_with_clauses(lex->with_clauses_list))
res= NULL;
lex_end(lex);
err:
if (arena)
......@@ -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
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;
With_clause *with_clause=sl->get_with_clause();
if (with_clause)
if (with_elem)
{
With_element *barrier= with_clause->with_recursive ? NULL : with_elem;
if ((found= with_clause->find_table_def(table, barrier)))
With_clause *containing_with_clause= with_elem->get_owner();
With_element *barrier= containing_with_clause->with_recursive ?
NULL : with_elem;
if ((found= containing_with_clause->find_table_def(table, barrier)))
break;
sl= sl->master_unit()->outer_select();
}
master_unit= sl->master_unit();
/* 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