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