32
32
#include <google/protobuf/io/zero_copy_stream.h>
33
33
#include <google/protobuf/io/zero_copy_stream_impl.h>
35
#include "drizzled/cached_directory.h"
35
#include <drizzled/cached_directory.h>
37
36
#include <drizzled/definitions.h>
38
37
#include <drizzled/base.h>
39
38
#include <drizzled/cursor.h>
41
40
#include <drizzled/session.h>
42
41
#include <drizzled/error.h>
43
42
#include <drizzled/gettext.h>
44
#include <drizzled/unireg.h>
45
43
#include <drizzled/data_home.h>
46
#include "drizzled/errmsg_print.h"
47
#include "drizzled/xid.h"
48
#include "drizzled/sql_table.h"
49
#include "drizzled/global_charset_info.h"
50
#include "drizzled/charset.h"
51
#include "drizzled/internal/my_sys.h"
52
#include "drizzled/db.h"
44
#include <drizzled/errmsg_print.h>
45
#include <drizzled/xid.h>
46
#include <drizzled/sql_table.h>
47
#include <drizzled/charset.h>
48
#include <drizzled/internal/my_sys.h>
54
49
#include <drizzled/table_proto.h>
55
50
#include <drizzled/plugin/event_observer.h>
57
51
#include <drizzled/table/shell.h>
59
#include "drizzled/message/cache.h"
52
#include <drizzled/message/cache.h>
53
#include <drizzled/key.h>
54
#include <drizzled/session/transactions.h>
55
#include <drizzled/open_tables_state.h>
61
57
#include <boost/algorithm/string/compare.hpp>
63
59
static bool shutdown_has_begun= false; // Once we put in the container for the vector/etc for engines this will go away.
71
static EngineVector vector_of_engines;
72
static EngineVector vector_of_schema_engines;
64
static EngineVector g_engines;
65
static EngineVector g_schema_engines;
74
67
const std::string DEFAULT_STRING("default");
75
68
const std::string UNKNOWN_STRING("UNKNOWN");
80
73
EngineVector &StorageEngine::getSchemaEngines()
82
return vector_of_schema_engines;
75
return g_schema_engines;
85
StorageEngine::StorageEngine(const std::string name_arg,
78
StorageEngine::StorageEngine(const std::string &name_arg,
86
79
const std::bitset<HTON_BIT_SIZE> &flags_arg) :
87
80
Plugin(name_arg, "StorageEngine"),
88
81
MonitoredInTransaction(), /* This gives the storage engine a "slot" or ID */
100
93
statement_ctx.markModifiedNonTransData();
104
96
int StorageEngine::renameTable(Session &session, const identifier::Table &from, const identifier::Table &to)
107
98
setTransactionReadWrite(session);
109
99
if (unlikely(plugin::EventObserver::beforeRenameTable(session, from, to)))
100
return ER_EVENT_OBSERVER_PLUGIN;
101
int error= doRenameTable(session, from, to);
102
if (unlikely(plugin::EventObserver::afterRenameTable(session, from, to, error)))
111
103
error= ER_EVENT_OBSERVER_PLUGIN;
115
error = doRenameTable(session, from, to);
116
if (unlikely(plugin::EventObserver::afterRenameTable(session, from, to, error)))
118
error= ER_EVENT_OBSERVER_PLUGIN;
177
157
if (engine->check_flag(HTON_BIT_SCHEMA_DICTIONARY))
178
vector_of_schema_engines.push_back(engine);
158
g_schema_engines.push_back(engine);
183
163
void StorageEngine::removePlugin(StorageEngine *)
185
if (shutdown_has_begun == false)
187
vector_of_engines.clear();
188
vector_of_schema_engines.clear();
190
shutdown_has_begun= true;
165
if (shutdown_has_begun)
167
shutdown_has_begun= true;
169
g_schema_engines.clear();
194
class FindEngineByName
195
: public std::unary_function<StorageEngine *, bool>
197
const std::string &predicate;
200
explicit FindEngineByName(const std::string &target_arg) :
201
predicate(target_arg)
205
result_type operator() (argument_type engine)
207
return boost::iequals(engine->getName(), predicate);
211
172
StorageEngine *StorageEngine::findByName(const std::string &predicate)
213
EngineVector::iterator iter= std::find_if(vector_of_engines.begin(),
214
vector_of_engines.end(),
215
FindEngineByName(predicate));
216
if (iter != vector_of_engines.end())
174
BOOST_FOREACH(EngineVector::reference it, g_engines)
218
StorageEngine *engine= *iter;
219
if (engine->is_user_selectable())
176
if (not boost::iequals(it->getName(), predicate))
178
if (it->is_user_selectable())
228
187
if (boost::iequals(predicate, DEFAULT_STRING))
229
188
return session.getDefaultStorageEngine();
231
EngineVector::iterator iter= std::find_if(vector_of_engines.begin(),
232
vector_of_engines.end(),
233
FindEngineByName(predicate));
234
if (iter != vector_of_engines.end())
236
StorageEngine *engine= *iter;
237
if (engine->is_user_selectable())
189
return findByName(predicate);
244
class StorageEngineCloseConnection : public std::unary_function<StorageEngine *, void>
248
StorageEngineCloseConnection(Session *session_arg) : session(session_arg) {}
250
there's no need to rollback here as all transactions must
251
be rolled back already
253
inline result_type operator() (argument_type engine)
255
if (*session->getEngineData(engine))
256
engine->close_connection(session);
262
194
don't bother to rollback here, it's done already
264
void StorageEngine::closeConnection(Session* session)
196
void StorageEngine::closeConnection(Session& session)
266
std::for_each(vector_of_engines.begin(), vector_of_engines.end(),
267
StorageEngineCloseConnection(session));
198
BOOST_FOREACH(EngineVector::reference it, g_engines)
200
if (*session.getEngineData(it))
201
it->close_connection(&session);
270
205
bool StorageEngine::flushLogs(StorageEngine *engine)
274
if (std::find_if(vector_of_engines.begin(), vector_of_engines.end(),
275
std::mem_fun(&StorageEngine::flush_logs))
276
!= vector_of_engines.begin())
281
if (engine->flush_logs())
209
if (std::find_if(g_engines.begin(), g_engines.end(), std::mem_fun(&StorageEngine::flush_logs))
210
!= g_engines.begin()) // Shouldn't this be .end()?
213
else if (engine->flush_logs())
315
class StorageEngineDoesTableExist: public std::unary_function<StorageEngine *, bool>
318
const identifier::Table &identifier;
321
StorageEngineDoesTableExist(Session& session_arg, const identifier::Table &identifier_arg) :
322
session(session_arg),
323
identifier(identifier_arg)
326
result_type operator() (argument_type engine)
328
return engine->doDoesTableExist(session, identifier);
333
247
Utility method which hides some of the details of getTableDefinition()
336
250
const identifier::Table &identifier,
337
251
bool include_temporary_tables)
339
if (include_temporary_tables)
341
if (session.doDoesTableExist(identifier))
345
EngineVector::iterator iter=
346
std::find_if(vector_of_engines.begin(), vector_of_engines.end(),
347
StorageEngineDoesTableExist(session, identifier));
349
if (iter == vector_of_engines.end())
253
if (include_temporary_tables && session.open_tables.doDoesTableExist(identifier))
255
BOOST_FOREACH(EngineVector::reference it, g_engines)
257
if (it->doDoesTableExist(session, identifier))
357
263
bool plugin::StorageEngine::doDoesTableExist(Session&, const drizzled::identifier::Table&)
365
Call this function in order to give the Cursor the possiblity
366
to ask engine if there are any new tables that should be written to disk
367
or any dropped tables that need to be removed from disk
369
int StorageEngine::getTableDefinition(Session& session,
370
const identifier::Table &identifier,
371
message::table::shared_ptr &table_message,
372
bool include_temporary_tables)
374
drizzled::error_t err= static_cast<drizzled::error_t>(ENOENT);
376
if (include_temporary_tables)
378
Table *table= session.find_temporary_table(identifier);
381
table_message.reset(new message::Table(*table->getShare()->getTableMessage()));
386
drizzled::message::table::shared_ptr table_ptr;
387
if ((table_ptr= drizzled::message::Cache::singleton().find(identifier)))
389
table_message= table_ptr;
392
message::Table message;
393
EngineVector::iterator iter=
394
std::find_if(vector_of_engines.begin(), vector_of_engines.end(),
395
StorageEngineGetTableDefinition(session, identifier, message, err));
397
if (iter == vector_of_engines.end())
401
table_message.reset(new message::Table(message));
403
drizzled::message::Cache::singleton().insert(identifier, table_message);
408
270
message::table::shared_ptr StorageEngine::getTableMessage(Session& session,
409
identifier::Table::const_reference identifier,
410
drizzled::error_t &error,
271
const identifier::Table& identifier,
411
272
bool include_temporary_tables)
413
error= static_cast<drizzled::error_t>(ENOENT);
274
drizzled::error_t error= static_cast<drizzled::error_t>(ENOENT);
415
275
if (include_temporary_tables)
417
Table *table= session.find_temporary_table(identifier);
277
if (Table *table= session.open_tables.find_temporary_table(identifier))
421
279
return message::table::shared_ptr(new message::Table(*table->getShare()->getTableMessage()));
431
289
message::Table message;
432
290
EngineVector::iterator iter=
433
std::find_if(vector_of_engines.begin(), vector_of_engines.end(),
291
std::find_if(g_engines.begin(), g_engines.end(),
434
292
StorageEngineGetTableDefinition(session, identifier, message, error));
436
if (iter == vector_of_engines.end())
294
if (iter == g_engines.end())
438
error= static_cast<drizzled::error_t>(ENOENT);
439
296
return message::table::shared_ptr();
441
298
message::table::shared_ptr table_message(new message::Table(message));
445
302
return table_message;
449
An interceptor to hijack the text of the error message without
450
setting an error in the thread. We need the text to present it
451
in the form of a warning to the user.
454
class Ha_delete_table_error_handler: public Internal_error_handler
457
Ha_delete_table_error_handler() : Internal_error_handler() {}
458
virtual bool handle_error(drizzled::error_t sql_errno,
460
DRIZZLE_ERROR::enum_warning_level level,
462
char buff[DRIZZLE_ERRMSG_SIZE];
467
Ha_delete_table_error_handler::
468
handle_error(drizzled::error_t ,
470
DRIZZLE_ERROR::enum_warning_level ,
473
/* Grab the error message */
474
strncpy(buff, message, sizeof(buff)-1);
478
305
class DropTableByIdentifier: public std::unary_function<EngineVector::value_type, bool>
480
Session::reference session;
481
identifier::Table::const_reference identifier;
308
const identifier::Table& identifier;
482
309
drizzled::error_t &error;
486
DropTableByIdentifier(Session::reference session_arg,
487
identifier::Table::const_reference identifier_arg,
313
DropTableByIdentifier(Session& session_arg,
314
const identifier::Table& identifier_arg,
488
315
drizzled::error_t &error_arg) :
489
316
session(session_arg),
490
317
identifier(identifier_arg),
520
bool StorageEngine::dropTable(Session::reference session,
521
identifier::Table::const_reference identifier,
347
bool StorageEngine::dropTable(Session& session,
348
const identifier::Table& identifier,
522
349
drizzled::error_t &error)
526
EngineVector::const_iterator iter= std::find_if(vector_of_engines.begin(), vector_of_engines.end(),
353
EngineVector::const_iterator iter= std::find_if(g_engines.begin(), g_engines.end(),
527
354
DropTableByIdentifier(session, identifier, error));
533
else if (iter == vector_of_engines.end())
360
else if (iter == g_engines.end())
535
362
error= ER_BAD_TABLE_ERROR;
545
372
const identifier::Table &identifier)
547
374
drizzled::error_t error;
549
if (not dropTable(session, identifier, error))
375
return dropTable(session, identifier, error);
557
bool StorageEngine::dropTable(Session::reference session,
378
bool StorageEngine::dropTable(Session& session,
558
379
StorageEngine &engine,
559
identifier::Table::const_reference identifier,
380
const identifier::Table& identifier,
560
381
drizzled::error_t &error)
642
456
if (error == ER_TABLE_PERMISSION_DENIED)
644
457
my_error(ER_TABLE_PERMISSION_DENIED, identifier);
649
identifier.getSQLPath(path);
650
my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), path.c_str(), error);
459
my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), identifier.getSQLPath().c_str(), error);
653
460
table.delete_table();
656
462
return(error == EE_OK);
661
467
return create(arg);
664
class AddTableIdentifier :
665
public std::unary_function<StorageEngine *, void>
667
CachedDirectory &directory;
668
const identifier::Schema &identifier;
669
identifier::Table::vector &set_of_identifiers;
673
AddTableIdentifier(CachedDirectory &directory_arg, const identifier::Schema &identifier_arg, identifier::Table::vector &of_names) :
674
directory(directory_arg),
675
identifier(identifier_arg),
676
set_of_identifiers(of_names)
680
result_type operator() (argument_type engine)
682
engine->doGetTableIdentifiers(directory, identifier, set_of_identifiers);
687
void StorageEngine::getIdentifiers(Session &session, const identifier::Schema &schema_identifier, identifier::Table::vector &set_of_identifiers)
470
void StorageEngine::getIdentifiers(Session &session, const identifier::Schema &schema_identifier, identifier::table::vector &set_of_identifiers)
689
472
CachedDirectory directory(schema_identifier.getPath(), set_of_table_definition_ext);
691
474
if (schema_identifier == INFORMATION_SCHEMA_IDENTIFIER)
693
477
else if (schema_identifier == DATA_DICTIONARY_IDENTIFIER)
480
else if (directory.fail())
697
if (directory.fail())
699
errno= directory.getError();
703
schema_identifier.getSQLPath(path);
704
my_error(ER_BAD_DB_ERROR, MYF(ME_BELL+ME_WAITTANG), path.c_str());
708
my_error(ER_CANT_READ_DIR, MYF(ME_BELL+ME_WAITTANG), directory.getPath(), errno);
482
errno= directory.getError();
484
my_error(ER_BAD_DB_ERROR, MYF(ME_BELL+ME_WAITTANG), schema_identifier.getSQLPath().c_str());
486
my_error(ER_CANT_READ_DIR, MYF(ME_BELL+ME_WAITTANG), directory.getPath(), errno);
715
std::for_each(vector_of_engines.begin(), vector_of_engines.end(),
716
AddTableIdentifier(directory, schema_identifier, set_of_identifiers));
490
BOOST_FOREACH(EngineVector::reference it, g_engines)
491
it->doGetTableIdentifiers(directory, schema_identifier, set_of_identifiers);
718
session.doGetTableIdentifiers(directory, schema_identifier, set_of_identifiers);
493
session.open_tables.doGetTableIdentifiers(directory, schema_identifier, set_of_identifiers);
721
496
class DropTable: public std::unary_function<identifier::Table&, bool>
739
/* This will later be converted to identifier::Tables */
740
class DropTables: public std::unary_function<StorageEngine *, void>
743
identifier::Table::vector &table_identifiers;
747
DropTables(Session &session_arg, identifier::Table::vector &table_identifiers_arg) :
748
session(session_arg),
749
table_identifiers(table_identifiers_arg)
752
result_type operator() (argument_type engine)
754
// True returning from DropTable means the table has been successfully
755
// deleted, so it should be removed from the list of tables to drop
756
table_identifiers.erase(std::remove_if(table_identifiers.begin(),
757
table_identifiers.end(),
758
DropTable(session, engine)),
759
table_identifiers.end());
764
515
This only works for engines which use file based DFE.
805
std::for_each(vector_of_engines.begin(), vector_of_engines.end(),
806
DropTables(session, table_identifiers));
556
BOOST_FOREACH(EngineVector::reference it, g_engines)
558
table_identifiers.erase(std::remove_if(table_identifiers.begin(), table_identifiers.end(), DropTable(session, it)),
559
table_identifiers.end());
809
563
Now we just clean up anything that might left over.
967
721
get_error_message(error, &str);
968
my_error(ER_ROW_IS_REFERENCED_2, MYF(0), str.c_ptr_safe());
722
my_error(ER_ROW_IS_REFERENCED_2, MYF(0), str.c_str());
971
725
case HA_ERR_NO_REFERENCED_ROW:
974
728
get_error_message(error, &str);
975
my_error(ER_NO_REFERENCED_ROW_2, MYF(0), str.c_ptr_safe());
729
my_error(ER_NO_REFERENCED_ROW_2, MYF(0), str.c_str());
978
732
case HA_ERR_TABLE_DEF_CHANGED:
1009
763
textno= ER_WARN_DATA_OUT_OF_RANGE;
1011
765
case HA_ERR_LOCK_OR_ACTIVE_TRANSACTION:
1012
my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
1013
ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
766
my_message(ER_LOCK_OR_ACTIVE_TRANSACTION, ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
1021
774
bool temporary= false;
1023
776
temporary= get_error_message(error, &str);
1024
if (!str.is_empty())
1026
779
const char* engine_name= getName().c_str();
1028
my_error(ER_GET_TEMPORARY_ERRMSG, MYF(0), error, str.ptr(),
781
my_error(ER_GET_TEMPORARY_ERRMSG, MYF(0), error, str.ptr(), engine_name);
1031
783
my_error(ER_GET_ERRMSG, MYF(0), error, str.ptr(), engine_name);
1157
909
if (not success)
1159
std::string error_message;
1160
identifier.getSQLPath(error_message);
1162
my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
1163
error_message.c_str(),
1164
table_message.InitializationErrorString().c_str());
911
my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0), identifier.getSQLPath().c_str(), table_message.InitializationErrorString().c_str());
1167
914
if (close(fd) == -1)
1203
class CanCreateTable: public std::unary_function<StorageEngine *, bool>
1205
const identifier::Table &identifier;
1208
CanCreateTable(const identifier::Table &identifier_arg) :
1209
identifier(identifier_arg)
1212
result_type operator() (argument_type engine)
1214
return not engine->doCanCreateTable(identifier);
1220
951
@note on success table can be created.
1222
953
bool StorageEngine::canCreateTable(const identifier::Table &identifier)
1224
EngineVector::iterator iter=
1225
std::find_if(vector_of_engines.begin(), vector_of_engines.end(),
1226
CanCreateTable(identifier));
1228
if (iter == vector_of_engines.end())
955
BOOST_FOREACH(EngineVector::reference it, g_engines)
957
if (not it->doCanCreateTable(identifier))
1236
963
bool StorageEngine::readTableFile(const std::string &path, message::Table &table_message)