From 5e0f4e53c5902a3f5f41ec2a4dda3f6691a80230 Mon Sep 17 00:00:00 2001 From: "gkodinov/kgeorge@macbook.gmz" <> Date: Tue, 21 Nov 2006 10:11:43 +0200 Subject: [PATCH] Bug#23556: TRUNCATE TABLE still maps to DELETE This is the 5.0 part of the fix. Currently TRUNCATE command will not call delete_all_rows() in the handler (that implements the "fast" TRUNCATE for InnoDB) when there are triggers on the table. As decided by the architecture team TRUNCATE must use "fast" TRUNCATE even when there are triggers. Thus it must ignore the triggers. Made TRUNCATE to ignore the triggers and call delete_all_rows() for all storage engines to maintain engine consistency. --- mysql-test/r/trigger.result | 25 +++++++++++++++++++++++++ mysql-test/t/trigger.test | 25 +++++++++++++++++++++++++ sql/sql_delete.cc | 6 +++++- 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result index 5d643057666..54534ea5930 100644 --- a/mysql-test/r/trigger.result +++ b/mysql-test/r/trigger.result @@ -1241,4 +1241,29 @@ i j 2 2 13 13 drop table t1; +CREATE TABLE t1 (a INT PRIMARY KEY); +CREATE TABLE t2 (a INT PRIMARY KEY); +INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8); +CREATE TRIGGER trg_t1 BEFORE DELETE on t1 FOR EACH ROW +INSERT INTO t2 VALUES (OLD.a); +FLUSH STATUS; +TRUNCATE t1; +SHOW STATUS LIKE 'handler_delete'; +Variable_name Value +Handler_delete 0 +SELECT COUNT(*) FROM t2; +COUNT(*) +0 +INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8); +DELETE FROM t2; +FLUSH STATUS; +DELETE FROM t1; +SHOW STATUS LIKE 'handler_delete'; +Variable_name Value +Handler_delete 8 +SELECT COUNT(*) FROM t2; +COUNT(*) +8 +DROP TRIGGER trg_t1; +DROP TABLE t1,t2; End of 5.0 tests diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test index 92320648033..dd3293b815f 100644 --- a/mysql-test/t/trigger.test +++ b/mysql-test/t/trigger.test @@ -1498,5 +1498,30 @@ update t1 set i= i+ 10 where j > 2; select * from t1; drop table t1; +# +# Bug#23556 TRUNCATE TABLE still maps to DELETE +# +CREATE TABLE t1 (a INT PRIMARY KEY); +CREATE TABLE t2 (a INT PRIMARY KEY); +INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8); + +CREATE TRIGGER trg_t1 BEFORE DELETE on t1 FOR EACH ROW + INSERT INTO t2 VALUES (OLD.a); + +FLUSH STATUS; +TRUNCATE t1; +SHOW STATUS LIKE 'handler_delete'; +SELECT COUNT(*) FROM t2; + +INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8); +DELETE FROM t2; + +FLUSH STATUS; +DELETE FROM t1; +SHOW STATUS LIKE 'handler_delete'; +SELECT COUNT(*) FROM t2; + +DROP TRIGGER trg_t1; +DROP TABLE t1,t2; --echo End of 5.0 tests diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index e13e7728708..0d47c2a2623 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -76,10 +76,14 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, Test if the user wants to delete all rows and deletion doesn't have any side-effects (because of triggers), so we can use optimized handler::delete_all_rows() method. + We implement fast TRUNCATE for InnoDB even if triggers are present. + TRUNCATE ignores triggers. */ if (!using_limit && const_cond && (!conds || conds->val_int()) && !(specialflag & (SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE)) && - !(table->triggers && table->triggers->has_delete_triggers())) + (thd->lex->sql_command == SQLCOM_TRUNCATE || + !(table->triggers && table->triggers->has_delete_triggers())) + ) { deleted= table->file->records; if (!(error=table->file->delete_all_rows()))