diff options
author | Sergei Petrunia <sergey@mariadb.com> | 2022-10-21 12:04:00 +0300 |
---|---|---|
committer | Sergei Petrunia <sergey@mariadb.com> | 2022-10-21 18:08:05 +0300 |
commit | 6bc2e9338127cf9e97fa76cc97ab23f9c929991b (patch) | |
tree | 8e95d38fe2ab7b7a1be22e9249fe9bc4ef45c68a /sql/sql_explain.cc | |
parent | 0c06320ae9a78996c28539ac310ad4fbf9d419bb (diff) | |
download | mariadb-git-6bc2e9338127cf9e97fa76cc97ab23f9c929991b.tar.gz |
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).
Diffstat (limited to 'sql/sql_explain.cc')
-rw-r--r-- | sql/sql_explain.cc | 15 |
1 files changed, 13 insertions, 2 deletions
diff --git a/sql/sql_explain.cc b/sql/sql_explain.cc index 8690a4a38bb..1ac17de2663 100644 --- a/sql/sql_explain.cc +++ b/sql/sql_explain.cc @@ -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; |