Commit fc774316 authored by Dmitry Shulga's avatar Dmitry Shulga

MDEV-25006: Failed assertion on executing EXPLAIN DELETE statement as a prepared statement

Attempt to execute EXPLAIN statement on multi-table DELETE statement
leads to firing firing of the assertion
  DBUG_ASSERT(! is_set());
in the method Diagnostics_area::set_eof_status.

For example, above mentioned assertion failure happens
in case any of the following statements
  EXPLAIN DELETE FROM t1.* USING t1
  EXPLAIN DELETE b FROM t1 AS a JOIN t1 AS b
are executed in prepared statement mode provided the table t1
does exist.

This assertion is hit by the reason that a status of
Diagnostics_area is set twice. The first time it is set from
the function do_select() when the method multi_delete::send_eof()
called. The second time it is set when the method
Explain_query::send_explain() calls the method select_send::send_eof
(this method invokes the method Diagnostics_area::set_eof_status that
finally hits assertion)

The second invocation for a setter method of the class Diagnostics_area
is correct and run to send a response containing explain data.

But first invocation of a setter method of the class Diagnostics_area
is wrong since the function do_select() shouldn't be called at all
for handling of the EXPLAIN statement.

The reason by that the function do_select() is called during handling of
the EXPLAIN statement is that the flag SELECT_DESCRIBE not set in the
data member JOIN::select_options. The flag SELECT_DESCRIBE
if is copied from values select_lex->options.

During parsing of EXPLAIN statement this flag is set but latter reset
from the function reinit_stmt_before_use() that is called on
execution of prepared statement.
  void reinit_stmt_before_use(THD *thd, LEX *lex)
  {
    ...
    for (; sl; sl= sl->next_select_in_list())
    {
      if (sl->changed_elements & TOUCHED_SEL_COND)
      {
        /* remove option which was put by mysql_explain_union() */
        sl->options&= ~SELECT_DESCRIBE;
      ...
      }
   ...
  }

So, to fix the issue the flag SELECT_DESCRIBE is set forcibly at the
mysql_select() function in case thd->lex->describe set,
that is in case EXPLAIN being executed.
parent dd9e5827
...@@ -5402,5 +5402,22 @@ EXISTS(SELECT 1 FROM t1 GROUP BY a IN (select a from t1)) ...@@ -5402,5 +5402,22 @@ EXISTS(SELECT 1 FROM t1 GROUP BY a IN (select a from t1))
0 0
DROP TABLE t1; DROP TABLE t1;
# #
# MDEV-25006: Failed assertion on executing EXPLAIN DELETE statement as a prepared statement
#
CREATE TABLE t1(c1 CHAR(255) PRIMARY KEY);
PREPARE stmt FROM 'EXPLAIN DELETE b FROM t1 AS a JOIN t1 AS b';
EXECUTE stmt;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE a system NULL NULL NULL NULL 0 const row not found
1 SIMPLE b system NULL NULL NULL NULL 0 const row not found
DROP TABLE t1;
CREATE TABLE t1(a INT);
PREPARE stmt FROM 'EXPLAIN DELETE FROM t1.* USING t1';
EXECUTE stmt;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 system NULL NULL NULL NULL 0 const row not found
DEALLOCATE PREPARE stmt;
DROP TABLE t1;
#
# End of 10.2 tests # End of 10.2 tests
# #
...@@ -4912,6 +4912,20 @@ EXECUTE stmt; ...@@ -4912,6 +4912,20 @@ EXECUTE stmt;
EXECUTE stmt; EXECUTE stmt;
DROP TABLE t1; DROP TABLE t1;
--echo #
--echo # MDEV-25006: Failed assertion on executing EXPLAIN DELETE statement as a prepared statement
--echo #
CREATE TABLE t1(c1 CHAR(255) PRIMARY KEY);
PREPARE stmt FROM 'EXPLAIN DELETE b FROM t1 AS a JOIN t1 AS b';
EXECUTE stmt;
DROP TABLE t1;
CREATE TABLE t1(a INT);
PREPARE stmt FROM 'EXPLAIN DELETE FROM t1.* USING t1';
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
DROP TABLE t1;
--echo # --echo #
--echo # End of 10.2 tests --echo # End of 10.2 tests
--echo # --echo #
...@@ -3801,6 +3801,9 @@ mysql_select(THD *thd, ...@@ -3801,6 +3801,9 @@ mysql_select(THD *thd,
} }
else else
{ {
if (thd->lex->describe)
select_options|= SELECT_DESCRIBE;
/* /*
When in EXPLAIN, delay deleting the joins so that they are still When in EXPLAIN, delay deleting the joins so that they are still
available when we're producing EXPLAIN EXTENDED warning text. available when we're producing EXPLAIN EXTENDED warning text.
......
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