Commit ad7da60d authored by Igor Babaev's avatar Igor Babaev

Fixed bug mdev-12368.

Mutually recursive CTE could cause a crash of the server in the case
when they were not Standard compliant. The crash happened in
mysql_derived_prepare(), because the destructor the derived_result
object created for a CTE that was mutually recursive with some others
was called twice. Yet this destructor should not be called for resursive
references.
parent 5a4537f0
......@@ -2453,3 +2453,38 @@ id name dob father mother
8 Grandpa Ben 1940-10-21 NULL NULL
6 Grandgrandma Martha 1923-05-17 NULL NULL
drop table folks;
#
# mdev-12368: crash with mutually recursive CTE
# that arenot Standard compliant
#
create table value_nodes (v char(4));
create table module_nodes(m char(4));
create table module_arguments(m char(4), v char(4));
create table module_results(m char(4), v char(4));
with recursive
reached_values as
(
select v from value_nodes where v in ('v3','v7','v9')
union
select module_results.v from module_results, applied_modules
where module_results.m = applied_modules.m
),
applied_modules as
(
select module_nodes.m
from
module_nodes
left join
(
module_arguments
left join
reached_values
on module_arguments.v = reached_values.v
)
on reached_values.v is null and
module_nodes.m = module_arguments.m
where module_arguments.m is null
)
select * from reached_values;
ERROR HY000: Restrictions imposed on recursive definitions are violated for table 'applied_modules'
drop table value_nodes, module_nodes, module_arguments, module_results;
......@@ -1559,3 +1559,42 @@ as
select * from ancestors;
drop table folks;
--echo #
--echo # mdev-12368: crash with mutually recursive CTE
--echo # that arenot Standard compliant
--echo #
create table value_nodes (v char(4));
create table module_nodes(m char(4));
create table module_arguments(m char(4), v char(4));
create table module_results(m char(4), v char(4));
--ERROR ER_NOT_STANDARD_COMPLIANT_RECURSIVE
with recursive
reached_values as
(
select v from value_nodes where v in ('v3','v7','v9')
union
select module_results.v from module_results, applied_modules
where module_results.m = applied_modules.m
),
applied_modules as
(
select module_nodes.m
from
module_nodes
left join
(
module_arguments
left join
reached_values
on module_arguments.v = reached_values.v
)
on reached_values.v is null and
module_nodes.m = module_arguments.m
where module_arguments.m is null
)
select * from reached_values;
drop table value_nodes, module_nodes, module_arguments, module_results;
\ No newline at end of file
......@@ -789,9 +789,12 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *derived)
*/
if (res)
{
if (derived->table && !derived->is_with_table_recursive_reference())
free_tmp_table(thd, derived->table);
delete derived->derived_result;
if (!derived->is_with_table_recursive_reference())
{
if (derived->table)
free_tmp_table(thd, derived->table);
delete derived->derived_result;
}
}
else
{
......
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