#At file:///home/alik/MySQL/bzr/00/bug55850/mysql-5.5-bugteam-bug55850/ based on revid:alexander.nozdrin@stripped
3097 Alexander Nozdrin 2010-10-06
Preliminary patch for Bug#55850 (Trigger warnings not cleared).
The problem was that the warnings risen by a trigger were not cleared.
The warnings should be cleared if the trigger completes successfully.
The fix is to remove "trigger warnings" after executing the trigger
in Table_triggers_list::process_triggers().
modified:
mysql-test/r/sp-error.result
mysql-test/t/sp-error.test
sql/sql_error.cc
sql/sql_error.h
sql/sql_trigger.cc
=== modified file 'mysql-test/r/sp-error.result'
--- a/mysql-test/r/sp-error.result 2010-10-06 17:35:29 +0000
+++ b/mysql-test/r/sp-error.result 2010-10-06 19:03:48 +0000
@@ -1949,3 +1949,26 @@ Warning 1365 Division by 0
DROP PROCEDURE p1;
DROP PROCEDURE p2;
SET sql_mode = @sql_mode_saved;
+#
+# Bug#55850: Trigger warnings not cleared.
+#
+DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t2;
+DROP PROCEDURE IF EXISTS p1;
+CREATE TABLE t1(x SMALLINT, y SMALLINT, z SMALLINT);
+CREATE TABLE t2(a SMALLINT, b SMALLINT, c SMALLINT,
+d SMALLINT, e SMALLINT, f SMALLINT);
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
+INSERT INTO t2(a, b, c) VALUES(99999, 99999, 99999);
+CREATE TRIGGER t1_ai AFTER INSERT ON t1 FOR EACH ROW
+INSERT INTO t2(d, e, f) VALUES(99999, 99999, 99999);
+CREATE PROCEDURE p1()
+INSERT INTO t1 VALUES(99999, 99999, 99999);
+CALL p1();
+Warnings:
+Warning 1264 Out of range value for column 'x' at row 1
+Warning 1264 Out of range value for column 'y' at row 1
+Warning 1264 Out of range value for column 'z' at row 1
+DROP TABLE t1;
+DROP TABLE t2;
+DROP PROCEDURE p1;
=== modified file 'mysql-test/t/sp-error.test'
--- a/mysql-test/t/sp-error.test 2010-07-30 15:28:36 +0000
+++ b/mysql-test/t/sp-error.test 2010-10-06 19:03:48 +0000
@@ -2813,3 +2813,46 @@ SHOW WARNINGS;
DROP PROCEDURE p1;
DROP PROCEDURE p2;
SET sql_mode = @sql_mode_saved;
+
+--echo #
+--echo # Bug#55850: Trigger warnings not cleared.
+--echo #
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t2;
+DROP PROCEDURE IF EXISTS p1;
+--enable_warnings
+
+CREATE TABLE t1(x SMALLINT, y SMALLINT, z SMALLINT);
+CREATE TABLE t2(a SMALLINT, b SMALLINT, c SMALLINT,
+ d SMALLINT, e SMALLINT, f SMALLINT);
+
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
+ INSERT INTO t2(a, b, c) VALUES(99999, 99999, 99999);
+
+CREATE TRIGGER t1_ai AFTER INSERT ON t1 FOR EACH ROW
+ INSERT INTO t2(d, e, f) VALUES(99999, 99999, 99999);
+
+CREATE PROCEDURE p1()
+ INSERT INTO t1 VALUES(99999, 99999, 99999);
+
+# What happened before the patch was:
+# - INSERT INTO t1 added 3 warnings about overflow in 'x', 'y' and 'z' columns;
+# - t1_bi run and added 3 warnings about overflow in 'a', 'b' and 'c' columns;
+# - t1_ai run and added 3 warnings about overflow in 'd', 'e' and 'f' columns;
+# => we had 9 warnings.
+#
+# Now what happens is:
+# - INSERT INTO t1 adds 3 warnings about overflow in 'x', 'y' and 'z' columns;
+# - t1_bi adds 3 warnings about overflow in 'a', 'b' and 'c' columns;
+# - The warnings added by triggers are cleared;
+# - t1_ai run and added 3 warnings about overflow in 'd', 'e' and 'f' columns;
+# - The warnings added by triggers are cleared;
+# => we have 3 warnings.
+
+CALL p1();
+
+DROP TABLE t1;
+DROP TABLE t2;
+DROP PROCEDURE p1;
=== modified file 'sql/sql_error.cc'
--- a/sql/sql_error.cc 2010-10-06 17:35:29 +0000
+++ b/sql/sql_error.cc 2010-10-06 19:03:48 +0000
@@ -566,6 +566,14 @@ MYSQL_ERROR *Warning_info::push_warning(
return cond;
}
+
+void Warning_info::remove_warning(THD *thd, const MYSQL_ERROR *warning)
+{
+ m_warn_count[warning->get_level()]--;
+ m_statement_warn_count--;
+}
+
+
/*
Push the warning to error list if there is still room in the list
=== modified file 'sql/sql_error.h'
--- a/sql/sql_error.h 2010-10-06 17:35:29 +0000
+++ b/sql/sql_error.h 2010-10-06 19:03:48 +0000
@@ -97,6 +97,9 @@ public:
return m_statement_warn_count;
}
+ void remove_warning()
+ { --m_statement_warn_count; }
+
Diagnostics_area() { reset_diagnostics_area(); }
private:
@@ -489,6 +492,8 @@ public:
MYSQL_ERROR::enum_warning_level level,
const char* msg);
+ void remove_warning(THD *thd, const MYSQL_ERROR *warning);
+
/**
Set the read only status for this statement area.
This is a privileged operation, reserved for the implementation of
=== modified file 'sql/sql_trigger.cc'
--- a/sql/sql_trigger.cc 2010-09-30 10:43:43 +0000
+++ b/sql/sql_trigger.cc 2010-10-06 19:03:48 +0000
@@ -2032,6 +2032,8 @@ bool Table_triggers_list::process_trigge
thd->reset_sub_statement_state(&statement_state, SUB_STMT_TRIGGER);
+ uint statement_warn_count_saved= thd->warning_info->statement_warn_count();
+
/*
Reset current_select before call execute_trigger() and
restore it after return from one. This way error is set
@@ -2039,13 +2041,32 @@ bool Table_triggers_list::process_trigge
*/
save_current_select= thd->lex->current_select;
thd->lex->current_select= NULL;
+
err_status=
sp_trigger->execute_trigger(thd,
&trigger_table->s->db,
&trigger_table->s->table_name,
&subject_table_grants[event][time_type]);
+
thd->lex->current_select= save_current_select;
+ if (statement_warn_count_saved < thd->warning_info->statement_warn_count())
+ {
+ List_iterator<MYSQL_ERROR> it(thd->warning_info->warn_list());
+ MYSQL_ERROR *err;
+ uint idx= 0;
+ while ((err= it++))
+ {
+ if (++idx <= statement_warn_count_saved)
+ continue;
+
+ thd->warning_info->remove_warning(thd, err);
+ thd->stmt_da->remove_warning();
+
+ it.remove();
+ }
+ }
+
thd->restore_sub_statement_state(&statement_state);
return err_status;
Attachment: [text/bzr-bundle] bzr/alexander.nozdrin@oracle.com-20101006190348-81uq2f270fxdq97i.bundle