List:Commits« Previous MessageNext Message »
From:Ingo Struewing Date:June 19 2009 2:45pm
Subject:bzr commit into mysql-6.0-backup branch (ingo.struewing:2825) Bug#20667
View as plain text  
#At file:///home2/mydev/bzrroot/mysql-6.0-bug20667-1/ based on revid:charles.bell@stripped

 2825 Ingo Struewing	2009-06-19
      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-19 14:45:15 +0000
@@ -1053,18 +1053,21 @@ 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
 SELECT * FROM t3;
 c1
-1
 2
 UNLOCK TABLES;
 DROP TABLE t1, t2, t3;
@@ -1096,18 +1099,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-19 14:45:15 +0000
@@ -60,3 +60,28 @@ 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;
+LOCK TABLE t1 READ;
+TRUNCATE TABLE t1;
+ERROR HY000: Table 't1' was locked with a READ lock and can't be updated
+UNLOCK TABLES;
+CREATE TABLE t2 (c1 INT) ENGINE=MyISAM;
+LOCK TABLE t2 WRITE;
+TRUNCATE TABLE t1;
+ERROR HY000: Table 't1' was not locked with LOCK TABLES
+UNLOCK TABLES;
+DROP TABLE t1;
+DROP TABLE t2;
+# 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-19 14:45:15 +0000
@@ -688,12 +688,16 @@ 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);
 TRUNCATE TABLE t1;
 SELECT * FROM t3;
 UNLOCK TABLES;
@@ -719,14 +723,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-19 14:45:15 +0000
@@ -69,3 +69,29 @@ 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;
+#
+LOCK TABLE t1 READ;
+--error ER_TABLE_NOT_LOCKED_FOR_WRITE
+TRUNCATE TABLE t1;
+UNLOCK TABLES;
+#
+CREATE TABLE t2 (c1 INT) ENGINE=MyISAM;
+LOCK TABLE t2 WRITE;
+--error ER_TABLE_NOT_LOCKED
+TRUNCATE TABLE t1;
+UNLOCK TABLES;
+DROP TABLE t1;
+DROP TABLE t2;
+
+--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-19 14:45:15 +0000
@@ -434,6 +434,41 @@ 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;
+  DBUG_ENTER("Locked_tables_list::get_table");
+  DBUG_PRINT("enter", ("search: '%s'.'%s'", db, table_name));
+
+  for (tlist= m_locked_tables; tlist; tlist= tlist->next_global)
+  {
+    DBUG_PRINT("thd", ("tlist: '%s'.'%s'  lock_type: %u",
+                       tlist->db, tlist->table_name, tlist->lock_type));
+    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(table_name, tlist->table_name)))
+      break;
+  }
+
+  DBUG_PRINT("exit", (tlist ? "match" : "not found"));
+  DBUG_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-19 14:45:15 +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-19 14:45:15 +0000
@@ -1143,24 +1143,46 @@ 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)
+      {
+        my_error(ER_TABLE_NOT_LOCKED, MYF(0), table_list->table_name);
+        DBUG_RETURN(TRUE);
+      }
+      if (table->reginfo.lock_type != TL_WRITE)
+      {
+        my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0), table_list->table_name);
+        DBUG_RETURN(TRUE);
+      }
+      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
+    {
+      /*
+        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 +1209,16 @@ 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;
+      table= thd->locked_tables_list.get_table(table_list->db,
+                                               table_list->table_name);
+      if (table)
+        table->mdl_ticket->downgrade_exclusive_lock();
+    }
+    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-19 14:45:15 +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-20090619144515-kv06vfukyp039nxl.bundle
Thread
bzr commit into mysql-6.0-backup branch (ingo.struewing:2825) Bug#20667Ingo Struewing19 Jun
  • Re: bzr commit into mysql-6.0-backup branch (ingo.struewing:2825)Bug#20667Konstantin Osipov16 Jul
    • Re: bzr commit into mysql-6.0-backup branch (ingo.struewing:2825)Bug#20667Konstantin Osipov17 Jul