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