List:Commits« Previous MessageNext Message »
From:Konstantin Osipov Date:May 20 2010 12:07pm
Subject:bzr commit into mysql-trunk-runtime branch (kostja:3019) Bug#42643
View as plain text  
#At file:///opt/local/work/trunk-runtime/ based on revid:kostja@stripped

 3019 Konstantin Osipov	2010-05-20 [merge]
      Bug#42643, with review comments.

    added:
      sql/datadict.cc
      sql/datadict.h
      sql/sql_truncate.cc
      sql/sql_truncate.h
    modified:
      .bzrignore
      libmysqld/CMakeLists.txt
      libmysqld/Makefile.am
      mysql-test/extra/binlog_tests/binlog_truncate.test
      mysql-test/include/mix1.inc
      mysql-test/r/innodb_bug38231.result
      mysql-test/r/innodb_mysql.result
      mysql-test/r/mdl_sync.result
      mysql-test/r/partition_innodb_semi_consistent.result
      mysql-test/r/truncate.result
      mysql-test/suite/binlog/r/binlog_truncate_innodb.result
      mysql-test/suite/binlog/r/binlog_truncate_myisam.result
      mysql-test/suite/binlog/t/binlog_truncate_innodb.test
      mysql-test/suite/binlog/t/binlog_truncate_myisam.test
      mysql-test/suite/binlog/t/disabled.def
      mysql-test/t/innodb_bug38231.test
      mysql-test/t/mdl_sync.test
      mysql-test/t/partition_innodb_semi_consistent.test
      mysql-test/t/truncate.test
      sql/CMakeLists.txt
      sql/Makefile.am
      sql/sql_base.cc
      sql/sql_bitmap.h
      sql/sql_delete.cc
      sql/sql_delete.h
      sql/sql_parse.cc
      sql/sql_rename.cc
      sql/sql_show.cc
      sql/sql_table.cc
      sql/sql_view.cc
      sql/sql_view.h
      sql/table.h
=== modified file '.bzrignore'
--- a/.bzrignore	2010-04-21 19:59:19 +0000
+++ b/.bzrignore	2010-05-20 12:07:41 +0000
@@ -996,6 +996,8 @@ libmysqld/.deps/sql_crypt.Po
 libmysqld/.deps/sql_cursor.Po
 libmysqld/.deps/sql_db.Po
 libmysqld/.deps/sql_delete.Po
+libmysqld/.deps/sql_truncate.Po
+libmysqld/.deps/datadict.Po
 libmysqld/.deps/sql_derived.Po
 libmysqld/.deps/sql_do.Po
 libmysqld/.deps/sql_error.Po
@@ -1172,6 +1174,8 @@ libmysqld/sql_cursor.cc
 libmysqld/sql_cursor.h
 libmysqld/sql_db.cc
 libmysqld/sql_delete.cc
+libmysqld/sql_truncate.cc
+libmysqld/datadict.cc
 libmysqld/sql_derived.cc
 libmysqld/sql_do.cc
 libmysqld/sql_error.cc
@@ -2062,6 +2066,8 @@ sql/.deps/sql_crypt.Po
 sql/.deps/sql_cursor.Po
 sql/.deps/sql_db.Po
 sql/.deps/sql_delete.Po
+sql/.deps/sql_truncate.Po
+sql/.deps/datadict.Po
 sql/.deps/sql_derived.Po
 sql/.deps/sql_do.Po
 sql/.deps/sql_error.Po

=== modified file 'libmysqld/CMakeLists.txt'
--- a/libmysqld/CMakeLists.txt	2010-04-13 15:04:45 +0000
+++ b/libmysqld/CMakeLists.txt	2010-05-20 12:07:41 +0000
@@ -63,7 +63,8 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc l
            ../sql/sql_class.cc ../sql/sql_crypt.cc ../sql/sql_cursor.cc 
            ../sql/sql_db.cc ../sql/sql_delete.cc ../sql/sql_derived.cc 
            ../sql/sql_do.cc ../sql/sql_error.cc ../sql/sql_handler.cc 
-           ../sql/sql_help.cc ../sql/sql_insert.cc
+           ../sql/sql_help.cc ../sql/sql_insert.cc ../sql/datadict.cc
+           ../sql/sql_truncate.cc
            ../sql/sql_lex.cc ../sql/keycaches.cc
            ../sql/sql_list.cc ../sql/sql_load.cc ../sql/sql_locale.cc 
            ../sql/sql_binlog.cc ../sql/sql_manager.cc ../sql/sql_map.cc 

=== modified file 'libmysqld/Makefile.am'
--- a/libmysqld/Makefile.am	2010-04-13 15:04:45 +0000
+++ b/libmysqld/Makefile.am	2010-05-20 12:07:41 +0000
@@ -63,9 +63,10 @@ sqlsources = derror.cc field.cc field_co
 	protocol.cc net_serv.cc opt_range.cc \
 	opt_sum.cc procedure.cc records.cc sql_acl.cc \
 	sql_load.cc discover.cc sql_locale.cc \
-	sql_profile.cc \
+	sql_profile.cc sql_truncate.cc \
 	sql_analyse.cc sql_base.cc sql_cache.cc sql_class.cc \
 	sql_crypt.cc sql_db.cc sql_delete.cc sql_error.cc sql_insert.cc \
+	datadict.cc \
 	sql_lex.cc sql_list.cc sql_manager.cc sql_map.cc \
 	scheduler.cc sql_connect.cc sql_parse.cc \
 	sql_prepare.cc sql_derived.cc sql_rename.cc \

=== modified file 'mysql-test/extra/binlog_tests/binlog_truncate.test'
--- a/mysql-test/extra/binlog_tests/binlog_truncate.test	2009-02-06 16:06:41 +0000
+++ b/mysql-test/extra/binlog_tests/binlog_truncate.test	2010-03-17 20:06:37 +0000
@@ -25,3 +25,44 @@ TRUNCATE TABLE t2;
 source include/show_binlog_events.inc;
 
 DROP TABLE t1,t2;
+
+--echo #
+--echo # Bug#42643: InnoDB does not support replication of TRUNCATE TABLE
+--echo #
+
+eval CREATE TABLE t1 (a INT) ENGINE=$engine;
+eval CREATE TABLE t2 (a INT) ENGINE=$engine;
+INSERT INTO t1 VALUES (1),(2);
+
+let $binlog_start = query_get_value("SHOW MASTER STATUS", Position, 1);
+if (`select length('$before_truncate') > 0`) {
+  eval $before_truncate;
+}
+
+--echo # Connection: default
+BEGIN;
+INSERT INTO t2 SELECT * FROM t1;
+
+connect (truncate,localhost,root,,);
+--echo # Connection: truncate
+send TRUNCATE TABLE t1;
+
+connection default;
+--echo # Connection: default
+INSERT INTO t2 SELECT * FROM t1;
+SELECT COUNT(*) FROM t2;
+COMMIT;
+
+connection truncate;
+--echo # Connection: truncate
+--echo # Reaping TRUNCATE TABLE
+--reap
+SELECT COUNT(*) FROM t1;
+SELECT COUNT(*) FROM t2;
+
+connection default;
+--echo # Connection: default
+
+source include/show_binlog_events.inc;
+disconnect truncate;
+DROP TABLE t1,t2;

=== modified file 'mysql-test/include/mix1.inc'
--- a/mysql-test/include/mix1.inc	2009-12-08 07:39:49 +0000
+++ b/mysql-test/include/mix1.inc	2010-03-17 20:06:37 +0000
@@ -1351,6 +1351,13 @@ connection con1;
 SELECT * FROM t1;
 ROLLBACK;
 
+--echo # Switch to connection con2
+connection con2;
+ROLLBACK;
+
+--echo # Switch to connection con1
+connection con1;
+
 --echo # 2. test for serialized update:
 
 CREATE TABLE t2 (a INT);
@@ -1435,6 +1442,7 @@ connection con2;
 --reap
 SELECT * FROM t1;
 
+--enable_abort_on_error
 connection default;
 disconnect con1;
 disconnect con2;
@@ -1556,3 +1564,32 @@ SELECT 1 FROM (SELECT COUNT(DISTINCT c1)
 DROP TABLE t1;
 
 --echo End of 5.1 tests
+
+--echo #
+--echo # Bug#42643: InnoDB does not support replication of TRUNCATE TABLE
+--echo #
+
+eval CREATE TABLE t1 (a INT) ENGINE=$engine_type;
+INSERT INTO t1 VALUES (1),(2),(3);
+BEGIN;
+SELECT * FROM t1 ORDER BY a;
+--echo # Connection con1
+connect (con1, localhost, root,,);
+--send TRUNCATE TABLE t1;
+--echo # Connection default
+connection default;
+let $wait_condition= SELECT COUNT(*)=1 FROM information_schema.processlist
+  WHERE state='Waiting for table' AND info='TRUNCATE TABLE t1';
+--source include/wait_condition.inc
+SELECT * FROM t1 ORDER BY a;
+ROLLBACK;
+--echo # Connection con1
+connection con1;
+--echo # Reaping TRUNCATE TABLE
+--reap
+SELECT * FROM t1;
+--echo # Disconnect con1
+disconnect con1;
+--echo # Connection default
+connection default;
+DROP TABLE t1;

=== modified file 'mysql-test/r/innodb_bug38231.result'
--- a/mysql-test/r/innodb_bug38231.result	2008-12-14 21:26:31 +0000
+++ b/mysql-test/r/innodb_bug38231.result	2010-03-17 20:06:37 +0000
@@ -1,11 +1,2 @@
 SET storage_engine=InnoDB;
-INSERT INTO bug38231 VALUES (1), (10), (300);
-SET autocommit=0;
-SELECT * FROM bug38231 FOR UPDATE;
-a
-1
-10
-300
-TRUNCATE TABLE bug38231;
-COMMIT;
 DROP TABLE bug38231;

=== modified file 'mysql-test/r/innodb_mysql.result'
--- a/mysql-test/r/innodb_mysql.result	2010-03-24 15:03:44 +0000
+++ b/mysql-test/r/innodb_mysql.result	2010-05-20 12:07:41 +0000
@@ -1590,6 +1590,9 @@ SELECT * FROM t1;
 a	b
 1	12
 ROLLBACK;
+# Switch to connection con2
+ROLLBACK;
+# Switch to connection con1
 # 2. test for serialized update:
 CREATE TABLE t2 (a INT);
 TRUNCATE t1;
@@ -1764,6 +1767,33 @@ id	select_type	table	type	possible_keys	
 2	DERIVED	t1	index	c3,c2	c2	14	NULL	5	
 DROP TABLE t1;
 End of 5.1 tests
+#
+# Bug#42643: InnoDB does not support replication of TRUNCATE TABLE
+#
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(2),(3);
+BEGIN;
+SELECT * FROM t1 ORDER BY a;
+a
+1
+2
+3
+# Connection con1
+TRUNCATE TABLE t1;;
+# Connection default
+SELECT * FROM t1 ORDER BY a;
+a
+1
+2
+3
+ROLLBACK;
+# Connection con1
+# Reaping TRUNCATE TABLE
+SELECT * FROM t1;
+a
+# Disconnect con1
+# Connection default
+DROP TABLE t1;
 drop table if exists t1, t2, t3;
 create table t1(a int);
 insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);

=== modified file 'mysql-test/r/mdl_sync.result'
--- a/mysql-test/r/mdl_sync.result	2010-03-13 10:58:27 +0000
+++ b/mysql-test/r/mdl_sync.result	2010-03-17 20:06:37 +0000
@@ -2381,3 +2381,41 @@ commit;
 # Reap ALTER TABLE.
 set debug_sync= 'RESET';
 drop table t1;
+#
+# Bug#42643: InnoDB does not support replication of TRUNCATE TABLE
+#
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(2),(3);
+# Connection: con1
+SET debug_sync='truncate_by_delete SIGNAL parked_truncate WAIT_FOR go_truncate';
+TRUNCATE TABLE t1;
+# Connection: default
+SET debug_sync= 'now WAIT_FOR parked_truncate';
+# Connection: con2
+SET debug_sync='after_open_table_ignore_flush SIGNAL parked_show WAIT_FOR go_show';
+SHOW FIELDS FROM t1;
+# Connection: default
+SET debug_sync= 'now WAIT_FOR parked_show';
+# Connection: con3
+SET debug_sync= 'after_flush_unlock SIGNAL parked_flush WAIT_FOR go_flush';
+FLUSH TABLES t1;
+# Connection: default
+SET debug_sync= 'now WAIT_FOR parked_flush';
+SET debug_sync= 'now SIGNAL go_truncate';
+# Connection: con1
+# Reaping...
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+# Connection: default
+SET debug_sync= 'now SIGNAL go_show';
+# Connection: con2 (SHOW FIELDS FROM t1)
+# Reaping...
+Field	Type	Null	Key	Default	Extra
+a	int(11)	YES		NULL	
+# Connection: default
+SET debug_sync= 'now SIGNAL go_flush';
+# Connection: con3 (FLUSH TABLES t1)
+# Reaping...
+# Connection: default
+SET debug_sync= 'RESET';
+DROP TABLE t1;

=== modified file 'mysql-test/r/partition_innodb_semi_consistent.result'
--- a/mysql-test/r/partition_innodb_semi_consistent.result	2009-12-04 23:02:48 +0000
+++ b/mysql-test/r/partition_innodb_semi_consistent.result	2010-03-17 20:06:37 +0000
@@ -64,6 +64,7 @@ a	b
 # Switch to connection con2
 UPDATE t1 SET b = 21 WHERE a = 1;
 ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+ROLLBACK;
 # Switch to connection con1
 SELECT * FROM t1;
 a	b
@@ -99,6 +100,7 @@ a	b
 SELECT * FROM t1;
 a	b
 1	init+con1+con2
+COMMIT;
 # Switch to connection con1
 # 3. test for updated key column:
 TRUNCATE t1;

=== modified file 'mysql-test/r/truncate.result'
--- a/mysql-test/r/truncate.result	2009-12-11 12:24:23 +0000
+++ b/mysql-test/r/truncate.result	2010-03-17 20:06:37 +0000
@@ -99,7 +99,7 @@ LOCK TABLE t1 WRITE;
 SELECT * FROM v1;
 ERROR HY000: Table 'v1' was not locked with LOCK TABLES
 TRUNCATE v1;
-ERROR 42S02: Table 'test.v1' doesn't exist
+ERROR HY000: Table 'v1' was not locked with LOCK TABLES
 SELECT * FROM v1;
 ERROR HY000: Table 'v1' was not locked with LOCK TABLES
 UNLOCK TABLES;
@@ -107,7 +107,7 @@ LOCK TABLE t1 WRITE, t2 WRITE;
 SELECT * FROM v1;
 ERROR HY000: Table 'v1' was not locked with LOCK TABLES
 TRUNCATE v1;
-ERROR 42S02: Table 'test.v1' doesn't exist
+ERROR HY000: Table 'v1' was not locked with LOCK TABLES
 SELECT * FROM v1;
 ERROR HY000: Table 'v1' was not locked with LOCK TABLES
 UNLOCK TABLES;
@@ -117,7 +117,7 @@ c1
 1
 3
 TRUNCATE v1;
-ERROR 42S02: Table 'test.v1' doesn't exist
+ERROR HY000: Table 'v1' was not locked with LOCK TABLES
 SELECT * FROM v1;
 c1
 1
@@ -129,7 +129,7 @@ c1
 1
 3
 TRUNCATE v1;
-ERROR 42S02: Table 'test.v1' doesn't exist
+ERROR HY000: Table 'v1' was not locked with LOCK TABLES
 SELECT * FROM v1;
 c1
 1

=== modified file 'mysql-test/suite/binlog/r/binlog_truncate_innodb.result'
--- a/mysql-test/suite/binlog/r/binlog_truncate_innodb.result	2009-02-06 16:06:41 +0000
+++ b/mysql-test/suite/binlog/r/binlog_truncate_innodb.result	2010-03-17 20:06:37 +0000
@@ -1,3 +1,6 @@
+SET @old_binlog_format=@@binlog_format;
+SET BINLOG_FORMAT=ROW;
+RESET MASTER;
 CREATE TABLE t1 (a INT) ENGINE=InnoDB;
 CREATE TABLE t2 (a INT) ENGINE=InnoDB;
 INSERT INTO t2 VALUES (1),(2),(3);
@@ -9,6 +12,45 @@ Log_name	Pos	Event_type	Server_id	End_lo
 master-bin.000001	#	Query	#	#	use `test`; TRUNCATE TABLE t1
 master-bin.000001	#	Query	#	#	use `test`; TRUNCATE TABLE t2
 DROP TABLE t1,t2;
+#
+# Bug#42643: InnoDB does not support replication of TRUNCATE TABLE
+#
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+CREATE TABLE t2 (a INT) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(2);
+# Connection: default
+BEGIN;
+INSERT INTO t2 SELECT * FROM t1;
+# Connection: truncate
+TRUNCATE TABLE t1;
+# Connection: default
+INSERT INTO t2 SELECT * FROM t1;
+SELECT COUNT(*) FROM t2;
+COUNT(*)
+4
+COMMIT;
+# Connection: truncate
+# Reaping TRUNCATE TABLE
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+0
+SELECT COUNT(*) FROM t2;
+COUNT(*)
+4
+# Connection: default
+show binlog events from <binlog_start>;
+Log_name	Pos	Event_type	Server_id	End_log_pos	Info
+master-bin.000001	#	Query	#	#	BEGIN
+master-bin.000001	#	Table_map	#	#	table_id: # (test.t2)
+master-bin.000001	#	Write_rows	#	#	table_id: # flags: STMT_END_F
+master-bin.000001	#	Table_map	#	#	table_id: # (test.t2)
+master-bin.000001	#	Write_rows	#	#	table_id: # flags: STMT_END_F
+master-bin.000001	#	Xid	#	#	COMMIT /* XID */
+master-bin.000001	#	Query	#	#	use `test`; TRUNCATE TABLE t1
+DROP TABLE t1,t2;
+# Even though the isolation level might be permissive, truncate
+# table follows a stricter isolation as its locking is based on
+# (exclusive) metadata locks.
 CREATE TABLE t1 (a INT) ENGINE=InnoDB;
 CREATE TABLE t2 (a INT) ENGINE=InnoDB;
 INSERT INTO t2 VALUES (1),(2),(3);
@@ -22,6 +64,43 @@ Log_name	Pos	Event_type	Server_id	End_lo
 master-bin.000001	#	Query	#	#	use `test`; TRUNCATE TABLE t1
 master-bin.000001	#	Query	#	#	use `test`; TRUNCATE TABLE t2
 DROP TABLE t1,t2;
+#
+# Bug#42643: InnoDB does not support replication of TRUNCATE TABLE
+#
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+CREATE TABLE t2 (a INT) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(2);
+SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+# Connection: default
+BEGIN;
+INSERT INTO t2 SELECT * FROM t1;
+# Connection: truncate
+TRUNCATE TABLE t1;
+# Connection: default
+INSERT INTO t2 SELECT * FROM t1;
+SELECT COUNT(*) FROM t2;
+COUNT(*)
+4
+COMMIT;
+# Connection: truncate
+# Reaping TRUNCATE TABLE
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+0
+SELECT COUNT(*) FROM t2;
+COUNT(*)
+4
+# Connection: default
+show binlog events from <binlog_start>;
+Log_name	Pos	Event_type	Server_id	End_log_pos	Info
+master-bin.000001	#	Query	#	#	BEGIN
+master-bin.000001	#	Table_map	#	#	table_id: # (test.t2)
+master-bin.000001	#	Write_rows	#	#	table_id: # flags: STMT_END_F
+master-bin.000001	#	Table_map	#	#	table_id: # (test.t2)
+master-bin.000001	#	Write_rows	#	#	table_id: # flags: STMT_END_F
+master-bin.000001	#	Xid	#	#	COMMIT /* XID */
+master-bin.000001	#	Query	#	#	use `test`; TRUNCATE TABLE t1
+DROP TABLE t1,t2;
 CREATE TABLE t1 (a INT) ENGINE=InnoDB;
 CREATE TABLE t2 (a INT) ENGINE=InnoDB;
 INSERT INTO t2 VALUES (1),(2),(3);
@@ -35,6 +114,193 @@ Log_name	Pos	Event_type	Server_id	End_lo
 master-bin.000001	#	Query	#	#	use `test`; TRUNCATE TABLE t1
 master-bin.000001	#	Query	#	#	use `test`; TRUNCATE TABLE t2
 DROP TABLE t1,t2;
+#
+# Bug#42643: InnoDB does not support replication of TRUNCATE TABLE
+#
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+CREATE TABLE t2 (a INT) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(2);
+SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
+# Connection: default
+BEGIN;
+INSERT INTO t2 SELECT * FROM t1;
+# Connection: truncate
+TRUNCATE TABLE t1;
+# Connection: default
+INSERT INTO t2 SELECT * FROM t1;
+SELECT COUNT(*) FROM t2;
+COUNT(*)
+4
+COMMIT;
+# Connection: truncate
+# Reaping TRUNCATE TABLE
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+0
+SELECT COUNT(*) FROM t2;
+COUNT(*)
+4
+# Connection: default
+show binlog events from <binlog_start>;
+Log_name	Pos	Event_type	Server_id	End_log_pos	Info
+master-bin.000001	#	Query	#	#	BEGIN
+master-bin.000001	#	Table_map	#	#	table_id: # (test.t2)
+master-bin.000001	#	Write_rows	#	#	table_id: # flags: STMT_END_F
+master-bin.000001	#	Table_map	#	#	table_id: # (test.t2)
+master-bin.000001	#	Write_rows	#	#	table_id: # flags: STMT_END_F
+master-bin.000001	#	Xid	#	#	COMMIT /* XID */
+master-bin.000001	#	Query	#	#	use `test`; TRUNCATE TABLE t1
+DROP TABLE t1,t2;
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+CREATE TABLE t2 (a INT) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1),(2),(3);
+SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
+**** Truncate of empty table shall be logged
+TRUNCATE TABLE t1;
+SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
+TRUNCATE TABLE t2;
+show binlog events from <binlog_start>;
+Log_name	Pos	Event_type	Server_id	End_log_pos	Info
+master-bin.000001	#	Query	#	#	use `test`; TRUNCATE TABLE t1
+master-bin.000001	#	Query	#	#	use `test`; TRUNCATE TABLE t2
+DROP TABLE t1,t2;
+#
+# Bug#42643: InnoDB does not support replication of TRUNCATE TABLE
+#
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+CREATE TABLE t2 (a INT) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(2);
+SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
+# Connection: default
+BEGIN;
+INSERT INTO t2 SELECT * FROM t1;
+# Connection: truncate
+TRUNCATE TABLE t1;
+# Connection: default
+INSERT INTO t2 SELECT * FROM t1;
+SELECT COUNT(*) FROM t2;
+COUNT(*)
+4
+COMMIT;
+# Connection: truncate
+# Reaping TRUNCATE TABLE
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+0
+SELECT COUNT(*) FROM t2;
+COUNT(*)
+4
+# Connection: default
+show binlog events from <binlog_start>;
+Log_name	Pos	Event_type	Server_id	End_log_pos	Info
+master-bin.000001	#	Query	#	#	BEGIN
+master-bin.000001	#	Table_map	#	#	table_id: # (test.t2)
+master-bin.000001	#	Write_rows	#	#	table_id: # flags: STMT_END_F
+master-bin.000001	#	Table_map	#	#	table_id: # (test.t2)
+master-bin.000001	#	Write_rows	#	#	table_id: # flags: STMT_END_F
+master-bin.000001	#	Xid	#	#	COMMIT /* XID */
+master-bin.000001	#	Query	#	#	use `test`; TRUNCATE TABLE t1
+DROP TABLE t1,t2;
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+CREATE TABLE t2 (a INT) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1),(2),(3);
+SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
+**** Truncate of empty table shall be logged
+TRUNCATE TABLE t1;
+SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
+TRUNCATE TABLE t2;
+show binlog events from <binlog_start>;
+Log_name	Pos	Event_type	Server_id	End_log_pos	Info
+master-bin.000001	#	Query	#	#	use `test`; TRUNCATE TABLE t1
+master-bin.000001	#	Query	#	#	use `test`; TRUNCATE TABLE t2
+DROP TABLE t1,t2;
+#
+# Bug#42643: InnoDB does not support replication of TRUNCATE TABLE
+#
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+CREATE TABLE t2 (a INT) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(2);
+SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
+# Connection: default
+BEGIN;
+INSERT INTO t2 SELECT * FROM t1;
+# Connection: truncate
+TRUNCATE TABLE t1;
+# Connection: default
+INSERT INTO t2 SELECT * FROM t1;
+SELECT COUNT(*) FROM t2;
+COUNT(*)
+4
+COMMIT;
+# Connection: truncate
+# Reaping TRUNCATE TABLE
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+0
+SELECT COUNT(*) FROM t2;
+COUNT(*)
+4
+# Connection: default
+show binlog events from <binlog_start>;
+Log_name	Pos	Event_type	Server_id	End_log_pos	Info
+master-bin.000001	#	Query	#	#	BEGIN
+master-bin.000001	#	Table_map	#	#	table_id: # (test.t2)
+master-bin.000001	#	Write_rows	#	#	table_id: # flags: STMT_END_F
+master-bin.000001	#	Table_map	#	#	table_id: # (test.t2)
+master-bin.000001	#	Write_rows	#	#	table_id: # flags: STMT_END_F
+master-bin.000001	#	Xid	#	#	COMMIT /* XID */
+master-bin.000001	#	Query	#	#	use `test`; TRUNCATE TABLE t1
+DROP TABLE t1,t2;
+SET BINLOG_FORMAT=STATEMENT;
+RESET MASTER;
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+CREATE TABLE t2 (a INT) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1),(2),(3);
+SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
+**** Truncate of empty table shall be logged
+TRUNCATE TABLE t1;
+SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
+TRUNCATE TABLE t2;
+show binlog events from <binlog_start>;
+Log_name	Pos	Event_type	Server_id	End_log_pos	Info
+master-bin.000001	#	Query	#	#	use `test`; TRUNCATE TABLE t1
+master-bin.000001	#	Query	#	#	use `test`; TRUNCATE TABLE t2
+DROP TABLE t1,t2;
+#
+# Bug#42643: InnoDB does not support replication of TRUNCATE TABLE
+#
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+CREATE TABLE t2 (a INT) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(2);
+SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
+# Connection: default
+BEGIN;
+INSERT INTO t2 SELECT * FROM t1;
+# Connection: truncate
+TRUNCATE TABLE t1;
+# Connection: default
+INSERT INTO t2 SELECT * FROM t1;
+SELECT COUNT(*) FROM t2;
+COUNT(*)
+4
+COMMIT;
+# Connection: truncate
+# Reaping TRUNCATE TABLE
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+0
+SELECT COUNT(*) FROM t2;
+COUNT(*)
+4
+# Connection: default
+show binlog events from <binlog_start>;
+Log_name	Pos	Event_type	Server_id	End_log_pos	Info
+master-bin.000001	#	Query	#	#	BEGIN
+master-bin.000001	#	Query	#	#	use `test`; INSERT INTO t2 SELECT * FROM t1
+master-bin.000001	#	Query	#	#	use `test`; INSERT INTO t2 SELECT * FROM t1
+master-bin.000001	#	Xid	#	#	COMMIT /* XID */
+master-bin.000001	#	Query	#	#	use `test`; TRUNCATE TABLE t1
+DROP TABLE t1,t2;
 CREATE TABLE t1 (a INT) ENGINE=InnoDB;
 CREATE TABLE t2 (a INT) ENGINE=InnoDB;
 INSERT INTO t2 VALUES (1),(2),(3);
@@ -48,6 +314,41 @@ Log_name	Pos	Event_type	Server_id	End_lo
 master-bin.000001	#	Query	#	#	use `test`; TRUNCATE TABLE t1
 master-bin.000001	#	Query	#	#	use `test`; TRUNCATE TABLE t2
 DROP TABLE t1,t2;
+#
+# Bug#42643: InnoDB does not support replication of TRUNCATE TABLE
+#
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+CREATE TABLE t2 (a INT) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(2);
+SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
+# Connection: default
+BEGIN;
+INSERT INTO t2 SELECT * FROM t1;
+# Connection: truncate
+TRUNCATE TABLE t1;
+# Connection: default
+INSERT INTO t2 SELECT * FROM t1;
+SELECT COUNT(*) FROM t2;
+COUNT(*)
+4
+COMMIT;
+# Connection: truncate
+# Reaping TRUNCATE TABLE
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+0
+SELECT COUNT(*) FROM t2;
+COUNT(*)
+4
+# Connection: default
+show binlog events from <binlog_start>;
+Log_name	Pos	Event_type	Server_id	End_log_pos	Info
+master-bin.000001	#	Query	#	#	BEGIN
+master-bin.000001	#	Query	#	#	use `test`; INSERT INTO t2 SELECT * FROM t1
+master-bin.000001	#	Query	#	#	use `test`; INSERT INTO t2 SELECT * FROM t1
+master-bin.000001	#	Xid	#	#	COMMIT /* XID */
+master-bin.000001	#	Query	#	#	use `test`; TRUNCATE TABLE t1
+DROP TABLE t1,t2;
 CREATE TABLE t1 (a INT) ENGINE=InnoDB;
 CREATE TABLE t2 (a INT) ENGINE=InnoDB;
 INSERT INTO t2 VALUES (1),(2),(3);
@@ -61,3 +362,39 @@ Log_name	Pos	Event_type	Server_id	End_lo
 master-bin.000001	#	Query	#	#	use `test`; TRUNCATE TABLE t1
 master-bin.000001	#	Query	#	#	use `test`; TRUNCATE TABLE t2
 DROP TABLE t1,t2;
+#
+# Bug#42643: InnoDB does not support replication of TRUNCATE TABLE
+#
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+CREATE TABLE t2 (a INT) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(2);
+SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
+# Connection: default
+BEGIN;
+INSERT INTO t2 SELECT * FROM t1;
+# Connection: truncate
+TRUNCATE TABLE t1;
+# Connection: default
+INSERT INTO t2 SELECT * FROM t1;
+SELECT COUNT(*) FROM t2;
+COUNT(*)
+4
+COMMIT;
+# Connection: truncate
+# Reaping TRUNCATE TABLE
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+0
+SELECT COUNT(*) FROM t2;
+COUNT(*)
+4
+# Connection: default
+show binlog events from <binlog_start>;
+Log_name	Pos	Event_type	Server_id	End_log_pos	Info
+master-bin.000001	#	Query	#	#	BEGIN
+master-bin.000001	#	Query	#	#	use `test`; INSERT INTO t2 SELECT * FROM t1
+master-bin.000001	#	Query	#	#	use `test`; INSERT INTO t2 SELECT * FROM t1
+master-bin.000001	#	Xid	#	#	COMMIT /* XID */
+master-bin.000001	#	Query	#	#	use `test`; TRUNCATE TABLE t1
+DROP TABLE t1,t2;
+SET BINLOG_FORMAT=@old_binlog_format;

=== modified file 'mysql-test/suite/binlog/r/binlog_truncate_myisam.result'
--- a/mysql-test/suite/binlog/r/binlog_truncate_myisam.result	2009-02-10 21:26:37 +0000
+++ b/mysql-test/suite/binlog/r/binlog_truncate_myisam.result	2010-03-17 20:06:37 +0000
@@ -1,3 +1,5 @@
+SET @old_binlog_format=@@binlog_format;
+SET BINLOG_FORMAT=ROW;
 RESET MASTER;
 CREATE TABLE t1 (a INT) ENGINE=MyISAM;
 CREATE TABLE t2 (a INT) ENGINE=MyISAM;
@@ -10,3 +12,91 @@ Log_name	Pos	Event_type	Server_id	End_lo
 master-bin.000001	#	Query	#	#	use `test`; TRUNCATE TABLE t1
 master-bin.000001	#	Query	#	#	use `test`; TRUNCATE TABLE t2
 DROP TABLE t1,t2;
+#
+# Bug#42643: InnoDB does not support replication of TRUNCATE TABLE
+#
+CREATE TABLE t1 (a INT) ENGINE=MyISAM;
+CREATE TABLE t2 (a INT) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (1),(2);
+# Connection: default
+BEGIN;
+INSERT INTO t2 SELECT * FROM t1;
+# Connection: truncate
+TRUNCATE TABLE t1;
+# Connection: default
+INSERT INTO t2 SELECT * FROM t1;
+SELECT COUNT(*) FROM t2;
+COUNT(*)
+4
+COMMIT;
+# Connection: truncate
+# Reaping TRUNCATE TABLE
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+0
+SELECT COUNT(*) FROM t2;
+COUNT(*)
+4
+# Connection: default
+show binlog events from <binlog_start>;
+Log_name	Pos	Event_type	Server_id	End_log_pos	Info
+master-bin.000001	#	Query	#	#	BEGIN
+master-bin.000001	#	Table_map	#	#	table_id: # (test.t2)
+master-bin.000001	#	Write_rows	#	#	table_id: # flags: STMT_END_F
+master-bin.000001	#	Query	#	#	COMMIT
+master-bin.000001	#	Query	#	#	BEGIN
+master-bin.000001	#	Table_map	#	#	table_id: # (test.t2)
+master-bin.000001	#	Write_rows	#	#	table_id: # flags: STMT_END_F
+master-bin.000001	#	Query	#	#	COMMIT
+master-bin.000001	#	Query	#	#	use `test`; TRUNCATE TABLE t1
+DROP TABLE t1,t2;
+SET BINLOG_FORMAT=STATEMENT;
+RESET MASTER;
+CREATE TABLE t1 (a INT) ENGINE=MyISAM;
+CREATE TABLE t2 (a INT) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (1),(2),(3);
+**** Truncate of empty table shall be logged
+TRUNCATE TABLE t1;
+TRUNCATE TABLE t2;
+show binlog events from <binlog_start>;
+Log_name	Pos	Event_type	Server_id	End_log_pos	Info
+master-bin.000001	#	Query	#	#	use `test`; TRUNCATE TABLE t1
+master-bin.000001	#	Query	#	#	use `test`; TRUNCATE TABLE t2
+DROP TABLE t1,t2;
+#
+# Bug#42643: InnoDB does not support replication of TRUNCATE TABLE
+#
+CREATE TABLE t1 (a INT) ENGINE=MyISAM;
+CREATE TABLE t2 (a INT) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (1),(2);
+# Connection: default
+BEGIN;
+INSERT INTO t2 SELECT * FROM t1;
+# Connection: truncate
+TRUNCATE TABLE t1;
+# Connection: default
+INSERT INTO t2 SELECT * FROM t1;
+SELECT COUNT(*) FROM t2;
+COUNT(*)
+4
+COMMIT;
+# Connection: truncate
+# Reaping TRUNCATE TABLE
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+0
+SELECT COUNT(*) FROM t2;
+COUNT(*)
+4
+# Connection: default
+show binlog events from <binlog_start>;
+Log_name	Pos	Event_type	Server_id	End_log_pos	Info
+master-bin.000001	#	Query	#	#	BEGIN
+master-bin.000001	#	Query	#	#	use `test`; INSERT INTO t2 SELECT * FROM t1
+master-bin.000001	#	Query	#	#	COMMIT
+master-bin.000001	#	Query	#	#	BEGIN
+master-bin.000001	#	Query	#	#	use `test`; INSERT INTO t2 SELECT * FROM t1
+master-bin.000001	#	Query	#	#	COMMIT
+master-bin.000001	#	Query	#	#	use `test`; TRUNCATE TABLE t1
+DROP TABLE t1,t2;
+SET BINLOG_FORMAT=@old_binlog_format;

=== modified file 'mysql-test/suite/binlog/t/binlog_truncate_innodb.test'
--- a/mysql-test/suite/binlog/t/binlog_truncate_innodb.test	2009-02-10 21:26:37 +0000
+++ b/mysql-test/suite/binlog/t/binlog_truncate_innodb.test	2010-03-17 20:06:37 +0000
@@ -1,20 +1,18 @@
 source include/have_log_bin.inc;
 source include/have_innodb.inc;
 
-# It is necessary to reset the master since otherwise the binlog test
-# might show the wrong binary log. The default for SHOW BINLOG EVENTS
-# is to show the first binary log, not the current one (which is
-# actually a better idea).
+let $engine = InnoDB;
+
+SET @old_binlog_format=@@binlog_format;
 
+SET BINLOG_FORMAT=ROW;
 RESET MASTER;
 
-let $engine = InnoDB;
 source extra/binlog_tests/binlog_truncate.test;
 
-# Under transaction isolation level READ UNCOMMITTED and READ
-# COMMITTED, InnoDB does not permit statement-based replication of
-# row-deleting statement. In these cases, TRUNCATE TABLE should still
-# be replicated as a statement.
+--echo # Even though the isolation level might be permissive, truncate
+--echo # table follows a stricter isolation as its locking is based on
+--echo # (exclusive) metadata locks.
 
 let $before_truncate = SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
 source extra/binlog_tests/binlog_truncate.test;
@@ -27,3 +25,16 @@ source extra/binlog_tests/binlog_truncat
 
 let $before_truncate = SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
 source extra/binlog_tests/binlog_truncate.test;
+
+SET BINLOG_FORMAT=STATEMENT;
+RESET MASTER;
+
+source extra/binlog_tests/binlog_truncate.test;
+
+let $before_truncate = SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
+source extra/binlog_tests/binlog_truncate.test;
+
+let $before_truncate = SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
+source extra/binlog_tests/binlog_truncate.test;
+
+SET BINLOG_FORMAT=@old_binlog_format;

=== modified file 'mysql-test/suite/binlog/t/binlog_truncate_myisam.test'
--- a/mysql-test/suite/binlog/t/binlog_truncate_myisam.test	2009-02-10 21:26:37 +0000
+++ b/mysql-test/suite/binlog/t/binlog_truncate_myisam.test	2010-03-17 20:06:37 +0000
@@ -1,11 +1,17 @@
 source include/have_log_bin.inc;
 
-# It is necessary to reset the master since otherwise the binlog test
-# might show the wrong binary log. The default for SHOW BINLOG EVENTS
-# is to show the first binary log, not the current one (which is
-# actually a better idea).
+SET @old_binlog_format=@@binlog_format;
 
+let $engine = MyISAM;
+
+SET BINLOG_FORMAT=ROW;
+RESET MASTER;
+
+source extra/binlog_tests/binlog_truncate.test;
+
+SET BINLOG_FORMAT=STATEMENT;
 RESET MASTER;
 
-let $engine = MyISAM;
 source extra/binlog_tests/binlog_truncate.test;
+
+SET BINLOG_FORMAT=@old_binlog_format;

=== modified file 'mysql-test/suite/binlog/t/disabled.def'
--- a/mysql-test/suite/binlog/t/disabled.def	2010-01-13 23:27:22 +0000
+++ b/mysql-test/suite/binlog/t/disabled.def	2010-03-17 20:06:37 +0000
@@ -9,6 +9,5 @@
 #  Do not use any TAB characters for whitespace.
 #
 ##############################################################################
-binlog_truncate_innodb	: BUG#42643 2009-02-06 mats Changes to InnoDB requires to complete fix for BUG#36763
 binlog_unsafe           : BUG#50312 2010-01-13 lsoares Warnings for unsafe sub-statement not returned to client
 

=== modified file 'mysql-test/t/innodb_bug38231.test'
--- a/mysql-test/t/innodb_bug38231.test	2009-01-08 12:31:34 +0000
+++ b/mysql-test/t/innodb_bug38231.test	2010-03-17 20:06:37 +0000
@@ -49,27 +49,9 @@ UNLOCK TABLES;
 -- disconnect con1
 -- disconnect con2
 
-# test that TRUNCATE works with with row-level locks
-
 -- enable_query_log
 -- enable_result_log
 
-INSERT INTO bug38231 VALUES (1), (10), (300);
-
--- connect (con4,localhost,root,,)
-
--- connection con4
-SET autocommit=0;
-SELECT * FROM bug38231 FOR UPDATE;
-
 -- connection default
-TRUNCATE TABLE bug38231;
-
--- connection con4
-COMMIT;
-
--- connection default
-
--- disconnect con4
 
 DROP TABLE bug38231;

=== modified file 'mysql-test/t/mdl_sync.test'
--- a/mysql-test/t/mdl_sync.test	2010-03-13 10:58:27 +0000
+++ b/mysql-test/t/mdl_sync.test	2010-03-17 20:06:37 +0000
@@ -3468,6 +3468,83 @@ connection default;
 set debug_sync= 'RESET';
 drop table t1;
 
+--echo #
+--echo # Bug#42643: InnoDB does not support replication of TRUNCATE TABLE
+--echo #
+
+connect (con1,localhost,root,,test,,);
+connect (con2,localhost,root,,test,,);
+connect (con3,localhost,root,,test,,);
+
+connection default;
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1),(2),(3);
+
+--echo # Connection: con1
+connection con1;
+SET debug_sync='truncate_by_delete SIGNAL parked_truncate WAIT_FOR go_truncate';
+send TRUNCATE TABLE t1;
+
+connection default;
+--echo # Connection: default
+SET debug_sync= 'now WAIT_FOR parked_truncate';
+
+connection con2;
+--echo # Connection: con2
+SET debug_sync='after_open_table_ignore_flush SIGNAL parked_show WAIT_FOR go_show';
+send SHOW FIELDS FROM t1;
+
+connection default;
+--echo # Connection: default
+SET debug_sync= 'now WAIT_FOR parked_show';
+
+connection con3;
+--echo # Connection: con3
+SET debug_sync= 'after_flush_unlock SIGNAL parked_flush WAIT_FOR go_flush';
+send FLUSH TABLES t1;
+
+connection default;
+--echo # Connection: default
+SET debug_sync= 'now WAIT_FOR parked_flush';
+SET debug_sync= 'now SIGNAL go_truncate';
+
+connection con1;
+--echo # Connection: con1
+--echo # Reaping...
+--error ER_LOCK_DEADLOCK
+reap;
+
+connection default;
+--echo # Connection: default
+SET debug_sync= 'now SIGNAL go_show';
+
+connection con2;
+--echo # Connection: con2 (SHOW FIELDS FROM t1)
+--echo # Reaping...
+reap;
+
+connection default;
+--echo # Connection: default
+SET debug_sync= 'now SIGNAL go_flush';
+
+connection con3;
+--echo # Connection: con3 (FLUSH TABLES t1)
+--echo # Reaping...
+reap;
+
+disconnect con1;
+disconnect con2;
+disconnect con3;
+
+connection default;
+--echo # Connection: default
+SET debug_sync= 'RESET';
+DROP TABLE t1;
 
 # Check that all connections opened by test cases in this file are really
 # gone so execution of other tests won't be affected by their presence.

=== modified file 'mysql-test/t/partition_innodb_semi_consistent.test'
--- a/mysql-test/t/partition_innodb_semi_consistent.test	2010-02-16 17:23:21 +0000
+++ b/mysql-test/t/partition_innodb_semi_consistent.test	2010-03-17 20:06:37 +0000
@@ -101,6 +101,7 @@ connection con2;
 --error ER_LOCK_WAIT_TIMEOUT
 UPDATE t1 SET b = 21 WHERE a = 1;
 --disable_info
+ROLLBACK;
 
 --echo # Switch to connection con1
 connection con1;
@@ -150,6 +151,7 @@ SELECT * FROM t1;
 connection con2;
 --reap
 SELECT * FROM t1;
+COMMIT;
 
 --echo # Switch to connection con1
 connection con1;

=== modified file 'mysql-test/t/truncate.test'
--- a/mysql-test/t/truncate.test	2009-12-11 12:24:23 +0000
+++ b/mysql-test/t/truncate.test	2010-03-17 20:06:37 +0000
@@ -102,7 +102,7 @@ SELECT * FROM v1;
 LOCK TABLE t1 WRITE;
 --error ER_TABLE_NOT_LOCKED
 SELECT * FROM v1;
---error ER_NO_SUCH_TABLE
+--error ER_TABLE_NOT_LOCKED
 TRUNCATE v1;
 --error ER_TABLE_NOT_LOCKED
 SELECT * FROM v1;
@@ -111,7 +111,7 @@ UNLOCK TABLES;
 LOCK TABLE t1 WRITE, t2 WRITE;
 --error ER_TABLE_NOT_LOCKED
 SELECT * FROM v1;
---error ER_NO_SUCH_TABLE
+--error ER_TABLE_NOT_LOCKED
 TRUNCATE v1;
 --error ER_TABLE_NOT_LOCKED
 SELECT * FROM v1;
@@ -119,14 +119,14 @@ UNLOCK TABLES;
 #
 LOCK TABLE v1 WRITE;
 SELECT * FROM v1;
---error ER_NO_SUCH_TABLE
+--error ER_TABLE_NOT_LOCKED
 TRUNCATE v1;
 SELECT * FROM v1;
 UNLOCK TABLES;
 #
 LOCK TABLE t1 WRITE, t2 WRITE, v1 WRITE;
 SELECT * FROM v1;
---error ER_NO_SUCH_TABLE
+--error ER_TABLE_NOT_LOCKED
 TRUNCATE v1;
 SELECT * FROM v1;
 UNLOCK TABLES;

=== modified file 'sql/CMakeLists.txt'
--- a/sql/CMakeLists.txt	2010-04-27 09:37:46 +0000
+++ b/sql/CMakeLists.txt	2010-05-20 12:07:41 +0000
@@ -75,7 +75,7 @@ SET (SQL_SOURCE
                sql_connect.cc scheduler.cc 
                sql_profile.cc event_parse_data.cc
                sql_signal.cc rpl_handler.cc mdl.cc
-               transaction.cc sys_vars.cc
+               transaction.cc sys_vars.cc sql_truncate.cc datadict.cc
                ${GEN_SOURCES}
                ${MYSYS_LIBWRAP_SOURCE})
 

=== modified file 'sql/Makefile.am'
--- a/sql/Makefile.am	2010-04-13 15:04:45 +0000
+++ b/sql/Makefile.am	2010-05-20 12:07:41 +0000
@@ -39,7 +39,9 @@ DTRACEFILES =           filesort.o \
                         sql_connect.o \
                         sql_cursor.o \
                         sql_delete.o \
+                        sql_truncate.o \
                         sql_insert.o \
+                        datadict.o \
                         sql_parse.o \
                         sql_prepare.o \
                         sql_select.o \
@@ -56,7 +58,9 @@ DTRACEFILES_DEPEND =    filesort.o \
                         sql_connect.o \
                         sql_cursor.o \
                         sql_delete.o \
+                        sql_truncate.o \
                         sql_insert.o \
+                        datadict.o \
                         sql_parse.o \
                         sql_prepare.o \
                         sql_select.o \
@@ -121,7 +125,8 @@ noinst_HEADERS =	item.h item_func.h item
 			sql_audit.h \
 			contributors.h sql_servers.h sql_signal.h records.h \
 			sql_prepare.h rpl_handler.h replication.h mdl.h \
-			sql_plist.h transaction.h sys_vars.h
+			sql_plist.h transaction.h sys_vars.h sql_truncate.h \
+			datadict.h
 
 mysqld_SOURCES =	sql_lex.cc sql_handler.cc sql_partition.cc \
 			item.cc item_sum.cc item_buff.cc item_func.cc \
@@ -136,10 +141,10 @@ mysqld_SOURCES =	sql_lex.cc sql_handler.
 			sql_connect.cc scheduler.cc sql_parse.cc \
 			keycaches.cc set_var.cc sql_yacc.yy sys_vars.cc \
 			sql_base.cc table.cc sql_select.cc sql_insert.cc \
-			sql_profile.cc \
+			datadict.cc sql_profile.cc \
 			sql_prepare.cc sql_error.cc sql_locale.cc \
 			sql_update.cc sql_delete.cc uniques.cc sql_do.cc \
-			procedure.cc sql_test.cc \
+			procedure.cc sql_test.cc sql_truncate.cc \
 			log.cc init.cc derror.cc sql_acl.cc \
 			unireg.cc des_key_file.cc \
 			log_event.cc rpl_record.cc \

=== added file 'sql/datadict.cc'
--- a/sql/datadict.cc	1970-01-01 00:00:00 +0000
+++ b/sql/datadict.cc	2010-05-20 12:07:41 +0000
@@ -0,0 +1,147 @@
+/* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
+
+#include "datadict.h"
+#include "sql_priv.h"
+#include "sql_class.h"
+#include "sql_table.h"
+
+
+/**
+  Check type of .frm if we are not going to parse it.
+
+  @param  path  path to file
+
+  @retval  FRMTYPE_ERROR        error
+  @retval  FRMTYPE_TABLE        table
+  @retval  FRMTYPE_VIEW         view
+*/
+
+frm_type_enum dd_frm_type(THD *thd, char *path, enum legacy_db_type *dbt)
+{
+  File file;
+  uchar header[10];     //"TYPE=VIEW\n" it is 10 characters
+  size_t error;
+  DBUG_ENTER("dd_frm_type");
+
+  *dbt= DB_TYPE_UNKNOWN;
+
+  if ((file= mysql_file_open(key_file_frm,
+                             path, O_RDONLY | O_SHARE, MYF(0))) < 0)
+    DBUG_RETURN(FRMTYPE_ERROR);
+  error= mysql_file_read(file, (uchar*) header, sizeof(header), MYF(MY_NABP));
+  mysql_file_close(file, MYF(MY_WME));
+
+  if (error)
+    DBUG_RETURN(FRMTYPE_ERROR);
+  if (!strncmp((char*) header, "TYPE=VIEW\n", sizeof(header)))
+    DBUG_RETURN(FRMTYPE_VIEW);
+
+  /*
+    This is just a check for DB_TYPE. We'll return default unknown type
+    if the following test is true (arg #3). This should not have effect
+    on return value from this function (default FRMTYPE_TABLE)
+  */
+  if (header[0] != (uchar) 254 || header[1] != 1 ||
+      (header[2] != FRM_VER && header[2] != FRM_VER+1 &&
+       (header[2] < FRM_VER+3 || header[2] > FRM_VER+4)))
+    DBUG_RETURN(FRMTYPE_TABLE);
+
+  *dbt= (enum legacy_db_type) (uint) *(header + 3);
+  DBUG_RETURN(FRMTYPE_TABLE);                   // Is probably a .frm table
+}
+
+
+/**
+  Given a table name, check if the storage engine for the
+  table referred by this name supports an option 'flag'.
+  Return an error if the table does not exist or is not a
+  base table.
+
+  @pre Any metadata lock on the table.
+
+  @param[in]     thd     The current session.
+  @param[in]     db      Table schema.
+  @param[in]     table_name  Table database.
+  @param[in]     flag    The option to check.
+  @param[out]    yes_no  The result. Undefined if error.
+*/
+
+bool dd_check_storage_engine_flag(THD *thd,
+                                  const char *db, const char *table_name,
+                                  uint32 flag,
+                                  bool *yes_no)
+{
+  char path[FN_REFLEN + 1];
+  enum legacy_db_type db_type;
+  handlerton *table_type;
+
+  /* There should be at least some lock on the table.  */
+  DBUG_ASSERT(thd->mdl_context.is_lock_owner(MDL_key::TABLE, db, table_name,
+                                             MDL_SHARED));
+
+  (void) build_table_filename(path, sizeof(path) - 1, db,
+                              table_name, reg_ext, 0);
+
+  dd_frm_type(thd, path, &db_type);
+
+  /* Type is unknown if the object is not found or is not a table. */
+  if (db_type == DB_TYPE_UNKNOWN)
+  {
+    my_error(ER_NO_SUCH_TABLE, MYF(0), db, table_name);
+    return TRUE;
+  }
+  table_type= ha_resolve_by_legacy_type(thd, db_type);
+
+  *yes_no= ha_check_storage_engine_flag(table_type, flag);
+  return FALSE;
+}
+
+
+/*
+  Regenerate a metadata locked table.
+
+  @param  thd   Thread context.
+  @param  db    Name of the database to which the table belongs to.
+  @param  name  Table name.
+
+  @retval  FALSE  Success.
+  @retval  TRUE   Error.
+*/
+
+bool dd_recreate_table(THD *thd, const char *db, const char *table_name)
+{
+  bool error= TRUE;
+  HA_CREATE_INFO create_info;
+  char path[FN_REFLEN + 1];
+  DBUG_ENTER("dd_recreate_table");
+
+  /* There should be a exclusive metadata lock on the table. */
+  DBUG_ASSERT(thd->mdl_context.is_lock_owner(MDL_key::TABLE, db, table_name,
+                                             MDL_EXCLUSIVE));
+
+  memset(&create_info, 0, sizeof(create_info));
+
+  /* Create a path to the table, but without a extension. */
+  build_table_filename(path, sizeof(path) - 1, db, table_name, "", 0);
+
+  /* Attempt to reconstruct the table. */
+  mysql_mutex_lock(&LOCK_open);
+  error= ha_create_table(thd, path, db, table_name, &create_info, TRUE);
+  mysql_mutex_unlock(&LOCK_open);
+
+  DBUG_RETURN(error);
+}
+

=== added file 'sql/datadict.h'
--- a/sql/datadict.h	1970-01-01 00:00:00 +0000
+++ b/sql/datadict.h	2010-05-20 12:07:41 +0000
@@ -0,0 +1,39 @@
+#ifndef DATADICT_INCLUDED
+#define DATADICT_INCLUDED
+/* Copyright 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+#include "handler.h"
+/*
+  Data dictionary API.
+*/
+
+enum frm_type_enum
+{
+  FRMTYPE_ERROR= 0,
+  FRMTYPE_TABLE,
+  FRMTYPE_VIEW
+};
+
+
+frm_type_enum dd_frm_type(THD *thd, char *path, enum legacy_db_type *dbt);
+
+bool dd_check_storage_engine_flag(THD *thd,
+                                  const char *db, const char *table_name,
+                                  uint32 flag,
+                                  bool *yes_no);
+bool dd_recreate_table(THD *thd, const char *db, const char *table_name);
+
+#endif // DATADICT_INCLUDED

=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc	2010-05-05 22:02:08 +0000
+++ b/sql/sql_base.cc	2010-05-20 12:07:41 +0000
@@ -27,7 +27,7 @@
 #include "sql_show.h"    // append_identifier
 #include "strfunc.h"     // find_type
 #include "parse_file.h"  // sql_parse_prepare, File_parser
-#include "sql_view.h"    // mysql_frm_type, mysql_make_view, VIEW_ANY_ACL
+#include "sql_view.h"    // mysql_make_view, VIEW_ANY_ACL
 #include "sql_parse.h"   // check_table_access
 #include "sql_insert.h"  // kill_delayed_threads
 #include "sql_acl.h"     // *_ACL, check_grant_all_columns,
@@ -52,6 +52,7 @@
 #include <hash.h>
 #include "rpl_filter.h"
 #include "sql_table.h"                          // build_table_filename
+#include "datadict.h"   // dd_frm_type()
 #ifdef  __WIN__
 #include <io.h>
 #endif
@@ -2672,7 +2673,7 @@ bool open_table(THD *thd, TABLE_LIST *ta
         during prelocking process (in this case in theory we still
         should hold shared metadata lock on it).
       */
-      if (mysql_frm_type(thd, path, &not_used) == FRMTYPE_VIEW)
+      if (dd_frm_type(thd, path, &not_used) == FRMTYPE_VIEW)
       {
         if (!tdc_open_view(thd, table_list, alias, key, key_length,
                            mem_root, 0))

=== modified file 'sql/sql_bitmap.h'
--- a/sql/sql_bitmap.h	2010-03-31 14:05:33 +0000
+++ b/sql/sql_bitmap.h	2010-05-20 12:07:41 +0000
@@ -22,6 +22,7 @@
 #ifndef SQL_BITMAP_INCLUDED
 #define SQL_BITMAP_INCLUDED
 
+#include <my_sys.h>
 #include <my_bitmap.h>
 
 template <uint default_width> class Bitmap

=== modified file 'sql/sql_delete.cc'
--- a/sql/sql_delete.cc	2010-03-31 14:05:33 +0000
+++ b/sql/sql_delete.cc	2010-05-20 12:07:41 +0000
@@ -14,7 +14,7 @@
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
 /*
-  Delete of records and truncate of tables.
+  Delete of records tables.
 
   Multi-table deletes were introduced by Monty and Sinisa
 */
@@ -48,8 +48,7 @@
 */
 
 bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
-                  SQL_LIST *order, ha_rows limit, ulonglong options,
-                  bool reset_auto_increment)
+                  SQL_LIST *order, ha_rows limit, ulonglong options)
 {
   bool          will_batch;
   int		error, loc_error;
@@ -60,18 +59,13 @@ bool mysql_delete(THD *thd, TABLE_LIST *
   bool		transactional_table, safe_update, const_cond;
   bool          const_cond_result;
   ha_rows	deleted= 0;
-  bool          triggers_applicable;
   uint usable_index= MAX_KEY;
   SELECT_LEX   *select_lex= &thd->lex->select_lex;
   THD::killed_state killed_status= THD::NOT_KILLED;
+  THD::enum_binlog_query_type query_type= THD::ROW_QUERY_TYPE;
   DBUG_ENTER("mysql_delete");
   bool save_binlog_row_based;
 
-  THD::enum_binlog_query_type query_type=
-    thd->lex->sql_command == SQLCOM_TRUNCATE ?
-    THD::STMT_QUERY_TYPE :
-    THD::ROW_QUERY_TYPE;
-
   if (open_and_lock_tables(thd, table_list, TRUE, 0))
     DBUG_RETURN(TRUE);
   if (!(table= table_list->table))
@@ -130,25 +124,20 @@ bool mysql_delete(THD *thd, TABLE_LIST *
     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.
-
     We can use delete_all_rows() if and only if:
     - We allow new functions (not using option --skip-new), and are
       not in safe mode (not using option --safe-mode)
     - There is no limit clause
     - The condition is constant
     - If there is a condition, then it it produces a non-zero value
-    - If the current command is DELETE FROM with no where clause
-      (i.e., not TRUNCATE) then:
-      - We should not be binlogging this statement row-based, and
+    - If the current command is DELETE FROM with no where clause, then:
+      - We should not be binlogging this statement in row-based, and
       - there should be no delete triggers associated with the table.
   */
   if (!using_limit && const_cond_result &&
       !(specialflag & (SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE)) &&
-      (thd->lex->sql_command == SQLCOM_TRUNCATE ||
        (!thd->is_current_stmt_binlog_format_row() &&
-        !(table->triggers && table->triggers->has_delete_triggers()))))
+        !(table->triggers && table->triggers->has_delete_triggers())))
   {
     /* Update the table->file->stats.records number */
     table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
@@ -161,7 +150,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *
         query in row format, so we have to log it in statement format.
       */
       query_type= THD::STMT_QUERY_TYPE;
-      error= -1;				// ok
+      error= -1;
       deleted= maybe_deleted;
       save_binlog_row_based= thd->is_current_stmt_binlog_format_row();
       goto cleanup;
@@ -214,11 +203,6 @@ bool mysql_delete(THD *thd, TABLE_LIST *
     if (thd->is_error())
       DBUG_RETURN(TRUE);
     my_ok(thd, (ha_rows) thd->row_count_func);
-    /*
-      We don't need to call reset_auto_increment in this case, because
-      mysql_truncate always gives a NULL conds argument, hence we never
-      get here.
-    */
     DBUG_RETURN(0);				// Nothing to delete
   }
 
@@ -288,12 +272,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *
   init_ftfuncs(thd, select_lex, 1);
   thd_proc_info(thd, "updating");
 
-  /* NOTE: TRUNCATE must not invoke triggers. */
-
-  triggers_applicable= table->triggers &&
-                       thd->lex->sql_command != SQLCOM_TRUNCATE;
-
-  if (triggers_applicable &&
+  if (table->triggers &&
       table->triggers->has_triggers(TRG_EVENT_DELETE,
                                     TRG_ACTION_AFTER))
   {
@@ -323,7 +302,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *
     if (!(select && select->skip_record())&& ! thd->is_error() )
     {
 
-      if (triggers_applicable &&
+      if (table->triggers &&
           table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
                                             TRG_ACTION_BEFORE, FALSE))
       {
@@ -334,7 +313,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *
       if (!(error= table->file->ha_delete_row(table->record[0])))
       {
 	deleted++;
-        if (triggers_applicable &&
+        if (table->triggers &&
             table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
                                               TRG_ACTION_AFTER, FALSE))
         {
@@ -379,21 +358,6 @@ bool mysql_delete(THD *thd, TABLE_LIST *
   if (options & OPTION_QUICK)
     (void) table->file->extra(HA_EXTRA_NORMAL);
 
-  if (reset_auto_increment && (error < 0))
-  {
-    /*
-      We're really doing a truncate and need to reset the table's
-      auto-increment counter.
-    */
-    int error2= table->file->ha_reset_auto_increment(0);
-
-    if (error2 && (error2 != HA_ERR_WRONG_COMMAND))
-    {
-      table->file->print_error(error2, MYF(0));
-      error= 1;
-    }
-  }
-
 cleanup:
   /*
     Invalidate the table in the query cache if something changed. This must
@@ -419,29 +383,22 @@ cleanup:
           thd->is_current_stmt_binlog_format_row() &&
           find_temporary_table(thd, table_list)))
     {
-      bool const is_trans=
-        thd->lex->sql_command == SQLCOM_TRUNCATE ?
-        FALSE :
-        transactional_table;
-
       int errcode= 0;
       if (error < 0)
         thd->clear_error();
       else
         errcode= query_error_code(thd, killed_status == THD::NOT_KILLED);
-      
+
       /*
         [binlog]: If 'handler::delete_all_rows()' was called and the
         storage engine does not inject the rows itself, we replicate
         statement-based; otherwise, 'ha_delete_row()' was used to
         delete specific rows which we might log row-based.
-
-        Note that TRUNCATE TABLE is not transactional and should
-        therefore be treated as a DDL.
       */
       int log_result= thd->binlog_query(query_type,
                                         thd->query(), thd->query_length(),
-                                        is_trans, FALSE, FALSE, errcode);
+                                        transactional_table, FALSE, FALSE,
+                                        errcode);
 
       if (log_result)
       {
@@ -456,11 +413,7 @@ cleanup:
   if (error < 0 || 
       (thd->lex->ignore && !thd->is_error() && !thd->is_fatal_error))
   {
-    /*
-      If a TRUNCATE TABLE was issued, the number of rows should be reported as
-      zero since the exact number is unknown.
-    */
-    thd->row_count_func= reset_auto_increment ? 0 : deleted;
+    thd->row_count_func= deleted;
     my_ok(thd, (ha_rows) thd->row_count_func);
     DBUG_PRINT("info",("%ld records deleted",(long) deleted));
   }
@@ -1064,227 +1017,3 @@ bool multi_delete::send_eof()
   return 0;
 }
 
-
-/***************************************************************************
-  TRUNCATE TABLE
-****************************************************************************/
-
-/*
-  Row-by-row truncation if the engine does not support table recreation.
-  Probably a InnoDB table.
-*/
-
-static bool mysql_truncate_by_delete(THD *thd, TABLE_LIST *table_list)
-{
-  bool error;
-  DBUG_ENTER("mysql_truncate_by_delete");
-  table_list->lock_type= TL_WRITE;
-  table_list->mdl_request.set_type(MDL_SHARED_WRITE);
-  mysql_init_select(thd->lex);
-  /* Delete all rows from table */
-  error= mysql_delete(thd, table_list, NULL, NULL, HA_POS_ERROR, LL(0), TRUE);
-  /*
-    All effects of a TRUNCATE TABLE operation are rolled back if a row by row
-    deletion fails. Otherwise, operation is automatically committed at the end.
-  */
-  if (error)
-  {
-    DBUG_ASSERT(thd->stmt_da->is_error());
-    trans_rollback_stmt(thd);
-    trans_rollback(thd);
-  }
-  DBUG_RETURN(error);
-}
-
-
-/*
-  Optimize delete of all rows by doing a full generate of the table
-  This will work even if the .ISM and .ISD tables are destroyed
-
-  dont_send_ok should be set if:
-  - We should always wants to generate the table (even if the table type
-    normally can't safely do this.
-  - We don't want an ok to be sent to the end user.
-  - We don't want to log the truncate command
-  - If we want to keep exclusive metadata lock on the table (obtained by
-    caller) on exit without errors.
-*/
-
-bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
-{
-  HA_CREATE_INFO create_info;
-  char path[FN_REFLEN + 1];
-  TABLE *table;
-  bool error= TRUE;
-  uint path_length;
-  /*
-    Is set if we're under LOCK TABLES, and used
-    to downgrade the exclusive lock after the
-    table was truncated.
-  */
-  MDL_ticket *mdl_ticket= NULL;
-  bool has_mdl_lock= FALSE;
-  bool is_temporary_table= false;
-  DBUG_ENTER("mysql_truncate");
-
-  bzero((char*) &create_info,sizeof(create_info));
-
-  /* Remove tables from the HANDLER's hash. */
-  mysql_ha_rm_tables(thd, table_list);
-
-  /* If it is a temporary table, close and regenerate it */
-  if (!dont_send_ok && (table= find_temporary_table(thd, table_list)))
-  {
-    is_temporary_table= true;
-    handlerton *table_type= table->s->db_type();
-    TABLE_SHARE *share= table->s;
-    /* Note that a temporary table cannot be partitioned */
-    if (!ha_check_storage_engine_flag(table_type, HTON_CAN_RECREATE))
-      goto trunc_by_del;
-
-    table->file->info(HA_STATUS_AUTO | HA_STATUS_NO_LOCK);
-
-    close_temporary_table(thd, table, 0, 0);    // Don't free share
-    ha_create_table(thd, share->normalized_path.str,
-                    share->db.str, share->table_name.str, &create_info, 1);
-    // We don't need to call invalidate() because this table is not in cache
-    if ((error= (int) !(open_temporary_table(thd, share->path.str,
-                                             share->db.str,
-					     share->table_name.str, 1))))
-      (void) rm_temporary_table(table_type, path);
-    else
-      thd->thread_specific_used= TRUE;
-    
-    free_table_share(share);
-    my_free((char*) table,MYF(0));
-    /*
-      If we return here we will not have logged the truncation to the bin log
-      and we will not my_ok() to the client.
-    */
-    goto end;
-  }
-
-  path_length= build_table_filename(path, sizeof(path) - 1, table_list->db,
-                                    table_list->table_name, reg_ext, 0);
-
-  if (!dont_send_ok)
-  {
-    enum legacy_db_type table_type;
-    /*
-      FIXME: Code of TRUNCATE breaks the meta-data
-      locking protocol since it tries to find out the table storage
-      engine and therefore accesses table in some way without holding
-      any kind of meta-data lock.
-    */
-    mysql_frm_type(thd, path, &table_type);
-    if (table_type == DB_TYPE_UNKNOWN)
-    {
-      my_error(ER_NO_SUCH_TABLE, MYF(0),
-               table_list->db, table_list->table_name);
-      DBUG_RETURN(TRUE);
-    }
-#ifdef WITH_PARTITION_STORAGE_ENGINE
-    /*
-      TODO: Add support for TRUNCATE PARTITION for NDB and other engines
-      supporting native partitioning
-    */
-    if (table_type != DB_TYPE_PARTITION_DB &&
-        thd->lex->alter_info.flags & ALTER_ADMIN_PARTITION)
-    {
-      my_error(ER_PARTITION_MGMT_ON_NONPARTITIONED, MYF(0));
-      DBUG_RETURN(TRUE);
-    }
-#endif
-    if (!ha_check_storage_engine_flag(ha_resolve_by_legacy_type(thd,
-                                                                table_type),
-                                      HTON_CAN_RECREATE) ||
-        thd->lex->alter_info.flags & ALTER_ADMIN_PARTITION)
-      goto trunc_by_del;
-
-
-    if (thd->locked_tables_mode)
-    {
-      if (!(table= find_table_for_mdl_upgrade(thd->open_tables, table_list->db,
-                                              table_list->table_name, FALSE)))
-        DBUG_RETURN(TRUE);
-      mdl_ticket= table->mdl_ticket;
-      if (wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN))
-        goto end;
-      close_all_tables_for_name(thd, table->s, FALSE);
-    }
-    else
-    {
-      MDL_request mdl_global_request, mdl_request;
-      MDL_request_list mdl_requests;
-      /*
-        Even though we could use the previous execution branch
-        here just as well, we must not try to open the table: 
-        MySQL manual documents that TRUNCATE can be used to 
-        repair a damaged table, i.e. a table that can not be
-        fully "opened". In particular MySQL manual says:
-
-        As long as the table format file tbl_name.frm  is valid,
-        the table can be re-created as an empty table with TRUNCATE
-        TABLE, even if the data or index files have become corrupted.
-      */
-
-      mdl_global_request.init(MDL_key::GLOBAL, "", "", MDL_INTENTION_EXCLUSIVE);
-      mdl_request.init(MDL_key::TABLE, table_list->db, table_list->table_name,
-                       MDL_EXCLUSIVE);
-      mdl_requests.push_front(&mdl_request);
-      mdl_requests.push_front(&mdl_global_request);
-
-      if (thd->mdl_context.acquire_locks(&mdl_requests,
-                                         thd->variables.lock_wait_timeout))
-        DBUG_RETURN(TRUE);
-
-      has_mdl_lock= TRUE;
-      mysql_mutex_lock(&LOCK_open);
-      tdc_remove_table(thd, TDC_RT_REMOVE_ALL, table_list->db,
-                       table_list->table_name);
-      mysql_mutex_unlock(&LOCK_open);
-    }
-  }
-
-  /*
-    Remove the .frm extension AIX 5.2 64-bit compiler bug (BUG#16155): this
-    crashes, replacement works.  *(path + path_length - reg_ext_length)=
-     '\0';
-  */
-  path[path_length - reg_ext_length] = 0;
-  mysql_mutex_lock(&LOCK_open);
-  error= ha_create_table(thd, path, table_list->db, table_list->table_name,
-                         &create_info, 1);
-  mysql_mutex_unlock(&LOCK_open);
-  query_cache_invalidate3(thd, table_list, 0);
-
-end:
-  if (!dont_send_ok)
-  {
-    if (thd->locked_tables_mode && thd->locked_tables_list.reopen_tables(thd))
-      thd->locked_tables_list.unlink_all_closed_tables(thd, NULL, 0);
-    /*
-      Even if we failed to reopen some tables,
-      the operation itself succeeded, write the binlog.
-    */
-    if (!error)
-    {
-      /* In RBR, the statement is not binlogged if the table is temporary. */
-      if (!is_temporary_table || !thd->is_current_stmt_binlog_format_row())
-        error= write_bin_log(thd, TRUE, thd->query(), thd->query_length());
-      if (!error)
-        my_ok(thd);             // This should return record count
-    }
-    if (has_mdl_lock)
-      thd->mdl_context.release_transactional_locks();
-    if (mdl_ticket)
-      mdl_ticket->downgrade_exclusive_lock(MDL_SHARED_NO_READ_WRITE);
-  }
-
-  DBUG_PRINT("exit", ("error: %d", error));
-  DBUG_RETURN(error);
-
-trunc_by_del:
-  error= mysql_truncate_by_delete(thd, table_list);
-  DBUG_RETURN(error);
-}

=== modified file 'sql/sql_delete.h'
--- a/sql/sql_delete.h	2010-04-12 13:17:37 +0000
+++ b/sql/sql_delete.h	2010-05-20 12:07:41 +0000
@@ -27,8 +27,6 @@ typedef struct st_sql_list SQL_LIST;
 
 int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds);
 bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
-                  SQL_LIST *order, ha_rows rows, ulonglong options,
-                  bool reset_auto_increment);
-bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok);
+                  SQL_LIST *order, ha_rows rows, ulonglong options);
 
 #endif /* SQL_DELETE_INCLUDED */

=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc	2010-05-05 22:02:08 +0000
+++ b/sql/sql_parse.cc	2010-05-20 12:07:41 +0000
@@ -49,6 +49,7 @@
                               // mysql_recreate_table,
                               // mysql_backup_table,
                               // mysql_restore_table
+#include "sql_truncate.h"     // mysql_truncate_table
 #include "sql_connect.h"      // check_user,
                               // decrease_user_connections,
                               // thd_init_client_charset, check_mqh,
@@ -3281,7 +3282,8 @@ end_with_restore_list:
     }
     if (thd->global_read_lock.wait_if_global_read_lock(thd, FALSE, TRUE))
       goto error;
-    res= mysql_truncate(thd, first_table, 0);
+    if (! (res= mysql_truncate_table(thd, first_table)))
+      my_ok(thd);
     break;
   case SQLCOM_DELETE:
   {
@@ -3294,8 +3296,7 @@ end_with_restore_list:
     MYSQL_DELETE_START(thd->query());
     res = mysql_delete(thd, all_tables, select_lex->where,
                        &select_lex->order_list,
-                       unit->select_limit_cnt, select_lex->options,
-                       FALSE);
+                       unit->select_limit_cnt, select_lex->options);
     MYSQL_DELETE_DONE(res, (ulong) thd->row_count_func);
     break;
   }

=== modified file 'sql/sql_rename.cc'
--- a/sql/sql_rename.cc	2010-05-05 22:02:08 +0000
+++ b/sql/sql_rename.cc	2010-05-20 12:07:41 +0000
@@ -29,6 +29,7 @@
                         // start_waiting_global_read_lock
 #include "sql_base.h"   // tdc_remove_table
 #include "sql_handler.h"                        // mysql_ha_rm_tables
+#include "datadict.h"
 
 static TABLE_LIST *rename_tables(THD *thd, TABLE_LIST *table_list,
 				 bool skip_error);
@@ -283,7 +284,7 @@ do_rename(THD *thd, TABLE_LIST *ren_tabl
   build_table_filename(name, sizeof(name) - 1,
                        ren_table->db, old_alias, reg_ext, 0);
 
-  frm_type= mysql_frm_type(thd, name, &table_type);
+  frm_type= dd_frm_type(thd, name, &table_type);
   switch (frm_type)
   {
     case FRMTYPE_TABLE:

=== modified file 'sql/sql_show.cc'
--- a/sql/sql_show.cc	2010-04-28 10:04:11 +0000
+++ b/sql/sql_show.cc	2010-05-20 12:07:41 +0000
@@ -27,7 +27,6 @@
                                               // primary_key_name,
                                               // build_table_filename
 #include "repl_failsafe.h"
-#include "sql_view.h"                           // mysql_frm_type
 #include "sql_parse.h"             // check_access, check_table_access
 #include "sql_partition.h"         // partition_element
 #include "sql_db.h"     // check_db_dir_existence, load_db_opt_by_name
@@ -50,6 +49,8 @@
 #endif
 #include <my_dir.h>
 #include "lock.h"                           // MYSQL_LOCK_IGNORE_FLUSH
+#include "debug_sync.h"
+#include "datadict.h"   // dd_frm_type()
 
 #define STR_OR_NIL(S) ((S) ? (S) : "<nil>")
 
@@ -2959,6 +2960,9 @@ fill_schema_show_cols_or_idxs(THD *thd, 
                                        (can_deadlock ?
                                         MYSQL_OPEN_FAIL_ON_MDL_CONFLICT : 0)));
   lex->sql_command= save_sql_command;
+
+  DEBUG_SYNC(thd, "after_open_table_ignore_flush");
+
   /*
     get_all_tables() returns 1 on failure and 0 on success thus
     return only these and not the result code of ::process_table()
@@ -3018,7 +3022,7 @@ static int fill_schema_table_names(THD *
     char path[FN_REFLEN + 1];
     (void) build_table_filename(path, sizeof(path) - 1, db_name->str, 
                                 table_name->str, reg_ext, 0);
-    switch (mysql_frm_type(thd, path, &not_used)) {
+    switch (dd_frm_type(thd, path, &not_used)) {
     case FRMTYPE_ERROR:
       table->field[3]->store(STRING_WITH_LEN("ERROR"),
                              system_charset_info);

=== modified file 'sql/sql_table.cc'
--- a/sql/sql_table.cc	2010-05-13 09:24:59 +0000
+++ b/sql/sql_table.cc	2010-05-20 12:07:41 +0000
@@ -27,8 +27,8 @@
                         // start_waiting_global_read_lock,
                         // unlock_table_names, mysql_unlock_tables
 #include "strfunc.h"    // find_type2, find_set
-#include "sql_view.h" // mysql_frm_type, view_checksum, mysql_frm_type
-#include "sql_delete.h"                         // mysql_truncate
+#include "sql_view.h" // view_checksum 
+#include "sql_truncate.h"                       // regenerate_locked_table 
 #include "sql_partition.h"                      // mem_alloc_error,
                                                 // generate_partition_syntax,
                                                 // partition_info
@@ -52,6 +52,7 @@
 #include "sql_show.h"
 #include "transaction.h"
 #include "keycaches.h"
+#include "datadict.h"  // dd_frm_type()
 
 #ifdef __WIN__
 #include <io.h>
@@ -2096,7 +2097,7 @@ int mysql_rm_table_part2(THD *thd, TABLE
         ((access(path, F_OK) &&
           ha_create_table_from_engine(thd, db, alias)) ||
          (!drop_view &&
-          mysql_frm_type(thd, path, &frm_db_type) != FRMTYPE_TABLE)))
+          dd_frm_type(thd, path, &frm_db_type) != FRMTYPE_TABLE)))
     {
       // Table was not found on disk and table can't be created from engine
       if (if_exists)
@@ -2116,7 +2117,7 @@ int mysql_rm_table_part2(THD *thd, TABLE
       */
       if (frm_db_type == DB_TYPE_UNKNOWN)
       {
-        mysql_frm_type(thd, path, &frm_db_type);
+        dd_frm_type(thd, path, &frm_db_type);
         DBUG_PRINT("info", ("frm_db_type %d from %s", frm_db_type, path));
       }
       table_type= ha_resolve_by_legacy_type(thd, frm_db_type);
@@ -4557,12 +4558,18 @@ static int prepare_for_repair(THD *thd, 
 			     "Failed renaming data file");
     goto end;
   }
-  if (mysql_truncate(thd, table_list, 1))
+  if (dd_recreate_table(thd, table_list->db, table_list->table_name))
   {
     error= send_check_errmsg(thd, table_list, "repair",
 			     "Failed generating table from .frm file");
     goto end;
   }
+  /*
+    'FALSE' for 'using_transactions' means don't postpone
+    invalidation till the end of a transaction, but do it
+    immediately.
+  */
+  query_cache_invalidate3(thd, table_list, FALSE);
   if (mysql_file_rename(key_file_misc, tmp, from, MYF(MY_WME)))
   {
     error= send_check_errmsg(thd, table_list, "repair",
@@ -6535,7 +6542,7 @@ bool mysql_alter_table(THD *thd,char *ne
     into the main table list, like open_tables does).
     This code is wrong and will be removed, please do not copy.
   */
-  frm_type= mysql_frm_type(thd, new_name_buff, &table_type);
+  frm_type= dd_frm_type(thd, new_name_buff, &table_type);
   /* Rename a view */
   /* Sic: there is a race here */
   if (frm_type == FRMTYPE_VIEW && !(alter_info->flags & ~ALTER_RENAME))

=== added file 'sql/sql_truncate.cc'
--- a/sql/sql_truncate.cc	1970-01-01 00:00:00 +0000
+++ b/sql/sql_truncate.cc	2010-05-20 12:07:41 +0000
@@ -0,0 +1,403 @@
+/* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
+
+#include "sql_truncate.h"
+#include "sql_priv.h"
+#include "transaction.h"
+#include "debug_sync.h"
+#include "records.h"     // READ_RECORD
+#include "table.h"       // TABLE
+#include "sql_class.h"   // THD
+#include "sql_base.h"   // open_and_lock_tables
+#include "sql_table.h"  // write_bin_log
+#include "sql_handler.h" // mysql_ha_rm_tables
+#include "datadict.h"    // dd_recreate_table()
+#include "lock.h"        // MYSQL_OPEN_TEMPORARY_ONLY
+
+
+/*
+  Delete all rows of a locked table.
+
+  @param  thd           Thread context.
+  @param  table_list    Table list element for the table.
+  @param  rows_deleted  Whether rows might have been deleted.
+
+  @retval  FALSE  Success.
+  @retval  TRUE   Error.
+*/
+
+static bool
+delete_all_rows(THD *thd, TABLE *table)
+{
+  int error;
+  READ_RECORD info;
+  bool is_bulk_delete;
+  bool some_rows_deleted= FALSE;
+  bool save_binlog_row_based= thd->is_current_stmt_binlog_format_row();
+  DBUG_ENTER("delete_all_rows");
+
+  /* Replication of truncate table must be statement based. */
+  thd->clear_current_stmt_binlog_format_row();
+  /*
+    Attempt to delete all rows in the table.
+    If it is unsupported, switch to row by row deletion.
+  */
+  if (! (error= table->file->ha_delete_all_rows()))
+    goto end;
+  if (error != HA_ERR_WRONG_COMMAND)
+  {
+    /*
+      If a transactional engine fails in the middle of
+      deletion, we expect it to be able to roll it back.
+      Some reasons for the engine to fail would be media
+      failure or corrupted data dictionary (i.e. in case of
+      a partitioned table). We have sufficiently strong
+      metadata locks to rule out any potential deadlocks.
+
+      If a non-transactional engine fails here (that would
+      not be MyISAM, since MyISAM does TRUNCATE by
+      recreate), and binlog is on, replication breaks,
+      since nothing gets written to the binary log.
+      (XXX: is this a bug?)
+    */
+    table->file->print_error(error, MYF(0));
+    goto end;
+  }
+  /*
+    A workaround for Bug#53696  "Performance schema engine violates the
+    PSEA API by calling my_error()".
+  */
+  if (thd->is_error())
+    goto end;
+
+  /* Handler didn't support fast delete. Delete rows one by one. */
+
+  init_read_record(&info, thd, table, NULL, TRUE, TRUE, FALSE);
+
+  /*
+    Start bulk delete. If the engine does not support it,
+    go on, it's not an error.
+  */
+  is_bulk_delete= ! table->file->start_bulk_delete();
+
+  table->mark_columns_needed_for_delete();
+
+  for (error= info.read_record(&info); !error && !thd->killed;
+       error= info.read_record(&info))
+  {
+    if ((error= table->file->ha_delete_row(table->record[0])))
+    {
+      table->file->print_error(error, MYF(0));
+      break;
+    }
+    some_rows_deleted= TRUE;
+  }
+
+  if (error == -1)                              /* HA_ERR_END_OF_FILE */
+    error= 0;
+
+  /* Close down the bulk delete. */
+  if (is_bulk_delete)
+  {
+    int bulk_delete_error= table->file->end_bulk_delete();
+    if (bulk_delete_error && !error)
+    {
+      table->file->print_error(bulk_delete_error, MYF(0));
+      error= bulk_delete_error;
+    }
+  }
+  end_read_record(&info);
+
+  /*
+    Regardless of the error status, the query must be written to the
+    binary log if rows of the table is non-transactional.
+  */
+  if (some_rows_deleted && !table->file->has_transactions())
+  {
+    thd->transaction.stmt.modified_non_trans_table= TRUE;
+    thd->transaction.all.modified_non_trans_table= TRUE;
+  }
+
+  if (error || thd->killed)
+    goto end;
+
+  /* Truncate resets the auto-increment counter. */
+  error= table->file->ha_reset_auto_increment(0);
+  if (error)
+  {
+    if (error != HA_ERR_WRONG_COMMAND)
+      table->file->print_error(error, MYF(0));
+    else
+      error= 0;
+  }
+
+end:
+  if (save_binlog_row_based)
+    thd->set_current_stmt_binlog_format_row();
+
+  DBUG_RETURN(test(error));
+}
+
+
+/*
+  Close and recreate a temporary table. In case of success,
+  write truncate statement into the binary log if in statement
+  mode.
+
+  @param  thd     Thread context.
+  @param  table   The temporary table.
+
+  @retval  FALSE  Success.
+  @retval  TRUE   Error.
+*/
+
+static bool recreate_temporary_table(THD *thd, TABLE *table)
+{
+  bool error= TRUE;
+  TABLE_SHARE *share= table->s;
+  HA_CREATE_INFO create_info;
+  handlerton *table_type= table->s->db_type();
+  DBUG_ENTER("recreate_temporary_table");
+
+  memset(&create_info, 0, sizeof(create_info));
+
+  table->file->info(HA_STATUS_AUTO | HA_STATUS_NO_LOCK);
+
+  /* Don't free share. */
+  close_temporary_table(thd, table, FALSE, FALSE);
+
+  /*
+    We must use share->normalized_path.str since for temporary tables it
+    differs from what dd_recreate_table() would generate based
+    on table and schema names.
+  */
+  ha_create_table(thd, share->normalized_path.str, share->db.str,
+                  share->table_name.str, &create_info, 1);
+
+  if (open_temporary_table(thd, share->path.str, share->db.str,
+                           share->table_name.str, 1))
+  {
+    error= FALSE;
+    thd->thread_specific_used= TRUE;
+  }
+  else
+    rm_temporary_table(table_type, share->path.str);
+
+  free_table_share(share);
+  my_free(table, MYF(0));
+
+  DBUG_RETURN(error);
+}
+
+
+/*
+  Optimized delete of all rows by doing a full generate of the table.
+
+  @remark Will work even if the .MYI and .MYD files are destroyed.
+          In other words, it works as long as the .FRM is intact and
+          the engine supports re-create.
+
+  @param  thd         Thread context.
+  @param  table_ref   Table list element for the table to be truncated.
+
+  @retval  FALSE  Success.
+  @retval  TRUE   Error.
+*/
+
+bool mysql_truncate_table(THD *thd, TABLE_LIST *table_ref)
+{
+  TABLE *table;
+  bool error= TRUE;
+  MDL_ticket *mdl_ticket= NULL;
+  DBUG_ENTER("mysql_truncate_table");
+
+  /* Remove tables from the HANDLER's hash. */
+  mysql_ha_rm_tables(thd, table_ref);
+
+  /* If it is a temporary table, no need to take locks. */
+  if ((table= find_temporary_table(thd, table_ref)))
+  {
+    /* Note that a temporary table cannot be partitioned */
+    if (ha_check_storage_engine_flag(table->s->db_type(), HTON_CAN_RECREATE))
+    {
+      error= recreate_temporary_table(thd, table);
+      DBUG_ASSERT(! thd->transaction.stmt.modified_non_trans_table);
+    }
+    else
+    {
+      /*
+        The engine does not support truncate-by-recreate.
+        Open the table and delete all rows.
+        Sic: this can in fact open several tables
+        if it's a temporary MyISAMMRG table.
+      */
+      if (open_and_lock_tables(thd, table_ref, TL_WRITE,
+                               MYSQL_OPEN_TEMPORARY_ONLY))
+        DBUG_RETURN(TRUE);
+
+      error= delete_all_rows(thd, table_ref->table);
+    }
+    /*
+      No need to invalidate the query cache, queries with temporary
+      tables are not in the cache.
+    */
+  }
+  else /* It's not a temporary table. */
+  {
+    bool hton_can_recreate;
+    /*
+      Before doing anything else,
+      acquire a metadata lock on the table, or ensure we have one.
+      We don't use open_and_lock_tables() right away because
+      we want to be able to truncate (and recreate) corrupted tables,
+      those that we can't fully open.
+      MySQL manual documents that TRUNCATE can be used to repair a
+      damaged table, i.e. a table that can not be fully "opened".
+      In particular MySQL manual says:
+
+      As long as the table format file tbl_name.frm is valid, the table
+      can be re-created as an empty table with TRUNCATE TABLE, even if
+      the data or index files have become corrupted.
+    */
+    if (thd->locked_tables_mode)
+    {
+      if (!(table= find_table_for_mdl_upgrade(thd->open_tables, table_ref->db,
+                                              table_ref->table_name, FALSE)))
+        DBUG_RETURN(TRUE);
+      mdl_ticket= table->mdl_ticket;
+      hton_can_recreate= ha_check_storage_engine_flag(table->s->db_type(),
+                                                      HTON_CAN_RECREATE);
+    }
+    else
+    {
+      /*
+        Even though we could use the previous execution branch here just as
+        well, we must not try to open the table:
+      */
+      MDL_request mdl_global_request, mdl_request;
+      MDL_request_list mdl_requests;
+
+      mdl_global_request.init(MDL_key::GLOBAL, "", "", MDL_INTENTION_EXCLUSIVE);
+      mdl_request.init(MDL_key::TABLE, table_ref->db, table_ref->table_name,
+                       MDL_SHARED_NO_READ_WRITE);
+      mdl_requests.push_front(&mdl_request);
+      mdl_requests.push_front(&mdl_global_request);
+
+      if (thd->mdl_context.acquire_locks(&mdl_requests,
+                                         thd->variables.lock_wait_timeout))
+        DBUG_RETURN(TRUE);
+
+      mdl_ticket= mdl_request.ticket;
+
+      if (dd_check_storage_engine_flag(thd, table_ref->db, table_ref->table_name,
+                                       HTON_CAN_RECREATE, &hton_can_recreate))
+      {
+        DBUG_RETURN(TRUE);
+      }
+    }
+    if (hton_can_recreate)
+    {
+      /*
+        Acquire an exclusive lock. The storage engine can recreate the
+        table only if there are no references to it from anywhere,
+        i.e. no cached TABLE in the table cache. To remove
+        the table from cache we need an exclusive lock.
+      */
+      if (thd->locked_tables_mode)
+      {
+        mdl_ticket= table->mdl_ticket;
+        if (wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN))
+          DBUG_RETURN(TRUE);
+        close_all_tables_for_name(thd, table->s, FALSE);
+      }
+      else
+      {
+        ulong timeout= thd->variables.lock_wait_timeout;
+        if (thd->mdl_context.upgrade_shared_lock_to_exclusive(mdl_ticket, timeout))
+          DBUG_RETURN(TRUE);
+        mysql_mutex_lock(&LOCK_open);
+        tdc_remove_table(thd, TDC_RT_REMOVE_ALL,
+                         table_ref->db, table_ref->table_name);
+        mysql_mutex_unlock(&LOCK_open);
+      }
+      /*
+        The storage engine can truncate the table by creating
+        an empty table with the same structure.
+      */
+      error= dd_recreate_table(thd, table_ref->db, table_ref->table_name);
+
+      if (thd->locked_tables_mode && thd->locked_tables_list.reopen_tables(thd))
+        thd->locked_tables_list.unlink_all_closed_tables(thd, NULL, 0);
+    }
+    else
+    {
+      /*
+        Delete all rows in the table. Our metadata lock
+        guarantees that no transaction is reading or writing into the
+        table. Yet to open a write cursor we need a thr_lock lock.
+        Use open_and_lock_tables() to do the necessary job.
+      */
+
+      /* Allow to open base tables only. */
+      table_ref->required_type= FRMTYPE_TABLE;
+      table_ref->lock_type= TL_WRITE;
+      /* We don't need to load triggers. */
+      DBUG_ASSERT(table_ref->trg_event_map == 0);
+
+      /*
+        Open the table as it will handle some required preparations.
+        Ignore pending FLUSH TABLES since we don't want to release
+        the MDL lock taken above and otherwise there is no way
+        to wait for FLUSH TABLES in deadlock-free fashion.
+      */
+      if (open_and_lock_tables(thd, table_ref, TL_WRITE,
+                               MYSQL_OPEN_IGNORE_FLUSH |
+                               MYSQL_OPEN_SKIP_TEMPORARY))
+      {
+        DBUG_RETURN(TRUE);
+      }
+
+      error= delete_all_rows(thd, table_ref->table);
+    }
+    query_cache_invalidate3(thd, table_ref, FALSE);
+  }
+
+  /*
+    DDL is logged in statement format, regardless of binlog format.
+    In RBR, the statement is not binlogged if the table is temporary.
+    No need to binlog failed truncate-by-recreate.
+  */
+  if ((!error || thd->transaction.stmt.modified_non_trans_table) &&
+      !thd->is_current_stmt_binlog_format_row())
+    error|= write_bin_log(thd, !error, thd->query(), thd->query_length());
+  /*
+    All effects of a TRUNCATE TABLE operation are rolled back if a row
+    by row deletion fails. Otherwise, it is automatically committed at
+    the end.
+  */
+  if (error)
+  {
+    trans_rollback_stmt(thd);
+    trans_rollback(thd);
+  }
+
+  if (thd->locked_tables_mode && mdl_ticket)
+    mdl_ticket->downgrade_exclusive_lock(MDL_SHARED_NO_READ_WRITE);
+
+  DBUG_PRINT("exit", ("error: %d", error));
+  DBUG_RETURN(test(error));
+}
+
+

=== added file 'sql/sql_truncate.h'
--- a/sql/sql_truncate.h	1970-01-01 00:00:00 +0000
+++ b/sql/sql_truncate.h	2010-05-20 12:07:41 +0000
@@ -0,0 +1,23 @@
+#ifndef SQL_TRUNCATE_INCLUDED
+#define SQL_TRUNCATE_INCLUDED
+/* Copyright 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+class THD;
+class TABLE_LIST;
+
+bool mysql_truncate_table(THD *thd, TABLE_LIST *table_ref);
+
+#endif

=== modified file 'sql/sql_view.cc'
--- a/sql/sql_view.cc	2010-04-07 11:58:40 +0000
+++ b/sql/sql_view.cc	2010-05-20 12:07:41 +0000
@@ -32,6 +32,7 @@
 #include "sp.h"
 #include "sp_head.h"
 #include "sp_cache.h"
+#include "datadict.h"   // dd_frm_type()
 
 #define MD5_BUFF_LENGTH 33
 
@@ -1663,7 +1664,7 @@ bool mysql_drop_view(THD *thd, TABLE_LIS
                          view->db, view->table_name, reg_ext, 0);
 
     if (access(path, F_OK) || 
-        FRMTYPE_VIEW != (type= mysql_frm_type(thd, path, &not_used)))
+        FRMTYPE_VIEW != (type= dd_frm_type(thd, path, &not_used)))
     {
       char name[FN_REFLEN];
       my_snprintf(name, sizeof(name), "%s.%s", view->db, view->table_name);
@@ -1742,54 +1743,6 @@ bool mysql_drop_view(THD *thd, TABLE_LIS
 
 
 /*
-  Check type of .frm if we are not going to parse it
-
-  SYNOPSIS
-    mysql_frm_type()
-    path	path to file
-
-  RETURN
-    FRMTYPE_ERROR	error
-    FRMTYPE_TABLE	table
-    FRMTYPE_VIEW	view
-*/
-
-frm_type_enum mysql_frm_type(THD *thd, char *path, enum legacy_db_type *dbt)
-{
-  File file;
-  uchar header[10];	//"TYPE=VIEW\n" it is 10 characters
-  size_t error;
-  DBUG_ENTER("mysql_frm_type");
-
-  *dbt= DB_TYPE_UNKNOWN;
-
-  if ((file= mysql_file_open(key_file_frm,
-                             path, O_RDONLY | O_SHARE, MYF(0))) < 0)
-    DBUG_RETURN(FRMTYPE_ERROR);
-  error= mysql_file_read(file, (uchar*) header, sizeof(header), MYF(MY_NABP));
-  mysql_file_close(file, MYF(MY_WME));
-
-  if (error)
-    DBUG_RETURN(FRMTYPE_ERROR);
-  if (!strncmp((char*) header, "TYPE=VIEW\n", sizeof(header)))
-    DBUG_RETURN(FRMTYPE_VIEW);
-
-  /*
-    This is just a check for DB_TYPE. We'll return default unknown type
-    if the following test is true (arg #3). This should not have effect
-    on return value from this function (default FRMTYPE_TABLE)
-  */
-  if (header[0] != (uchar) 254 || header[1] != 1 ||
-      (header[2] != FRM_VER && header[2] != FRM_VER+1 &&
-       (header[2] < FRM_VER+3 || header[2] > FRM_VER+4)))
-    DBUG_RETURN(FRMTYPE_TABLE);
-
-  *dbt= (enum legacy_db_type) (uint) *(header + 3);
-  DBUG_RETURN(FRMTYPE_TABLE);                   // Is probably a .frm table
-}
-
-
-/*
   check of key (primary or unique) presence in updatable view
 
   SYNOPSIS

=== modified file 'sql/sql_view.h'
--- a/sql/sql_view.h	2010-03-31 14:05:33 +0000
+++ b/sql/sql_view.h	2010-05-20 12:07:41 +0000
@@ -43,8 +43,6 @@ bool check_key_in_view(THD *thd, TABLE_L
 
 bool insert_view_fields(THD *thd, List<Item> *list, TABLE_LIST *view);
 
-frm_type_enum mysql_frm_type(THD *thd, char *path, enum legacy_db_type *dbt);
-
 int view_checksum(THD *thd, TABLE_LIST *view);
 
 extern TYPELIB updatable_views_with_limit_typelib;

=== modified file 'sql/table.h'
--- a/sql/table.h	2010-04-12 13:17:37 +0000
+++ b/sql/table.h	2010-05-20 12:07:41 +0000
@@ -20,6 +20,7 @@
 #include "sql_plist.h"
 #include "sql_list.h"                           /* Sql_alloc */
 #include "mdl.h"
+#include "datadict.h"
 
 #ifndef MYSQL_CLIENT
 
@@ -305,14 +306,6 @@ enum tmp_table_type
   NO_TMP_TABLE, NON_TRANSACTIONAL_TMP_TABLE, TRANSACTIONAL_TMP_TABLE,
   INTERNAL_TMP_TABLE, SYSTEM_TMP_TABLE
 };
-
-enum frm_type_enum
-{
-  FRMTYPE_ERROR= 0,
-  FRMTYPE_TABLE,
-  FRMTYPE_VIEW
-};
-
 enum release_type { RELEASE_NORMAL, RELEASE_WAIT_FOR_DROP };
 
 typedef struct st_filesort_info


Attachment: [text/bzr-bundle] bzr/kostja@sun.com-20100520120741-i253if43sooteyy7.bundle
Thread
bzr commit into mysql-trunk-runtime branch (kostja:3019) Bug#42643Konstantin Osipov20 May