summaryrefslogtreecommitdiff
path: root/sql/sql_explain.cc
diff options
context:
space:
mode:
authorSergei Petrunia <sergey@mariadb.com>2022-10-21 12:04:00 +0300
committerSergei Petrunia <sergey@mariadb.com>2022-10-21 18:08:05 +0300
commit6bc2e9338127cf9e97fa76cc97ab23f9c929991b (patch)
tree8e95d38fe2ab7b7a1be22e9249fe9bc4ef45c68a /sql/sql_explain.cc
parent0c06320ae9a78996c28539ac310ad4fbf9d419bb (diff)
downloadmariadb-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.cc15
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;