Fixed bug #55421 - Protocol::end_statement(): Assertion `0' on
multi-table UPDATE IGNORE. The problem was that if there was an active SELECT statement during trigger execution, an error risen during the execution may cause a crash. The fix is to temporary reset LEX::current_select before trigger execution and restore it afterwards. This way errors risen during the trigger execution are processed as if there was no active SELECT.
This commit is contained in:
parent
3d5b9792e6
commit
70807d1473
@ -474,4 +474,25 @@ SHOW CREATE TRIGGER db1.trg;
|
||||
ERROR 42000: Access denied; you need the TRIGGER privilege for this operation
|
||||
DROP USER 'no_rights'@'localhost';
|
||||
DROP DATABASE db1;
|
||||
DROP DATABASE IF EXISTS mysqltest_db1;
|
||||
CREATE DATABASE mysqltest_db1;
|
||||
USE mysqltest_db1;
|
||||
GRANT ALL ON mysqltest_db1.* TO mysqltest_u1@localhost;
|
||||
CREATE TABLE t1 (
|
||||
a1 int,
|
||||
a2 int
|
||||
);
|
||||
INSERT INTO t1 VALUES (1, 20);
|
||||
CREATE TRIGGER mysqltest_db1.upd_t1
|
||||
BEFORE UPDATE ON t1 FOR EACH ROW SET new.a2 = 200;
|
||||
CREATE TABLE t2 (
|
||||
a1 int
|
||||
);
|
||||
INSERT INTO t2 VALUES (2);
|
||||
REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_u1@localhost;
|
||||
UPDATE IGNORE t1, t2 SET t1.a1 = 2, t2.a1 = 3 WHERE t1.a1 = 1 AND t2.a1 = 2;
|
||||
ERROR 42000: TRIGGER command denied to user 'mysqltest_u1'@'localhost' for table 't1'
|
||||
DROP DATABASE mysqltest_db1;
|
||||
DROP USER mysqltest_u1@localhost;
|
||||
USE test;
|
||||
End of 5.1 tests.
|
||||
|
@ -932,4 +932,52 @@ disconnect con1;
|
||||
DROP USER 'no_rights'@'localhost';
|
||||
DROP DATABASE db1;
|
||||
|
||||
#
|
||||
# Bug#55421 Protocol::end_statement(): Assertion `0' on multi-table UPDATE IGNORE
|
||||
# To reproduce a crash we need to provoke a trigger execution with
|
||||
# the following conditions:
|
||||
# - active SELECT statement during trigger execution
|
||||
# (i.e. LEX::current_select != NULL);
|
||||
# - IGNORE option (i.e. LEX::current_select->no_error == TRUE);
|
||||
--disable_warnings
|
||||
DROP DATABASE IF EXISTS mysqltest_db1;
|
||||
--enable_warnings
|
||||
|
||||
CREATE DATABASE mysqltest_db1;
|
||||
USE mysqltest_db1;
|
||||
|
||||
GRANT ALL ON mysqltest_db1.* TO mysqltest_u1@localhost;
|
||||
|
||||
--connect(con1,localhost,mysqltest_u1,,mysqltest_db1)
|
||||
|
||||
CREATE TABLE t1 (
|
||||
a1 int,
|
||||
a2 int
|
||||
);
|
||||
INSERT INTO t1 VALUES (1, 20);
|
||||
|
||||
CREATE TRIGGER mysqltest_db1.upd_t1
|
||||
BEFORE UPDATE ON t1 FOR EACH ROW SET new.a2 = 200;
|
||||
|
||||
CREATE TABLE t2 (
|
||||
a1 int
|
||||
);
|
||||
|
||||
INSERT INTO t2 VALUES (2);
|
||||
|
||||
--connection default
|
||||
|
||||
REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_u1@localhost;
|
||||
|
||||
--error ER_TABLEACCESS_DENIED_ERROR
|
||||
UPDATE IGNORE t1, t2 SET t1.a1 = 2, t2.a1 = 3 WHERE t1.a1 = 1 AND t2.a1 = 2;
|
||||
# Cleanup
|
||||
|
||||
DROP DATABASE mysqltest_db1;
|
||||
DROP USER mysqltest_u1@localhost;
|
||||
|
||||
--disconnect con1
|
||||
--connection default
|
||||
USE test;
|
||||
|
||||
--echo End of 5.1 tests.
|
||||
|
@ -1989,6 +1989,7 @@ bool Table_triggers_list::process_triggers(THD *thd,
|
||||
bool err_status;
|
||||
Sub_statement_state statement_state;
|
||||
sp_head *sp_trigger= bodies[event][time_type];
|
||||
SELECT_LEX *save_current_select;
|
||||
|
||||
if (sp_trigger == NULL)
|
||||
return FALSE;
|
||||
@ -2012,11 +2013,19 @@ bool Table_triggers_list::process_triggers(THD *thd,
|
||||
|
||||
thd->reset_sub_statement_state(&statement_state, SUB_STMT_TRIGGER);
|
||||
|
||||
/*
|
||||
Reset current_select before call execute_trigger() and
|
||||
restore it after return from one. This way error is set
|
||||
in case of failure during trigger execution.
|
||||
*/
|
||||
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;
|
||||
|
||||
thd->restore_sub_statement_state(&statement_state);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user