Skip to content

Commit fbc1cc9

Browse files
committed
MDEV-26009 Server crash when calling twice procedure using FOR-loop
The problem was that instructions sp_instr_cursor_copy_struct and sp_instr_copen uses the same lex, adding and removing "tail" of prelocked tables and forgetting that tail of all tables is kept in LEX::query_tables_last. If the LEX used only by one instruction or the query do not have prelocked tables it is not important. But to work correctly in all cases LEX::query_tables_last should be reset to make new tables added in the correct list (after last table in the LEX instead after last table of the prelocking "tail" which was cut).
1 parent cf86580 commit fbc1cc9

File tree

3 files changed

+120
-0
lines changed

3 files changed

+120
-0
lines changed

mysql-test/main/sp-cursor.result

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -737,3 +737,66 @@ rec.en1
737737
c
738738
DROP PROCEDURE p1;
739739
DROP TABLE t1;
740+
#
741+
# MDEV-26009: Server crash when calling twice procedure using FOR-loop
742+
#
743+
CREATE TABLE t1 ( id int, name varchar(24));
744+
INSERT INTO t1 values (1, 'x'), (2, 'y'), (3, 'z');
745+
create function get_name(_id int) returns varchar(24)
746+
return (select name from t1 where id = _id);
747+
select get_name(id) from t1;
748+
get_name(id)
749+
x
750+
y
751+
z
752+
create procedure test_proc()
753+
begin
754+
declare _cur cursor for select get_name(id) from t1;
755+
for row in _cur do select 1; end for;
756+
end;
757+
^^
758+
call test_proc();
759+
1
760+
1
761+
1
762+
1
763+
1
764+
1
765+
call test_proc();
766+
1
767+
1
768+
1
769+
1
770+
1
771+
1
772+
drop procedure test_proc;
773+
drop function get_name;
774+
drop table t1;
775+
CREATE TABLE t1 (id int, name varchar(24));
776+
INSERT INTO t1 (id, name) VALUES (1, 'x'),(2, 'y'),(3, 'z');
777+
create function get_name(_id int) returns varchar(24)
778+
return (select name from t1 where id = _id);
779+
create view v1 as select get_name(id) from t1;
780+
create procedure test_proc()
781+
begin
782+
declare _cur cursor for select 1 from v1;
783+
for row in _cur do select 1; end for;
784+
end$$
785+
call test_proc();
786+
1
787+
1
788+
1
789+
1
790+
1
791+
1
792+
call test_proc();
793+
1
794+
1
795+
1
796+
1
797+
1
798+
1
799+
drop procedure test_proc;
800+
drop view v1;
801+
drop function get_name;
802+
drop table t1;

mysql-test/main/sp-cursor.test

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -744,3 +744,59 @@ DELIMITER ;$$
744744
CALL p1();
745745
DROP PROCEDURE p1;
746746
DROP TABLE t1;
747+
748+
749+
--echo #
750+
--echo # MDEV-26009: Server crash when calling twice procedure using FOR-loop
751+
--echo #
752+
753+
754+
CREATE TABLE t1 ( id int, name varchar(24));
755+
INSERT INTO t1 values (1, 'x'), (2, 'y'), (3, 'z');
756+
757+
create function get_name(_id int) returns varchar(24)
758+
return (select name from t1 where id = _id);
759+
760+
select get_name(id) from t1;
761+
762+
delimiter ^^;
763+
764+
create procedure test_proc()
765+
begin
766+
declare _cur cursor for select get_name(id) from t1;
767+
for row in _cur do select 1; end for;
768+
end;
769+
^^
770+
delimiter ;^^
771+
772+
call test_proc();
773+
call test_proc();
774+
775+
drop procedure test_proc;
776+
drop function get_name;
777+
drop table t1;
778+
779+
780+
CREATE TABLE t1 (id int, name varchar(24));
781+
INSERT INTO t1 (id, name) VALUES (1, 'x'),(2, 'y'),(3, 'z');
782+
783+
create function get_name(_id int) returns varchar(24)
784+
return (select name from t1 where id = _id);
785+
786+
create view v1 as select get_name(id) from t1;
787+
788+
delimiter $$;
789+
create procedure test_proc()
790+
begin
791+
declare _cur cursor for select 1 from v1;
792+
for row in _cur do select 1; end for;
793+
end$$
794+
delimiter ;$$
795+
796+
call test_proc();
797+
call test_proc();
798+
799+
drop procedure test_proc;
800+
drop view v1;
801+
drop function get_name;
802+
drop table t1;

sql/sp_head.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3486,6 +3486,7 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp,
34863486
lex_query_tables_own_last= m_lex->query_tables_own_last;
34873487
prelocking_tables= *lex_query_tables_own_last;
34883488
*lex_query_tables_own_last= NULL;
3489+
m_lex->query_tables_last= m_lex->query_tables_own_last;
34893490
m_lex->mark_as_requiring_prelocking(NULL);
34903491
}
34913492
thd->rollback_item_tree_changes();

0 commit comments

Comments
 (0)