17
17
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
32
#include <google/protobuf/io/zero_copy_stream.h>
33
#include <google/protobuf/io/zero_copy_stream_impl.h>
35
#include "drizzled/cached_directory.h"
20
#include <drizzled/server_includes.h>
37
21
#include <drizzled/definitions.h>
38
22
#include <drizzled/base.h>
39
#include <drizzled/cursor.h>
40
#include <drizzled/plugin/storage_engine.h>
23
#include <drizzled/handler.h>
24
#include <drizzled/handlerton.h>
41
25
#include <drizzled/session.h>
42
26
#include <drizzled/error.h>
43
27
#include <drizzled/gettext.h>
44
#include <drizzled/unireg.h>
45
#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"
54
#include <drizzled/table_proto.h>
55
#include <drizzled/plugin/event_observer.h>
57
#include <drizzled/table/shell.h>
59
#include "drizzled/message/cache.h"
61
#include <boost/algorithm/string/compare.hpp>
63
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;
74
const std::string DEFAULT_STRING("default");
75
const std::string UNKNOWN_STRING("UNKNOWN");
76
const std::string DEFAULT_DEFINITION_FILE_EXT(".dfe");
78
static std::set<std::string> set_of_table_definition_ext;
80
EngineVector &StorageEngine::getSchemaEngines()
82
return vector_of_schema_engines;
85
StorageEngine::StorageEngine(const std::string name_arg,
86
const std::bitset<HTON_BIT_SIZE> &flags_arg) :
87
Plugin(name_arg, "StorageEngine"),
88
MonitoredInTransaction(), /* This gives the storage engine a "slot" or ID */
93
StorageEngine::~StorageEngine()
97
void StorageEngine::setTransactionReadWrite(Session& session)
99
TransactionContext &statement_ctx= session.transaction.stmt;
100
statement_ctx.markModifiedNonTransData();
104
int StorageEngine::renameTable(Session &session, const TableIdentifier &from, const TableIdentifier &to)
107
setTransactionReadWrite(session);
109
if (unlikely(plugin::EventObserver::beforeRenameTable(session, from, to)))
111
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;
126
Delete all files with extension from bas_ext().
128
@param name Base name of table
131
We assume that the Cursor may return more extensions than
132
was actually used for the file.
135
0 If we successfully deleted at least one file from base_ext and
136
didn't get any other errors than ENOENT
140
int StorageEngine::doDropTable(Session&, const TableIdentifier &identifier)
144
int enoent_or_zero= ENOENT; // Error if no file was deleted
145
char buff[FN_REFLEN];
147
for (const char **ext= bas_ext(); *ext ; ext++)
149
internal::fn_format(buff, identifier.getPath().c_str(), "", *ext,
150
MY_UNPACK_FILENAME|MY_APPEND_EXT);
151
if (internal::my_delete_with_symlink(buff, MYF(0)))
153
if ((error= errno) != ENOENT)
158
enoent_or_zero= 0; // No error for ENOENT
161
error= enoent_or_zero;
166
bool StorageEngine::addPlugin(StorageEngine *engine)
169
vector_of_engines.push_back(engine);
171
if (engine->getTableDefinitionFileExtension().length())
173
assert(engine->getTableDefinitionFileExtension().length() == DEFAULT_DEFINITION_FILE_EXT.length());
174
set_of_table_definition_ext.insert(engine->getTableDefinitionFileExtension());
177
if (engine->check_flag(HTON_BIT_SCHEMA_DICTIONARY))
178
vector_of_schema_engines.push_back(engine);
183
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;
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
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())
218
StorageEngine *engine= *iter;
219
if (engine->is_user_selectable())
226
StorageEngine *StorageEngine::findByName(Session& session, const std::string &predicate)
228
if (boost::iequals(predicate, DEFAULT_STRING))
229
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())
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
don't bother to rollback here, it's done already
264
void StorageEngine::closeConnection(Session* session)
266
std::for_each(vector_of_engines.begin(), vector_of_engines.end(),
267
StorageEngineCloseConnection(session));
270
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())
287
class StorageEngineGetTableDefinition: public std::unary_function<StorageEngine *,bool>
290
const TableIdentifier &identifier;
291
message::Table &table_message;
295
StorageEngineGetTableDefinition(Session& session_arg,
296
const TableIdentifier &identifier_arg,
297
message::Table &table_message_arg,
299
session(session_arg),
300
identifier(identifier_arg),
301
table_message(table_message_arg),
304
result_type operator() (argument_type engine)
306
int ret= engine->doGetTableDefinition(session, identifier, table_message);
311
return err == EEXIST || err != ENOENT;
315
class StorageEngineDoesTableExist: public std::unary_function<StorageEngine *, bool>
318
const TableIdentifier &identifier;
321
StorageEngineDoesTableExist(Session& session_arg, const TableIdentifier &identifier_arg) :
322
session(session_arg),
323
identifier(identifier_arg)
326
result_type operator() (argument_type engine)
328
return engine->doDoesTableExist(session, identifier);
333
Utility method which hides some of the details of getTableDefinition()
335
bool plugin::StorageEngine::doesTableExist(Session &session,
336
const TableIdentifier &identifier,
337
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())
357
bool plugin::StorageEngine::doDoesTableExist(Session&, const drizzled::TableIdentifier&)
359
std::cerr << " Engine was called for doDoesTableExist() and does not implement it: " << this->getName() << "\n";
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 TableIdentifier &identifier,
371
message::table::shared_ptr &table_message,
372
bool include_temporary_tables)
376
if (include_temporary_tables)
378
Table *table= session.find_temporary_table(identifier);
381
table_message.reset(new message::Table(*table->getShare()->getTableProto()));
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);
409
An interceptor to hijack the text of the error message without
410
setting an error in the thread. We need the text to present it
411
in the form of a warning to the user.
414
class Ha_delete_table_error_handler: public Internal_error_handler
417
Ha_delete_table_error_handler() : Internal_error_handler() {}
418
virtual bool handle_error(uint32_t sql_errno,
420
DRIZZLE_ERROR::enum_warning_level level,
422
char buff[DRIZZLE_ERRMSG_SIZE];
427
Ha_delete_table_error_handler::
428
handle_error(uint32_t ,
430
DRIZZLE_ERROR::enum_warning_level ,
433
/* Grab the error message */
434
strncpy(buff, message, sizeof(buff)-1);
439
returns ENOENT if the file doesn't exists.
441
int StorageEngine::dropTable(Session& session,
442
const TableIdentifier &identifier)
446
message::table::shared_ptr src_proto;
447
StorageEngine *engine;
449
error_proto= StorageEngine::getTableDefinition(session, identifier, src_proto);
451
if (error_proto == ER_CORRUPT_TABLE_DEFINITION)
453
std::string error_message;
454
identifier.getSQLPath(error_message);
456
error_message.append(" : ");
457
error_message.append(src_proto->InitializationErrorString());
459
my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0), error_message.c_str());
461
return ER_CORRUPT_TABLE_DEFINITION;
465
engine= StorageEngine::findByName(session, src_proto->engine().name());
467
engine= StorageEngine::findByName(session, "");
471
std::string error_message;
472
identifier.getSQLPath(error_message);
473
my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0), error_message.c_str());
475
return ER_CORRUPT_TABLE_DEFINITION;
478
error= StorageEngine::dropTable(session, *engine, identifier);
480
if (error_proto && error == 0)
486
int StorageEngine::dropTable(Session& session,
487
StorageEngine &engine,
488
const TableIdentifier &identifier)
492
engine.setTransactionReadWrite(session);
494
if (unlikely(plugin::EventObserver::beforeDropTable(session, identifier)))
496
error= ER_EVENT_OBSERVER_PLUGIN;
500
error= engine.doDropTable(session, identifier);
501
if (unlikely(plugin::EventObserver::afterDropTable(session, identifier, error)))
503
error= ER_EVENT_OBSERVER_PLUGIN;
507
drizzled::message::Cache::singleton().erase(identifier);
514
Initiates table-file and calls appropriate database-creator.
521
int StorageEngine::createTable(Session &session,
522
const TableIdentifier &identifier,
523
message::Table& table_message)
526
TableShare share(identifier);
527
table::Shell table(share);
528
message::Table tmp_proto;
530
if (share.parse_table_proto(session, table_message) || share.open_table_from_share(&session, identifier, "", 0, 0, table))
532
// @note Error occured, we should probably do a little more here.
536
/* Check for legal operations against the Engine using the proto (if used) */
537
if (table_message.type() == message::Table::TEMPORARY &&
538
share.storage_engine->check_flag(HTON_BIT_TEMPORARY_NOT_SUPPORTED) == true)
540
error= HA_ERR_UNSUPPORTED;
542
else if (table_message.type() != message::Table::TEMPORARY &&
543
share.storage_engine->check_flag(HTON_BIT_TEMPORARY_ONLY) == true)
545
error= HA_ERR_UNSUPPORTED;
549
share.storage_engine->setTransactionReadWrite(session);
551
error= share.storage_engine->doCreateTable(session,
560
identifier.getSQLPath(path);
561
my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), path.c_str(), error);
564
table.delete_table();
570
Cursor *StorageEngine::getCursor(Table &arg)
575
class AddTableIdentifier :
576
public std::unary_function<StorageEngine *, void>
578
CachedDirectory &directory;
579
const SchemaIdentifier &identifier;
580
TableIdentifier::vector &set_of_identifiers;
584
AddTableIdentifier(CachedDirectory &directory_arg, const SchemaIdentifier &identifier_arg, TableIdentifier::vector &of_names) :
585
directory(directory_arg),
586
identifier(identifier_arg),
587
set_of_identifiers(of_names)
591
result_type operator() (argument_type engine)
593
engine->doGetTableIdentifiers(directory, identifier, set_of_identifiers);
598
void StorageEngine::getIdentifiers(Session &session, const SchemaIdentifier &schema_identifier, TableIdentifier::vector &set_of_identifiers)
600
static SchemaIdentifier INFORMATION_SCHEMA_IDENTIFIER("information_schema");
601
static SchemaIdentifier DATA_DICTIONARY_IDENTIFIER("data_dictionary");
603
CachedDirectory directory(schema_identifier.getPath(), set_of_table_definition_ext);
605
if (schema_identifier == INFORMATION_SCHEMA_IDENTIFIER)
607
else if (schema_identifier == DATA_DICTIONARY_IDENTIFIER)
611
if (directory.fail())
613
errno= directory.getError();
617
schema_identifier.getSQLPath(path);
618
my_error(ER_BAD_DB_ERROR, MYF(ME_BELL+ME_WAITTANG), path.c_str());
622
my_error(ER_CANT_READ_DIR, MYF(ME_BELL+ME_WAITTANG), directory.getPath(), errno);
629
std::for_each(vector_of_engines.begin(), vector_of_engines.end(),
630
AddTableIdentifier(directory, schema_identifier, set_of_identifiers));
632
session.doGetTableIdentifiers(directory, schema_identifier, set_of_identifiers);
635
class DropTable: public std::unary_function<TableIdentifier&, bool>
638
StorageEngine *engine;
642
DropTable(Session &session_arg, StorageEngine *engine_arg) :
643
session(session_arg),
647
result_type operator() (argument_type identifier)
649
return engine->doDropTable(session, identifier) == 0;
653
/* This will later be converted to TableIdentifiers */
654
class DropTables: public std::unary_function<StorageEngine *, void>
657
TableIdentifier::vector &table_identifiers;
661
DropTables(Session &session_arg, TableIdentifier::vector &table_identifiers_arg) :
662
session(session_arg),
663
table_identifiers(table_identifiers_arg)
666
result_type operator() (argument_type engine)
668
// True returning from DropTable means the table has been successfully
669
// deleted, so it should be removed from the list of tables to drop
670
table_identifiers.erase(std::remove_if(table_identifiers.begin(),
671
table_identifiers.end(),
672
DropTable(session, engine)),
673
table_identifiers.end());
678
This only works for engines which use file based DFE.
680
Note-> Unlike MySQL, we do not, on purpose, delete files that do not match any engines.
682
void StorageEngine::removeLostTemporaryTables(Session &session, const char *directory)
684
CachedDirectory dir(directory, set_of_table_definition_ext);
685
TableIdentifier::vector table_identifiers;
689
errno= dir.getError();
690
my_error(ER_CANT_READ_DIR, MYF(0), directory, errno);
695
CachedDirectory::Entries files= dir.getEntries();
697
for (CachedDirectory::Entries::iterator fileIter= files.begin();
698
fileIter != files.end(); fileIter++)
702
CachedDirectory::Entry *entry= *fileIter;
704
/* We remove the file extension. */
705
length= entry->filename.length();
706
entry->filename.resize(length - DEFAULT_DEFINITION_FILE_EXT.length());
710
path+= entry->filename;
711
message::Table definition;
712
if (StorageEngine::readTableFile(path, definition))
714
TableIdentifier identifier(definition.schema(), definition.name(), path);
715
table_identifiers.push_back(identifier);
719
std::for_each(vector_of_engines.begin(), vector_of_engines.end(),
720
DropTables(session, table_identifiers));
723
Now we just clean up anything that might left over.
725
We rescan because some of what might have been there should
726
now be all nice and cleaned up.
728
std::set<std::string> all_exts= set_of_table_definition_ext;
730
for (EngineVector::iterator iter= vector_of_engines.begin();
731
iter != vector_of_engines.end() ; iter++)
733
for (const char **ext= (*iter)->bas_ext(); *ext ; ext++)
734
all_exts.insert(*ext);
737
CachedDirectory rescan(directory, all_exts);
739
files= rescan.getEntries();
740
for (CachedDirectory::Entries::iterator fileIter= files.begin();
741
fileIter != files.end(); fileIter++)
744
CachedDirectory::Entry *entry= *fileIter;
748
path+= entry->filename;
750
unlink(path.c_str());
756
Print error that we got from Cursor function.
759
In case of delete table it's only safe to use the following parts of
760
the 'table' structure:
761
- table->getShare()->path
764
void StorageEngine::print_error(int error, myf errflag, Table &table)
766
print_error(error, errflag, &table);
769
void StorageEngine::print_error(int error, myf errflag, Table *table)
771
int textno= ER_GET_ERRNO;
774
textno=ER_OPEN_AS_READONLY;
780
textno=ER_FILE_NOT_FOUND;
782
case HA_ERR_KEY_NOT_FOUND:
783
case HA_ERR_NO_ACTIVE_RECORD:
784
case HA_ERR_END_OF_FILE:
785
textno=ER_KEY_NOT_FOUND;
787
case HA_ERR_WRONG_MRG_TABLE_DEF:
788
textno=ER_WRONG_MRG_TABLE;
790
case HA_ERR_FOUND_DUPP_KEY:
793
uint32_t key_nr= table->get_dup_key(error);
794
if ((int) key_nr >= 0)
796
const char *err_msg= ER(ER_DUP_ENTRY_WITH_KEY_NAME);
798
print_keydup_error(key_nr, err_msg, *table);
805
case HA_ERR_FOREIGN_DUPLICATE_KEY:
808
uint32_t key_nr= table->get_dup_key(error);
809
if ((int) key_nr >= 0)
813
/* Write the key in the error message */
814
char key[MAX_KEY_LENGTH];
815
String str(key,sizeof(key),system_charset_info);
817
/* Table is opened and defined at this point */
818
key_unpack(&str,table,(uint32_t) key_nr);
819
max_length= (DRIZZLE_ERRMSG_SIZE-
820
(uint32_t) strlen(ER(ER_FOREIGN_DUPLICATE_KEY)));
821
if (str.length() >= max_length)
823
str.length(max_length-4);
824
str.append(STRING_WITH_LEN("..."));
826
my_error(ER_FOREIGN_DUPLICATE_KEY, MYF(0), table->getShare()->getTableName(),
827
str.c_ptr(), key_nr+1);
833
case HA_ERR_FOUND_DUPP_UNIQUE:
834
textno=ER_DUP_UNIQUE;
836
case HA_ERR_RECORD_CHANGED:
840
textno=ER_NOT_KEYFILE;
842
case HA_ERR_WRONG_IN_RECORD:
843
textno= ER_CRASHED_ON_USAGE;
845
case HA_ERR_CRASHED_ON_USAGE:
846
textno=ER_CRASHED_ON_USAGE;
848
case HA_ERR_NOT_A_TABLE:
851
case HA_ERR_CRASHED_ON_REPAIR:
852
textno=ER_CRASHED_ON_REPAIR;
854
case HA_ERR_OUT_OF_MEM:
855
textno=ER_OUT_OF_RESOURCES;
857
case HA_ERR_WRONG_COMMAND:
858
textno=ER_ILLEGAL_HA;
860
case HA_ERR_OLD_FILE:
861
textno=ER_OLD_KEYFILE;
863
case HA_ERR_UNSUPPORTED:
864
textno=ER_UNSUPPORTED_EXTENSION;
866
case HA_ERR_RECORD_FILE_FULL:
867
case HA_ERR_INDEX_FILE_FULL:
868
textno=ER_RECORD_FILE_FULL;
870
case HA_ERR_LOCK_WAIT_TIMEOUT:
871
textno=ER_LOCK_WAIT_TIMEOUT;
873
case HA_ERR_LOCK_TABLE_FULL:
874
textno=ER_LOCK_TABLE_FULL;
876
case HA_ERR_LOCK_DEADLOCK:
877
textno=ER_LOCK_DEADLOCK;
879
case HA_ERR_READ_ONLY_TRANSACTION:
880
textno=ER_READ_ONLY_TRANSACTION;
882
case HA_ERR_CANNOT_ADD_FOREIGN:
883
textno=ER_CANNOT_ADD_FOREIGN;
885
case HA_ERR_ROW_IS_REFERENCED:
888
get_error_message(error, &str);
889
my_error(ER_ROW_IS_REFERENCED_2, MYF(0), str.c_ptr_safe());
892
case HA_ERR_NO_REFERENCED_ROW:
895
get_error_message(error, &str);
896
my_error(ER_NO_REFERENCED_ROW_2, MYF(0), str.c_ptr_safe());
899
case HA_ERR_TABLE_DEF_CHANGED:
900
textno=ER_TABLE_DEF_CHANGED;
902
case HA_ERR_NO_SUCH_TABLE:
904
my_error(ER_NO_SUCH_TABLE, MYF(0), table->getShare()->getSchemaName(),
905
table->getShare()->getTableName());
907
case HA_ERR_RBR_LOGGING_FAILED:
908
textno= ER_BINLOG_ROW_LOGGING_FAILED;
910
case HA_ERR_DROP_INDEX_FK:
913
const char *ptr= "???";
914
uint32_t key_nr= table->get_dup_key(error);
915
if ((int) key_nr >= 0)
916
ptr= table->key_info[key_nr].name;
917
my_error(ER_DROP_INDEX_FK, MYF(0), ptr);
920
case HA_ERR_TABLE_NEEDS_UPGRADE:
921
textno=ER_TABLE_NEEDS_UPGRADE;
923
case HA_ERR_TABLE_READONLY:
924
textno= ER_OPEN_AS_READONLY;
926
case HA_ERR_AUTOINC_READ_FAILED:
927
textno= ER_AUTOINC_READ_FAILED;
929
case HA_ERR_AUTOINC_ERANGE:
930
textno= ER_WARN_DATA_OUT_OF_RANGE;
932
case HA_ERR_LOCK_OR_ACTIVE_TRANSACTION:
933
my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
934
ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
939
The error was "unknown" to this function.
940
Ask Cursor if it has got a message for this error
942
bool temporary= false;
944
temporary= get_error_message(error, &str);
947
const char* engine_name= getName().c_str();
949
my_error(ER_GET_TEMPORARY_ERRMSG, MYF(0), error, str.ptr(),
952
my_error(ER_GET_ERRMSG, MYF(0), error, str.ptr(), engine_name);
956
my_error(ER_GET_ERRNO,errflag,error);
961
my_error(textno, errflag, table->getShare()->getTableName(), error);
966
Return an error message specific to this Cursor.
968
@param error error code previously returned by Cursor
969
@param buf pointer to String where to add error message
972
Returns true if this is a temporary error
974
bool StorageEngine::get_error_message(int , String* )
980
void StorageEngine::print_keydup_error(uint32_t key_nr, const char *msg, Table &table)
982
/* Write the duplicated key in the error message */
983
char key[MAX_KEY_LENGTH];
984
String str(key,sizeof(key),system_charset_info);
986
if (key_nr == MAX_KEY)
989
str.copy("", 0, system_charset_info);
990
my_printf_error(ER_DUP_ENTRY, msg, MYF(0), str.c_ptr(), "*UNKNOWN*");
994
/* Table is opened and defined at this point */
995
key_unpack(&str, &table, (uint32_t) key_nr);
996
uint32_t max_length=DRIZZLE_ERRMSG_SIZE-(uint32_t) strlen(msg);
997
if (str.length() >= max_length)
999
str.length(max_length-4);
1000
str.append(STRING_WITH_LEN("..."));
1002
my_printf_error(ER_DUP_ENTRY, msg,
1003
MYF(0), str.c_ptr(), table.key_info[key_nr].name);
1008
int StorageEngine::deleteDefinitionFromPath(const TableIdentifier &identifier)
1010
std::string path(identifier.getPath());
1012
path.append(DEFAULT_DEFINITION_FILE_EXT);
1014
return internal::my_delete(path.c_str(), MYF(0));
1017
int StorageEngine::renameDefinitionFromPath(const TableIdentifier &dest, const TableIdentifier &src)
1019
message::Table table_message;
1020
std::string src_path(src.getPath());
1021
std::string dest_path(dest.getPath());
1023
src_path.append(DEFAULT_DEFINITION_FILE_EXT);
1024
dest_path.append(DEFAULT_DEFINITION_FILE_EXT);
1026
bool was_read= StorageEngine::readTableFile(src_path.c_str(), table_message);
1033
dest.copyToTableMessage(table_message);
1035
int error= StorageEngine::writeDefinitionFromPath(dest, table_message);
1039
if (unlink(src_path.c_str()))
1040
perror(src_path.c_str());
1046
int StorageEngine::writeDefinitionFromPath(const TableIdentifier &identifier, message::Table &table_message)
1048
char definition_file_tmp[FN_REFLEN];
1049
std::string file_name(identifier.getPath());
1051
file_name.append(DEFAULT_DEFINITION_FILE_EXT);
1053
snprintf(definition_file_tmp, sizeof(definition_file_tmp), "%sXXXXXX", file_name.c_str());
1055
int fd= mkstemp(definition_file_tmp);
1059
perror(definition_file_tmp);
1063
google::protobuf::io::ZeroCopyOutputStream* output=
1064
new google::protobuf::io::FileOutputStream(fd);
1070
success= table_message.SerializeToZeroCopyStream(output);
1079
my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
1080
table_message.InitializationErrorString().c_str());
1083
if (close(fd) == -1)
1084
perror(definition_file_tmp);
1086
if (unlink(definition_file_tmp) == -1)
1087
perror(definition_file_tmp);
1089
return ER_CORRUPT_TABLE_DEFINITION;
1094
if (close(fd) == -1)
1097
perror(definition_file_tmp);
1099
if (unlink(definition_file_tmp))
1100
perror(definition_file_tmp);
1105
if (rename(definition_file_tmp, file_name.c_str()) == -1)
1108
perror(definition_file_tmp);
1110
if (unlink(definition_file_tmp))
1111
perror(definition_file_tmp);
1119
class CanCreateTable: public std::unary_function<StorageEngine *, bool>
1121
const TableIdentifier &identifier;
1124
CanCreateTable(const TableIdentifier &identifier_arg) :
1125
identifier(identifier_arg)
1128
result_type operator() (argument_type engine)
1130
return not engine->doCanCreateTable(identifier);
32
While we have legacy_db_type, we have this array to
33
check for dups and to find handlerton from legacy_db_type.
34
Remove when legacy_db_type is finally gone
36
st_plugin_int *hton2plugin[MAX_HA];
38
static handlerton *installed_htons[128];
40
static const LEX_STRING sys_table_aliases[]=
42
{ C_STRING_WITH_LEN("INNOBASE") }, { C_STRING_WITH_LEN("INNODB") },
43
{ C_STRING_WITH_LEN("HEAP") }, { C_STRING_WITH_LEN("MEMORY") },
1136
@note on success table can be created.
1138
bool StorageEngine::canCreateTable(const TableIdentifier &identifier)
1140
EngineVector::iterator iter=
1141
std::find_if(vector_of_engines.begin(), vector_of_engines.end(),
1142
CanCreateTable(identifier));
1144
if (iter == vector_of_engines.end())
1152
bool StorageEngine::readTableFile(const std::string &path, message::Table &table_message)
1154
std::fstream input(path.c_str(), std::ios::in | std::ios::binary);
1159
if (table_message.ParseFromIstream(&input))
48
handlerton *ha_resolve_by_legacy_type(Session *session,
49
enum legacy_db_type db_type)
54
return ha_default_handlerton(session);
56
if (db_type > DB_TYPE_UNKNOWN && db_type < DB_TYPE_DEFAULT &&
57
(plugin= ha_lock_engine(session, installed_htons[db_type])))
58
return plugin_data(plugin, handlerton*);
66
static plugin_ref ha_default_plugin(Session *session)
68
if (session->variables.table_plugin)
69
return session->variables.table_plugin;
70
return my_plugin_lock(session, &global_system_variables.table_plugin);
75
Return the default storage engine handlerton for thread
77
@param ha_default_handlerton(session)
78
@param session current thread
83
handlerton *ha_default_handlerton(Session *session)
85
plugin_ref plugin= ha_default_plugin(session);
87
handlerton *hton= plugin_data(plugin, handlerton*);
94
Return the storage engine handlerton for the supplied name
96
@param session current thread
97
@param name name of storage engine
100
pointer to storage engine plugin handle
102
plugin_ref ha_resolve_by_name(Session *session, const LEX_STRING *name)
104
const LEX_STRING *table_alias;
108
/* my_strnncoll is a macro and gcc doesn't do early expansion of macro */
109
if (session && !my_charset_utf8_general_ci.coll->strnncoll(&my_charset_utf8_general_ci,
110
(const unsigned char *)name->str, name->length,
111
(const unsigned char *)STRING_WITH_LEN("DEFAULT"), 0))
112
return ha_default_plugin(session);
114
if ((plugin= my_plugin_lock_by_name(session, name, DRIZZLE_STORAGE_ENGINE_PLUGIN)))
116
handlerton *hton= plugin_data(plugin, handlerton *);
117
if (!(hton->flags.test(HTON_BIT_NOT_USER_SELECTABLE)))
121
unlocking plugin immediately after locking is relatively low cost.
123
plugin_unlock(session, plugin);
127
We check for the historical aliases.
129
for (table_alias= sys_table_aliases; table_alias->str; table_alias+= 2)
131
if (!my_strnncoll(&my_charset_utf8_general_ci,
132
(const unsigned char *)name->str, name->length,
133
(const unsigned char *)table_alias->str,
134
table_alias->length))
136
name= table_alias + 1;
145
plugin_ref ha_lock_engine(Session *session, handlerton *hton)
149
st_plugin_int **plugin= hton2plugin + hton->slot;
151
return my_plugin_lock(session, &plugin);
158
Use other database handler if databasehandler is not compiled in.
160
handlerton *ha_checktype(Session *session, enum legacy_db_type database_type,
161
bool no_substitute, bool report_error)
163
handlerton *hton= ha_resolve_by_legacy_type(session, database_type);
164
if (ha_storage_engine_is_enabled(hton))
171
const char *engine_name= ha_resolve_storage_engine_name(hton);
172
my_error(ER_FEATURE_DISABLED,MYF(0),engine_name,engine_name);
177
return ha_default_handlerton(session);
181
handler *get_new_handler(TABLE_SHARE *share, MEM_ROOT *alloc,
186
if (db_type && db_type->state == SHOW_OPTION_YES && db_type->create)
188
if ((file= db_type->create(db_type, share, alloc)))
193
Try the default table type
194
Here the call to current_session() is ok as we call this function a lot of
195
times but we enter this branch very seldom.
197
return(get_new_handler(share, alloc, ha_default_handlerton(current_session)));
201
int ha_finalize_handlerton(st_plugin_int *plugin)
203
handlerton *hton= (handlerton *)plugin->data;
208
case SHOW_OPTION_DISABLED:
210
case SHOW_OPTION_YES:
211
if (installed_htons[hton->db_type] == hton)
212
installed_htons[hton->db_type]= NULL;
216
if (hton && plugin->plugin->deinit)
217
(void)plugin->plugin->deinit(hton);
219
free((unsigned char*)hton);
225
int ha_initialize_handlerton(st_plugin_int *plugin)
229
hton= (handlerton *)malloc(sizeof(handlerton));
230
memset(hton, 0, sizeof(handlerton));
232
/* Historical Requirement */
233
plugin->data= hton; // shortcut for the future
234
if (plugin->plugin->init)
236
if (plugin->plugin->init(hton))
238
errmsg_printf(ERRMSG_LVL_ERROR, _("Plugin '%s' init function returned error."),
244
hton->name= plugin->name.str;
247
the switch below and hton->state should be removed when
248
command-line options for plugins will be implemented
250
switch (hton->state) {
253
case SHOW_OPTION_YES:
256
/* now check the db_type for conflict */
257
if (hton->db_type <= DB_TYPE_UNKNOWN ||
258
hton->db_type >= DB_TYPE_DEFAULT ||
259
installed_htons[hton->db_type])
261
int idx= (int) DB_TYPE_FIRST_DYNAMIC;
263
while (idx < (int) DB_TYPE_DEFAULT && installed_htons[idx])
266
if (idx == (int) DB_TYPE_DEFAULT)
268
errmsg_printf(ERRMSG_LVL_WARN, _("Too many storage engines!"));
271
if (hton->db_type != DB_TYPE_UNKNOWN)
272
errmsg_printf(ERRMSG_LVL_WARN,
273
_("Storage engine '%s' has conflicting typecode. Assigning value %d."),
274
plugin->plugin->name, idx);
275
hton->db_type= (enum legacy_db_type) idx;
1166
my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
1167
table_message.InitializationErrorString().empty() ? "": table_message.InitializationErrorString().c_str());
1172
perror(path.c_str());
1180
} /* namespace plugin */
1181
} /* namespace drizzled */
277
installed_htons[hton->db_type]= hton;
278
tmp= hton->savepoint_offset;
279
hton->savepoint_offset= savepoint_alloc_size;
280
savepoint_alloc_size+= tmp;
281
hton->slot= total_ha++;
282
hton2plugin[hton->slot]=plugin;
289
hton->state= SHOW_OPTION_DISABLED;
294
This is entirely for legacy. We will create a new "disk based" hton and a
295
"memory" hton which will be configurable longterm. We should be able to
296
remove partition and myisammrg.
298
if (strcmp(plugin->plugin->name, "MEMORY") == 0)
301
if (strcmp(plugin->plugin->name, "MyISAM") == 0)
309
enum legacy_db_type ha_legacy_type(const handlerton *db_type)
311
return (db_type == NULL) ? DB_TYPE_UNKNOWN : db_type->db_type;
314
const char *ha_resolve_storage_engine_name(const handlerton *db_type)
316
return db_type == NULL ? "UNKNOWN" : hton2plugin[db_type->slot]->name.str;
319
bool ha_check_storage_engine_flag(const handlerton *db_type, const hton_flag_bits flag)
321
return db_type == NULL ? false : db_type->flags.test(static_cast<size_t>(flag));
324
bool ha_storage_engine_is_enabled(const handlerton *db_type)
326
return (db_type && db_type->create) ?
327
(db_type->state == SHOW_OPTION_YES) : false;
330
LEX_STRING *ha_storage_engine_name(const handlerton *hton)
332
return &hton2plugin[hton->slot]->name;