1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2008 Sun Microsystems, Inc.
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; version 2 of the License.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
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>
37
#include <drizzled/definitions.h>
38
#include <drizzled/base.h>
39
#include <drizzled/cursor.h>
40
#include <drizzled/plugin/storage_engine.h>
41
#include <drizzled/session.h>
42
#include <drizzled/error.h>
43
#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>
53
#include <drizzled/table_proto.h>
54
#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
#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";
364
message::table::shared_ptr StorageEngine::getTableMessage(Session& session,
365
identifier::Table::const_reference identifier,
366
bool include_temporary_tables)
368
drizzled::error_t error;
369
error= static_cast<drizzled::error_t>(ENOENT);
371
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;
387
EngineVector::iterator iter=
388
std::find_if(vector_of_engines.begin(), vector_of_engines.end(),
389
StorageEngineGetTableDefinition(session, identifier, message, error));
391
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;
403
An interceptor to hijack the text of the error message without
404
setting an error in the thread. We need the text to present it
405
in the form of a warning to the user.
408
class Ha_delete_table_error_handler: public Internal_error_handler
411
Ha_delete_table_error_handler() : Internal_error_handler() {}
412
virtual bool handle_error(drizzled::error_t sql_errno,
414
DRIZZLE_ERROR::enum_warning_level level,
416
char buff[DRIZZLE_ERRMSG_SIZE];
421
Ha_delete_table_error_handler::
422
handle_error(drizzled::error_t ,
424
DRIZZLE_ERROR::enum_warning_level ,
427
/* Grab the error message */
428
strncpy(buff, message, sizeof(buff)-1);
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)
517
engine.setTransactionReadWrite(session);
519
assert(identifier.isTmp());
521
if (unlikely(plugin::EventObserver::beforeDropTable(session, identifier)))
523
error= ER_EVENT_OBSERVER_PLUGIN;
527
error= static_cast<drizzled::error_t>(engine.doDropTable(session, identifier));
529
if (unlikely(plugin::EventObserver::afterDropTable(session, identifier, error)))
531
error= ER_EVENT_OBSERVER_PLUGIN;
535
drizzled::message::Cache::singleton().erase(identifier);
547
Initiates table-file and calls appropriate database-creator.
554
bool StorageEngine::createTable(Session &session,
555
const identifier::Table &identifier,
556
message::Table& table_message)
558
drizzled::error_t error= EE_OK;
560
TableShare share(identifier);
561
table::Shell table(share);
562
message::Table tmp_proto;
564
if (share.parse_table_proto(session, table_message) || share.open_table_from_share(&session, identifier, "", 0, 0, table))
566
// @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);
575
/* Check for legal operations against the Engine using the proto (if used) */
576
if (table_message.type() == message::Table::TEMPORARY &&
577
share.storage_engine->check_flag(HTON_BIT_TEMPORARY_NOT_SUPPORTED) == true)
579
error= HA_ERR_UNSUPPORTED;
581
else if (table_message.type() != message::Table::TEMPORARY &&
582
share.storage_engine->check_flag(HTON_BIT_TEMPORARY_ONLY) == true)
584
error= HA_ERR_UNSUPPORTED;
588
share.storage_engine->setTransactionReadWrite(session);
590
error= static_cast<drizzled::error_t>(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);
607
table.delete_table();
610
return(error == EE_OK);
613
Cursor *StorageEngine::getCursor(Table &arg)
618
class AddTableIdentifier :
619
public std::unary_function<StorageEngine *, void>
621
CachedDirectory &directory;
622
const identifier::Schema &identifier;
623
identifier::Table::vector &set_of_identifiers;
627
AddTableIdentifier(CachedDirectory &directory_arg, const identifier::Schema &identifier_arg, identifier::Table::vector &of_names) :
628
directory(directory_arg),
629
identifier(identifier_arg),
630
set_of_identifiers(of_names)
634
result_type operator() (argument_type engine)
636
engine->doGetTableIdentifiers(directory, identifier, set_of_identifiers);
641
void StorageEngine::getIdentifiers(Session &session, const identifier::Schema &schema_identifier, identifier::Table::vector &set_of_identifiers)
643
CachedDirectory directory(schema_identifier.getPath(), set_of_table_definition_ext);
645
if (schema_identifier == INFORMATION_SCHEMA_IDENTIFIER)
647
else if (schema_identifier == DATA_DICTIONARY_IDENTIFIER)
651
if (directory.fail())
653
errno= directory.getError();
657
schema_identifier.getSQLPath(path);
658
my_error(ER_BAD_DB_ERROR, MYF(ME_BELL+ME_WAITTANG), path.c_str());
662
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));
672
session.doGetTableIdentifiers(directory, schema_identifier, set_of_identifiers);
675
class DropTable: public std::unary_function<identifier::Table&, bool>
678
StorageEngine *engine;
682
DropTable(Session &session_arg, StorageEngine *engine_arg) :
683
session(session_arg),
687
result_type operator() (argument_type identifier)
689
return engine->doDropTable(session, identifier) == 0;
693
/* This will later be converted to identifier::Tables */
694
class DropTables: public std::unary_function<StorageEngine *, void>
697
identifier::Table::vector &table_identifiers;
701
DropTables(Session &session_arg, identifier::Table::vector &table_identifiers_arg) :
702
session(session_arg),
703
table_identifiers(table_identifiers_arg)
706
result_type operator() (argument_type engine)
708
// True returning from DropTable means the table has been successfully
709
// 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)),
713
table_identifiers.end());
718
This only works for engines which use file based DFE.
720
Note-> Unlike MySQL, we do not, on purpose, delete files that do not match any engines.
722
void StorageEngine::removeLostTemporaryTables(Session &session, const char *directory)
724
CachedDirectory dir(directory, set_of_table_definition_ext);
725
identifier::Table::vector table_identifiers;
729
errno= dir.getError();
730
my_error(ER_CANT_READ_DIR, MYF(0), directory, errno);
735
CachedDirectory::Entries files= dir.getEntries();
737
for (CachedDirectory::Entries::iterator fileIter= files.begin();
738
fileIter != files.end(); fileIter++)
742
CachedDirectory::Entry *entry= *fileIter;
744
/* We remove the file extension. */
745
length= entry->filename.length();
746
entry->filename.resize(length - DEFAULT_DEFINITION_FILE_EXT.length());
750
path+= entry->filename;
751
message::Table definition;
752
if (StorageEngine::readTableFile(path, definition))
754
identifier::Table identifier(definition.schema(), definition.name(), path);
755
table_identifiers.push_back(identifier);
759
std::for_each(vector_of_engines.begin(), vector_of_engines.end(),
760
DropTables(session, table_identifiers));
763
Now we just clean up anything that might left over.
765
We rescan because some of what might have been there should
766
now be all nice and cleaned up.
768
std::set<std::string> all_exts= set_of_table_definition_ext;
770
for (EngineVector::iterator iter= vector_of_engines.begin();
771
iter != vector_of_engines.end() ; iter++)
773
for (const char **ext= (*iter)->bas_ext(); *ext ; ext++)
774
all_exts.insert(*ext);
777
CachedDirectory rescan(directory, all_exts);
779
files= rescan.getEntries();
780
for (CachedDirectory::Entries::iterator fileIter= files.begin();
781
fileIter != files.end(); fileIter++)
784
CachedDirectory::Entry *entry= *fileIter;
788
path+= entry->filename;
790
unlink(path.c_str());
796
Print error that we got from Cursor function.
799
In case of delete table it's only safe to use the following parts of
800
the 'table' structure:
801
- table->getShare()->path
804
void StorageEngine::print_error(int error, myf errflag, const Table &table) const
806
drizzled::error_t textno= ER_GET_ERRNO;
809
textno=ER_OPEN_AS_READONLY;
815
textno=ER_FILE_NOT_FOUND;
817
case HA_ERR_KEY_NOT_FOUND:
818
case HA_ERR_NO_ACTIVE_RECORD:
819
case HA_ERR_END_OF_FILE:
820
textno=ER_KEY_NOT_FOUND;
822
case HA_ERR_WRONG_MRG_TABLE_DEF:
823
textno=ER_WRONG_MRG_TABLE;
825
case HA_ERR_FOUND_DUPP_KEY:
827
uint32_t key_nr= table.get_dup_key(error);
828
if ((int) key_nr >= 0)
830
const char *err_msg= ER(ER_DUP_ENTRY_WITH_KEY_NAME);
832
print_keydup_error(key_nr, err_msg, table);
839
case HA_ERR_FOREIGN_DUPLICATE_KEY:
841
uint32_t key_nr= table.get_dup_key(error);
842
if ((int) key_nr >= 0)
846
/* Write the key in the error message */
847
char key[MAX_KEY_LENGTH];
848
String str(key,sizeof(key),system_charset_info);
850
/* Table is opened and defined at this point */
851
key_unpack(&str, &table,(uint32_t) key_nr);
852
max_length= (DRIZZLE_ERRMSG_SIZE-
853
(uint32_t) strlen(ER(ER_FOREIGN_DUPLICATE_KEY)));
854
if (str.length() >= max_length)
856
str.length(max_length-4);
857
str.append(STRING_WITH_LEN("..."));
859
my_error(ER_FOREIGN_DUPLICATE_KEY, MYF(0), table.getShare()->getTableName(),
860
str.c_ptr(), key_nr+1);
866
case HA_ERR_FOUND_DUPP_UNIQUE:
867
textno=ER_DUP_UNIQUE;
869
case HA_ERR_RECORD_CHANGED:
873
textno=ER_NOT_KEYFILE;
875
case HA_ERR_WRONG_IN_RECORD:
876
textno= ER_CRASHED_ON_USAGE;
878
case HA_ERR_CRASHED_ON_USAGE:
879
textno=ER_CRASHED_ON_USAGE;
881
case HA_ERR_NOT_A_TABLE:
882
textno= static_cast<drizzled::error_t>(error);
884
case HA_ERR_CRASHED_ON_REPAIR:
885
textno=ER_CRASHED_ON_REPAIR;
887
case HA_ERR_OUT_OF_MEM:
888
textno=ER_OUT_OF_RESOURCES;
890
case HA_ERR_WRONG_COMMAND:
891
textno=ER_ILLEGAL_HA;
893
case HA_ERR_OLD_FILE:
894
textno=ER_OLD_KEYFILE;
896
case HA_ERR_UNSUPPORTED:
897
textno=ER_UNSUPPORTED_EXTENSION;
899
case HA_ERR_RECORD_FILE_FULL:
900
case HA_ERR_INDEX_FILE_FULL:
901
textno=ER_RECORD_FILE_FULL;
903
case HA_ERR_LOCK_WAIT_TIMEOUT:
904
textno=ER_LOCK_WAIT_TIMEOUT;
906
case HA_ERR_LOCK_TABLE_FULL:
907
textno=ER_LOCK_TABLE_FULL;
909
case HA_ERR_LOCK_DEADLOCK:
910
textno=ER_LOCK_DEADLOCK;
912
case HA_ERR_READ_ONLY_TRANSACTION:
913
textno=ER_READ_ONLY_TRANSACTION;
915
case HA_ERR_CANNOT_ADD_FOREIGN:
916
textno=ER_CANNOT_ADD_FOREIGN;
918
case HA_ERR_ROW_IS_REFERENCED:
921
get_error_message(error, &str);
922
my_error(ER_ROW_IS_REFERENCED_2, MYF(0), str.c_ptr_safe());
925
case HA_ERR_NO_REFERENCED_ROW:
928
get_error_message(error, &str);
929
my_error(ER_NO_REFERENCED_ROW_2, MYF(0), str.c_ptr_safe());
932
case HA_ERR_TABLE_DEF_CHANGED:
933
textno=ER_TABLE_DEF_CHANGED;
935
case HA_ERR_NO_SUCH_TABLE:
937
identifier::Table identifier(table.getShare()->getSchemaName(), table.getShare()->getTableName());
938
my_error(ER_TABLE_UNKNOWN, identifier);
941
case HA_ERR_RBR_LOGGING_FAILED:
942
textno= ER_BINLOG_ROW_LOGGING_FAILED;
944
case HA_ERR_DROP_INDEX_FK:
946
const char *ptr= "???";
947
uint32_t key_nr= table.get_dup_key(error);
948
if ((int) key_nr >= 0)
949
ptr= table.key_info[key_nr].name;
950
my_error(ER_DROP_INDEX_FK, MYF(0), ptr);
953
case HA_ERR_TABLE_NEEDS_UPGRADE:
954
textno=ER_TABLE_NEEDS_UPGRADE;
956
case HA_ERR_TABLE_READONLY:
957
textno= ER_OPEN_AS_READONLY;
959
case HA_ERR_AUTOINC_READ_FAILED:
960
textno= ER_AUTOINC_READ_FAILED;
962
case HA_ERR_AUTOINC_ERANGE:
963
textno= ER_WARN_DATA_OUT_OF_RANGE;
965
case HA_ERR_LOCK_OR_ACTIVE_TRANSACTION:
966
my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
967
ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
972
The error was "unknown" to this function.
973
Ask Cursor if it has got a message for this error
975
bool temporary= false;
977
temporary= get_error_message(error, &str);
980
const char* engine_name= getName().c_str();
982
my_error(ER_GET_TEMPORARY_ERRMSG, MYF(0), error, str.ptr(),
985
my_error(ER_GET_ERRMSG, MYF(0), error, str.ptr(), engine_name);
989
my_error(ER_GET_ERRNO,errflag,error);
995
my_error(textno, errflag, table.getShare()->getTableName(), error);
1000
Return an error message specific to this Cursor.
1002
@param error error code previously returned by Cursor
1003
@param buf pointer to String where to add error message
1006
Returns true if this is a temporary error
1008
bool StorageEngine::get_error_message(int , String* ) const
1014
void StorageEngine::print_keydup_error(uint32_t key_nr, const char *msg, const Table &table) const
1016
/* Write the duplicated key in the error message */
1017
char key[MAX_KEY_LENGTH];
1018
String str(key,sizeof(key),system_charset_info);
1020
if (key_nr == MAX_KEY)
1022
/* Key is unknown */
1023
str.copy("", 0, system_charset_info);
1024
my_printf_error(ER_DUP_ENTRY, msg, MYF(0), str.c_ptr(), "*UNKNOWN*");
1028
/* Table is opened and defined at this point */
1029
key_unpack(&str, &table, (uint32_t) key_nr);
1030
uint32_t max_length=DRIZZLE_ERRMSG_SIZE-(uint32_t) strlen(msg);
1031
if (str.length() >= max_length)
1033
str.length(max_length-4);
1034
str.append(STRING_WITH_LEN("..."));
1036
my_printf_error(ER_DUP_ENTRY, msg,
1037
MYF(0), str.c_ptr(), table.key_info[key_nr].name);
1042
int StorageEngine::deleteDefinitionFromPath(const identifier::Table &identifier)
1044
std::string path(identifier.getPath());
1046
path.append(DEFAULT_DEFINITION_FILE_EXT);
1048
return internal::my_delete(path.c_str(), MYF(0));
1051
int StorageEngine::renameDefinitionFromPath(const identifier::Table &dest, const identifier::Table &src)
1053
message::Table table_message;
1054
std::string src_path(src.getPath());
1055
std::string dest_path(dest.getPath());
1057
src_path.append(DEFAULT_DEFINITION_FILE_EXT);
1058
dest_path.append(DEFAULT_DEFINITION_FILE_EXT);
1060
bool was_read= StorageEngine::readTableFile(src_path.c_str(), table_message);
1067
dest.copyToTableMessage(table_message);
1069
int error= StorageEngine::writeDefinitionFromPath(dest, table_message);
1073
if (unlink(src_path.c_str()))
1074
perror(src_path.c_str());
1080
int StorageEngine::writeDefinitionFromPath(const identifier::Table &identifier, message::Table &table_message)
1082
char definition_file_tmp[FN_REFLEN];
1083
std::string file_name(identifier.getPath());
1085
file_name.append(DEFAULT_DEFINITION_FILE_EXT);
1087
snprintf(definition_file_tmp, sizeof(definition_file_tmp), "%sXXXXXX", file_name.c_str());
1089
int fd= mkstemp(definition_file_tmp);
1093
perror(definition_file_tmp);
1097
google::protobuf::io::ZeroCopyOutputStream* output=
1098
new google::protobuf::io::FileOutputStream(fd);
1104
success= table_message.SerializeToZeroCopyStream(output);
1113
std::string error_message;
1114
identifier.getSQLPath(error_message);
1116
my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
1117
error_message.c_str(),
1118
table_message.InitializationErrorString().c_str());
1121
if (close(fd) == -1)
1122
perror(definition_file_tmp);
1124
if (unlink(definition_file_tmp) == -1)
1125
perror(definition_file_tmp);
1127
return ER_CORRUPT_TABLE_DEFINITION;
1132
if (close(fd) == -1)
1135
perror(definition_file_tmp);
1137
if (unlink(definition_file_tmp))
1138
perror(definition_file_tmp);
1143
if (rename(definition_file_tmp, file_name.c_str()) == -1)
1146
perror(definition_file_tmp);
1148
if (unlink(definition_file_tmp))
1149
perror(definition_file_tmp);
1157
class CanCreateTable: public std::unary_function<StorageEngine *, bool>
1159
const identifier::Table &identifier;
1162
CanCreateTable(const identifier::Table &identifier_arg) :
1163
identifier(identifier_arg)
1166
result_type operator() (argument_type engine)
1168
return not engine->doCanCreateTable(identifier);
1174
@note on success table can be created.
1176
bool StorageEngine::canCreateTable(const identifier::Table &identifier)
1178
EngineVector::iterator iter=
1179
std::find_if(vector_of_engines.begin(), vector_of_engines.end(),
1180
CanCreateTable(identifier));
1182
if (iter == vector_of_engines.end())
1190
bool StorageEngine::readTableFile(const std::string &path, message::Table &table_message)
1192
std::fstream input(path.c_str(), std::ios::in | std::ios::binary);
1197
if (table_message.ParseFromIstream(&input))
1204
my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
1205
table_message.name().empty() ? path.c_str() : table_message.name().c_str(),
1206
table_message.InitializationErrorString().empty() ? "": table_message.InitializationErrorString().c_str());
1211
perror(path.c_str());
1217
std::ostream& operator<<(std::ostream& output, const StorageEngine &engine)
1219
output << "StorageEngine:(";
1220
output << engine.getName();
1226
} /* namespace plugin */
1227
} /* namespace drizzled */