diff --git a/mysql-test/main/sp-cursor.result b/mysql-test/main/sp-cursor.result index f1dd8ed5eaa..42952be16e2 100644 --- a/mysql-test/main/sp-cursor.result +++ b/mysql-test/main/sp-cursor.result @@ -713,3 +713,27 @@ END; $$ CALL p1; DROP PROCEDURE p1; +# +# MDEV-17278 CURSOR FOR LOOP - ERROR: unexpected end of stream, read 0 bytes (SERVER CRASH) +# +CREATE TABLE t1 (id2 int, id int, en1 enum('aaa','a','b','c')); +INSERT INTO t1 VALUES(1,1,'aaa'),(2,2,'a'),(3,3,'b'),(4,4,'c'); +CREATE PROCEDURE p1() +BEGIN +FOR rec IN (SELECT en1 FROM t1) +DO +SELECT rec.en1; +END FOR; +END; +$$ +CALL p1(); +rec.en1 +aaa +rec.en1 +a +rec.en1 +b +rec.en1 +c +DROP PROCEDURE p1; +DROP TABLE t1; diff --git a/mysql-test/main/sp-cursor.test b/mysql-test/main/sp-cursor.test index 735514ff376..97483ef9caf 100644 --- a/mysql-test/main/sp-cursor.test +++ b/mysql-test/main/sp-cursor.test @@ -723,3 +723,24 @@ $$ DELIMITER ;$$ CALL p1; DROP PROCEDURE p1; + + +--echo # +--echo # MDEV-17278 CURSOR FOR LOOP - ERROR: unexpected end of stream, read 0 bytes (SERVER CRASH) +--echo # + +CREATE TABLE t1 (id2 int, id int, en1 enum('aaa','a','b','c')); +INSERT INTO t1 VALUES(1,1,'aaa'),(2,2,'a'),(3,3,'b'),(4,4,'c'); +DELIMITER $$; +CREATE PROCEDURE p1() +BEGIN + FOR rec IN (SELECT en1 FROM t1) + DO + SELECT rec.en1; + END FOR; +END; +$$ +DELIMITER ;$$ +CALL p1(); +DROP PROCEDURE p1; +DROP TABLE t1; diff --git a/mysql-test/suite/compat/oracle/r/sp-cursor-rowtype.result b/mysql-test/suite/compat/oracle/r/sp-cursor-rowtype.result index 093d52ba4e3..a60bbc38883 100644 --- a/mysql-test/suite/compat/oracle/r/sp-cursor-rowtype.result +++ b/mysql-test/suite/compat/oracle/r/sp-cursor-rowtype.result @@ -1479,3 +1479,28 @@ f1() 1 DROP FUNCTION f1; DROP TABLE t1; +# +# MDEV-17278 CURSOR FOR LOOP - ERROR: unexpected end of stream, read 0 bytes (SERVER CRASH) +# +CREATE TABLE t1 (id2 int, id int, en1 enum('aaa','a','b','c')); +INSERT INTO t1 VALUES(1,1,'aaa'),(2,2,'a'),(3,3,'b'),(4,4,'c'); +CREATE PROCEDURE p1() +AS +BEGIN +FOR rec IN (SELECT en1 FROM t1) +LOOP +SELECT rec.en1; +END LOOP; +END; +$$ +CALL p1(); +rec.en1 +aaa +rec.en1 +a +rec.en1 +b +rec.en1 +c +DROP PROCEDURE p1; +DROP TABLE t1; diff --git a/mysql-test/suite/compat/oracle/t/sp-cursor-rowtype.test b/mysql-test/suite/compat/oracle/t/sp-cursor-rowtype.test index 31e28d5c8de..ba0ca9b6a60 100644 --- a/mysql-test/suite/compat/oracle/t/sp-cursor-rowtype.test +++ b/mysql-test/suite/compat/oracle/t/sp-cursor-rowtype.test @@ -1572,3 +1572,26 @@ DELIMITER ;$$ SELECT f1(); DROP FUNCTION f1; DROP TABLE t1; + + +--echo # +--echo # MDEV-17278 CURSOR FOR LOOP - ERROR: unexpected end of stream, read 0 bytes (SERVER CRASH) +--echo # + +CREATE TABLE t1 (id2 int, id int, en1 enum('aaa','a','b','c')); +INSERT INTO t1 VALUES(1,1,'aaa'),(2,2,'a'),(3,3,'b'),(4,4,'c'); + +DELIMITER $$; +CREATE PROCEDURE p1() +AS +BEGIN + FOR rec IN (SELECT en1 FROM t1) + LOOP + SELECT rec.en1; + END LOOP; +END; +$$ +DELIMITER ;$$ +CALL p1(); +DROP PROCEDURE p1; +DROP TABLE t1; diff --git a/sql/sp_head.cc b/sql/sp_head.cc index c8b9576fe88..28411509adf 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -4475,19 +4475,21 @@ sp_instr_cursor_copy_struct::exec_core(THD *thd, uint *nextp) if (!(ret= tmp.open(thd))) { Row_definition_list defs; + /* + Create row elements on the caller arena. + It's the same arena that was used during sp_rcontext::create(). + This puts cursor%ROWTYPE elements on the same mem_root + where explicit ROW elements and table%ROWTYPE reside: + - tmp.export_structure() allocates new Spvar_definition instances + and their components (such as TYPELIBs). + - row->row_create_items() creates new Item_field instances. + They all are created on the same mem_root. + */ + Query_arena current_arena; + thd->set_n_backup_active_arena(thd->spcont->callers_arena, ¤t_arena); if (!(ret= tmp.export_structure(thd, &defs))) - { - /* - Create row elements on the caller arena. - It's the same arena that was used during sp_rcontext::create(). - This puts cursor%ROWTYPE elements on the same mem_root - where explicit ROW elements and table%ROWTYPE reside. - */ - Query_arena current_arena; - thd->set_n_backup_active_arena(thd->spcont->callers_arena, ¤t_arena); row->row_create_items(thd, &defs); - thd->restore_active_arena(thd->spcont->callers_arena, ¤t_arena); - } + thd->restore_active_arena(thd->spcont->callers_arena, ¤t_arena); tmp.close(thd); } }