#At file:///home2/mydev/bzrroot/mysql-6.0-bug20667-1/ based on revid:charles.bell@stripped
2825 Ingo Struewing 2009-06-18
Bug#20667 - Truncate table fails for a write locked table
TRUNCATE TABLE was not allowed under LOCK TABLES.
The patch removes this restriction. mysql_truncate()
does now handle that case.
@ mysql-test/r/merge.result
Bug#20667 - Truncate table fails for a write locked table
Updated test result.
@ mysql-test/r/truncate.result
Bug#20667 - Truncate table fails for a write locked table
Updated test result.
@ mysql-test/t/merge.test
Bug#20667 - Truncate table fails for a write locked table
Updated test case due to now working TRUNCATE under LOCK TABLES.
Added some SELECTs to show that child tables are truncated.
@ mysql-test/t/truncate.test
Bug#20667 - Truncate table fails for a write locked table
Added test.
@ sql/sql_class.cc
Bug#20667 - Truncate table fails for a write locked table
Added implementation for Locked_tables_list::get_table().
@ sql/sql_class.h
Bug#20667 - Truncate table fails for a write locked table
Added declaration for Locked_tables_list::get_table().
@ sql/sql_delete.cc
Bug#20667 - Truncate table fails for a write locked table
Added two branches for thd->locked_tables_mode.
@ sql/sql_parse.cc
Bug#20667 - Truncate table fails for a write locked table
Deleted rejection of TRUNCATE in case of LOCK TABLES.
modified:
mysql-test/r/merge.result
mysql-test/r/truncate.result
mysql-test/t/merge.test
mysql-test/t/truncate.test
sql/sql_class.cc
sql/sql_class.h
sql/sql_delete.cc
sql/sql_parse.cc
=== modified file 'mysql-test/r/merge.result'
--- a/mysql-test/r/merge.result 2009-04-22 10:02:28 +0000
+++ b/mysql-test/r/merge.result 2009-06-18 14:28:23 +0000
@@ -1053,15 +1053,20 @@ c1
LOCK TABLE t1 WRITE, t2 WRITE, t3 WRITE;
INSERT INTO t1 VALUES (1);
TRUNCATE TABLE t3;
-ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
SELECT * FROM t3;
c1
-1
-2
+UNLOCK TABLES;
+SELECT * FROM t1;
+c1
+SELECT * FROM t2;
+c1
#
# Truncate child table under locked tables.
+LOCK TABLE t1 WRITE, t2 WRITE, t3 WRITE;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t2 VALUES (2);
TRUNCATE TABLE t1;
-ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
+ERROR HY000: MyISAM table 't1' is in use (most likely by a MERGE table). Try FLUSH TABLES.
SELECT * FROM t3;
c1
1
@@ -1096,18 +1101,24 @@ INSERT INTO t1 VALUES (1);
CREATE TABLE t4 (c1 INT, INDEX(c1));
LOCK TABLE t4 WRITE;
TRUNCATE TABLE t3;
-ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
SELECT * FROM t3;
c1
-1
-2
+SELECT * FROM t1;
+c1
+SELECT * FROM t2;
+c1
#
# Truncate temporary child table under locked tables.
+INSERT INTO t1 VALUES (1);
+INSERT INTO t2 VALUES (2);
TRUNCATE TABLE t1;
-ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
SELECT * FROM t3;
c1
-1
+2
+SELECT * FROM t1;
+c1
+SELECT * FROM t2;
+c1
2
UNLOCK TABLES;
DROP TABLE t1, t2, t3, t4;
=== modified file 'mysql-test/r/truncate.result'
--- a/mysql-test/r/truncate.result 2007-04-17 10:32:01 +0000
+++ b/mysql-test/r/truncate.result 2009-06-18 14:28:23 +0000
@@ -60,3 +60,18 @@ truncate table v1;
ERROR 42S02: Table 'test.v1' doesn't exist
drop view v1;
drop table t1;
+#
+# Bug#20667 - Truncate table fails for a write locked table
+#
+CREATE TABLE t1 (c1 INT) ENGINE=MyISAM;
+LOCK TABLE t1 WRITE;
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1;
+c1
+1
+TRUNCATE TABLE t1;
+SELECT * FROM t1;
+c1
+UNLOCK TABLES;
+DROP TABLE t1;
+# End of 6.0 tests
=== modified file 'mysql-test/t/merge.test'
--- a/mysql-test/t/merge.test 2009-04-22 10:02:28 +0000
+++ b/mysql-test/t/merge.test 2009-06-18 14:28:23 +0000
@@ -688,12 +688,17 @@ SELECT * FROM t3;
--echo # Truncate MERGE table under locked tables.
LOCK TABLE t1 WRITE, t2 WRITE, t3 WRITE;
INSERT INTO t1 VALUES (1);
---error ER_LOCK_OR_ACTIVE_TRANSACTION
TRUNCATE TABLE t3;
SELECT * FROM t3;
+UNLOCK TABLES;
+SELECT * FROM t1;
+SELECT * FROM t2;
--echo #
--echo # Truncate child table under locked tables.
---error ER_LOCK_OR_ACTIVE_TRANSACTION
+LOCK TABLE t1 WRITE, t2 WRITE, t3 WRITE;
+INSERT INTO t1 VALUES (1);
+INSERT INTO t2 VALUES (2);
+--error ER_UNKNOWN_ERROR
TRUNCATE TABLE t1;
SELECT * FROM t3;
UNLOCK TABLES;
@@ -719,14 +724,18 @@ SELECT * FROM t3;
INSERT INTO t1 VALUES (1);
CREATE TABLE t4 (c1 INT, INDEX(c1));
LOCK TABLE t4 WRITE;
---error ER_LOCK_OR_ACTIVE_TRANSACTION
TRUNCATE TABLE t3;
SELECT * FROM t3;
+SELECT * FROM t1;
+SELECT * FROM t2;
--echo #
--echo # Truncate temporary child table under locked tables.
---error ER_LOCK_OR_ACTIVE_TRANSACTION
+INSERT INTO t1 VALUES (1);
+INSERT INTO t2 VALUES (2);
TRUNCATE TABLE t1;
SELECT * FROM t3;
+SELECT * FROM t1;
+SELECT * FROM t2;
UNLOCK TABLES;
DROP TABLE t1, t2, t3, t4;
=== modified file 'mysql-test/t/truncate.test'
--- a/mysql-test/t/truncate.test 2007-04-17 10:32:01 +0000
+++ b/mysql-test/t/truncate.test 2009-06-18 14:28:23 +0000
@@ -69,3 +69,17 @@ drop table t1;
# End of 5.0 tests
+--echo #
+--echo # Bug#20667 - Truncate table fails for a write locked table
+--echo #
+CREATE TABLE t1 (c1 INT) ENGINE=MyISAM;
+LOCK TABLE t1 WRITE;
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1;
+TRUNCATE TABLE t1;
+SELECT * FROM t1;
+UNLOCK TABLES;
+DROP TABLE t1;
+
+--echo # End of 6.0 tests
+
=== modified file 'sql/sql_class.cc'
--- a/sql/sql_class.cc 2009-06-12 02:01:08 +0000
+++ b/sql/sql_class.cc 2009-06-18 14:28:23 +0000
@@ -434,6 +434,36 @@ bool Drop_table_error_handler::handle_co
}
+/**
+ Find a table in the list of locked tables.
+
+ @param[in] db database name
+ @param[in] table_name table name
+
+ @return table pointer
+ @retval NULL error
+*/
+
+TABLE *Locked_tables_list::get_table(const char *db,
+ const char *table_name)
+{
+ TABLE_LIST *tlist;
+
+ for (tlist= m_locked_tables; tlist; tlist= tlist->next_global)
+ {
+ if (!(lower_case_table_names ?
+ my_strcasecmp(system_charset_info, db, tlist->db) :
+ strcmp(db, tlist->db)) &&
+ !(lower_case_table_names ?
+ my_strcasecmp(system_charset_info, table_name, tlist->table_name) :
+ strcmp(db, tlist->db)))
+ break;
+ }
+
+ return tlist ? tlist->table : NULL;
+}
+
+
THD::THD()
:Statement(&main_lex, &main_mem_root, CONVENTIONAL_EXECUTION,
/* statement id */ 0),
=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h 2009-06-12 02:01:08 +0000
+++ b/sql/sql_class.h 2009-06-18 14:28:23 +0000
@@ -1251,6 +1251,7 @@ public:
bool remove_from_locked_tables);
void unlink_all_closed_tables();
bool reopen_tables(THD *thd);
+ TABLE *get_table(const char *db, const char *table_name);
};
=== modified file 'sql/sql_delete.cc'
--- a/sql/sql_delete.cc 2009-05-31 12:05:01 +0000
+++ b/sql/sql_delete.cc 2009-06-18 14:28:23 +0000
@@ -1143,24 +1143,36 @@ bool mysql_truncate(THD *thd, TABLE_LIST
if (table_type == DB_TYPE_NDBCLUSTER)
global_schema_lock_guard.lock();
- /*
- FIXME: Actually code of TRUNCATE breaks meta-data locking protocol since
- tries to get table enging and therefore accesses table in some way
- without holding any kind of meta-data lock.
- */
- mdl_request= MDL_request::create(0, table_list->db,
- table_list->table_name, thd->mem_root);
- mdl_request->set_type(MDL_EXCLUSIVE);
- thd->mdl_context.add_request(mdl_request);
- if (thd->mdl_context.acquire_exclusive_locks())
+
+ if (thd->locked_tables_mode)
{
- thd->mdl_context.remove_request(mdl_request);
- DBUG_RETURN(TRUE);
+ table= thd->locked_tables_list.get_table(table_list->db,
+ table_list->table_name);
+ if (!table || wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN))
+ DBUG_RETURN(TRUE);
+ close_all_tables_for_name(thd, table->s, FALSE);
+ }
+ else
+ {
+ /*
+ FIXME: Actually code of TRUNCATE breaks meta-data locking protocol since
+ tries to get table enging and therefore accesses table in some way
+ without holding any kind of meta-data lock.
+ */
+ mdl_request= MDL_request::create(0, table_list->db,
+ table_list->table_name, thd->mem_root);
+ mdl_request->set_type(MDL_EXCLUSIVE);
+ thd->mdl_context.add_request(mdl_request);
+ if (thd->mdl_context.acquire_exclusive_locks())
+ {
+ thd->mdl_context.remove_request(mdl_request);
+ DBUG_RETURN(TRUE);
+ }
+ pthread_mutex_lock(&LOCK_open);
+ tdc_remove_table(thd, TDC_RT_REMOVE_ALL, table_list->db,
+ table_list->table_name);
+ pthread_mutex_unlock(&LOCK_open);
}
- pthread_mutex_lock(&LOCK_open);
- tdc_remove_table(thd, TDC_RT_REMOVE_ALL, table_list->db,
- table_list->table_name);
- pthread_mutex_unlock(&LOCK_open);
}
/*
@@ -1187,7 +1199,12 @@ end:
write_bin_log(thd, TRUE, thd->query, thd->query_length);
my_ok(thd); // This should return record count
}
- if (mdl_request)
+ if (thd->locked_tables_mode)
+ {
+ if (thd->locked_tables_list.reopen_tables(thd))
+ error= TRUE;
+ }
+ else if (mdl_request)
{
thd->mdl_context.release_lock(mdl_request->ticket);
thd->mdl_context.remove_request(mdl_request);
=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc 2009-06-12 02:01:08 +0000
+++ b/sql/sql_parse.cc 2009-06-18 14:28:23 +0000
@@ -3376,7 +3376,7 @@ end_with_restore_list:
Don't allow this within a transaction because we want to use
re-generate table
*/
- if (thd->locked_tables_mode || thd->active_transaction())
+ if (thd->active_transaction())
{
my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
Attachment: [text/bzr-bundle] bzr/ingo.struewing@sun.com-20090618142823-8wx892713x4vs76i.bundle
| Thread |
|---|
| • bzr commit into mysql-6.0-backup branch (ingo.struewing:2825) Bug#20667 | Ingo Struewing | 18 Jun |