mirror of
https://github.com/MariaDB/server.git
synced 2026-01-06 05:22:24 +03:00
MDEV-23160: SIGSEGV in Explain_node::print_explain_for_children on UNION SELECT
and also MDEV-25564, MDEV-18157.
Attempt to produce EXPLAIN output caused a crash in
Explain_node::print_explain_for_children. The cause of this was that an
Explain_node (actually a derived) had a link to child select#N, but
there was no query plan present for select#N.
The query plan wasn't present because the subquery was eliminated.
- Either it was a degenerate subquery like "(SELECT 1)" in MDEV-25564.
- Or it was a subquery in a UNION subquery's ORDER BY clause:
col IN (SELECT ... UNION
SELECT ... ORDER BY (SELECT FROM t1))
In such cases, legacy code structure in subquery/union processing code(*)
makes it hard to detect that the subquery was eliminated, so we end up
with EXPLAIN data structures (Explain_node::children) having dangling
links to child subqueries.
Do make the checks and don't follow the dangling links.
(In ideal world, we should not have these dangling links. But fixing
the code (*) would have high risk for the stable versions).
This commit is contained in:
@@ -639,7 +639,11 @@ int Explain_node::print_explain_for_children(Explain_query *query,
|
||||
for (int i= 0; i < (int) children.elements(); i++)
|
||||
{
|
||||
Explain_node *node= query->get_node(children.at(i));
|
||||
if (node->print_explain(query, output, explain_flags, is_analyze))
|
||||
/*
|
||||
Note: node may not be present because for certain kinds of subqueries,
|
||||
the optimizer is not able to see that they were eliminated.
|
||||
*/
|
||||
if (node && node->print_explain(query, output, explain_flags, is_analyze))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@@ -683,8 +687,15 @@ void Explain_node::print_explain_json_for_children(Explain_query *query,
|
||||
for (int i= 0; i < (int) children.elements(); i++)
|
||||
{
|
||||
Explain_node *node= query->get_node(children.at(i));
|
||||
/* Derived tables are printed inside Explain_table_access objects */
|
||||
|
||||
/*
|
||||
Note: node may not be present because for certain kinds of subqueries,
|
||||
the optimizer is not able to see that they were eliminated.
|
||||
*/
|
||||
if (!node)
|
||||
continue;
|
||||
|
||||
/* Derived tables are printed inside Explain_table_access objects */
|
||||
if (!is_connection_printable_in_json(node->connection_type))
|
||||
continue;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user