Commit 2992d531 authored by Dmitry Shulga's avatar Dmitry Shulga

MDEV-31661: Assertion `thd->lex == sp_instr_lex' failed in LEX*...

MDEV-31661: Assertion `thd->lex == sp_instr_lex' failed in LEX* sp_lex_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.
parent 856196ea
......@@ -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;
......@@ -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;
......@@ -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;
}
......
......@@ -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) */
/**
......
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