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 identifier::Table &from, const identifier::Table &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 identifier::Table &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 identifier::Table &identifier;
291
message::Table &table_message;
292
drizzled::error_t &err;
295
StorageEngineGetTableDefinition(Session& session_arg,
296
const identifier::Table &identifier_arg,
297
message::Table &table_message_arg,
298
drizzled::error_t &err_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);
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);
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
Utility method which hides some of the details of getTableDefinition()
335
bool plugin::StorageEngine::doesTableExist(Session &session,
336
const identifier::Table &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::identifier::Table&)
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 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
message::table::shared_ptr StorageEngine::getTableMessage(Session& session,
409
identifier::Table::const_reference identifier,
410
drizzled::error_t &error,
411
bool include_temporary_tables)
413
error= static_cast<drizzled::error_t>(ENOENT);
415
if (include_temporary_tables)
417
Table *table= session.find_temporary_table(identifier);
421
return message::table::shared_ptr(new message::Table(*table->getShare()->getTableMessage()));
425
drizzled::message::table::shared_ptr table_ptr;
426
if ((table_ptr= drizzled::message::Cache::singleton().find(identifier)))
431
message::Table message;
432
EngineVector::iterator iter=
433
std::find_if(vector_of_engines.begin(), vector_of_engines.end(),
434
StorageEngineGetTableDefinition(session, identifier, message, error));
436
if (iter == vector_of_engines.end())
438
error= static_cast<drizzled::error_t>(ENOENT);
439
return message::table::shared_ptr();
441
message::table::shared_ptr table_message(new message::Table(message));
443
drizzled::message::Cache::singleton().insert(identifier, table_message);
445
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
class DropTableByIdentifier: public std::unary_function<EngineVector::value_type, bool>
480
Session::reference session;
481
identifier::Table::const_reference identifier;
482
drizzled::error_t &error;
486
DropTableByIdentifier(Session::reference session_arg,
487
identifier::Table::const_reference identifier_arg,
488
drizzled::error_t &error_arg) :
489
session(session_arg),
490
identifier(identifier_arg),
494
result_type operator() (argument_type engine)
496
if (not engine->doDoesTableExist(session, identifier))
499
int local_error= engine->doDropTable(session, identifier);
507
case HA_ERR_NO_SUCH_TABLE:
509
error= static_cast<drizzled::error_t>(HA_ERR_NO_SUCH_TABLE);
513
error= static_cast<drizzled::error_t>(local_error);
520
bool StorageEngine::dropTable(Session::reference session,
521
identifier::Table::const_reference identifier,
522
drizzled::error_t &error)
526
EngineVector::const_iterator iter= std::find_if(vector_of_engines.begin(), vector_of_engines.end(),
527
DropTableByIdentifier(session, identifier, error));
533
else if (iter == vector_of_engines.end())
535
error= ER_BAD_TABLE_ERROR;
539
drizzled::message::Cache::singleton().erase(identifier);
544
bool StorageEngine::dropTable(Session& session,
545
const identifier::Table &identifier)
547
drizzled::error_t error;
549
if (not dropTable(session, identifier, error))
557
bool StorageEngine::dropTable(Session::reference session,
558
StorageEngine &engine,
559
identifier::Table::const_reference identifier,
560
drizzled::error_t &error)
563
engine.setTransactionReadWrite(session);
565
assert(identifier.isTmp());
567
if (unlikely(plugin::EventObserver::beforeDropTable(session, identifier)))
569
error= ER_EVENT_OBSERVER_PLUGIN;
573
error= static_cast<drizzled::error_t>(engine.doDropTable(session, identifier));
575
if (unlikely(plugin::EventObserver::afterDropTable(session, identifier, error)))
577
error= ER_EVENT_OBSERVER_PLUGIN;
581
drizzled::message::Cache::singleton().erase(identifier);
593
Initiates table-file and calls appropriate database-creator.
600
bool StorageEngine::createTable(Session &session,
601
const identifier::Table &identifier,
602
message::Table& table_message)
604
drizzled::error_t error= EE_OK;
606
TableShare share(identifier);
607
table::Shell table(share);
608
message::Table tmp_proto;
610
if (share.parse_table_proto(session, table_message) || share.open_table_from_share(&session, identifier, "", 0, 0, table))
612
// @note Error occured, we should probably do a little more here.
613
// ER_CORRUPT_TABLE_DEFINITION,ER_CORRUPT_TABLE_DEFINITION_ENUM
615
my_error(ER_CORRUPT_TABLE_DEFINITION_UNKNOWN, identifier);
621
/* Check for legal operations against the Engine using the proto (if used) */
622
if (table_message.type() == message::Table::TEMPORARY &&
623
share.storage_engine->check_flag(HTON_BIT_TEMPORARY_NOT_SUPPORTED) == true)
625
error= HA_ERR_UNSUPPORTED;
627
else if (table_message.type() != message::Table::TEMPORARY &&
628
share.storage_engine->check_flag(HTON_BIT_TEMPORARY_ONLY) == true)
630
error= HA_ERR_UNSUPPORTED;
634
share.storage_engine->setTransactionReadWrite(session);
636
error= static_cast<drizzled::error_t>(share.storage_engine->doCreateTable(session,
642
if (error == ER_TABLE_PERMISSION_DENIED)
644
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);
653
table.delete_table();
656
return(error == EE_OK);
659
Cursor *StorageEngine::getCursor(Table &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)
689
CachedDirectory directory(schema_identifier.getPath(), set_of_table_definition_ext);
691
if (schema_identifier == INFORMATION_SCHEMA_IDENTIFIER)
693
else if (schema_identifier == DATA_DICTIONARY_IDENTIFIER)
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);
715
std::for_each(vector_of_engines.begin(), vector_of_engines.end(),
716
AddTableIdentifier(directory, schema_identifier, set_of_identifiers));
718
session.doGetTableIdentifiers(directory, schema_identifier, set_of_identifiers);
721
class DropTable: public std::unary_function<identifier::Table&, bool>
724
StorageEngine *engine;
728
DropTable(Session &session_arg, StorageEngine *engine_arg) :
729
session(session_arg),
733
result_type operator() (argument_type identifier)
735
return engine->doDropTable(session, identifier) == 0;
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
This only works for engines which use file based DFE.
766
Note-> Unlike MySQL, we do not, on purpose, delete files that do not match any engines.
768
void StorageEngine::removeLostTemporaryTables(Session &session, const char *directory)
770
CachedDirectory dir(directory, set_of_table_definition_ext);
771
identifier::Table::vector table_identifiers;
775
errno= dir.getError();
776
my_error(ER_CANT_READ_DIR, MYF(0), directory, errno);
781
CachedDirectory::Entries files= dir.getEntries();
783
for (CachedDirectory::Entries::iterator fileIter= files.begin();
784
fileIter != files.end(); fileIter++)
788
CachedDirectory::Entry *entry= *fileIter;
790
/* We remove the file extension. */
791
length= entry->filename.length();
792
entry->filename.resize(length - DEFAULT_DEFINITION_FILE_EXT.length());
796
path+= entry->filename;
797
message::Table definition;
798
if (StorageEngine::readTableFile(path, definition))
800
identifier::Table identifier(definition.schema(), definition.name(), path);
801
table_identifiers.push_back(identifier);
805
std::for_each(vector_of_engines.begin(), vector_of_engines.end(),
806
DropTables(session, table_identifiers));
809
Now we just clean up anything that might left over.
811
We rescan because some of what might have been there should
812
now be all nice and cleaned up.
814
std::set<std::string> all_exts= set_of_table_definition_ext;
816
for (EngineVector::iterator iter= vector_of_engines.begin();
817
iter != vector_of_engines.end() ; iter++)
819
for (const char **ext= (*iter)->bas_ext(); *ext ; ext++)
820
all_exts.insert(*ext);
823
CachedDirectory rescan(directory, all_exts);
825
files= rescan.getEntries();
826
for (CachedDirectory::Entries::iterator fileIter= files.begin();
827
fileIter != files.end(); fileIter++)
830
CachedDirectory::Entry *entry= *fileIter;
834
path+= entry->filename;
836
unlink(path.c_str());
842
Print error that we got from Cursor function.
845
In case of delete table it's only safe to use the following parts of
846
the 'table' structure:
847
- table->getShare()->path
850
void StorageEngine::print_error(int error, myf errflag, const Table &table) const
852
drizzled::error_t textno= ER_GET_ERRNO;
855
textno=ER_OPEN_AS_READONLY;
861
textno=ER_FILE_NOT_FOUND;
863
case HA_ERR_KEY_NOT_FOUND:
864
case HA_ERR_NO_ACTIVE_RECORD:
865
case HA_ERR_END_OF_FILE:
866
textno=ER_KEY_NOT_FOUND;
868
case HA_ERR_WRONG_MRG_TABLE_DEF:
869
textno=ER_WRONG_MRG_TABLE;
871
case HA_ERR_FOUND_DUPP_KEY:
873
uint32_t key_nr= table.get_dup_key(error);
874
if ((int) key_nr >= 0)
876
const char *err_msg= ER(ER_DUP_ENTRY_WITH_KEY_NAME);
878
print_keydup_error(key_nr, err_msg, table);
885
case HA_ERR_FOREIGN_DUPLICATE_KEY:
887
uint32_t key_nr= table.get_dup_key(error);
888
if ((int) key_nr >= 0)
892
/* Write the key in the error message */
893
char key[MAX_KEY_LENGTH];
894
String str(key,sizeof(key),system_charset_info);
896
/* Table is opened and defined at this point */
897
key_unpack(&str, &table,(uint32_t) key_nr);
898
max_length= (DRIZZLE_ERRMSG_SIZE-
899
(uint32_t) strlen(ER(ER_FOREIGN_DUPLICATE_KEY)));
900
if (str.length() >= max_length)
902
str.length(max_length-4);
903
str.append(STRING_WITH_LEN("..."));
905
my_error(ER_FOREIGN_DUPLICATE_KEY, MYF(0), table.getShare()->getTableName(),
906
str.c_ptr(), key_nr+1);
912
case HA_ERR_FOUND_DUPP_UNIQUE:
913
textno=ER_DUP_UNIQUE;
915
case HA_ERR_RECORD_CHANGED:
919
textno=ER_NOT_KEYFILE;
921
case HA_ERR_WRONG_IN_RECORD:
922
textno= ER_CRASHED_ON_USAGE;
924
case HA_ERR_CRASHED_ON_USAGE:
925
textno=ER_CRASHED_ON_USAGE;
927
case HA_ERR_NOT_A_TABLE:
928
textno= static_cast<drizzled::error_t>(error);
930
case HA_ERR_CRASHED_ON_REPAIR:
931
textno=ER_CRASHED_ON_REPAIR;
933
case HA_ERR_OUT_OF_MEM:
934
textno=ER_OUT_OF_RESOURCES;
936
case HA_ERR_WRONG_COMMAND:
937
textno=ER_ILLEGAL_HA;
939
case HA_ERR_OLD_FILE:
940
textno=ER_OLD_KEYFILE;
942
case HA_ERR_UNSUPPORTED:
943
textno=ER_UNSUPPORTED_EXTENSION;
945
case HA_ERR_RECORD_FILE_FULL:
946
case HA_ERR_INDEX_FILE_FULL:
947
textno=ER_RECORD_FILE_FULL;
949
case HA_ERR_LOCK_WAIT_TIMEOUT:
950
textno=ER_LOCK_WAIT_TIMEOUT;
952
case HA_ERR_LOCK_TABLE_FULL:
953
textno=ER_LOCK_TABLE_FULL;
955
case HA_ERR_LOCK_DEADLOCK:
956
textno=ER_LOCK_DEADLOCK;
958
case HA_ERR_READ_ONLY_TRANSACTION:
959
textno=ER_READ_ONLY_TRANSACTION;
961
case HA_ERR_CANNOT_ADD_FOREIGN:
962
textno=ER_CANNOT_ADD_FOREIGN;
964
case HA_ERR_ROW_IS_REFERENCED:
967
get_error_message(error, &str);
968
my_error(ER_ROW_IS_REFERENCED_2, MYF(0), str.c_ptr_safe());
971
case HA_ERR_NO_REFERENCED_ROW:
974
get_error_message(error, &str);
975
my_error(ER_NO_REFERENCED_ROW_2, MYF(0), str.c_ptr_safe());
978
case HA_ERR_TABLE_DEF_CHANGED:
979
textno=ER_TABLE_DEF_CHANGED;
981
case HA_ERR_NO_SUCH_TABLE:
983
identifier::Table identifier(table.getShare()->getSchemaName(), table.getShare()->getTableName());
984
my_error(ER_TABLE_UNKNOWN, identifier);
987
case HA_ERR_RBR_LOGGING_FAILED:
988
textno= ER_BINLOG_ROW_LOGGING_FAILED;
990
case HA_ERR_DROP_INDEX_FK:
992
const char *ptr= "???";
993
uint32_t key_nr= table.get_dup_key(error);
994
if ((int) key_nr >= 0)
995
ptr= table.key_info[key_nr].name;
996
my_error(ER_DROP_INDEX_FK, MYF(0), ptr);
999
case HA_ERR_TABLE_NEEDS_UPGRADE:
1000
textno=ER_TABLE_NEEDS_UPGRADE;
1002
case HA_ERR_TABLE_READONLY:
1003
textno= ER_OPEN_AS_READONLY;
1005
case HA_ERR_AUTOINC_READ_FAILED:
1006
textno= ER_AUTOINC_READ_FAILED;
1008
case HA_ERR_AUTOINC_ERANGE:
1009
textno= ER_WARN_DATA_OUT_OF_RANGE;
1011
case HA_ERR_LOCK_OR_ACTIVE_TRANSACTION:
1012
my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
1013
ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
1018
The error was "unknown" to this function.
1019
Ask Cursor if it has got a message for this error
1021
bool temporary= false;
1023
temporary= get_error_message(error, &str);
1024
if (!str.is_empty())
1026
const char* engine_name= getName().c_str();
1028
my_error(ER_GET_TEMPORARY_ERRMSG, MYF(0), error, str.ptr(),
1031
my_error(ER_GET_ERRMSG, MYF(0), error, str.ptr(), engine_name);
1035
my_error(ER_GET_ERRNO,errflag,error);
1041
my_error(textno, errflag, table.getShare()->getTableName(), error);
1046
Return an error message specific to this Cursor.
1048
@param error error code previously returned by Cursor
1049
@param buf pointer to String where to add error message
1052
Returns true if this is a temporary error
1054
bool StorageEngine::get_error_message(int , String* ) const
1060
void StorageEngine::print_keydup_error(uint32_t key_nr, const char *msg, const Table &table) const
1062
/* Write the duplicated key in the error message */
1063
char key[MAX_KEY_LENGTH];
1064
String str(key,sizeof(key),system_charset_info);
1066
if (key_nr == MAX_KEY)
1068
/* Key is unknown */
1069
str.copy("", 0, system_charset_info);
1070
my_printf_error(ER_DUP_ENTRY, msg, MYF(0), str.c_ptr(), "*UNKNOWN*");
1074
/* Table is opened and defined at this point */
1075
key_unpack(&str, &table, (uint32_t) key_nr);
1076
uint32_t max_length=DRIZZLE_ERRMSG_SIZE-(uint32_t) strlen(msg);
1077
if (str.length() >= max_length)
1079
str.length(max_length-4);
1080
str.append(STRING_WITH_LEN("..."));
1082
my_printf_error(ER_DUP_ENTRY, msg,
1083
MYF(0), str.c_ptr(), table.key_info[key_nr].name);
1088
int StorageEngine::deleteDefinitionFromPath(const identifier::Table &identifier)
1090
std::string path(identifier.getPath());
1092
path.append(DEFAULT_DEFINITION_FILE_EXT);
1094
return internal::my_delete(path.c_str(), MYF(0));
1097
int StorageEngine::renameDefinitionFromPath(const identifier::Table &dest, const identifier::Table &src)
1099
message::Table table_message;
1100
std::string src_path(src.getPath());
1101
std::string dest_path(dest.getPath());
1103
src_path.append(DEFAULT_DEFINITION_FILE_EXT);
1104
dest_path.append(DEFAULT_DEFINITION_FILE_EXT);
1106
bool was_read= StorageEngine::readTableFile(src_path.c_str(), table_message);
1113
dest.copyToTableMessage(table_message);
1115
int error= StorageEngine::writeDefinitionFromPath(dest, table_message);
1119
if (unlink(src_path.c_str()))
1120
perror(src_path.c_str());
1126
int StorageEngine::writeDefinitionFromPath(const identifier::Table &identifier, message::Table &table_message)
1128
char definition_file_tmp[FN_REFLEN];
1129
std::string file_name(identifier.getPath());
1131
file_name.append(DEFAULT_DEFINITION_FILE_EXT);
1133
snprintf(definition_file_tmp, sizeof(definition_file_tmp), "%sXXXXXX", file_name.c_str());
1135
int fd= mkstemp(definition_file_tmp);
1139
perror(definition_file_tmp);
1143
google::protobuf::io::ZeroCopyOutputStream* output=
1144
new google::protobuf::io::FileOutputStream(fd);
1150
success= table_message.SerializeToZeroCopyStream(output);
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());
1167
if (close(fd) == -1)
1168
perror(definition_file_tmp);
1170
if (unlink(definition_file_tmp) == -1)
1171
perror(definition_file_tmp);
1173
return ER_CORRUPT_TABLE_DEFINITION;
1178
if (close(fd) == -1)
1181
perror(definition_file_tmp);
1183
if (unlink(definition_file_tmp))
1184
perror(definition_file_tmp);
1189
if (rename(definition_file_tmp, file_name.c_str()) == -1)
1192
perror(definition_file_tmp);
1194
if (unlink(definition_file_tmp))
1195
perror(definition_file_tmp);
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);
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") },
1220
@note on success table can be created.
1222
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())
1236
bool StorageEngine::readTableFile(const std::string &path, message::Table &table_message)
1238
std::fstream input(path.c_str(), std::ios::in | std::ios::binary);
1243
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
sql_print_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
sql_print_warning(_("Too many storage engines!"));
271
if (hton->db_type != DB_TYPE_UNKNOWN)
272
sql_print_warning(_("Storage engine '%s' has conflicting typecode. "
273
"Assigning value %d."), plugin->plugin->name, idx);
274
hton->db_type= (enum legacy_db_type) idx;
1250
my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
1251
table_message.name().empty() ? path.c_str() : table_message.name().c_str(),
1252
table_message.InitializationErrorString().empty() ? "": table_message.InitializationErrorString().c_str());
1257
perror(path.c_str());
1263
std::ostream& operator<<(std::ostream& output, const StorageEngine &engine)
1265
output << "StorageEngine:(";
1266
output << engine.getName();
1272
} /* namespace plugin */
1273
} /* namespace drizzled */
276
installed_htons[hton->db_type]= hton;
277
tmp= hton->savepoint_offset;
278
hton->savepoint_offset= savepoint_alloc_size;
279
savepoint_alloc_size+= tmp;
280
hton->slot= total_ha++;
281
hton2plugin[hton->slot]=plugin;
288
hton->state= SHOW_OPTION_DISABLED;
293
This is entirely for legacy. We will create a new "disk based" hton and a
294
"memory" hton which will be configurable longterm. We should be able to
295
remove partition and myisammrg.
297
if (strcmp(plugin->plugin->name, "MEMORY") == 0)
300
if (strcmp(plugin->plugin->name, "MyISAM") == 0)
308
enum legacy_db_type ha_legacy_type(const handlerton *db_type)
310
return (db_type == NULL) ? DB_TYPE_UNKNOWN : db_type->db_type;
313
const char *ha_resolve_storage_engine_name(const handlerton *db_type)
315
return db_type == NULL ? "UNKNOWN" : hton2plugin[db_type->slot]->name.str;
318
bool ha_check_storage_engine_flag(const handlerton *db_type, const hton_flag_bits flag)
320
return db_type == NULL ? false : db_type->flags.test(static_cast<size_t>(flag));
323
bool ha_storage_engine_is_enabled(const handlerton *db_type)
325
return (db_type && db_type->create) ?
326
(db_type->state == SHOW_OPTION_YES) : false;
329
LEX_STRING *ha_storage_engine_name(const handlerton *hton)
331
return &hton2plugin[hton->slot]->name;