Skip to content

Commit

Permalink
MDEV-31661: Assertion `thd->lex == sp_instr_lex' failed in LEX* sp_le…
Browse files Browse the repository at this point in the history
…x_instr::parse_expr(THD*, sp_head*, LEX*)

This is the follow-up patch for the task MDEV-5816 that fixes assert failure
that happened after recompilation of a stored routine containing a cursor
on its second execution.

The reason of assertion hit is that a state of the SP instruction sp_instr_cpush
wasn't reset after its SQL statement re-compiled.

To fix the issue the virtual method sp_lex_instr::on_after_expr_parsing
is overridden in the derived class sp_instr_cpush. Implementation of this method
does resetting of the data member sp_instr_cpush::m_metadata_changed

Additionally, implementation of the method
 sp_instr_set_trigger_field::on_after_expr_parsing
has been slightly modified to set the data member
 sp_instr_set_trigger_field::value
just before successful return. This data member is used to check whether this
SP instruction is still valid or should be re-compiled.
Resetting this data member before an instance of the class Item_trigger_field
be successfully allocated theoretically could lead to clearing of instruction's
state despite the fact that memory allocation was failed.
  • Loading branch information
dmitryshulga committed Jul 20, 2023
1 parent 856196e commit 2992d53
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 3 deletions.
21 changes: 21 additions & 0 deletions mysql-test/main/sp_validation.result
Original file line number Diff line number Diff line change
Expand Up @@ -1890,4 +1890,25 @@ SET @@debug_dbug=@orig_dbug;
DROP TABLE t1;
DROP TABLE t2;
DROP VIEW v1;
#
# MDEV-31661: Assertion `thd->lex == sp_instr_lex' failed in LEX* sp_lex_instr::parse_expr(THD*, sp_head*, LEX*)
#
CREATE OR REPLACE PROCEDURE p1()
BEGIN
DECLARE c CURSOR FOR SELECT * FROM t1;
OPEN c;
CLOSE c;
END;
$
CALL p1;
ERROR 42S02: Table 'test.t1' doesn't exist
CREATE TABLE t1 (id INT);
CALL p1;
# Second execution of the stored procedure p1() after the dependent
# table t1 has been created resulted in assert failure for server built
# with debug
CALL p1;
# Clean up
DROP PROCEDURE p1;
DROP TABLE t1;
SET sql_mode = default;
31 changes: 31 additions & 0 deletions mysql-test/main/sp_validation.test
Original file line number Diff line number Diff line change
Expand Up @@ -2682,4 +2682,35 @@ SET @@debug_dbug=@orig_dbug;
DROP TABLE t1;
DROP TABLE t2;
DROP VIEW v1;

--echo #
--echo # MDEV-31661: Assertion `thd->lex == sp_instr_lex' failed in LEX* sp_lex_instr::parse_expr(THD*, sp_head*, LEX*)
--echo #

--delimiter $

CREATE OR REPLACE PROCEDURE p1()
BEGIN
DECLARE c CURSOR FOR SELECT * FROM t1;
OPEN c;
CLOSE c;
END;
$

--delimiter ;

--error ER_NO_SUCH_TABLE
CALL p1;
CREATE TABLE t1 (id INT);

CALL p1;
--echo # Second execution of the stored procedure p1() after the dependent
--echo # table t1 has been created resulted in assert failure for server built
--echo # with debug
CALL p1;

--echo # Clean up
DROP PROCEDURE p1;
DROP TABLE t1;

SET sql_mode = default;
8 changes: 5 additions & 3 deletions sql/sp_instr.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1209,20 +1209,22 @@ bool sp_instr_set_trigger_field::on_after_expr_parsing(THD *thd)
{
DBUG_ASSERT(thd->lex->current_select->item_list.elements == 1);

value= thd->lex->current_select->item_list.head();
DBUG_ASSERT(value != nullptr);
Item *val= thd->lex->current_select->item_list.head();
DBUG_ASSERT(val != nullptr);

trigger_field = new (thd->mem_root)
Item_trigger_field(thd, thd->lex->current_context(),
Item_trigger_field::NEW_ROW,
m_trigger_field_name, UPDATE_ACL, false);

if (!value || !trigger_field)
if (!val || !trigger_field)
return true;

thd->spcont->m_sp->m_cur_instr_trig_field_items.link_in_list(
trigger_field, &trigger_field->next_trg_field);

value= val;

return false;
}

Expand Down
6 changes: 6 additions & 0 deletions sql/sp_instr.h
Original file line number Diff line number Diff line change
Expand Up @@ -1238,6 +1238,12 @@ class sp_instr_cpush : public sp_lex_instr, public sp_cursor
return m_cursor_stmt;
}

bool on_after_expr_parsing(THD *) override
{
m_metadata_changed= false;
return false;
}

private:
uint m_cursor; /**< Frame offset (for debugging) */
/**
Expand Down

0 comments on commit 2992d53

Please sign in to comment.