List:Commits« Previous MessageNext Message »
From:Dmitry Lenev Date:May 22 2009 9:50am
Subject:bzr commit into mysql-6.1-fk branch (dlenev:2737)
View as plain text  
#At file:///home/dlenev/src/bzr/mysql-6.1-mil14/ based on revid:dlenev@stripped

 2737 Dmitry Lenev	2009-05-22
      Milestone 14 "DDL checks and changes: DROP, TRUNCATE, RENAME".
      
      After-review fixes in progress.
      
      Get rid of unnecessary allocation of metadata lock requests.
      To achieve this instead of using TABLE_LIST::mdl_request pointer
      as indication that table which was dropped was a temporary table
      we use bool member in newly introduce Drop_table_rcontext class.

    modified:
      sql/ha_ndbcluster.cc
      sql/sql_db.cc
      sql/sql_table.cc
      sql/table.h
=== modified file 'sql/ha_ndbcluster.cc'
--- a/sql/ha_ndbcluster.cc	2009-04-22 22:12:25 +0000
+++ b/sql/ha_ndbcluster.cc	2009-05-22 09:50:20 +0000
@@ -7597,9 +7597,12 @@ int ndbcluster_find_files(handlerton *ht
       DBUG_PRINT("info", ("Remove table %s/%s", db, file_name_str));
       // Delete the table and all related files
       TABLE_LIST table_list;
+      MDL_request mdl_request;
       bzero((char*) &table_list,sizeof(table_list));
       table_list.db= (char*) db;
       table_list.alias= table_list.table_name= (char*)file_name_str;
+      mdl_request.init(0, db, file_name_str);
+      table_list.mdl_request= &mdl_request;
       /*
         set TNO_NO_NDB_DROP_TABLE flag to not drop ndb table.
         it should not exist anyways

=== modified file 'sql/sql_db.cc'
--- a/sql/sql_db.cc	2009-05-05 12:58:43 +0000
+++ b/sql/sql_db.cc	2009-05-22 09:50:20 +0000
@@ -1162,6 +1162,9 @@ static long mysql_rm_known_files(THD *th
 
       table_list->alias= table_list->table_name;	// If lower_case_table_names=2
       table_list->internal_tmp_table= is_prefix(file->name, tmp_file_prefix);
+      table_list->mdl_request= MDL_request::create(0, table_list->db,
+                                                   table_list->table_name,
+                                                   thd->mem_root);
       /* Link into list */
       (*tot_list_next)= table_list;
       tot_list_next= &table_list->next_local;

=== modified file 'sql/sql_table.cc'
--- a/sql/sql_table.cc	2009-05-21 07:08:15 +0000
+++ b/sql/sql_table.cc	2009-05-22 09:50:20 +0000
@@ -1748,6 +1748,33 @@ static bool fk_drop_table_add_parent_tab
 
 
 /**
+  Context carrying information about table being dropped for the whole
+  duration of DROP TABLE/DROP DATABASE operation.
+*/
+
+class Drop_table_rcontext: public Sql_alloc
+{
+public:
+
+  Drop_table_rcontext()
+    : table_type(NULL), is_temporary(FALSE)
+  {}
+
+  /**
+    Engine for table being dropped. NULL - if we don't know yet
+    what the table's engine is.
+  */
+  handlerton *table_type;
+  /**
+    Indicates that there is a temporary table which matches table
+    name specified in the statement and which is going to be dropped
+    as result.
+  */
+  bool is_temporary;
+};
+
+
+/**
   Runtime context for changes performed by DDL statement on a table
   which participates in foreign key constraints.
 
@@ -1961,7 +1988,7 @@ Foreign_key_ddl_rcontext::prepare_drop_t
           is a temporary table which shadows it and gets dropped instead of it)
           it must present among additionally locked tables.
         */
-        if (! tab || ! tab->mdl_request)
+        if (! tab || tab->drop_table_rctx->is_temporary)
           tab= find_table_in_local_list(all_parent_tables,
                                         fk_s->parent_table_db.str,
                                         fk_s->parent_table_name.str);
@@ -2020,7 +2047,7 @@ Foreign_key_ddl_rcontext::prepare_drop_t
                                       fk_s_p->child_table_db.str,
                                       fk_s_p->child_table_name.str);
 
-        if (! tab || ! tab->mdl_request)
+        if (! tab || tab->drop_table_rctx->is_temporary)
           tab= find_table_in_local_list(all_parent_tables,
                                         fk_s_p->child_table_db.str,
                                         fk_s_p->child_table_name.str);
@@ -2190,24 +2217,10 @@ lock_dropped_and_parent_tables(THD *thd,
 
   for (table= tables; table; table= table->next_local)
   {
-    if (! table->table)
+    if (! table->drop_table_rctx->is_temporary)
     {
-      /*
-        QQ: Ideally we should get rid of allocation here. But this can be
-            problematic due to fact that we set TABLE_LIST::mdl_lock_data
-            to 0 for temporary tables and rely on that (think of
-            re-execution). Any other ideas?
-      */
-      if (! (mdl_request= MDL_request::create(0, table->db,
-                                              table->table_name,
-                                              thd->mem_root)))
-      {
-        thd->mdl_context.remove_all_requests();
-        return TRUE;
-      }
-      mdl_request->set_type(MDL_EXCLUSIVE);
-      thd->mdl_context.add_request(mdl_request);
-      table->mdl_request= mdl_request;
+      table->mdl_request->set_type(MDL_EXCLUSIVE);
+      thd->mdl_context.add_request(table->mdl_request);
     }
   }
 
@@ -2260,7 +2273,7 @@ upgrade_mdl_for_dropped_and_parent_table
   /* Upgrade meta-data locks for all tables to be dropped. */
   for (table= tables; table; table= table->next_local)
   {
-    if (table->table->s->tmp_table == NO_TMP_TABLE)
+    if (! table->drop_table_rctx->is_temporary)
     {
       if (wait_while_table_is_used(thd, table->table, HA_EXTRA_FORCE_REOPEN))
       {
@@ -2332,12 +2345,13 @@ upgrade_mdl_for_dropped_and_parent_table
 */
 
 static bool
-fk_check_tables_before_drop(THD *thd, TABLE_LIST *tables,
+fk_check_tables_before_drop(THD *thd,
+                            TABLE_LIST *tables,
                             TABLE_LIST **parents_to_lock,
                             List<Foreign_key_name> *fk_names_to_lock,
                             bool *has_not_locked_parent_or_fk_name)
 {
-  TABLE_LIST *table;
+  TABLE_LIST *table, *tab;
   TABLE_SHARE *share;
   char key[MAX_DBKEY_LENGTH];
   uint key_length;
@@ -2352,7 +2366,7 @@ fk_check_tables_before_drop(THD *thd, TA
   for (table= tables; table; table= table->next_local)
   {
     /* Skip this table if it is a temporary table. */
-    if (table->table)
+    if (table->drop_table_rctx->is_temporary)
       continue;
 
     /*
@@ -2406,8 +2420,9 @@ fk_check_tables_before_drop(THD *thd, TA
       */
       while ((fk_p_s= fkeys_p_it++))
       {
-        if (! find_table_in_local_list(tables, fk_p_s->child_table_db.str,
-                                       fk_p_s->child_table_name.str))
+        if (! (tab= find_table_in_local_list(tables, fk_p_s->child_table_db.str,
+                                             fk_p_s->child_table_name.str)) ||
+            tab->drop_table_rctx->is_temporary)
         {
           my_error(ER_FK_CHILD_TABLE_EXISTS, MYF(0), fk_p_s->name.str,
                    thd->lex->sql_command == SQLCOM_DROP_DB ? "DROP DATABASE" :
@@ -2486,7 +2501,6 @@ fk_check_tables_before_drop(THD *thd, TA
                                                   child_table_db,
                                                   fk_c_s->name)) ||
              fk_names_to_lock->push_back(fk_name, thd->mem_root)))
-
         {
           pthread_mutex_lock(&LOCK_open);
           release_table_share(share);
@@ -2529,14 +2543,14 @@ fk_check_tables_before_drop(THD *thd,
                             TABLE_LIST *tables, TABLE_LIST **parents_locked,
                             List<Foreign_key_name> *fk_names_locked)
 {
-  TABLE_LIST *table;
+  TABLE_LIST *table, *tab;
   TABLE_SHARE *share;
   Foreign_key_name *fk_name;
 
   for (table= tables; table; table= table->next_local)
   {
     /* Skip this table if it is a temporary table. */
-    if (table->table->s->tmp_table != NO_TMP_TABLE)
+    if (table->drop_table_rctx->is_temporary)
       continue;
 
     share= table->table->s;
@@ -2547,8 +2561,9 @@ fk_check_tables_before_drop(THD *thd,
 
     while ((fk_p_s= fkeys_p_it++))
     {
-      if (! find_table_in_local_list(tables, fk_p_s->child_table_db.str,
-                                     fk_p_s->child_table_name.str))
+      if (! (tab= find_table_in_local_list(tables, fk_p_s->child_table_db.str,
+                                           fk_p_s->child_table_name.str)) ||
+          tab->drop_table_rctx->is_temporary)
       {
         my_error(ER_FK_CHILD_TABLE_EXISTS, MYF(0), fk_p_s->name.str,
                  thd->lex->sql_command == SQLCOM_DROP_DB ? "DROP DATABASE" :
@@ -2563,9 +2578,10 @@ fk_check_tables_before_drop(THD *thd,
 
     while ((fk_c_s= fkeys_c_it++))
     {
-      if (! find_table_in_local_list(tables,
+      if ((! (tab= find_table_in_local_list(tables,
                                      fk_c_s->parent_table_db.str,
-                                     fk_c_s->parent_table_name.str) &&
+                                     fk_c_s->parent_table_name.str)) ||
+           tab->drop_table_rctx->is_temporary) &&
           ! find_table_in_local_list(*parents_locked,
                                      fk_c_s->parent_table_db.str,
                                      fk_c_s->parent_table_name.str))
@@ -2592,7 +2608,8 @@ fk_check_tables_before_drop(THD *thd,
 
         @sa fk_take_mdl_on_fk_names().
       */
-      fk_name= thd->locked_tables_list.find_fk_name(table->db, fk_c_s->name.str);
+      fk_name= thd->locked_tables_list.find_fk_name(table->db,
+                                                    fk_c_s->name.str);
       DBUG_ASSERT(fk_name);
 
       if (fk_names_locked->push_back(fk_name, thd->mem_root))
@@ -2674,6 +2691,13 @@ int mysql_rm_table_part2(THD *thd, TABLE
   if (!drop_temporary)
     global_schema_lock_guard.lock();
 
+  /* Create per-table runtime contexts for the operation. */
+  for (table= tables; table; table= table->next_local)
+  {
+    if (! (table->drop_table_rctx= new(thd->mem_root) Drop_table_rcontext()))
+      DBUG_RETURN(1);
+  }
+
   /*
     If we have the table in the definition cache, we don't have to check the
     .frm file to find if the table is a normal table (not view) and what
@@ -2683,9 +2707,9 @@ int mysql_rm_table_part2(THD *thd, TABLE
   for (table= tables; table; table= table->next_local)
   {
     TABLE_SHARE *share;
-    table->db_type= NULL;
+
     if ((share= get_cached_table_share(table->db, table->table_name)))
-      table->db_type= share->db_type();
+      table->drop_table_rctx->table_type= share->db_type();
 
     /* Disable drop of enabled log tables */
     if (share && (share->table_category == TABLE_CATEGORY_PERFORMANCE) &&
@@ -2709,15 +2733,8 @@ int mysql_rm_table_part2(THD *thd, TABLE
     */
     for (table= tables; table; table= table->next_local)
     {
-      if ((table->table= find_temporary_table(thd, table->db,
-                                              table->table_name)))
-      {
-        /*
-          Since we don't acquire metadata lock if we have found temporary
-          table, we should do something to avoid releasing it at the end.
-        */
-        table->mdl_request= 0;
-      }
+      if (find_temporary_table(thd, table->db, table->table_name))
+        table->drop_table_rctx->is_temporary= TRUE;
     }
 
     if (!thd->locked_tables_mode)
@@ -2747,7 +2764,8 @@ retry_lock:
     else
     {
       for (table= tables; table; table= table->next_local)
-        if (! table->table)
+      {
+        if (! table->drop_table_rctx->is_temporary)
         {
           /*
             Check that each non-temporary table to be dropped is locked
@@ -2760,6 +2778,7 @@ retry_lock:
             DBUG_RETURN(1);
           table->mdl_request->ticket= table->table->mdl_ticket;
         }
+      }
 
       /*
         Check that we are not dropping parent tables withour dropping child
@@ -2806,8 +2825,8 @@ retry_lock:
     switch (error) {
     case  0:
       // removed temporary table
+      DBUG_ASSERT(drop_temporary || table->drop_table_rctx->is_temporary);
       tmp_table_deleted= 1;
-      table->table= 0;
       continue;
     case -1:
       DBUG_ASSERT(thd->in_sub_stmt);
@@ -2815,6 +2834,7 @@ retry_lock:
       goto err;
     default:
       // temporary table not found
+      DBUG_ASSERT(! table->drop_table_rctx->is_temporary);
       error= 0;
     }
 
@@ -2844,7 +2864,7 @@ retry_lock:
       built_query.append("`,");
     }
 
-    table_type= table->db_type;
+    table_type= table->drop_table_rctx->table_type;
     if (!drop_temporary)
     {
       if (opt_fk_all_engines &&
@@ -3108,7 +3128,7 @@ err:
     }
     for (table= tables; table; table= table->next_local)
     {
-      if (table->mdl_request)
+      if (! table->drop_table_rctx->is_temporary)
       {
         /*
           Under LOCK TABLES we may have several instances of table open

=== modified file 'sql/table.h'
--- a/sql/table.h	2009-05-14 14:18:43 +0000
+++ b/sql/table.h	2009-05-22 09:50:20 +0000
@@ -1088,6 +1088,7 @@ class SJ_MATERIALIZATION_INFO;
 class Index_hint;
 class Item_in_subselect;
 class Parent_info;
+class Drop_table_rcontext;
 
 
 /*
@@ -1424,7 +1425,6 @@ struct TABLE_LIST
   bool          check_option_processed;
   /* FRMTYPE_ERROR if any type is acceptable */
   enum frm_type_enum required_type;
-  handlerton	*db_type;		/* table_type for handler */
   char		timestamp_buffer[20];	/* buffer for timestamp (19+1) */
   /*
     This TABLE_LIST object is just placeholder for prelocking, it will be
@@ -1537,6 +1537,13 @@ struct TABLE_LIST
   */
   Parent_info *parent_info;
 
+  /**
+    For table list elements representing tables being dropped in DROP TABLES
+    and DROP DATABASE statements context holding information about such table
+    for the whole duration of the statement.
+  */
+  Drop_table_rcontext *drop_table_rctx;
+
   void calc_md5(char *buffer);
   void set_underlying_merge();
   int view_check_option(THD *thd, bool ignore_failure);


Attachment: [text/bzr-bundle] bzr/dlenev@mysql.com-20090522095020-v1lw99ewjmzmxbcm.bundle
Thread
bzr commit into mysql-6.1-fk branch (dlenev:2737)Dmitry Lenev22 May