00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <config.h>
00022 #include <drizzled/show.h>
00023 #include <drizzled/lock.h>
00024 #include <drizzled/session.h>
00025 #include <drizzled/statement/rename_table.h>
00026 #include <drizzled/pthread_globals.h>
00027 #include <drizzled/plugin/storage_engine.h>
00028 #include <drizzled/transaction_services.h>
00029 #include <drizzled/sql_lex.h>
00030 #include <drizzled/table/cache.h>
00031
00032 namespace drizzled {
00033
00034 bool statement::RenameTable::execute()
00035 {
00036 TableList *first_table= (TableList *) lex().select_lex.table_list.first;
00037 TableList *all_tables= lex().query_tables;
00038 assert(first_table == all_tables && first_table != 0);
00039 TableList *table;
00040
00041 if (session().inTransaction())
00042 {
00043 my_error(ER_TRANSACTIONAL_DDL_NOT_SUPPORTED, MYF(0));
00044 return true;
00045 }
00046
00047 for (table= first_table; table; table= table->next_local->next_local)
00048 {
00049 TableList old_list, new_list;
00050
00051
00052
00053
00054 old_list= table[0];
00055 new_list= table->next_local[0];
00056 }
00057
00058 if (renameTables(first_table))
00059 {
00060 return true;
00061 }
00062
00063 return false;
00064 }
00065
00066 bool statement::RenameTable::renameTables(TableList *table_list)
00067 {
00068 bool error= true;
00069 TableList *ren_table= NULL;
00070
00071
00072
00073
00074
00075 if (session().inTransaction())
00076 {
00077 my_message(ER_LOCK_OR_ACTIVE_TRANSACTION, ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
00078 return true;
00079 }
00080
00081 if (session().wait_if_global_read_lock(false, true))
00082 return true;
00083
00084 {
00085 boost::mutex::scoped_lock scopedLock(table::Cache::mutex());
00086
00087 if (not session().lock_table_names_exclusively(table_list))
00088 {
00089 error= false;
00090 ren_table= renameTablesInList(table_list, false);
00091
00092 if (ren_table)
00093 {
00094
00095 TableList *table;
00096
00097
00098 table_list= reverseTableList(table_list);
00099
00100
00101 for (table= table_list;
00102 table->next_local != ren_table;
00103 table= table->next_local->next_local)
00104 { }
00105
00106 table= table->next_local->next_local;
00107
00108
00109 renameTablesInList(table, true);
00110 error= true;
00111 }
00112
00113 table_list->unlock_table_names();
00114 }
00115 }
00116
00117
00118 if (not error)
00119 {
00120 TransactionServices::rawStatement(session(), *session().getQueryString(), *session().schema());
00121 session().my_ok();
00122 }
00123
00124 session().startWaitingGlobalReadLock();
00125
00126 return error;
00127 }
00128
00129 TableList *statement::RenameTable::reverseTableList(TableList *table_list)
00130 {
00131 TableList *prev= NULL;
00132
00133 while (table_list)
00134 {
00135 TableList *next= table_list->next_local;
00136 table_list->next_local= prev;
00137 prev= table_list;
00138 table_list= next;
00139 }
00140 return prev;
00141 }
00142
00143 bool statement::RenameTable::rename(TableList *ren_table,
00144 const char *new_db,
00145 const char *new_table_name,
00146 bool skip_error)
00147 {
00148 bool rc= true;
00149 const char *new_alias, *old_alias;
00150
00151 {
00152 old_alias= ren_table->getTableName();
00153 new_alias= new_table_name;
00154 }
00155
00156 plugin::StorageEngine *engine= NULL;
00157 message::table::shared_ptr table_message;
00158
00159 identifier::Table old_identifier(ren_table->getSchemaName(), old_alias, message::Table::STANDARD);
00160
00161 if (not (table_message= plugin::StorageEngine::getTableMessage(session(), old_identifier)))
00162 {
00163 my_error(ER_TABLE_UNKNOWN, old_identifier);
00164 return true;
00165 }
00166
00167 engine= plugin::StorageEngine::findByName(session(), table_message->engine().name());
00168
00169 identifier::Table new_identifier(new_db, new_alias, message::Table::STANDARD);
00170 if (plugin::StorageEngine::doesTableExist(session(), new_identifier))
00171 {
00172 my_error(ER_TABLE_EXISTS_ERROR, new_identifier);
00173 return 1;
00174 }
00175
00176 rc= rename_table(session(), engine, old_identifier, new_identifier);
00177 if (rc && ! skip_error)
00178 return true;
00179
00180 return false;
00181 }
00182
00183 TableList *statement::RenameTable::renameTablesInList(TableList *table_list,
00184 bool skip_error)
00185 {
00186 TableList *ren_table, *new_table;
00187
00188 for (ren_table= table_list; ren_table; ren_table= new_table->next_local)
00189 {
00190 new_table= ren_table->next_local;
00191 if (rename(ren_table, new_table->getSchemaName(), new_table->getTableName(), skip_error))
00192 return ren_table;
00193 }
00194 return 0;
00195 }
00196
00197 }