# At a local mysql-6.0-runtime repository of davi
2777 Davi Arnaut 2008-12-10
Bug#36649: Condition area is not properly cleaned up after stored routine invocation
The problem is that the diagnostics area of a trigger is not
isolated from the area of the statement that caused the trigger
invocation. In MySQL terms, it means that warnings generated
during the execution of the trigger are not removed from the
"warning area" at the end of the execution.
Before this fix, the rules for MySQL message list life cycle (see
manual entry for SHOW WARNINGS) did not apply to statements
inside stored programs:
- The manual says that the list of messages is cleared by a
statement that uses a table (any table). However, such
statement, if run inside a stored program did not clear the
message list.
- The manual says that the list is cleared by a statement that
generates a new error or a warning, but this was not the case
with stored program statements either and is changed to be the
case as well.
In other words, after this fix, a statement has the same effect
on the message list regardless of whether it's executed inside a
stored program/sub-statement or not.
This introduces an incompatible change:
- before this fix, a, e.g. statement inside a trigger could
never clear the global warning list
- after this fix, a trigger that generates a warning or uses a
table, clears the global warning list
This change is not backward compatible as it is intended to make
MySQL behavior similar to the SQL standard behavior:
A stored function or trigger will get its own "warning area" (or,
in standard terminology, diagnostics area). At the beginning of
the stored function or trigger, all messages from the caller area
will be copied to the area of the trigger. During execution, the
message list will be cleared according to the MySQL rules
described on the manual (SHOW WARNINGS entry). At the end of the
function/trigger, the "warning area" will be destroyed along with
all warnings it contains, except that if the last statement of
the function/trigger generated messages, these are copied into
the "warning area" of the caller.
Consequently, statements that use a table or generate a warning
*will* clear warnings inside the trigger, but that will have no
effect to the warning list of the calling (outer) statement.
modified:
mysql-test/r/implicit_commit.result
mysql-test/r/sp-dynamic.result
mysql-test/r/sp-vars.result
mysql-test/r/sp.result
mysql-test/r/sp_notembedded.result
mysql-test/r/trigger.result
mysql-test/t/sp.test
mysql-test/t/trigger.test
sql/sp_head.cc
sql/sp_head.h
sql/sql_error.cc
sql/sql_error.h
sql/sql_parse.cc
sql/sql_prepare.cc
per-file messages:
mysql-test/r/implicit_commit.result
Fix test case results.
mysql-test/r/sp-dynamic.result
Fix test case results.
mysql-test/r/sp-vars.result
Fix test case results.
mysql-test/r/sp.result
Fix test case results.
mysql-test/r/sp_notembedded.result
Fix test case results.
mysql-test/r/trigger.result
Fix test case results.
mysql-test/t/sp.test
Add test case for Bug#36649
mysql-test/t/trigger.test
Add test case for Bug#36649
sql/sp_head.cc
Emulate multiple warning areas -- one per stored program instance.
sql/sp_head.h
Add helper method to push and pop a warning area.
sql/sql_error.cc
Message list reset rules are the same for statements inside
or outside compound statements.
sql/sql_error.h
Add method to return the id of the warning area.
sql/sql_parse.cc
Message list reset rules are the same for statements inside
or outside compound statements.
sql/sql_prepare.cc
Message list reset rules are the same for statements inside
or outside compound statements.
=== modified file 'mysql-test/r/implicit_commit.result'
--- a/mysql-test/r/implicit_commit.result 2008-11-26 12:07:51 +0000
+++ b/mysql-test/r/implicit_commit.result 2008-12-10 18:27:24 +0000
@@ -55,8 +55,6 @@ create temporary table t2 as select * fr
CALL db1.test_if_commit();
IMPLICIT COMMIT
NO
-Warnings:
-Warning 1196 Some non-transactional changed tables couldn't be rolled back
#
# SQLCOM_DROP_TABLE TEMPORARY
#
@@ -81,8 +79,6 @@ update t2 set a=a+1 where (1) in (select
CALL db1.test_if_commit();
IMPLICIT COMMIT
NO
-Warnings:
-Warning 1196 Some non-transactional changed tables couldn't be rolled back
#
# SQLCOM_INSERT
#
@@ -91,8 +87,6 @@ insert into t2 set a=((1) in (select * f
CALL db1.test_if_commit();
IMPLICIT COMMIT
NO
-Warnings:
-Warning 1196 Some non-transactional changed tables couldn't be rolled back
#
# SQLCOM_INSERT_SELECT
#
@@ -101,8 +95,6 @@ insert into t2 select * from t1;
CALL db1.test_if_commit();
IMPLICIT COMMIT
NO
-Warnings:
-Warning 1196 Some non-transactional changed tables couldn't be rolled back
#
# SQLCOM_REPLACE
#
@@ -111,8 +103,6 @@ replace t2 set a=((1) in (select * from
CALL db1.test_if_commit();
IMPLICIT COMMIT
NO
-Warnings:
-Warning 1196 Some non-transactional changed tables couldn't be rolled back
#
# SQLCOM_REPLACE_SELECT
#
@@ -121,8 +111,6 @@ replace t2 select * from t1;
CALL db1.test_if_commit();
IMPLICIT COMMIT
NO
-Warnings:
-Warning 1196 Some non-transactional changed tables couldn't be rolled back
#
# SQLCOM_DELETE
#
@@ -131,8 +119,6 @@ delete from t2 where (1) in (select * fr
CALL db1.test_if_commit();
IMPLICIT COMMIT
NO
-Warnings:
-Warning 1196 Some non-transactional changed tables couldn't be rolled back
#
# SQLCOM_DELETE_MULTI
#
@@ -160,8 +146,6 @@ load data infile '../std_data_ln/words.d
CALL db1.test_if_commit();
IMPLICIT COMMIT
NO
-Warnings:
-Warning 1196 Some non-transactional changed tables couldn't be rolled back
drop table t4;
#
# SQLCOM_SHOW_DATABASES
=== modified file 'mysql-test/r/sp-dynamic.result'
--- a/mysql-test/r/sp-dynamic.result 2007-06-22 13:23:51 +0000
+++ b/mysql-test/r/sp-dynamic.result 2008-12-10 18:27:24 +0000
@@ -97,8 +97,6 @@ end|
call p1()|
a
1
-Warnings:
-Note 1051 Unknown table 't1'
call p1()|
a
1
@@ -371,9 +369,6 @@ call p1(@a)|
create table t1 (a int)
@rsql
create table t2 (a int)
-Warnings:
-Note 1051 Unknown table 't1'
-Note 1051 Unknown table 't2'
select @a|
@a
0
@@ -382,9 +377,6 @@ call p1(@a)|
create table t1 (a int)
@rsql
create table t2 (a int)
-Warnings:
-Note 1051 Unknown table 't1'
-Note 1051 Unknown table 't2'
select @a|
@a
0
=== modified file 'mysql-test/r/sp-vars.result'
--- a/mysql-test/r/sp-vars.result 2008-11-24 09:53:39 +0000
+++ b/mysql-test/r/sp-vars.result 2008-12-10 18:27:24 +0000
@@ -110,24 +110,6 @@ v7 v8 v9 v10 v11 v12 v13 v14 v15 v16
v17 v18 v19 v20
12.00 12.12 12.00 12.12
Warnings:
-Warning 1264 Out of range value for column 'v1' at row 1
-Warning 1264 Out of range value for column 'v1u' at row 1
-Warning 1264 Out of range value for column 'v2' at row 1
-Warning 1264 Out of range value for column 'v2u' at row 1
-Warning 1264 Out of range value for column 'v3' at row 1
-Warning 1264 Out of range value for column 'v3u' at row 1
-Warning 1264 Out of range value for column 'v4' at row 1
-Warning 1264 Out of range value for column 'v4u' at row 1
-Warning 1264 Out of range value for column 'v5' at row 1
-Warning 1264 Out of range value for column 'v5u' at row 1
-Warning 1264 Out of range value for column 'v6' at row 1
-Warning 1264 Out of range value for column 'v6u' at row 1
-Warning 1366 Incorrect integer value: 'String 10 ' for column 'v10' at row 1
-Warning 1366 Incorrect integer value: 'String10' for column 'v11' at row 1
-Warning 1265 Data truncated for column 'v12' at row 1
-Warning 1265 Data truncated for column 'v13' at row 1
-Warning 1366 Incorrect integer value: 'Hello, world' for column 'v16' at row 1
-Note 1265 Data truncated for column 'v18' at row 1
Note 1265 Data truncated for column 'v20' at row 1
CALL sp_vars_check_assignment();
i1 i2 i3 i4
@@ -143,21 +125,6 @@ d1 d2 d3
d1 d2 d3
1234.00 1234.12 1234.12
Warnings:
-Warning 1264 Out of range value for column 'i1' at row 1
-Warning 1264 Out of range value for column 'i2' at row 1
-Warning 1264 Out of range value for column 'i3' at row 1
-Warning 1264 Out of range value for column 'i4' at row 1
-Warning 1264 Out of range value for column 'i1' at row 1
-Warning 1264 Out of range value for column 'i2' at row 1
-Warning 1264 Out of range value for column 'i3' at row 1
-Warning 1264 Out of range value for column 'i4' at row 1
-Warning 1264 Out of range value for column 'u1' at row 1
-Warning 1264 Out of range value for column 'u2' at row 1
-Warning 1264 Out of range value for column 'u3' at row 1
-Warning 1264 Out of range value for column 'u4' at row 1
-Warning 1264 Out of range value for column 'u1' at row 1
-Warning 1264 Out of range value for column 'u2' at row 1
-Note 1265 Data truncated for column 'd3' at row 1
Note 1265 Data truncated for column 'd3' at row 1
SELECT sp_vars_check_ret1();
sp_vars_check_ret1()
@@ -198,24 +165,6 @@ v7 v8 v9 v10 v11 v12 v13 v14 v15 v16
v17 v18 v19 v20
12.00 12.12 12.00 12.12
Warnings:
-Warning 1264 Out of range value for column 'v1' at row 1
-Warning 1264 Out of range value for column 'v1u' at row 1
-Warning 1264 Out of range value for column 'v2' at row 1
-Warning 1264 Out of range value for column 'v2u' at row 1
-Warning 1264 Out of range value for column 'v3' at row 1
-Warning 1264 Out of range value for column 'v3u' at row 1
-Warning 1264 Out of range value for column 'v4' at row 1
-Warning 1264 Out of range value for column 'v4u' at row 1
-Warning 1264 Out of range value for column 'v5' at row 1
-Warning 1264 Out of range value for column 'v5u' at row 1
-Warning 1264 Out of range value for column 'v6' at row 1
-Warning 1264 Out of range value for column 'v6u' at row 1
-Warning 1366 Incorrect integer value: 'String 10 ' for column 'v10' at row 1
-Warning 1366 Incorrect integer value: 'String10' for column 'v11' at row 1
-Warning 1265 Data truncated for column 'v12' at row 1
-Warning 1265 Data truncated for column 'v13' at row 1
-Warning 1366 Incorrect integer value: 'Hello, world' for column 'v16' at row 1
-Note 1265 Data truncated for column 'v18' at row 1
Note 1265 Data truncated for column 'v20' at row 1
CALL sp_vars_check_assignment();
i1 i2 i3 i4
@@ -231,21 +180,6 @@ d1 d2 d3
d1 d2 d3
1234.00 1234.12 1234.12
Warnings:
-Warning 1264 Out of range value for column 'i1' at row 1
-Warning 1264 Out of range value for column 'i2' at row 1
-Warning 1264 Out of range value for column 'i3' at row 1
-Warning 1264 Out of range value for column 'i4' at row 1
-Warning 1264 Out of range value for column 'i1' at row 1
-Warning 1264 Out of range value for column 'i2' at row 1
-Warning 1264 Out of range value for column 'i3' at row 1
-Warning 1264 Out of range value for column 'i4' at row 1
-Warning 1264 Out of range value for column 'u1' at row 1
-Warning 1264 Out of range value for column 'u2' at row 1
-Warning 1264 Out of range value for column 'u3' at row 1
-Warning 1264 Out of range value for column 'u4' at row 1
-Warning 1264 Out of range value for column 'u1' at row 1
-Warning 1264 Out of range value for column 'u2' at row 1
-Note 1265 Data truncated for column 'd3' at row 1
Note 1265 Data truncated for column 'd3' at row 1
SELECT sp_vars_check_ret1();
sp_vars_check_ret1()
@@ -451,10 +385,6 @@ FF
HEX(v10)
FF
Warnings:
-Warning 1264 Out of range value for column 'v8' at row 1
-Warning 1264 Out of range value for column 'v9' at row 1
-Warning 1264 Out of range value for column 'v10' at row 1
-Warning 1264 Out of range value for column 'v1' at row 1
Warning 1264 Out of range value for column 'v5' at row 1
DROP PROCEDURE p1;
=== modified file 'mysql-test/r/sp.result'
--- a/mysql-test/r/sp.result 2008-11-03 12:12:00 +0000
+++ b/mysql-test/r/sp.result 2008-12-10 18:27:24 +0000
@@ -526,8 +526,6 @@ end|
delete from t1|
create table t3 ( s char(16), d int)|
call into_test4()|
-Warnings:
-Warning 1329 No data - zero rows fetched, selected, or processed
select * from t3|
s d
into4 NULL
@@ -1118,8 +1116,6 @@ end|
select f9()|
f9()
6
-Warnings:
-Note 1051 Unknown table 't3'
select f9() from t1 limit 1|
f9()
6
@@ -1160,8 +1156,6 @@ drop temporary table t3|
select f12_1()|
f12_1()
3
-Warnings:
-Note 1051 Unknown table 't3'
select f12_1() from t1 limit 1|
f12_1()
3
@@ -2113,12 +2107,7 @@ end if;
insert into t4 values (2, rc, t3);
end|
call bug1863(10)|
-Warnings:
-Note 1051 Unknown table 'temp_t1'
-Warning 1329 No data - zero rows fetched, selected, or processed
call bug1863(10)|
-Warnings:
-Warning 1329 No data - zero rows fetched, selected, or processed
select * from t4|
f1 rc t3
2 0 NULL
@@ -2383,11 +2372,7 @@ begin
end|
call bug4579_1()|
call bug4579_1()|
-Warnings:
-Warning 1329 No data - zero rows fetched, selected, or processed
call bug4579_1()|
-Warnings:
-Warning 1329 No data - zero rows fetched, selected, or processed
drop procedure bug4579_1|
drop procedure bug4579_2|
drop table t3|
@@ -3773,9 +3758,6 @@ Table Create Table
tm1 CREATE TEMPORARY TABLE `tm1` (
`spv1` decimal(3,3) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
-Warnings:
-Warning 1264 Out of range value for column 'spv1' at row 1
-Warning 1366 Incorrect decimal value: 'test' for column 'spv1' at row 1
call bug12589_2()|
Table Create Table
tm1 CREATE TEMPORARY TABLE `tm1` (
@@ -6134,35 +6116,6 @@ bug5274_f2()
x
Warnings:
Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
-Warning 1265 Data truncated for column 'bug5274_f1' at row 1
DROP FUNCTION bug5274_f1|
DROP FUNCTION bug5274_f2|
drop procedure if exists proc_21513|
@@ -6257,20 +6210,17 @@ f1(2)
0
Warnings:
Warning 1329 No data - zero rows fetched, selected, or processed
-Warning 1329 No data - zero rows fetched, selected, or processed
PREPARE s1 FROM 'SELECT f1(2)';
EXECUTE s1;
f1(2)
0
Warnings:
Warning 1329 No data - zero rows fetched, selected, or processed
-Warning 1329 No data - zero rows fetched, selected, or processed
EXECUTE s1;
f1(2)
0
Warnings:
Warning 1329 No data - zero rows fetched, selected, or processed
-Warning 1329 No data - zero rows fetched, selected, or processed
DROP PROCEDURE p1;
DROP PROCEDURE p2;
DROP FUNCTION f1;
@@ -6282,6 +6232,7 @@ create procedure mysqltest_db1.sp_bug285
call mysqltest_db1.sp_bug28551();
show warnings;
Level Code Message
+Note 1008 Can't drop database 'mysqltest_db1'; database doesn't exist
drop database mysqltest_db1;
drop database if exists mysqltest_db1;
drop table if exists test.t1;
@@ -6994,6 +6945,101 @@ SELECT * FROM t1 WHERE a = f1();
ERROR 42S02: Table 'test.t_non_existing' doesn't exist
DROP FUNCTION f1;
DROP TABLE t1;
+DROP PROCEDURE IF EXISTS p1;
+CREATE PROCEDURE p1(a INT, b CHAR)
+BEGIN
+IF a > 0 THEN
+CALL p1(a-1, 'ab');
+ELSE
+SELECT 1;
+END IF;
+END|
+SET @save_max_sp_recursion= @@max_sp_recursion_depth;
+SET @@max_sp_recursion_depth= 5;
+CALL p1(4, 'a');
+1
+1
+Warnings:
+Warning 1265 Data truncated for column 'b' at row 1
+Warning 1265 Data truncated for column 'b' at row 1
+Warning 1265 Data truncated for column 'b' at row 1
+Warning 1265 Data truncated for column 'b' at row 1
+SET @@max_sp_recursion_depth= @save_max_sp_recursion;
+DROP PROCEDURE p1;
+DROP PROCEDURE IF EXISTS p1;
+CREATE PROCEDURE p1(a CHAR)
+BEGIN
+SELECT 1;
+SELECT CAST('10 ' as UNSIGNED INTEGER);
+SELECT 1;
+END|
+CALL p1('data truncated parameter');
+1
+1
+CAST('10 ' as UNSIGNED INTEGER)
+10
+1
+1
+Warnings:
+Warning 1265 Data truncated for column 'a' at row 1
+Warning 1292 Truncated incorrect INTEGER value: '10 '
+DROP PROCEDURE p1;
+DROP PROCEDURE IF EXISTS p1;
+DROP PROCEDURE IF EXISTS p2;
+DROP PROCEDURE IF EXISTS p3;
+DROP PROCEDURE IF EXISTS p4;
+CREATE PROCEDURE p1()
+CALL p2()|
+CREATE PROCEDURE p2()
+CALL p3()|
+CREATE PROCEDURE p3()
+CALL p4()|
+CREATE PROCEDURE p4()
+BEGIN
+SELECT 1;
+SELECT CAST('10 ' as UNSIGNED INTEGER);
+SELECT 2;
+END|
+CALL p1();
+1
+1
+CAST('10 ' as UNSIGNED INTEGER)
+10
+2
+2
+Warnings:
+Warning 1292 Truncated incorrect INTEGER value: '10 '
+DROP PROCEDURE p1;
+DROP PROCEDURE p2;
+DROP PROCEDURE p3;
+DROP PROCEDURE p4;
+DROP FUNCTION IF EXISTS f1;
+DROP FUNCTION IF EXISTS f2;
+DROP FUNCTION IF EXISTS f3;
+DROP FUNCTION IF EXISTS f4;
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (a CHAR(2));
+INSERT INTO t1 VALUES ('aa');
+CREATE FUNCTION f1() RETURNS CHAR
+RETURN (SELECT f2())|
+CREATE FUNCTION f2() RETURNS CHAR
+RETURN (SELECT f3())|
+CREATE FUNCTION f3() RETURNS CHAR
+RETURN (SELECT f4())|
+CREATE FUNCTION f4() RETURNS CHAR
+BEGIN
+RETURN (SELECT a FROM t1);
+END|
+SELECT f1();
+f1()
+a
+Warnings:
+Warning 1265 Data truncated for column 'f4()' at row 1
+DROP FUNCTION f1;
+DROP FUNCTION f2;
+DROP FUNCTION f3;
+DROP FUNCTION f4;
+DROP TABLE t1;
# ------------------------------------------------------------------
# -- End of 6.0 tests
# ------------------------------------------------------------------
=== modified file 'mysql-test/r/sp_notembedded.result'
--- a/mysql-test/r/sp_notembedded.result 2008-03-26 19:27:23 +0000
+++ b/mysql-test/r/sp_notembedded.result 2008-12-10 18:27:24 +0000
@@ -21,9 +21,11 @@ end|
call bug4902_2()|
show warnings|
Level Code Message
+Note 1305 PROCEDURE test.bug4902_2 does not exist
call bug4902_2()|
show warnings|
Level Code Message
+Note 1305 PROCEDURE test.bug4902_2 does not exist
drop procedure bug4902_2|
drop table if exists t1|
create table t1 (
=== modified file 'mysql-test/r/trigger.result'
--- a/mysql-test/r/trigger.result 2008-07-14 12:49:19 +0000
+++ b/mysql-test/r/trigger.result 2008-12-10 18:27:24 +0000
@@ -2054,3 +2054,51 @@ drop trigger trg1;
drop trigger trg2;
drop table t1, t2;
End of 5.1 tests.
+DROP TRIGGER IF EXISTS trg1;
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (a INT);
+CREATE TRIGGER trg1 BEFORE INSERT ON t1 FOR EACH ROW
+BEGIN
+DECLARE a CHAR;
+SELECT 'ab' INTO a;
+SELECT 'ab' INTO a;
+SELECT 'a' INTO a;
+END|
+INSERT INTO t1 VALUES (1);
+Warnings:
+Warning 1265 Data truncated for column 'a' at row 1
+DROP TRIGGER trg1;
+DROP TABLE t1;
+DROP TRIGGER IF EXISTS trg1;
+DROP TRIGGER IF EXISTS trg2;
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (a INT);
+CREATE TRIGGER trg1 BEFORE INSERT ON t1 FOR EACH ROW
+BEGIN
+DECLARE trg1 CHAR;
+SELECT 'ab' INTO trg1;
+END|
+CREATE TRIGGER trg2 AFTER INSERT ON t1 FOR EACH ROW
+BEGIN
+DECLARE trg2 CHAR;
+SELECT 'ab' INTO trg2;
+END|
+INSERT INTO t1 VALUES (0);
+Warnings:
+Warning 1265 Data truncated for column 'trg1' at row 1
+Warning 1265 Data truncated for column 'trg2' at row 1
+SELECT * FROM t1;
+a
+0
+SHOW WARNINGS;
+Level Code Message
+INSERT INTO t1 VALUES (1),(2);
+Warnings:
+Warning 1265 Data truncated for column 'trg1' at row 1
+Warning 1265 Data truncated for column 'trg2' at row 1
+Warning 1265 Data truncated for column 'trg1' at row 1
+Warning 1265 Data truncated for column 'trg2' at row 1
+DROP TRIGGER trg1;
+DROP TRIGGER trg2;
+DROP TABLE t1;
+End of 6.0 tests.
=== modified file 'mysql-test/t/sp.test'
--- a/mysql-test/t/sp.test 2008-11-03 12:12:00 +0000
+++ b/mysql-test/t/sp.test 2008-12-10 18:27:24 +0000
@@ -8287,6 +8287,119 @@ SELECT * FROM t1 WHERE a = f1();
DROP FUNCTION f1;
DROP TABLE t1;
+#
+# Bug#36649: Condition area is not properly cleaned up after stored routine invocation
+#
+
+--disable_warnings
+DROP PROCEDURE IF EXISTS p1;
+--enable_warnings
+
+delimiter |;
+CREATE PROCEDURE p1(a INT, b CHAR)
+BEGIN
+ IF a > 0 THEN
+ CALL p1(a-1, 'ab');
+ ELSE
+ SELECT 1;
+ END IF;
+END|
+delimiter ;|
+
+SET @save_max_sp_recursion= @@max_sp_recursion_depth;
+SET @@max_sp_recursion_depth= 5;
+CALL p1(4, 'a');
+SET @@max_sp_recursion_depth= @save_max_sp_recursion;
+
+DROP PROCEDURE p1;
+
+#
+# Ensure that rules for message list clean up are being respected.
+#
+
+--disable_warnings
+DROP PROCEDURE IF EXISTS p1;
+--enable_warnings
+
+delimiter |;
+CREATE PROCEDURE p1(a CHAR)
+BEGIN
+ SELECT 1;
+ SELECT CAST('10 ' as UNSIGNED INTEGER);
+ SELECT 1;
+END|
+delimiter ;|
+
+CALL p1('data truncated parameter');
+
+DROP PROCEDURE p1;
+
+#
+# Cascading stored procedure/function calls.
+#
+
+--disable_warnings
+DROP PROCEDURE IF EXISTS p1;
+DROP PROCEDURE IF EXISTS p2;
+DROP PROCEDURE IF EXISTS p3;
+DROP PROCEDURE IF EXISTS p4;
+--enable_warnings
+
+delimiter |;
+CREATE PROCEDURE p1()
+ CALL p2()|
+CREATE PROCEDURE p2()
+ CALL p3()|
+CREATE PROCEDURE p3()
+ CALL p4()|
+CREATE PROCEDURE p4()
+BEGIN
+ SELECT 1;
+ SELECT CAST('10 ' as UNSIGNED INTEGER);
+ SELECT 2;
+END|
+delimiter ;|
+
+CALL p1();
+
+DROP PROCEDURE p1;
+DROP PROCEDURE p2;
+DROP PROCEDURE p3;
+DROP PROCEDURE p4;
+
+--disable_warnings
+DROP FUNCTION IF EXISTS f1;
+DROP FUNCTION IF EXISTS f2;
+DROP FUNCTION IF EXISTS f3;
+DROP FUNCTION IF EXISTS f4;
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TABLE t1 (a CHAR(2));
+
+INSERT INTO t1 VALUES ('aa');
+
+delimiter |;
+CREATE FUNCTION f1() RETURNS CHAR
+ RETURN (SELECT f2())|
+CREATE FUNCTION f2() RETURNS CHAR
+ RETURN (SELECT f3())|
+CREATE FUNCTION f3() RETURNS CHAR
+ RETURN (SELECT f4())|
+CREATE FUNCTION f4() RETURNS CHAR
+BEGIN
+ RETURN (SELECT a FROM t1);
+END|
+delimiter ;|
+
+SELECT f1();
+
+DROP FUNCTION f1;
+DROP FUNCTION f2;
+DROP FUNCTION f3;
+DROP FUNCTION f4;
+DROP TABLE t1;
+
--echo # ------------------------------------------------------------------
--echo # -- End of 6.0 tests
--echo # ------------------------------------------------------------------
=== modified file 'mysql-test/t/trigger.test'
--- a/mysql-test/t/trigger.test 2008-04-08 16:01:20 +0000
+++ b/mysql-test/t/trigger.test 2008-12-10 18:27:24 +0000
@@ -2337,3 +2337,68 @@ drop trigger trg2;
drop table t1, t2;
--echo End of 5.1 tests.
+
+#
+# Bug#36649: Condition area is not properly cleaned up after stored routine invocation
+#
+
+--disable_warnings
+DROP TRIGGER IF EXISTS trg1;
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TABLE t1 (a INT);
+
+delimiter |;
+CREATE TRIGGER trg1 BEFORE INSERT ON t1 FOR EACH ROW
+BEGIN
+ DECLARE a CHAR;
+ SELECT 'ab' INTO a;
+ SELECT 'ab' INTO a;
+ SELECT 'a' INTO a;
+END|
+delimiter ;|
+
+INSERT INTO t1 VALUES (1);
+
+DROP TRIGGER trg1;
+DROP TABLE t1;
+
+#
+# Successive trigger actuations
+#
+
+--disable_warnings
+DROP TRIGGER IF EXISTS trg1;
+DROP TRIGGER IF EXISTS trg2;
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TABLE t1 (a INT);
+
+delimiter |;
+
+CREATE TRIGGER trg1 BEFORE INSERT ON t1 FOR EACH ROW
+BEGIN
+ DECLARE trg1 CHAR;
+ SELECT 'ab' INTO trg1;
+END|
+
+CREATE TRIGGER trg2 AFTER INSERT ON t1 FOR EACH ROW
+BEGIN
+ DECLARE trg2 CHAR;
+ SELECT 'ab' INTO trg2;
+END|
+
+delimiter ;|
+
+INSERT INTO t1 VALUES (0);
+SELECT * FROM t1;
+SHOW WARNINGS;
+INSERT INTO t1 VALUES (1),(2);
+
+DROP TRIGGER trg1;
+DROP TRIGGER trg2;
+DROP TABLE t1;
+
+--echo End of 6.0 tests.
=== modified file 'sql/sp_head.cc'
--- a/sql/sp_head.cc 2008-12-04 16:50:07 +0000
+++ b/sql/sp_head.cc 2008-12-10 18:27:24 +0000
@@ -502,7 +502,7 @@ sp_head::operator delete(void *ptr, size
sp_head::sp_head()
:Query_arena(&main_mem_root, INITIALIZED_FOR_SP),
m_flags(0), m_recursion_level(0), m_next_cached_sp(0),
- m_cont_level(0)
+ m_warning_info(0), m_cont_level(0)
{
const LEX_STRING str_reset= { NULL, 0 };
@@ -1070,6 +1070,7 @@ sp_head::execute(THD *thd)
Item_change_list old_change_list;
String old_packet;
Reprepare_observer *save_reprepare_observer= thd->m_reprepare_observer;
+ Warning_info *saved_warning_info;
Object_creation_ctx *saved_creation_ctx;
@@ -1120,6 +1121,9 @@ sp_head::execute(THD *thd)
thd->is_slave_error= 0;
old_arena= thd->stmt_arena;
+ /* Push a new warning information area. */
+ saved_warning_info= backup_warning_info(thd);
+
/*
Switch query context. This has to be done early as this is sometimes
allocated trough sql_alloc
@@ -1321,6 +1325,9 @@ sp_head::execute(THD *thd)
thd->stmt_arena= old_arena;
state= EXECUTED;
+ /* Restore warning information area. */
+ restore_warning_info(thd, saved_warning_info);
+
done:
DBUG_PRINT("info", ("err_status: %d killed: %d is_slave_error: %d report_error: %d",
err_status, thd->killed, thd->is_slave_error,
@@ -4014,3 +4021,58 @@ sp_add_to_query_tables(THD *thd, LEX *le
return table;
}
+
+static inline
+void warn_info_copy(THD *thd, Warning_info *dest, Warning_info *src)
+{
+ MYSQL_ERROR *err;
+ List_iterator_fast<MYSQL_ERROR> it(src->warn_list());
+ while ((err= it++))
+ dest->push_warning(thd, err->level, err->code, err->msg);
+}
+
+
+/**
+ Push a new warning information area.
+
+ @note The new area is a copy of the caller's warning information area.
+
+ @param thd Thread context.
+
+ @return Saved warning information area.
+*/
+
+Warning_info *
+sp_head::backup_warning_info(THD *thd)
+{
+ Warning_info *saved= thd->warning_info;
+ DBUG_ENTER("sp_head::backup_warning_info");
+ m_warning_info.clear_warning_info(saved->warn_id());
+ warn_info_copy(thd, &m_warning_info, saved);
+ thd->warning_info= &m_warning_info;
+ DBUG_RETURN(saved);
+}
+
+
+/**
+ Restore the caller's original warning information area.
+
+ @param thd Thread context.
+ @param saved The saved warning information area.
+*/
+
+void
+sp_head::restore_warning_info(THD *thd, Warning_info *saved)
+{
+ DBUG_ENTER("sp_head::restore_warning_info");
+ DBUG_ASSERT(saved);
+ if (saved->warn_id() != m_warning_info.warn_id())
+ {
+ saved->opt_clear_warning_info(thd->query_id);
+ warn_info_copy(thd, saved, thd->warning_info);
+ }
+ m_warning_info.clear_warning_info(0);
+ thd->warning_info= saved;
+ DBUG_VOID_RETURN;
+}
+
=== modified file 'sql/sp_head.h'
--- a/sql/sp_head.h 2008-07-07 23:15:08 +0000
+++ b/sql/sp_head.h 2008-12-10 18:27:24 +0000
@@ -475,7 +475,7 @@ private:
MEM_ROOT *m_thd_root; ///< Temp. store for thd's mem_root
THD *m_thd; ///< Set if we have reset mem_root
-
+ Warning_info m_warning_info; ///< Warnings area of a routine instance
sp_pcontext *m_pcont; ///< Parse context
List<LEX> m_lex; ///< Temp. store for the other lex
DYNAMIC_ARRAY m_instr; ///< The "instructions"
@@ -522,6 +522,12 @@ private:
by routine.
*/
bool merge_table_list(THD *thd, TABLE_LIST *table, LEX *lex_for_tmp_check);
+
+ /** Push a new warning info area. */
+ Warning_info *backup_warning_info(THD *thd);
+
+ /** Pop the current warning info area. */
+ void restore_warning_info(THD *thd, Warning_info *saved);
}; // class sp_head : public Sql_alloc
=== modified file 'sql/sql_error.cc'
--- a/sql/sql_error.cc 2008-12-06 00:51:16 +0000
+++ b/sql/sql_error.cc 2008-12-10 18:27:24 +0000
@@ -267,8 +267,7 @@ void push_warning(THD *thd, MYSQL_ERROR:
!(thd->options & OPTION_SQL_NOTES))
DBUG_VOID_RETURN;
- if (! thd->spcont)
- thd->warning_info->opt_clear_warning_info(thd->query_id);
+ thd->warning_info->opt_clear_warning_info(thd->query_id);
thd->got_warning= 1;
=== modified file 'sql/sql_error.h'
--- a/sql/sql_error.h 2008-12-05 23:47:51 +0000
+++ b/sql/sql_error.h 2008-12-10 18:27:24 +0000
@@ -262,6 +262,9 @@ public:
return m_warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_ERROR];
}
+ /** Id of the warning information area. */
+ ulonglong warn_id() const { return m_warn_id; }
+
/** Do we have any errors and warnings that we can *show*? */
bool is_empty() const { return m_warn_list.elements == 0; }
=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc 2008-12-04 23:14:30 +0000
+++ b/sql/sql_parse.cc 2008-12-10 18:27:24 +0000
@@ -1849,9 +1849,8 @@ mysql_execute_command(THD *thd)
A better approach would be to reset this for any commands
that is not a SHOW command or a select that only access local
variables, but for now this is probably good enough.
- Don't reset warnings when executing a stored routine.
*/
- if ((all_tables || !lex->is_single_level_stmt()) && !thd->spcont)
+ if (all_tables)
thd->warning_info->opt_clear_warning_info(thd->query_id);
#ifdef HAVE_REPLICATION
=== modified file 'sql/sql_prepare.cc'
--- a/sql/sql_prepare.cc 2008-12-08 22:29:38 +0000
+++ b/sql/sql_prepare.cc 2008-12-10 18:27:24 +0000
@@ -1913,7 +1913,7 @@ static bool check_prepared_statement(Pre
get_table_list());
/* Reset warning count for each query that uses tables */
- if ((tables || !lex->is_single_level_stmt()) && !thd->spcont)
+ if (tables)
thd->warning_info->opt_clear_warning_info(thd->query_id);
switch (sql_command) {