Skip to content

Commit e0cd6f4

Browse files
committed
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.
1 parent 8f2e8cf commit e0cd6f4

File tree

5 files changed

+133
-7
lines changed

5 files changed

+133
-7
lines changed

mysql-test/r/cte_nonrecursive.result

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1079,3 +1079,52 @@ id select_type table type possible_keys key key_len ref rows Extra
10791079
3 DERIVED t2 ALL NULL NULL NULL NULL 3 Using where; Using join buffer (flat, BNL join)
10801080
NULL UNION RESULT <union1,4> ALL NULL NULL NULL NULL NULL
10811081
DROP TABLE t1,t2;
1082+
#
1083+
# MDEV-13780: tower of embedding CTEs with multiple usage of them
1084+
#
1085+
create table t1 (a int);
1086+
insert into t1 values (3), (2), (4), (7), (1), (2), (5);
1087+
with cte_e as
1088+
(
1089+
with cte_o as
1090+
(
1091+
with cte_i as (select * from t1 where a < 7)
1092+
select * from cte_i where a > 1
1093+
)
1094+
select * from cte_o as cto_o1 where a < 3
1095+
union
1096+
select * from cte_o as cto_o2 where a > 4
1097+
)
1098+
select * from cte_e as cte_e1 where a > 1
1099+
union
1100+
select * from cte_e as cte_e2;
1101+
a
1102+
2
1103+
5
1104+
explain extended with cte_e as
1105+
(
1106+
with cte_o as
1107+
(
1108+
with cte_i as (select * from t1 where a < 7)
1109+
select * from cte_i where a > 1
1110+
)
1111+
select * from cte_o as cto_o1 where a < 3
1112+
union
1113+
select * from cte_o as cto_o2 where a > 4
1114+
)
1115+
select * from cte_e as cte_e1 where a > 1
1116+
union
1117+
select * from cte_e as cte_e2;
1118+
id select_type table type possible_keys key key_len ref rows filtered Extra
1119+
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 14 100.00 Using where
1120+
2 DERIVED t1 ALL NULL NULL NULL NULL 7 100.00 Using where
1121+
5 UNION t1 ALL NULL NULL NULL NULL 7 100.00 Using where
1122+
NULL UNION RESULT <union2,5> ALL NULL NULL NULL NULL NULL NULL
1123+
6 UNION <derived9> ALL NULL NULL NULL NULL 14 100.00
1124+
9 DERIVED t1 ALL NULL NULL NULL NULL 7 100.00 Using where
1125+
12 UNION t1 ALL NULL NULL NULL NULL 7 100.00 Using where
1126+
NULL UNION RESULT <union9,12> ALL NULL NULL NULL NULL NULL NULL
1127+
NULL UNION RESULT <union1,6> ALL NULL NULL NULL NULL NULL NULL
1128+
Warnings:
1129+
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`
1130+
drop table t1;

mysql-test/r/cte_recursive.result

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2875,3 +2875,25 @@ f
28752875
2
28762876
set standard_compliant_cte=default;
28772877
DROP TABLE t;
2878+
#
2879+
# mdev-14184: recursive CTE embedded into CTE with multiple references
2880+
#
2881+
WITH
2882+
cte1 AS (
2883+
SELECT n FROM (
2884+
WITH RECURSIVE rec_cte(n) AS (
2885+
SELECT 1 as n1
2886+
UNION ALL
2887+
SELECT n+1 as n2 FROM rec_cte WHERE n < 3
2888+
) SELECT n FROM rec_cte
2889+
) AS X
2890+
),
2891+
cte2 as (
2892+
SELECT 2 FROM cte1
2893+
)
2894+
SELECT *
2895+
FROM cte1;
2896+
n
2897+
1
2898+
2
2899+
3

mysql-test/t/cte_nonrecursive.test

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -743,3 +743,31 @@ eval $q;
743743
eval explain $q;
744744

745745
DROP TABLE t1,t2;
746+
747+
--echo #
748+
--echo # MDEV-13780: tower of embedding CTEs with multiple usage of them
749+
--echo #
750+
751+
create table t1 (a int);
752+
insert into t1 values (3), (2), (4), (7), (1), (2), (5);
753+
754+
let $q=
755+
with cte_e as
756+
(
757+
with cte_o as
758+
(
759+
with cte_i as (select * from t1 where a < 7)
760+
select * from cte_i where a > 1
761+
)
762+
select * from cte_o as cto_o1 where a < 3
763+
union
764+
select * from cte_o as cto_o2 where a > 4
765+
)
766+
select * from cte_e as cte_e1 where a > 1
767+
union
768+
select * from cte_e as cte_e2;
769+
770+
eval $q;
771+
eval explain extended $q;
772+
773+
drop table t1;

mysql-test/t/cte_recursive.test

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1928,3 +1928,22 @@ set standard_compliant_cte=default;
19281928

19291929
DROP TABLE t;
19301930

1931+
--echo #
1932+
--echo # mdev-14184: recursive CTE embedded into CTE with multiple references
1933+
--echo #
1934+
1935+
WITH
1936+
cte1 AS (
1937+
SELECT n FROM (
1938+
WITH RECURSIVE rec_cte(n) AS (
1939+
SELECT 1 as n1
1940+
UNION ALL
1941+
SELECT n+1 as n2 FROM rec_cte WHERE n < 3
1942+
) SELECT n FROM rec_cte
1943+
) AS X
1944+
),
1945+
cte2 as (
1946+
SELECT 2 FROM cte1
1947+
)
1948+
SELECT *
1949+
FROM cte1;

sql/sql_cte.cc

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,10 @@ void With_element::check_dependencies_in_select(st_select_lex *sl,
349349
/* Now look for the dependencies in the subqueries of sl */
350350
st_select_lex_unit *inner_unit= sl->first_inner_unit();
351351
for (; inner_unit; inner_unit= inner_unit->next_unit())
352-
check_dependencies_in_unit(inner_unit, ctxt, in_subq, dep_map);
352+
{
353+
if (!inner_unit->with_element)
354+
check_dependencies_in_unit(inner_unit, ctxt, in_subq, dep_map);
355+
}
353356
}
354357

355358

@@ -838,7 +841,6 @@ st_select_lex_unit *With_element::clone_parsed_spec(THD *thd,
838841
with_table->next_global= spec_tables;
839842
}
840843
res= &lex->unit;
841-
res->set_with_clause(owner);
842844

843845
lex->unit.include_down(with_table->select_lex);
844846
lex->unit.set_slave(with_select);
@@ -847,6 +849,8 @@ st_select_lex_unit *With_element::clone_parsed_spec(THD *thd,
847849
insert_chain_before(
848850
(st_select_lex_node **) &(old_lex->all_selects_list),
849851
with_select));
852+
if (check_dependencies_in_with_clauses(lex->with_clauses_list))
853+
res= NULL;
850854
lex_end(lex);
851855
err:
852856
if (arena)
@@ -990,14 +994,18 @@ With_element *st_select_lex::find_table_def_in_with_clauses(TABLE_LIST *table)
990994
and it was unsuccesful. Yet for units cloned from the spec it has not
991995
been done yet.
992996
*/
993-
if (with_elem && sl->master_unit() == with_elem->spec)
997+
With_clause *attached_with_clause=sl->get_with_clause();
998+
if (attached_with_clause &&
999+
(found= attached_with_clause->find_table_def(table, NULL)))
9941000
break;
995-
With_clause *with_clause=sl->get_with_clause();
996-
if (with_clause)
1001+
if (with_elem)
9971002
{
998-
With_element *barrier= with_clause->with_recursive ? NULL : with_elem;
999-
if ((found= with_clause->find_table_def(table, barrier)))
1003+
With_clause *containing_with_clause= with_elem->get_owner();
1004+
With_element *barrier= containing_with_clause->with_recursive ?
1005+
NULL : with_elem;
1006+
if ((found= containing_with_clause->find_table_def(table, barrier)))
10001007
break;
1008+
sl= sl->master_unit()->outer_select();
10011009
}
10021010
master_unit= sl->master_unit();
10031011
/* Do not look for the table's definition beyond the scope of the view */

0 commit comments

Comments
 (0)