mirror of
https://github.com/MariaDB/server.git
synced 2025-08-07 00:04:31 +03:00
MDEV-36079: Stored routine with a cursor crashes on the second execution if a DDL statement happened
Attempt to run a cursor after change in metadata of tables it depends on resulted in firing assertion on allocating a memory from a memory root marked as read only. On every execution of a cursor its Query_arena is set up as a statement arena (see sp_lex_keeper::cursor_reset_lex_and_exec_core()). As a consequence, any memory allocations happened on execution of the cursor's query should be taken from the cursor's memory root. The reason of allocating a memory from the memory root marked as read only is that the cursor's memory root points to a memory root of sp_head that could be already marked as read only after first successful execution and this relation isn't changed on re-parsing of the cursor's query. To fix the issue, memory root of cursor is adjusted in the method sp_lex_instr::parse_expr() to point to the new memory root just created for re-parsing of failed query.
This commit is contained in:
@@ -441,3 +441,28 @@ SET @@debug_dbug=@save_dbug;
|
||||
DROP TABLE t1;
|
||||
DROP PROCEDURE p1;
|
||||
# End of 11.2 tests
|
||||
# MDEV-36079: Stored routine with a cursor crashes on
|
||||
# the second execution if a DDL statement happened
|
||||
CREATE OR REPLACE TABLE t1 (a INT);
|
||||
INSERT INTO t1 VALUES (1);
|
||||
CREATE PROCEDURE p1()
|
||||
BEGIN
|
||||
DECLARE va INT DEFAULT 0;
|
||||
DECLARE cur CURSOR FOR SELECT a FROM t1;
|
||||
OPEN cur;
|
||||
FETCH cur INTO va;
|
||||
SELECT va;
|
||||
CLOSE cur;
|
||||
END;
|
||||
$
|
||||
CALL p1;
|
||||
va
|
||||
1
|
||||
ALTER TABLE t1 MODIFY a INT UNSIGNED;
|
||||
CALL p1;
|
||||
va
|
||||
1
|
||||
# Clean up
|
||||
DROP PROCEDURE p1;
|
||||
DROP TABLE t1;
|
||||
# End of 11.8 tests
|
||||
|
@@ -469,3 +469,35 @@ DROP TABLE t1;
|
||||
DROP PROCEDURE p1;
|
||||
|
||||
--echo # End of 11.2 tests
|
||||
|
||||
--echo # MDEV-36079: Stored routine with a cursor crashes on
|
||||
--echo # the second execution if a DDL statement happened
|
||||
CREATE OR REPLACE TABLE t1 (a INT);
|
||||
INSERT INTO t1 VALUES (1);
|
||||
|
||||
--delimiter $
|
||||
CREATE PROCEDURE p1()
|
||||
BEGIN
|
||||
DECLARE va INT DEFAULT 0;
|
||||
DECLARE cur CURSOR FOR SELECT a FROM t1;
|
||||
|
||||
OPEN cur;
|
||||
FETCH cur INTO va;
|
||||
SELECT va;
|
||||
CLOSE cur;
|
||||
END;
|
||||
$
|
||||
|
||||
--delimiter ;
|
||||
|
||||
CALL p1;
|
||||
|
||||
ALTER TABLE t1 MODIFY a INT UNSIGNED;
|
||||
|
||||
CALL p1;
|
||||
|
||||
--echo # Clean up
|
||||
DROP PROCEDURE p1;
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo # End of 11.8 tests
|
||||
|
@@ -862,6 +862,13 @@ LEX* sp_lex_instr::parse_expr(THD *thd, sp_head *sp, LEX *sp_instr_lex)
|
||||
cleanup_items(cursor_lex->free_list);
|
||||
cursor_free_list= &cursor_lex->free_list;
|
||||
DBUG_ASSERT(thd->lex == sp_instr_lex);
|
||||
/*
|
||||
Adjust mem_root of the cursor's Query_arena to point the just created
|
||||
memory root allocated for re-parsing, else we would have the pointer to
|
||||
sp_head's memory_root that has already been marked as read_only after
|
||||
the first successful execution of the stored routine.
|
||||
*/
|
||||
cursor_lex->query_arena()->mem_root= m_mem_root_for_reparsing;
|
||||
lex_start(thd);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user