Skip to content

Commit 93dd70c

Browse files
committed
Fixed bug mdev-12375.
The function st_select_lex_unit::exec_recursive() incorrectly determined that a CTE mutually recursive with some others was stabilized in the case when the non-recursive part of the CTE returned an empty set. As a result the server fell into an infinite loop when executing a query using this CTE.
1 parent 046d442 commit 93dd70c

File tree

3 files changed

+126
-2
lines changed

3 files changed

+126
-2
lines changed

mysql-test/r/cte_recursive.result

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2488,3 +2488,64 @@ where module_arguments.m is null
24882488
select * from reached_values;
24892489
ERROR HY000: Restrictions imposed on recursive definitions are violated for table 'applied_modules'
24902490
drop table value_nodes, module_nodes, module_arguments, module_results;
2491+
#
2492+
# mdev-12375: query using one of two mutually recursive CTEs
2493+
# whose non-recursive part returns an empty set
2494+
#
2495+
create table value_nodes (v char(4));
2496+
insert into value_nodes values
2497+
('v1'), ('v2'), ('v3'), ('v4'), ('v5'), ('v6'), ('v7'), ('v8'), ('v9'),
2498+
('v10'), ('v11'), ('v12'), ('v13'), ('v14'), ('v15'), ('v16');
2499+
create table module_nodes(m char(4));
2500+
insert into module_nodes values
2501+
('m1'), ('m2'), ('m3'), ('m4'), ('m5'), ('m6'), ('m7');
2502+
create table module_arguments(m char(4), v char(4));
2503+
insert into module_arguments values
2504+
('m1','v3'), ('m1','v9'),
2505+
('m2','v4'), ('m2','v3'), ('m2','v7'),
2506+
('m3','v6'),
2507+
('m4','v4'), ('m4','v1'),
2508+
('m5','v10'), ('m5','v8'), ('m5','v3'),
2509+
('m6','v8'), ('m6','v1'),
2510+
('m7','v11'), ('m7','v12');
2511+
create table module_results(m char(4), v char(4));
2512+
insert into module_results values
2513+
('m1','v4'),
2514+
('m2','v1'), ('m2','v6'),
2515+
('m3','v10'),
2516+
('m4','v8'),
2517+
('m5','v11'), ('m5','v9'),
2518+
('m6','v12'), ('m6','v4'),
2519+
('m7','v2');
2520+
set statement max_recursive_iterations=2, standard_compliant_cte=0 for
2521+
with recursive
2522+
reached_values as
2523+
(
2524+
select v from value_nodes where v in ('v3','v7','v9')
2525+
union
2526+
select module_results.v from module_results, applied_modules
2527+
where module_results.m = applied_modules.m
2528+
),
2529+
applied_modules as
2530+
(
2531+
select * from module_nodes where 1=0
2532+
union
2533+
select module_nodes.m
2534+
from
2535+
module_nodes
2536+
left join
2537+
(
2538+
module_arguments
2539+
left join
2540+
reached_values
2541+
on module_arguments.v = reached_values.v
2542+
)
2543+
on reached_values.v is null and
2544+
module_nodes.m = module_arguments.m
2545+
where module_arguments.m is null
2546+
)
2547+
select * from applied_modules;
2548+
m
2549+
m1
2550+
m2
2551+
drop table value_nodes, module_nodes, module_arguments, module_results;

mysql-test/t/cte_recursive.test

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1597,4 +1597,67 @@ applied_modules as
15971597
)
15981598
select * from reached_values;
15991599

1600-
drop table value_nodes, module_nodes, module_arguments, module_results;
1600+
drop table value_nodes, module_nodes, module_arguments, module_results;
1601+
1602+
--echo #
1603+
--echo # mdev-12375: query using one of two mutually recursive CTEs
1604+
--echo # whose non-recursive part returns an empty set
1605+
--echo #
1606+
1607+
create table value_nodes (v char(4));
1608+
insert into value_nodes values
1609+
('v1'), ('v2'), ('v3'), ('v4'), ('v5'), ('v6'), ('v7'), ('v8'), ('v9'),
1610+
('v10'), ('v11'), ('v12'), ('v13'), ('v14'), ('v15'), ('v16');
1611+
create table module_nodes(m char(4));
1612+
insert into module_nodes values
1613+
('m1'), ('m2'), ('m3'), ('m4'), ('m5'), ('m6'), ('m7');
1614+
create table module_arguments(m char(4), v char(4));
1615+
insert into module_arguments values
1616+
('m1','v3'), ('m1','v9'),
1617+
('m2','v4'), ('m2','v3'), ('m2','v7'),
1618+
('m3','v6'),
1619+
('m4','v4'), ('m4','v1'),
1620+
('m5','v10'), ('m5','v8'), ('m5','v3'),
1621+
('m6','v8'), ('m6','v1'),
1622+
('m7','v11'), ('m7','v12');
1623+
create table module_results(m char(4), v char(4));
1624+
insert into module_results values
1625+
('m1','v4'),
1626+
('m2','v1'), ('m2','v6'),
1627+
('m3','v10'),
1628+
('m4','v8'),
1629+
('m5','v11'), ('m5','v9'),
1630+
('m6','v12'), ('m6','v4'),
1631+
('m7','v2');
1632+
1633+
set statement max_recursive_iterations=2, standard_compliant_cte=0 for
1634+
with recursive
1635+
reached_values as
1636+
(
1637+
select v from value_nodes where v in ('v3','v7','v9')
1638+
union
1639+
select module_results.v from module_results, applied_modules
1640+
where module_results.m = applied_modules.m
1641+
),
1642+
applied_modules as
1643+
(
1644+
select * from module_nodes where 1=0
1645+
union
1646+
select module_nodes.m
1647+
from
1648+
module_nodes
1649+
left join
1650+
(
1651+
module_arguments
1652+
left join
1653+
reached_values
1654+
on module_arguments.v = reached_values.v
1655+
)
1656+
on reached_values.v is null and
1657+
module_nodes.m = module_arguments.m
1658+
where module_arguments.m is null
1659+
)
1660+
select * from applied_modules;
1661+
1662+
drop table value_nodes, module_nodes, module_arguments, module_results;
1663+

sql/sql_union.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1247,7 +1247,7 @@ bool st_select_lex_unit::exec_recursive()
12471247
thd->inc_examined_row_count(examined_rows);
12481248

12491249
incr_table->file->info(HA_STATUS_VARIABLE);
1250-
if (incr_table->file->stats.records == 0)
1250+
if (with_element->level && incr_table->file->stats.records == 0)
12511251
with_element->set_as_stabilized();
12521252
else
12531253
with_element->level++;

0 commit comments

Comments
 (0)