home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 January / Chip_2001-01_cd1.bin / tema / mysql / mysql-3.23.28g-win-source.exe / sql / sql_rename.cpp < prev    next >
C/C++ Source or Header  |  2000-09-16  |  4KB  |  150 lines

  1. /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
  2.  
  3.    This program is free software; you can redistribute it and/or modify
  4.    it under the terms of the GNU General Public License as published by
  5.    the Free Software Foundation; either version 2 of the License, or
  6.    (at your option) any later version.
  7.  
  8.    This program is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.    GNU General Public License for more details.
  12.  
  13.    You should have received a copy of the GNU General Public License
  14.    along with this program; if not, write to the Free Software
  15.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  16.  
  17. /*
  18.   Atomic rename of table;  RENAME TABLE t1 to t2, tmp to t1 [,...]
  19. */
  20.  
  21. #include "mysql_priv.h"
  22.  
  23.  
  24. static TABLE_LIST *rename_tables(THD *thd, TABLE_LIST *table_list,
  25.                  bool skip_error);
  26.  
  27. /*
  28.   Every second entry in the table_list is the original name and every
  29.   second entry is the new name.
  30. */
  31.  
  32. bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list)
  33. {
  34.   bool error=1,got_all_locks=1;
  35.   TABLE_LIST *lock_table,*ren_table=0;
  36.   DBUG_ENTER("mysql_rename_tables");
  37.   
  38.   /* Avoid problems with a rename on a table that we have locked or
  39.      if the user is trying to to do this in a transcation context */
  40.  
  41.   if (thd->locked_tables || thd->active_transaction())
  42.   {
  43.     my_error(ER_LOCK_OR_ACTIVE_TRANSACTION,MYF(0));
  44.     DBUG_RETURN(1);
  45.   }
  46.       
  47.   VOID(pthread_mutex_lock(&LOCK_open));
  48.   for (lock_table=table_list ; lock_table ; lock_table=lock_table->next)
  49.   {
  50.     int got_lock;
  51.     if ((got_lock=lock_table_name(thd,lock_table)) < 0)
  52.       goto end;
  53.     if (got_lock)
  54.       got_all_locks=0;
  55.   }
  56.   
  57.   if (!got_all_locks && wait_for_locked_table_names(thd,table_list))
  58.     goto end;
  59.  
  60.   if (!(ren_table=rename_tables(thd,table_list,0)))
  61.     error=0;
  62.   
  63. end:
  64.   if (ren_table)
  65.   {
  66.     /* Rename didn't succeed;  rename back the tables in reverse order */
  67.     TABLE_LIST *prev=0,*table;
  68.     /* Reverse the table list */
  69.  
  70.     while (table_list)
  71.     {
  72.       TABLE_LIST *next=table_list->next;
  73.       table_list->next=prev;
  74.       prev=table_list;
  75.       table_list=next;
  76.     }
  77.     table_list=prev;
  78.  
  79.     /* Find the last renamed table */
  80.     for (table=table_list ;
  81.      table->next != ren_table ;
  82.      table=table->next->next) ;
  83.     table=table->next->next;            // Skipp error table
  84.     /* Revert to old names */
  85.     rename_tables(thd, table, 1);
  86.     /* Note that lock_table == 0 here, so the unlock loop will work */
  87.   }
  88.   if (!error)
  89.   {
  90.     mysql_update_log.write(thd,thd->query,thd->query_length);
  91.     if (mysql_bin_log.is_open())
  92.     {
  93.       Query_log_event qinfo(thd, thd->query);
  94.       mysql_bin_log.write(&qinfo);
  95.     }
  96.     send_ok(&thd->net);
  97.   }
  98.   for (TABLE_LIST *table=table_list ; table != lock_table ; table=table->next)
  99.     unlock_table_name(thd,table);
  100.   pthread_cond_broadcast(&COND_refresh);
  101.   pthread_mutex_unlock(&LOCK_open);
  102.   DBUG_RETURN(error);
  103. }
  104.  
  105.  
  106. /*
  107.   Rename all tables in list; Return pointer to wrong entry if something goes
  108.   wrong.  Note that the table_list may be empty!
  109. */
  110.  
  111. static TABLE_LIST *
  112. rename_tables(THD *thd, TABLE_LIST *table_list, bool skip_error)
  113. {
  114.   TABLE_LIST *ren_table,*new_table;
  115.   DBUG_ENTER("rename_tables");
  116.  
  117.   for (ren_table=table_list ; ren_table ; ren_table=new_table->next)
  118.   {
  119.     db_type table_type;
  120.     char name[FN_REFLEN];
  121.     new_table=ren_table->next;
  122.  
  123.     sprintf(name,"%s/%s/%s%s",mysql_data_home,
  124.         new_table->db,new_table->name,
  125.         reg_ext);
  126.     if (!access(name,F_OK))
  127.     {
  128.       my_error(ER_TABLE_EXISTS_ERROR,MYF(0),name);
  129.       return ren_table;                // This can't be skipped
  130.     }
  131.     sprintf(name,"%s/%s/%s%s",mysql_data_home,
  132.         ren_table->db,ren_table->name,
  133.         reg_ext);
  134.     if ((table_type=get_table_type(name)) == DB_TYPE_UNKNOWN)
  135.     {
  136.       my_error(ER_FILE_NOT_FOUND, MYF(0), name, my_errno);
  137.       if (!skip_error)
  138.     return ren_table;
  139.     }
  140.     else if (mysql_rename_table(table_type,
  141.                 ren_table->db, ren_table->name,
  142.                 new_table->db, new_table->name))
  143.     {
  144.       if (!skip_error)
  145.     return ren_table;
  146.     }
  147.   }
  148.   DBUG_RETURN(0);
  149. }
  150.