• Dmitry Shulga's avatar
    MDEV-25006: Failed assertion on executing EXPLAIN DELETE statement as a prepared statement · fc774316
    Dmitry Shulga authored
    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.
    fc774316
ps.test 125 KB