Commit 3f83e4c1 authored by Davi Arnaut's avatar Davi Arnaut

Bug#48449: hang on show create view after upgrading when view contains function of view

SHOW CREATE TABLE on a view (v1) that contains a function whose
statement uses another view (v2), could trigger a infinite loop
if the view referenced within the function causes a warning to
be raised while opening the said view (v2).

The problem was a infinite loop over the stack of internal error
handlers. The problem would be triggered if the stack contained
two or more handlers and the first two handlers didn't handle the
raised condition. In this case, the loop variable would always
point to the second handler in the stack.

The solution is to correct the loop variable assignment so that
the loop is able to iterate over all handlers in the stack.

mysql-test/r/view.result:
  Add test case result for Bug#48449.
mysql-test/std_data/bug48449.frm:
  Add a incomplete view definition that causes a warning to be
  issued.
mysql-test/t/view.test:
  Add test case for Bug#48449
sql/sql_class.cc:
  Iterate over all handlers in the stack.
parent 94207b1f
...@@ -3854,6 +3854,30 @@ Note 1449 The user specified as a definer ('unknown'@'unknown') does not exist ...@@ -3854,6 +3854,30 @@ Note 1449 The user specified as a definer ('unknown'@'unknown') does not exist
LOCK TABLES v1 READ; LOCK TABLES v1 READ;
ERROR HY000: The user specified as a definer ('unknown'@'unknown') does not exist ERROR HY000: The user specified as a definer ('unknown'@'unknown') does not exist
DROP VIEW v1; DROP VIEW v1;
#
# Bug#48449: hang on show create view after upgrading when
# view contains function of view
#
DROP VIEW IF EXISTS v1,v2;
DROP TABLE IF EXISTS t1,t2;
DROP FUNCTION IF EXISTS f1;
CREATE TABLE t1 (a INT);
CREATE TABLE t2 (a INT);
CREATE FUNCTION f1() RETURNS INT
BEGIN
SELECT a FROM v2 INTO @a;
RETURN @a;
END//
# Trigger pre-locking when opening v2.
CREATE VIEW v1 AS SELECT f1() FROM t1;
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `f1`() AS `f1()` from `t1` latin1 latin1_swedish_ci
Warnings:
Note 1599 View `test`.`v2` has no creation context
DROP VIEW v1,v2;
DROP TABLE t1,t2;
DROP FUNCTION f1;
# ----------------------------------------------------------------- # -----------------------------------------------------------------
# -- End of 5.1 tests. # -- End of 5.1 tests.
# ----------------------------------------------------------------- # -----------------------------------------------------------------
This diff was suppressed by a .gitattributes entry.
...@@ -3882,6 +3882,40 @@ CREATE DEFINER=`unknown`@`unknown` SQL SECURITY DEFINER VIEW v1 AS SELECT 1; ...@@ -3882,6 +3882,40 @@ CREATE DEFINER=`unknown`@`unknown` SQL SECURITY DEFINER VIEW v1 AS SELECT 1;
LOCK TABLES v1 READ; LOCK TABLES v1 READ;
DROP VIEW v1; DROP VIEW v1;
--echo #
--echo # Bug#48449: hang on show create view after upgrading when
--echo # view contains function of view
--echo #
--disable_warnings
DROP VIEW IF EXISTS v1,v2;
DROP TABLE IF EXISTS t1,t2;
DROP FUNCTION IF EXISTS f1;
--enable_warnings
CREATE TABLE t1 (a INT);
CREATE TABLE t2 (a INT);
delimiter //;
CREATE FUNCTION f1() RETURNS INT
BEGIN
SELECT a FROM v2 INTO @a;
RETURN @a;
END//
delimiter ;//
--echo # Trigger pre-locking when opening v2.
CREATE VIEW v1 AS SELECT f1() FROM t1;
let $MYSQLD_DATADIR= `SELECT @@datadir`;
copy_file std_data/bug48449.frm $MYSQLD_DATADIR/test/v2.frm;
SHOW CREATE VIEW v1;
DROP VIEW v1,v2;
DROP TABLE t1,t2;
DROP FUNCTION f1;
--echo # ----------------------------------------------------------------- --echo # -----------------------------------------------------------------
--echo # -- End of 5.1 tests. --echo # -- End of 5.1 tests.
--echo # ----------------------------------------------------------------- --echo # -----------------------------------------------------------------
...@@ -725,15 +725,12 @@ void THD::push_internal_handler(Internal_error_handler *handler) ...@@ -725,15 +725,12 @@ void THD::push_internal_handler(Internal_error_handler *handler)
bool THD::handle_error(uint sql_errno, const char *message, bool THD::handle_error(uint sql_errno, const char *message,
MYSQL_ERROR::enum_warning_level level) MYSQL_ERROR::enum_warning_level level)
{ {
if (!m_internal_handler)
return FALSE;
for (Internal_error_handler *error_handler= m_internal_handler; for (Internal_error_handler *error_handler= m_internal_handler;
error_handler; error_handler;
error_handler= m_internal_handler->m_prev_internal_handler) error_handler= error_handler->m_prev_internal_handler)
{ {
if (error_handler->handle_error(sql_errno, message, level, this)) if (error_handler->handle_error(sql_errno, message, level, this))
return TRUE; return TRUE;
} }
return FALSE; return FALSE;
......
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