43
44
#include <drizzled/gettext.h>
44
45
#include <drizzled/unireg.h>
45
46
#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>
47
#include "drizzled/errmsg_print.h"
48
#include "drizzled/xid.h"
49
#include "drizzled/sql_table.h"
50
#include "drizzled/global_charset_info.h"
51
#include "drizzled/charset.h"
52
#include "drizzled/internal/my_sys.h"
53
#include "drizzled/db.h"
53
55
#include <drizzled/table_proto.h>
54
56
#include <drizzled/plugin/event_observer.h>
55
#include <drizzled/internal_error_handler.h>
57
#include <drizzled/table/shell.h>
59
#include <drizzled/message/cache.h>
61
58
#include <boost/algorithm/string/compare.hpp>
63
60
static bool shutdown_has_begun= false; // Once we put in the container for the vector/etc for engines this will go away.
82
81
return vector_of_schema_engines;
85
StorageEngine::StorageEngine(const std::string name_arg,
86
const std::bitset<HTON_BIT_SIZE> &flags_arg) :
84
StorageEngine::StorageEngine(const string name_arg,
85
const bitset<HTON_BIT_SIZE> &flags_arg) :
87
86
Plugin(name_arg, "StorageEngine"),
88
87
MonitoredInTransaction(), /* This gives the storage engine a "slot" or ID */
226
StorageEngine *StorageEngine::findByName(Session& session, const std::string &predicate)
225
StorageEngine *StorageEngine::findByName(Session& session, const string &predicate)
228
227
if (boost::iequals(predicate, DEFAULT_STRING))
229
228
return session.getDefaultStorageEngine();
231
EngineVector::iterator iter= std::find_if(vector_of_engines.begin(),
232
vector_of_engines.end(),
233
FindEngineByName(predicate));
230
EngineVector::iterator iter= find_if(vector_of_engines.begin(),
231
vector_of_engines.end(),
232
FindEngineByName(predicate));
234
233
if (iter != vector_of_engines.end())
236
235
StorageEngine *engine= *iter;
264
263
void StorageEngine::closeConnection(Session* session)
266
std::for_each(vector_of_engines.begin(), vector_of_engines.end(),
267
StorageEngineCloseConnection(session));
265
for_each(vector_of_engines.begin(), vector_of_engines.end(),
266
StorageEngineCloseConnection(session));
270
269
bool StorageEngine::flushLogs(StorageEngine *engine)
272
271
if (engine == NULL)
274
if (std::find_if(vector_of_engines.begin(), vector_of_engines.end(),
275
std::mem_fun(&StorageEngine::flush_logs))
273
if (find_if(vector_of_engines.begin(), vector_of_engines.end(),
274
mem_fun(&StorageEngine::flush_logs))
276
275
!= vector_of_engines.begin())
287
class StorageEngineGetTableDefinition: public std::unary_function<StorageEngine *,bool>
286
class StorageEngineGetTableDefinition: public unary_function<StorageEngine *,bool>
289
288
Session& session;
290
const identifier::Table &identifier;
289
const TableIdentifier &identifier;
291
290
message::Table &table_message;
292
drizzled::error_t &err;
295
294
StorageEngineGetTableDefinition(Session& session_arg,
296
const identifier::Table &identifier_arg,
295
const TableIdentifier &identifier_arg,
297
296
message::Table &table_message_arg,
298
drizzled::error_t &err_arg) :
299
298
session(session_arg),
300
299
identifier(identifier_arg),
301
300
table_message(table_message_arg),
306
305
int ret= engine->doGetTableDefinition(session, identifier, table_message);
308
307
if (ret != ENOENT)
309
err= static_cast<drizzled::error_t>(ret);
311
return err == static_cast<drizzled::error_t>(EEXIST) or err != static_cast<drizzled::error_t>(ENOENT);
310
return err == EEXIST || err != ENOENT;
315
class StorageEngineDoesTableExist: public std::unary_function<StorageEngine *, bool>
314
class StorageEngineDoesTableExist: public unary_function<StorageEngine *, bool>
317
316
Session& session;
318
const identifier::Table &identifier;
317
const TableIdentifier &identifier;
321
StorageEngineDoesTableExist(Session& session_arg, const identifier::Table &identifier_arg) :
320
StorageEngineDoesTableExist(Session& session_arg, const TableIdentifier &identifier_arg) :
322
321
session(session_arg),
323
322
identifier(identifier_arg)
357
bool plugin::StorageEngine::doDoesTableExist(Session&, const drizzled::identifier::Table&)
356
bool plugin::StorageEngine::doDoesTableExist(Session&, const drizzled::TableIdentifier&)
359
std::cerr << " Engine was called for doDoesTableExist() and does not implement it: " << this->getName() << "\n";
358
cerr << " Engine was called for doDoesTableExist() and does not implement it: " << this->getName() << "\n";
364
message::table::shared_ptr StorageEngine::getTableMessage(Session& session,
365
identifier::Table::const_reference identifier,
366
bool include_temporary_tables)
364
Call this function in order to give the Cursor the possiblity
365
to ask engine if there are any new tables that should be written to disk
366
or any dropped tables that need to be removed from disk
368
int StorageEngine::getTableDefinition(Session& session,
369
const TableIdentifier &identifier,
370
message::Table &table_message,
371
bool include_temporary_tables)
368
drizzled::error_t error;
369
error= static_cast<drizzled::error_t>(ENOENT);
371
375
if (include_temporary_tables)
373
Table *table= session.find_temporary_table(identifier);
376
return message::table::shared_ptr(new message::Table(*table->getShare()->getTableMessage()));
380
drizzled::message::table::shared_ptr table_ptr;
381
if ((table_ptr= drizzled::message::Cache::singleton().find(identifier)))
386
message::Table message;
377
if (session.doGetTableDefinition(identifier, table_message) == EEXIST)
387
381
EngineVector::iterator iter=
388
std::find_if(vector_of_engines.begin(), vector_of_engines.end(),
389
StorageEngineGetTableDefinition(session, identifier, message, error));
382
find_if(vector_of_engines.begin(), vector_of_engines.end(),
383
StorageEngineGetTableDefinition(session, identifier, table_message, err));
391
385
if (iter == vector_of_engines.end())
393
return message::table::shared_ptr();
395
message::table::shared_ptr table_message(new message::Table(message));
397
drizzled::message::Cache::singleton().insert(identifier, table_message);
399
return table_message;
432
class DropTableByIdentifier: public std::unary_function<EngineVector::value_type, bool>
434
Session::reference session;
435
identifier::Table::const_reference identifier;
436
drizzled::error_t &error;
440
DropTableByIdentifier(Session::reference session_arg,
441
identifier::Table::const_reference identifier_arg,
442
drizzled::error_t &error_arg) :
443
session(session_arg),
444
identifier(identifier_arg),
448
result_type operator() (argument_type engine)
450
if (not engine->doDoesTableExist(session, identifier))
453
int local_error= engine->doDropTable(session, identifier);
461
case HA_ERR_NO_SUCH_TABLE:
463
error= static_cast<drizzled::error_t>(HA_ERR_NO_SUCH_TABLE);
467
error= static_cast<drizzled::error_t>(local_error);
474
bool StorageEngine::dropTable(Session::reference session,
475
identifier::Table::const_reference identifier,
476
drizzled::error_t &error)
480
EngineVector::const_iterator iter= std::find_if(vector_of_engines.begin(), vector_of_engines.end(),
481
DropTableByIdentifier(session, identifier, error));
487
else if (iter == vector_of_engines.end())
489
error= ER_BAD_TABLE_ERROR;
493
drizzled::message::Cache::singleton().erase(identifier);
498
bool StorageEngine::dropTable(Session& session,
499
const identifier::Table &identifier)
501
drizzled::error_t error;
503
if (not dropTable(session, identifier, error))
511
bool StorageEngine::dropTable(Session::reference session,
512
StorageEngine &engine,
513
identifier::Table::const_reference identifier,
514
drizzled::error_t &error)
424
returns ENOENT if the file doesn't exists.
426
int StorageEngine::dropTable(Session& session,
427
const TableIdentifier &identifier)
431
message::Table src_proto;
432
StorageEngine *engine;
434
error_proto= StorageEngine::getTableDefinition(session, identifier, src_proto);
436
if (error_proto == ER_CORRUPT_TABLE_DEFINITION)
438
string error_message;
440
error_message.append(const_cast<TableIdentifier &>(identifier).getSQLPath());
441
error_message.append(" : ");
442
error_message.append(src_proto.InitializationErrorString());
444
my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0), error_message.c_str());
446
return ER_CORRUPT_TABLE_DEFINITION;
449
engine= StorageEngine::findByName(session, src_proto.engine().name());
453
my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0), const_cast<TableIdentifier &>(identifier).getSQLPath().c_str());
455
return ER_CORRUPT_TABLE_DEFINITION;
458
error= StorageEngine::dropTable(session, *engine, identifier);
460
if (error_proto && error == 0)
466
int StorageEngine::dropTable(Session& session,
467
StorageEngine &engine,
468
const TableIdentifier &identifier)
517
472
engine.setTransactionReadWrite(session);
519
assert(identifier.isTmp());
521
474
if (unlikely(plugin::EventObserver::beforeDropTable(session, identifier)))
554
bool StorageEngine::createTable(Session &session,
555
const identifier::Table &identifier,
556
message::Table& table_message)
500
int StorageEngine::createTable(Session &session,
501
const TableIdentifier &identifier,
502
message::Table& table_message)
558
drizzled::error_t error= EE_OK;
560
506
TableShare share(identifier);
561
table::Shell table(share);
562
507
message::Table tmp_proto;
564
509
if (share.parse_table_proto(session, table_message) || share.open_table_from_share(&session, identifier, "", 0, 0, table))
566
511
// @note Error occured, we should probably do a little more here.
567
// ER_CORRUPT_TABLE_DEFINITION,ER_CORRUPT_TABLE_DEFINITION_ENUM
569
my_error(ER_CORRUPT_TABLE_DEFINITION_UNKNOWN, identifier);
588
528
share.storage_engine->setTransactionReadWrite(session);
590
error= static_cast<drizzled::error_t>(share.storage_engine->doCreateTable(session,
530
error= share.storage_engine->doCreateTable(session,
596
if (error == ER_TABLE_PERMISSION_DENIED)
598
my_error(ER_TABLE_PERMISSION_DENIED, identifier);
603
identifier.getSQLPath(path);
604
my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), path.c_str(), error);
538
my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), const_cast<TableIdentifier &>(identifier).getSQLPath().c_str(), error);
607
541
table.delete_table();
610
return(error == EE_OK);
613
Cursor *StorageEngine::getCursor(Table &arg)
547
Cursor *StorageEngine::getCursor(TableShare &share)
549
return create(share);
618
552
class AddTableIdentifier :
619
public std::unary_function<StorageEngine *, void>
553
public unary_function<StorageEngine *, void>
621
555
CachedDirectory &directory;
622
const identifier::Schema &identifier;
623
identifier::Table::vector &set_of_identifiers;
556
const SchemaIdentifier &identifier;
557
TableIdentifiers &set_of_identifiers;
627
AddTableIdentifier(CachedDirectory &directory_arg, const identifier::Schema &identifier_arg, identifier::Table::vector &of_names) :
561
AddTableIdentifier(CachedDirectory &directory_arg, const SchemaIdentifier &identifier_arg, TableIdentifiers &of_names) :
628
562
directory(directory_arg),
629
563
identifier(identifier_arg),
630
564
set_of_identifiers(of_names)
653
590
errno= directory.getError();
654
591
if (errno == ENOENT)
657
schema_identifier.getSQLPath(path);
658
my_error(ER_BAD_DB_ERROR, MYF(ME_BELL+ME_WAITTANG), path.c_str());
592
my_error(ER_BAD_DB_ERROR, MYF(ME_BELL+ME_WAITTANG), const_cast<SchemaIdentifier &>(schema_identifier).getSQLPath().c_str());
662
594
my_error(ER_CANT_READ_DIR, MYF(ME_BELL+ME_WAITTANG), directory.getPath(), errno);
669
std::for_each(vector_of_engines.begin(), vector_of_engines.end(),
670
AddTableIdentifier(directory, schema_identifier, set_of_identifiers));
599
for_each(vector_of_engines.begin(), vector_of_engines.end(),
600
AddTableIdentifier(directory, schema_identifier, set_of_identifiers));
672
602
session.doGetTableIdentifiers(directory, schema_identifier, set_of_identifiers);
675
class DropTable: public std::unary_function<identifier::Table&, bool>
605
class DropTable: public unary_function<TableIdentifier&, bool>
677
607
Session &session;
678
608
StorageEngine *engine;
693
/* This will later be converted to identifier::Tables */
694
class DropTables: public std::unary_function<StorageEngine *, void>
623
/* This will later be converted to TableIdentifiers */
624
class DropTables: public unary_function<StorageEngine *, void>
696
626
Session &session;
697
identifier::Table::vector &table_identifiers;
627
TableIdentifiers &table_identifiers;
701
DropTables(Session &session_arg, identifier::Table::vector &table_identifiers_arg) :
631
DropTables(Session &session_arg, TableIdentifiers &table_identifiers_arg) :
702
632
session(session_arg),
703
633
table_identifiers(table_identifiers_arg)
708
638
// True returning from DropTable means the table has been successfully
709
639
// deleted, so it should be removed from the list of tables to drop
710
table_identifiers.erase(std::remove_if(table_identifiers.begin(),
711
table_identifiers.end(),
712
DropTable(session, engine)),
640
table_identifiers.erase(remove_if(table_identifiers.begin(),
641
table_identifiers.end(),
642
DropTable(session, engine)),
713
643
table_identifiers.end());
751
681
message::Table definition;
752
682
if (StorageEngine::readTableFile(path, definition))
754
identifier::Table identifier(definition.schema(), definition.name(), path);
684
TableIdentifier identifier(definition.schema(), definition.name(), path);
755
685
table_identifiers.push_back(identifier);
759
std::for_each(vector_of_engines.begin(), vector_of_engines.end(),
760
DropTables(session, table_identifiers));
689
for_each(vector_of_engines.begin(), vector_of_engines.end(),
690
DropTables(session, table_identifiers));
763
693
Now we just clean up anything that might left over.
765
695
We rescan because some of what might have been there should
766
696
now be all nice and cleaned up.
768
std::set<std::string> all_exts= set_of_table_definition_ext;
698
set<string> all_exts= set_of_table_definition_ext;
770
700
for (EngineVector::iterator iter= vector_of_engines.begin();
771
701
iter != vector_of_engines.end() ; iter++)
801
731
- table->getShare()->path
804
void StorageEngine::print_error(int error, myf errflag, const Table &table) const
806
drizzled::error_t textno= ER_GET_ERRNO;
734
void StorageEngine::print_error(int error, myf errflag, Table &table)
736
print_error(error, errflag, &table);
739
void StorageEngine::print_error(int error, myf errflag, Table *table)
741
int textno= ER_GET_ERRNO;
809
744
textno=ER_OPEN_AS_READONLY;
848
785
String str(key,sizeof(key),system_charset_info);
850
787
/* Table is opened and defined at this point */
851
key_unpack(&str, &table,(uint32_t) key_nr);
788
key_unpack(&str,table,(uint32_t) key_nr);
852
789
max_length= (DRIZZLE_ERRMSG_SIZE-
853
790
(uint32_t) strlen(ER(ER_FOREIGN_DUPLICATE_KEY)));
854
791
if (str.length() >= max_length)
933
870
textno=ER_TABLE_DEF_CHANGED;
935
872
case HA_ERR_NO_SUCH_TABLE:
937
identifier::Table identifier(table.getShare()->getSchemaName(), table.getShare()->getTableName());
938
my_error(ER_TABLE_UNKNOWN, identifier);
874
my_error(ER_NO_SUCH_TABLE, MYF(0), table->getShare()->getSchemaName(),
875
table->getShare()->getTableName());
941
877
case HA_ERR_RBR_LOGGING_FAILED:
942
878
textno= ER_BINLOG_ROW_LOGGING_FAILED;
944
880
case HA_ERR_DROP_INDEX_FK:
946
883
const char *ptr= "???";
947
uint32_t key_nr= table.get_dup_key(error);
884
uint32_t key_nr= table->get_dup_key(error);
948
885
if ((int) key_nr >= 0)
949
ptr= table.key_info[key_nr].name;
886
ptr= table->key_info[key_nr].name;
950
887
my_error(ER_DROP_INDEX_FK, MYF(0), ptr);
1006
942
Returns true if this is a temporary error
1008
bool StorageEngine::get_error_message(int , String* ) const
944
bool StorageEngine::get_error_message(int , String* )
1014
void StorageEngine::print_keydup_error(uint32_t key_nr, const char *msg, const Table &table) const
950
void StorageEngine::print_keydup_error(uint32_t key_nr, const char *msg, Table &table)
1016
952
/* Write the duplicated key in the error message */
1017
953
char key[MAX_KEY_LENGTH];
1042
int StorageEngine::deleteDefinitionFromPath(const identifier::Table &identifier)
978
int StorageEngine::deleteDefinitionFromPath(const TableIdentifier &identifier)
1044
std::string path(identifier.getPath());
980
string path(identifier.getPath());
1046
982
path.append(DEFAULT_DEFINITION_FILE_EXT);
1048
984
return internal::my_delete(path.c_str(), MYF(0));
1051
int StorageEngine::renameDefinitionFromPath(const identifier::Table &dest, const identifier::Table &src)
987
int StorageEngine::renameDefinitionFromPath(const TableIdentifier &dest, const TableIdentifier &src)
1053
989
message::Table table_message;
1054
std::string src_path(src.getPath());
1055
std::string dest_path(dest.getPath());
990
string src_path(src.getPath());
991
string dest_path(dest.getPath());
1057
993
src_path.append(DEFAULT_DEFINITION_FILE_EXT);
1058
994
dest_path.append(DEFAULT_DEFINITION_FILE_EXT);
1174
1105
@note on success table can be created.
1176
bool StorageEngine::canCreateTable(const identifier::Table &identifier)
1107
bool StorageEngine::canCreateTable(const TableIdentifier &identifier)
1178
1109
EngineVector::iterator iter=
1179
std::find_if(vector_of_engines.begin(), vector_of_engines.end(),
1180
CanCreateTable(identifier));
1110
find_if(vector_of_engines.begin(), vector_of_engines.end(),
1111
CanCreateTable(identifier));
1182
1113
if (iter == vector_of_engines.end())