mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
MDEV-17024 Crash on large query
This problem manifested itself when a join query used two or more materialized CTE such that each of them employed the same recursive CTE. The bug caused a crash. The crash happened because the cleanup() function was performed premature for recursive CTE. This clean up was induced by the cleanup of the first CTE referenced the recusrsive CTE. This cleanup destroyed the structures that would allow to read from the temporary table containing the rows of the recursive CTE and an attempt to read these rows for the second CTE referencing the recursive CTE triggered a crash. The clean up for a recursive CTE R should be performed after the cleanup of the last materialized CTE that uses R.
This commit is contained in:
@ -1337,6 +1337,37 @@ bool st_select_lex_unit::cleanup()
|
||||
{
|
||||
DBUG_RETURN(FALSE);
|
||||
}
|
||||
/*
|
||||
When processing a PS/SP or an EXPLAIN command cleanup of a unit can
|
||||
be performed immediately when the unit is reached in the cleanup
|
||||
traversal initiated by the cleanup of the main unit.
|
||||
*/
|
||||
if (!thd->stmt_arena->is_stmt_prepare() && !thd->lex->describe &&
|
||||
with_element && with_element->is_recursive && union_result)
|
||||
{
|
||||
select_union_recursive *result= with_element->rec_result;
|
||||
if (++result->cleanup_count == with_element->rec_outer_references)
|
||||
{
|
||||
/*
|
||||
Perform cleanup for with_element and for all with elements
|
||||
mutually recursive with it.
|
||||
*/
|
||||
cleaned= 1;
|
||||
with_element->get_next_mutually_recursive()->spec->cleanup();
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
Just increment by 1 cleanup_count for with_element and
|
||||
for all with elements mutually recursive with it.
|
||||
*/
|
||||
With_element *with_elem= with_element;
|
||||
while ((with_elem= with_elem->get_next_mutually_recursive()) !=
|
||||
with_element)
|
||||
with_elem->rec_result->cleanup_count++;
|
||||
DBUG_RETURN(FALSE);
|
||||
}
|
||||
}
|
||||
cleaned= 1;
|
||||
|
||||
for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
|
||||
@ -1367,7 +1398,7 @@ bool st_select_lex_unit::cleanup()
|
||||
|
||||
if (with_element && with_element->is_recursive)
|
||||
{
|
||||
if (union_result )
|
||||
if (union_result)
|
||||
{
|
||||
((select_union_recursive *) union_result)->cleanup();
|
||||
delete union_result;
|
||||
|
Reference in New Issue
Block a user