Commit 400de202 authored by Alexander Barkov's avatar Alexander Barkov

MDEV-12209 sql_mode=ORACLE: Syntax error in a OPEN cursor with parameters makes the server crash

The bug was introduced in the patch for "MDEV-10597 Cursors with parameters".
The LEX created in assignment_source_expr was not put into
thd->lex->sphead->m_lex (the stack of LEX'es), so syntax error in "expr"
caused a wrong memory cleanup in sp_head::~sp_head().

The fix changes the code to use sp_head::push_lex() followed by
sp_head::restore_lex(), like it happens in all other similar cases.
parent 7ca2f816
......@@ -753,6 +753,32 @@ DROP PROCEDURE p1;
# End of MDEV-10597 Cursors with parameters
#
#
# MDEV-12209 sql_mode=ORACLE: Syntax error in a OPEN cursor with parameters makes the server crash
#
CREATE TABLE t1 (a INT, b VARCHAR(10));
INSERT INTO t1 VALUES (1,'A');
CREATE PROCEDURE p1(a INT,b VARCHAR)
AS
CURSOR c (p_a INT, p_b VARCHAR) IS SELECT * FROM t1 WHERE a=p_a;
BEGIN
OPEN c(a+, b);
LOOP
FETCH c INTO a, b;
EXIT WHEN c%NOTFOUND;
SELECT a, b;
END LOOP;
CLOSE c;
END;
$$
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ' b);
LOOP
FETCH c INTO a, b;
EXIT WHEN c%NOTFOUND;
SELECT a, b;
END LOOP;
CLOSE ' at line 5
DROP TABLE t1;
#
# MDEV-10577 sql_mode=ORACLE: %TYPE in variable declarations
#
CREATE TABLE t1 (a INT, b VARCHAR(10),c DATETIME(3));
......
......@@ -751,6 +751,29 @@ DROP PROCEDURE p1;
--echo # End of MDEV-10597 Cursors with parameters
--echo #
--echo #
--echo # MDEV-12209 sql_mode=ORACLE: Syntax error in a OPEN cursor with parameters makes the server crash
--echo #
CREATE TABLE t1 (a INT, b VARCHAR(10));
INSERT INTO t1 VALUES (1,'A');
DELIMITER $$;
--error ER_PARSE_ERROR
CREATE PROCEDURE p1(a INT,b VARCHAR)
AS
CURSOR c (p_a INT, p_b VARCHAR) IS SELECT * FROM t1 WHERE a=p_a;
BEGIN
OPEN c(a+, b);
LOOP
FETCH c INTO a, b;
EXIT WHEN c%NOTFOUND;
SELECT a, b;
END LOOP;
CLOSE c;
END;
$$
DELIMITER ;$$
DROP TABLE t1;
--echo #
--echo # MDEV-10577 sql_mode=ORACLE: %TYPE in variable declarations
......
......@@ -2144,20 +2144,23 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
*/
bool
sp_head::reset_lex(THD *thd)
sp_head::reset_lex(THD *thd, sp_lex_local *sublex)
{
DBUG_ENTER("sp_head::reset_lex");
LEX *oldlex= thd->lex;
sp_lex_local *sublex= new (thd->mem_root) sp_lex_local(thd, oldlex);
if (sublex == 0)
DBUG_RETURN(TRUE);
thd->set_local_lex(sublex);
(void)m_lex.push_front(oldlex);
DBUG_RETURN(m_lex.push_front(oldlex));
}
DBUG_RETURN(FALSE);
bool
sp_head::reset_lex(THD *thd)
{
DBUG_ENTER("sp_head::reset_lex");
sp_lex_local *sublex= new (thd->mem_root) sp_lex_local(thd, thd->lex);
DBUG_RETURN(sublex ? reset_lex(thd, sublex) : true);
}
......
......@@ -474,6 +474,9 @@ class sp_head :private Query_arena,
bool
reset_lex(THD *thd);
bool
reset_lex(THD *thd, sp_lex_local *sublex);
/**
Merge two LEX instances.
@param oldlex - the upper level LEX we're going to restore to.
......
......@@ -3290,19 +3290,20 @@ assignment_source_lex:
;
assignment_source_expr:
remember_lex assignment_source_lex
assignment_source_lex
{
DBUG_ASSERT(thd->free_list == NULL);
thd->set_local_lex($2); // This changes thd->lex to $2
Lex->sphead->reset_lex(thd, $1);
}
expr
{
DBUG_ASSERT($2 == thd->lex);
if (thd->restore_from_local_lex_to_old_lex($1)) // Restores thd->lex
MYSQL_YYABORT;
$$= $2;
$$->set_item_and_free_list($4, thd->free_list);
DBUG_ASSERT($1 == thd->lex);
$$= $1;
$$->sp_lex_in_use= true;
$$->set_item_and_free_list($3, thd->free_list);
thd->free_list= NULL;
if ($$->sphead->restore_lex(thd))
MYSQL_YYABORT;
}
;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment