mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
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.
This commit is contained in:
@ -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 @@ protected:
|
||||
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) */
|
||||
/**
|
||||
|
Reference in New Issue
Block a user