00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <config.h>
00021
00022 #include <drizzled/session.h>
00023 #include <drizzled/sql_base.h>
00024 #include <drizzled/charset.h>
00025 #include <drizzled/transaction_services.h>
00026 #include <drizzled/open_tables_state.h>
00027 #include <drizzled/table/cache.h>
00028 #include <drizzled/plugin/storage_engine.h>
00029 #include <drizzled/plugin/authorization.h>
00030
00031 namespace drizzled {
00032 namespace plugin {
00033
00034 class AddSchemaNames :
00035 public std::unary_function<StorageEngine *, void>
00036 {
00037 identifier::schema::vector &schemas;
00038
00039 public:
00040
00041 AddSchemaNames(identifier::schema::vector &of_names) :
00042 schemas(of_names)
00043 {
00044 }
00045
00046 result_type operator() (argument_type engine)
00047 {
00048 engine->doGetSchemaIdentifiers(schemas);
00049 }
00050 };
00051
00052 void StorageEngine::getIdentifiers(Session &session, identifier::schema::vector &schemas)
00053 {
00054
00055 std::for_each(StorageEngine::getSchemaEngines().begin(), StorageEngine::getSchemaEngines().end(),
00056 AddSchemaNames(schemas));
00057
00058 plugin::Authorization::pruneSchemaNames(*session.user(), schemas);
00059 }
00060
00061 class StorageEngineGetSchemaDefinition: public std::unary_function<StorageEngine *, bool>
00062 {
00063 const identifier::Schema &identifier;
00064 message::schema::shared_ptr &schema_proto;
00065
00066 public:
00067 StorageEngineGetSchemaDefinition(const identifier::Schema &identifier_arg,
00068 message::schema::shared_ptr &schema_proto_arg) :
00069 identifier(identifier_arg),
00070 schema_proto(schema_proto_arg)
00071 {
00072 }
00073
00074 result_type operator() (argument_type engine)
00075 {
00076 schema_proto= engine->doGetSchemaDefinition(identifier);
00077 return schema_proto;
00078 }
00079 };
00080
00081
00082
00083
00084 message::schema::shared_ptr StorageEngine::getSchemaDefinition(const drizzled::identifier::Table &identifier)
00085 {
00086 identifier::Schema schema_identifier= identifier;
00087 return StorageEngine::getSchemaDefinition(schema_identifier);
00088 }
00089
00090 message::schema::shared_ptr StorageEngine::getSchemaDefinition(const identifier::Schema &identifier)
00091 {
00092 message::schema::shared_ptr proto;
00093
00094 EngineVector::iterator iter=
00095 std::find_if(StorageEngine::getSchemaEngines().begin(), StorageEngine::getSchemaEngines().end(),
00096 StorageEngineGetSchemaDefinition(identifier, proto));
00097
00098 if (iter != StorageEngine::getSchemaEngines().end())
00099 {
00100 return proto;
00101 }
00102
00103 return message::schema::shared_ptr();
00104 }
00105
00106 bool StorageEngine::doesSchemaExist(const identifier::Schema &identifier)
00107 {
00108 message::schema::shared_ptr proto;
00109
00110 return StorageEngine::getSchemaDefinition(identifier);
00111 }
00112
00113
00114 const charset_info_st *StorageEngine::getSchemaCollation(const identifier::Schema &identifier)
00115 {
00116 message::schema::shared_ptr schmema_proto= StorageEngine::getSchemaDefinition(identifier);
00117 if (not schmema_proto || not schmema_proto->has_collation())
00118 return default_charset_info;
00119 const std::string buffer= schmema_proto->collation();
00120 if (const charset_info_st* cs= get_charset_by_name(buffer.c_str()))
00121 return cs;
00122 errmsg_printf(error::ERROR, _("Error while loading database options: '%s':"), identifier.getSQLPath().c_str());
00123 errmsg_printf(error::ERROR, ER(ER_UNKNOWN_COLLATION), buffer.c_str());
00124 return default_charset_info;
00125 }
00126
00127 class CreateSchema :
00128 public std::unary_function<StorageEngine *, void>
00129 {
00130 const drizzled::message::Schema &schema_message;
00131 uint64_t &success_count;
00132
00133 public:
00134
00135 CreateSchema(const drizzled::message::Schema &arg, uint64_t &success_count_arg) :
00136 schema_message(arg),
00137 success_count(success_count_arg)
00138 {
00139 }
00140
00141 result_type operator() (argument_type engine)
00142 {
00143
00144 bool success= engine->doCreateSchema(schema_message);
00145
00146 if (success)
00147 {
00148 success_count++;
00149 TransactionServices::allocateNewTransactionId();
00150 }
00151 }
00152 };
00153
00154 bool StorageEngine::createSchema(const drizzled::message::Schema &schema_message)
00155 {
00156
00157 uint64_t success_count= 0;
00158 std::for_each(StorageEngine::getSchemaEngines().begin(), StorageEngine::getSchemaEngines().end(),
00159 CreateSchema(schema_message, success_count));
00160
00161 if (success_count)
00162 {
00163 TransactionServices::allocateNewTransactionId();
00164 }
00165
00166 return (bool)success_count;
00167 }
00168
00169 class DropSchema :
00170 public std::unary_function<StorageEngine *, void>
00171 {
00172 uint64_t &success_count;
00173 const identifier::Schema &identifier;
00174
00175 public:
00176
00177 DropSchema(const identifier::Schema &arg, uint64_t &count_arg) :
00178 success_count(count_arg),
00179 identifier(arg)
00180 {
00181 }
00182
00183 result_type operator() (argument_type engine)
00184 {
00185
00186 bool success= engine->doDropSchema(identifier);
00187
00188 if (success)
00189 {
00190 success_count++;
00191 TransactionServices::allocateNewTransactionId();
00192 }
00193 }
00194 };
00195
00196 static bool drop_all_tables_in_schema(Session& session,
00197 const identifier::Schema& identifier,
00198 identifier::table::vector &dropped_tables,
00199 uint64_t &deleted)
00200 {
00201 plugin::StorageEngine::getIdentifiers(session, identifier, dropped_tables);
00202
00203 for (identifier::table::vector::iterator it= dropped_tables.begin(); it != dropped_tables.end(); it++)
00204 {
00205 boost::mutex::scoped_lock scopedLock(table::Cache::mutex());
00206
00207 message::table::shared_ptr message= StorageEngine::getTableMessage(session, *it, false);
00208 if (not message)
00209 {
00210 my_error(ER_TABLE_DROP, *it);
00211 return false;
00212 }
00213
00214 table::Cache::removeTable(session, *it, RTFC_WAIT_OTHER_THREAD_FLAG | RTFC_CHECK_KILLED_FLAG);
00215 if (not plugin::StorageEngine::dropTable(session, *it))
00216 {
00217 my_error(ER_TABLE_DROP, *it);
00218 return false;
00219 }
00220 TransactionServices::dropTable(session, *it, *message, true);
00221 deleted++;
00222 }
00223
00224 return true;
00225 }
00226
00227 bool StorageEngine::dropSchema(Session& session,
00228 const identifier::Schema& identifier,
00229 message::schema::const_reference schema_message)
00230 {
00231 uint64_t deleted= 0;
00232 bool error= false;
00233 identifier::table::vector dropped_tables;
00234
00235 do
00236 {
00237
00238
00239 {
00240
00241 identifier::table::vector set_of_identifiers;
00242 session.open_tables.doGetTableIdentifiers(identifier, set_of_identifiers);
00243
00244 for (identifier::table::vector::iterator iter= set_of_identifiers.begin(); iter != set_of_identifiers.end(); iter++)
00245 {
00246 if (session.open_tables.drop_temporary_table(*iter))
00247 {
00248 my_error(ER_TABLE_DROP, *iter);
00249 error= true;
00250 break;
00251 }
00252 }
00253 }
00254
00255
00256 table::Cache::removeSchema(identifier);
00257
00258 if (not drop_all_tables_in_schema(session, identifier, dropped_tables, deleted))
00259 {
00260 error= true;
00261 my_error(ER_DROP_SCHEMA, identifier);
00262 break;
00263 }
00264
00265 uint64_t counter= 0;
00266
00267 std::for_each(StorageEngine::getSchemaEngines().begin(), StorageEngine::getSchemaEngines().end(),
00268 DropSchema(identifier, counter));
00269
00270 if (not counter)
00271 {
00272 my_error(ER_DROP_SCHEMA, identifier);
00273 error= true;
00274
00275 break;
00276 }
00277 else
00278 {
00279
00280 TransactionServices::dropSchema(session, identifier, schema_message);
00281 }
00282 } while (0);
00283
00284 if (deleted > 0)
00285 {
00286 session.clear_error();
00287 session.server_status|= SERVER_STATUS_DB_DROPPED;
00288 session.my_ok((uint32_t) deleted);
00289 session.server_status&= ~SERVER_STATUS_DB_DROPPED;
00290 }
00291
00292
00293 return error;
00294 }
00295
00296 class AlterSchema :
00297 public std::unary_function<StorageEngine *, void>
00298 {
00299 uint64_t &success_count;
00300 const drizzled::message::Schema &schema_message;
00301
00302 public:
00303
00304 AlterSchema(const drizzled::message::Schema &arg, uint64_t &count_arg) :
00305 success_count(count_arg),
00306 schema_message(arg)
00307 {
00308 }
00309
00310 result_type operator() (argument_type engine)
00311 {
00312
00313 bool success= engine->doAlterSchema(schema_message);
00314
00315
00316 if (success)
00317 {
00318 success_count++;
00319 }
00320 }
00321 };
00322
00323 bool StorageEngine::alterSchema(const drizzled::message::Schema &schema_message)
00324 {
00325 uint64_t success_count= 0;
00326
00327 std::for_each(StorageEngine::getSchemaEngines().begin(), StorageEngine::getSchemaEngines().end(),
00328 AlterSchema(schema_message, success_count));
00329
00330 if (success_count)
00331 {
00332 TransactionServices::allocateNewTransactionId();
00333 }
00334
00335 return success_count ? true : false;
00336 }
00337
00338 }
00339 }