MDEV-33525: Recreate/reuse temporary table

Calling a stored function that uses a cursor inside its body
could produce the error ER_NO_SUCH_TABLE on the second execution
in case the cursor uses multi-table query and one of the tables
is a temporary table just created before querying the cursor and
dropped just after the query has been executed.

The reason for issue is that re-parsing of failed a SP instruction
caused be create/drop of the temporary table used LEX object
left from previous parsing of a SP instruction's query instead
re-initialize the lex object before parsing.

To fix the issue, add initialization of lex for cursor's
statement before re-parsing the query of a failed SP instruction.
This commit is contained in:
Dmitry Shulga 2024-03-18 17:43:16 +07:00
parent 1553a9dd79
commit b620b3949a
3 changed files with 64 additions and 0 deletions

View file

@ -1965,4 +1965,32 @@ b
2
3
DROP TABLE t1, t2;
#
# MDEV-33525: Recreate/reuse temporary table
#
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (1);
CREATE FUNCTION f1()
RETURNS INT
BEGIN
DECLARE res INT;
DECLARE t1_cur CURSOR FOR SELECT 100 FROM t1, t1_tmp;
CREATE TEMPORARY TABLE t1_tmp SELECT 1 a;
OPEN t1_cur;
CLOSE t1_cur;
DROP TEMPORARY TABLE t1_tmp;
RETURN 0;
END
|
SELECT f1();
f1()
0
# Without the patch, the second call of f1 would result in error:
# ER_NO_SUCH_TABLE (1146): Table 'test.t1' doesn't exist
SELECT f1();
f1()
0
# Clean up
DROP FUNCTION f1;
DROP TABLE t1;
SET sql_mode = default;

View file

@ -2760,5 +2760,40 @@ SELECT * FROM t2;
DROP TABLE t1, t2;
--echo #
--echo # MDEV-33525: Recreate/reuse temporary table
--echo #
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (1);
--delimiter |
CREATE FUNCTION f1()
RETURNS INT
BEGIN
DECLARE res INT;
DECLARE t1_cur CURSOR FOR SELECT 100 FROM t1, t1_tmp;
CREATE TEMPORARY TABLE t1_tmp SELECT 1 a;
OPEN t1_cur;
CLOSE t1_cur;
DROP TEMPORARY TABLE t1_tmp;
RETURN 0;
END
|
--delimiter ;
SELECT f1();
--echo # Without the patch, the second call of f1 would result in error:
--echo # ER_NO_SUCH_TABLE (1146): Table 'test.t1' doesn't exist
SELECT f1();
--echo # Clean up
DROP FUNCTION f1;
DROP TABLE t1;
SET sql_mode = default;
--enable_ps2_protocol

View file

@ -754,6 +754,7 @@ 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);
lex_start(thd);
}
thd->lex->sphead= sp;