List:Commits« Previous MessageNext Message »
From:eugene Date:October 13 2006 5:59pm
Subject:bk commit into 5.0 tree (evgen:1.2299) BUG#14959
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of evgen. When evgen does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2006-10-13 21:59:52+04:00, evgen@stripped +5 -0
  Bug#14959: ALTER TABLE isn't able to rename a view
  
  The mysql_alter_table() was able to rename only a table.
  
  The view/table renaming code is moved from the function rename_tables 
  to the new function called do_rename().
  The mysql_alter_table() function calls it when it needs to rename a view.

  mysql-test/r/rename.result@stripped, 2006-10-13 21:51:04+04:00, evgen@stripped +10 -0
    Added a test case for bug#14959: ALTER TABLE isn't able to rename a view

  mysql-test/t/rename.test@stripped, 2006-10-13 21:47:00+04:00, evgen@stripped +13 -0
    Added a test case for bug#14959: ALTER TABLE isn't able to rename a view

  sql/mysql_priv.h@stripped, 2006-10-13 21:56:45+04:00, evgen@stripped +3 -0
    Bug#14959: ALTER TABLE isn't able to rename a view
    Added the prototype of the do_rename() function.

  sql/sql_rename.cc@stripped, 2006-10-13 21:57:58+04:00, evgen@stripped +123 -71
    Bug#14959: ALTER TABLE isn't able to rename a view
    The view/table renaming code is moved from the function rename_tables
    to the new function called do_rename().

  sql/sql_table.cc@stripped, 2006-10-13 21:58:16+04:00, evgen@stripped +47 -1
    Bug#14959: ALTER TABLE isn't able to rename a view
    Added handling of a view rename to the mysql_alter_table() function.

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	evgen
# Host:	moonbone.local
# Root:	/work/14959-bug-5.0-opt-mysql

--- 1.412/sql/mysql_priv.h	2006-10-13 21:59:55 +04:00
+++ 1.413/sql/mysql_priv.h	2006-10-13 21:59:55 +04:00
@@ -648,6 +648,9 @@
 		   const char *table_name);
 void close_cached_table(THD *thd, TABLE *table);
 bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list);
+bool do_rename(THD *thd, TABLE_LIST *ren_table, char *new_db,
+                      char *new_table_name, char *new_table_alias,
+                      bool skip_error);
 bool mysql_change_db(THD *thd,const char *name,bool no_access_check);
 void mysql_parse(THD *thd,char *inBuf,uint length);
 bool mysql_test_parse_for_slave(THD *thd,char *inBuf,uint length);

--- 1.321/sql/sql_table.cc	2006-10-13 21:59:55 +04:00
+++ 1.322/sql/sql_table.cc	2006-10-13 21:59:55 +04:00
@@ -3154,9 +3154,10 @@
   ha_rows copied,deleted;
   ulonglong next_insert_id;
   uint db_create_options, used_fields;
-  enum db_type old_db_type,new_db_type;
+  enum db_type old_db_type, new_db_type, table_type;
   bool need_copy_table;
   bool no_table_reopen= FALSE, varchar= FALSE;
+  frm_type_enum frm_type;
   DBUG_ENTER("mysql_alter_table");
 
   thd->proc_info="init";
@@ -3174,6 +3175,51 @@
   if (alter_info->tablespace_op != NO_TABLESPACE_OP)
     DBUG_RETURN(mysql_discard_or_import_tablespace(thd,table_list,
 						   alter_info->tablespace_op));
+  sprintf(new_name_buff,"%s/%s/%s%s",mysql_data_home, db, table_name, reg_ext);
+  unpack_filename(new_name_buff, new_name_buff);
+  if (lower_case_table_names != 2)
+    my_casedn_str(files_charset_info, new_name_buff);
+  frm_type= mysql_frm_type(thd, new_name_buff, &table_type);
+  /* Rename a view */
+  if (frm_type == FRMTYPE_VIEW && !(alter_info->flags & ~ALTER_RENAME))
+  {
+    /*
+      Avoid problems with a rename on a table that we have locked or
+      if the user is trying to to do this in a transcation context
+    */
+
+    if (thd->locked_tables || thd->active_transaction())
+    {
+      my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
+                 ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
+      DBUG_RETURN(1);
+    }
+
+    if (wait_if_global_read_lock(thd,0,1))
+      DBUG_RETURN(1);
+    VOID(pthread_mutex_lock(&LOCK_open));
+    if (lock_table_names(thd, table_list))
+      goto view_err;
+    
+    error=0;
+    if (!do_rename(thd, table_list, new_db, new_name, new_name, 1))
+    {
+      if (mysql_bin_log.is_open())
+      {
+        thd->clear_error();
+        Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
+        mysql_bin_log.write(&qinfo);
+      }
+      send_ok(thd);
+    }
+
+    unlock_table_names(thd, table_list, (TABLE_LIST*) 0);
+
+view_err:
+    pthread_mutex_unlock(&LOCK_open);
+    start_waiting_global_read_lock(thd);
+    DBUG_RETURN(error);
+  }
   if (!(table=open_ltable(thd,table_list,TL_WRITE_ALLOW_READ)))
     DBUG_RETURN(TRUE);
 

--- 1.12/mysql-test/r/rename.result	2006-10-13 21:59:55 +04:00
+++ 1.13/mysql-test/r/rename.result	2006-10-13 21:59:55 +04:00
@@ -54,3 +54,13 @@
 t2
 t4
 drop table t2, t4;
+create table t1(f1 int);
+create view v1 as select * from t1;
+alter table v1 rename to v2;
+alter table v1 rename to v2;
+ERROR 42S02: Table 'test.v1' doesn't exist
+rename table v2 to v1;
+rename table v2 to v1;
+ERROR 42S01: Table 'v1' already exists
+drop view v1;
+drop table t1;

--- 1.12/mysql-test/t/rename.test	2006-10-13 21:59:55 +04:00
+++ 1.13/mysql-test/t/rename.test	2006-10-13 21:59:55 +04:00
@@ -72,4 +72,17 @@
 disconnect con1;
 connection default;
 
+#
+# Bug#14959: ALTER TABLE isn't able to rename a view
+#
+create table t1(f1 int);
+create view v1 as select * from t1;
+alter table v1 rename to v2;
+--error 1146
+alter table v1 rename to v2;
+rename table v2 to v1;
+--error 1050
+rename table v2 to v1;
+drop view v1;
+drop table t1;
 # End of 4.1 tests

--- 1.32/sql/sql_rename.cc	2006-10-13 21:59:55 +04:00
+++ 1.33/sql/sql_rename.cc	2006-10-13 21:59:55 +04:00
@@ -126,94 +126,146 @@
 
 
 /*
-  Rename all tables in list; Return pointer to wrong entry if something goes
-  wrong.  Note that the table_list may be empty!
+  Rename a single table or a view
+
+  SYNPOSIS
+    do_rename()
+      thd               Thread handle
+      ren_table         A table/view to be renamed
+      new_db            The database to which the table to be moved to
+      new_table_name    The new table/view name
+      new_table_alias   The new table/view alias
+      skip_error        Whether to skip error
+
+  DESCRIPTION
+    Rename a single table or a view.
+
+  RETURN
+    false     Ok
+    true      rename failed
 */
 
-static TABLE_LIST *
-rename_tables(THD *thd, TABLE_LIST *table_list, bool skip_error)
+bool
+do_rename(THD *thd, TABLE_LIST *ren_table, char *new_db, char *new_table_name,
+          char *new_table_alias, bool skip_error)
 {
-  TABLE_LIST *ren_table,*new_table;
+  int rc= 1;
+  char name[FN_REFLEN];
+  const char *new_alias, *old_alias;
   frm_type_enum frm_type;
   db_type table_type;
 
-  DBUG_ENTER("rename_tables");
+  DBUG_ENTER("do_rename");
 
-  for (ren_table= table_list; ren_table; ren_table= new_table->next_local)
+  if (lower_case_table_names == 2)
   {
-    int rc= 1;
-    char name[FN_REFLEN];
-    const char *new_alias, *old_alias;
-
-    new_table= ren_table->next_local;
-    if (lower_case_table_names == 2)
-    {
-      old_alias= ren_table->alias;
-      new_alias= new_table->alias;
-    }
-    else
-    {
-      old_alias= ren_table->table_name;
-      new_alias= new_table->table_name;
-    }
-    sprintf(name,"%s/%s/%s%s",mysql_data_home,
-	    new_table->db, new_alias, reg_ext);
-    unpack_filename(name, name);
-    if (!access(name,F_OK))
-    {
-      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
-      DBUG_RETURN(ren_table);			// This can't be skipped
-    }
-    sprintf(name,"%s/%s/%s%s",mysql_data_home,
-	    ren_table->db, old_alias,
-	    reg_ext);
-    unpack_filename(name, name);
+    old_alias= ren_table->alias;
+    new_alias= new_table_alias;
+  }
+  else
+  {
+    old_alias= ren_table->table_name;
+    new_alias= new_table_name;
+  }
+  sprintf(name,"%s/%s/%s%s",mysql_data_home,
+          new_db, new_alias, reg_ext);
+  unpack_filename(name, name);
+  if (!access(name,F_OK))
+  {
+    my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
+    DBUG_RETURN(ren_table);			// This can't be skipped
+  }
+  sprintf(name,"%s/%s/%s%s",mysql_data_home,
+          ren_table->db, old_alias,
+          reg_ext);
+  unpack_filename(name, name);
 
-    frm_type= mysql_frm_type(thd, name, &table_type);
-    switch (frm_type)
+  frm_type= mysql_frm_type(thd, name, &table_type);
+  switch (frm_type)
+  {
+    case FRMTYPE_TABLE:
     {
-      case FRMTYPE_TABLE:
+      if (table_type == DB_TYPE_UNKNOWN) 
+        my_error(ER_FILE_NOT_FOUND, MYF(0), name, my_errno);
+      else
       {
-        if (table_type == DB_TYPE_UNKNOWN) 
-          my_error(ER_FILE_NOT_FOUND, MYF(0), name, my_errno);
-        else
+        if (!(rc= mysql_rename_table(table_type, ren_table->db, old_alias,
+                                     new_db, new_alias)))
         {
-          if (!(rc= mysql_rename_table(table_type, ren_table->db, old_alias,
-                                       new_table->db, new_alias)))
+          if ((rc= Table_triggers_list::change_table_name(thd, ren_table->db,
+                                                          old_alias,
+                                                          new_db,
+                                                          new_alias)))
           {
-            if ((rc= Table_triggers_list::change_table_name(thd, ren_table->db,
-                                                            old_alias,
-                                                            new_table->db,
-                                                            new_alias)))
-            {
-              /*
-                We've succeeded in renaming table's .frm and in updating
-                corresponding handler data, but have failed to update table's
-                triggers appropriately. So let us revert operations on .frm
-                and handler's data and report about failure to rename table.
-              */
-              (void) mysql_rename_table(table_type, new_table->db, new_alias,
-                                        ren_table->db, old_alias);
-            }
+            /*
+              We've succeeded in renaming table's .frm and in updating
+              corresponding handler data, but have failed to update table's
+              triggers appropriately. So let us revert operations on .frm
+              and handler's data and report about failure to rename table.
+            */
+            (void) mysql_rename_table(table_type, new_db, new_alias,
+                                      ren_table->db, old_alias);
           }
         }
-        break;
       }
-      case FRMTYPE_VIEW:
-        /* change of schema is not allowed */
-        if (strcmp(ren_table->db, new_table->db))
-          my_error(ER_FORBID_SCHEMA_CHANGE, MYF(0), ren_table->db, 
-                   new_table->db);
-        else
-          rc= mysql_rename_view(thd, new_alias, ren_table);
-        break;
-      default:
-        DBUG_ASSERT(0); // should never happen
-      case FRMTYPE_ERROR:
-        my_error(ER_FILE_NOT_FOUND, MYF(0), name, my_errno);
-        break;
+      break;
     }
-    if (rc && !skip_error)
+    case FRMTYPE_VIEW:
+      /* change of schema is not allowed */
+      if (strcmp(ren_table->db, new_db))
+        my_error(ER_FORBID_SCHEMA_CHANGE, MYF(0), ren_table->db, 
+                 new_db);
+      else
+        rc= mysql_rename_view(thd, new_alias, ren_table);
+      break;
+    default:
+      DBUG_ASSERT(0); // should never happen
+    case FRMTYPE_ERROR:
+      my_error(ER_FILE_NOT_FOUND, MYF(0), name, my_errno);
+      break;
+  }
+  if (rc && !skip_error)
+    DBUG_RETURN(1);
+
+  DBUG_RETURN(0);
+
+}
+/*
+  Rename all tables in list; Return pointer to wrong entry if something goes
+  wrong.  Note that the table_list may be empty!
+*/
+
+/*
+  Rename tables/views in the list
+
+  SYNPOSIS
+    rename_tables()
+      thd               Thread handle
+      table_list        List of tables to rename
+      skip_error        Whether to skip errors
+
+  DESCRIPTION
+    Take a table/view name from and odd list element and rename it to a
+    the name taken from list element+1. Note that the table_list may be
+    empty.
+
+  RETURN
+    false     Ok
+    true      rename failed
+*/
+
+static TABLE_LIST *
+rename_tables(THD *thd, TABLE_LIST *table_list, bool skip_error)
+{
+  TABLE_LIST *ren_table,*new_table, *tmp_table;
+
+  DBUG_ENTER("rename_tables");
+
+  for (ren_table= table_list; ren_table; ren_table= new_table->next_local)
+  {
+    new_table= ren_table->next_local;
+    if (do_rename(thd, ren_table, new_table->db, new_table->table_name,
+                  new_table->alias, skip_error))
       DBUG_RETURN(ren_table);
   }
   DBUG_RETURN(0);
Thread
bk commit into 5.0 tree (evgen:1.2299) BUG#14959eugene13 Oct