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
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"
52
#include "drizzled/db.h"
54
#include <drizzled/table_proto.h>
55
#include <drizzled/plugin/event_observer.h>
57
#include <boost/algorithm/string/compare.hpp>
59
static bool shutdown_has_begun= false; // Once we put in the container for the vector/etc for engines this will go away.
69
static EngineVector vector_of_engines;
70
static EngineVector vector_of_schema_engines;
72
const std::string DEFAULT_STRING("default");
73
const std::string UNKNOWN_STRING("UNKNOWN");
74
const std::string DEFAULT_DEFINITION_FILE_EXT(".dfe");
76
static std::set<std::string> set_of_table_definition_ext;
78
EngineVector &StorageEngine::getSchemaEngines()
80
return vector_of_schema_engines;
83
StorageEngine::StorageEngine(const string name_arg,
84
const bitset<HTON_BIT_SIZE> &flags_arg) :
85
Plugin(name_arg, "StorageEngine"),
86
MonitoredInTransaction(), /* This gives the storage engine a "slot" or ID */
91
StorageEngine::~StorageEngine()
95
void StorageEngine::setTransactionReadWrite(Session& session)
97
TransactionContext &statement_ctx= session.transaction.stmt;
98
statement_ctx.markModifiedNonTransData();
102
int StorageEngine::renameTable(Session &session, const TableIdentifier &from, const TableIdentifier &to)
105
setTransactionReadWrite(session);
107
if (unlikely(plugin::EventObserver::beforeRenameTable(session, from, to)))
109
error= ER_EVENT_OBSERVER_PLUGIN;
113
error = doRenameTable(session, from, to);
114
if (unlikely(plugin::EventObserver::afterRenameTable(session, from, to, error)))
116
error= ER_EVENT_OBSERVER_PLUGIN;
124
Delete all files with extension from bas_ext().
126
@param name Base name of table
129
We assume that the Cursor may return more extensions than
130
was actually used for the file.
133
0 If we successfully deleted at least one file from base_ext and
134
didn't get any other errors than ENOENT
138
int StorageEngine::doDropTable(Session&, const TableIdentifier &identifier)
142
int enoent_or_zero= ENOENT; // Error if no file was deleted
143
char buff[FN_REFLEN];
145
for (const char **ext= bas_ext(); *ext ; ext++)
147
internal::fn_format(buff, identifier.getPath().c_str(), "", *ext,
148
MY_UNPACK_FILENAME|MY_APPEND_EXT);
149
if (internal::my_delete_with_symlink(buff, MYF(0)))
151
if ((error= errno) != ENOENT)
156
enoent_or_zero= 0; // No error for ENOENT
159
error= enoent_or_zero;
164
bool StorageEngine::addPlugin(StorageEngine *engine)
167
vector_of_engines.push_back(engine);
169
if (engine->getTableDefinitionFileExtension().length())
171
assert(engine->getTableDefinitionFileExtension().length() == DEFAULT_DEFINITION_FILE_EXT.length());
172
set_of_table_definition_ext.insert(engine->getTableDefinitionFileExtension());
175
if (engine->check_flag(HTON_BIT_SCHEMA_DICTIONARY))
176
vector_of_schema_engines.push_back(engine);
181
void StorageEngine::removePlugin(StorageEngine *)
183
if (shutdown_has_begun == false)
185
vector_of_engines.clear();
186
vector_of_schema_engines.clear();
188
shutdown_has_begun= true;
192
class FindEngineByName
193
: public unary_function<StorageEngine *, bool>
195
const string &predicate;
198
explicit FindEngineByName(const string &target_arg) :
199
predicate(target_arg)
203
result_type operator() (argument_type engine)
205
return boost::iequals(engine->getName(), predicate);
209
StorageEngine *StorageEngine::findByName(const string &predicate)
211
EngineVector::iterator iter= find_if(vector_of_engines.begin(),
212
vector_of_engines.end(),
213
FindEngineByName(predicate));
214
if (iter != vector_of_engines.end())
216
StorageEngine *engine= *iter;
217
if (engine->is_user_selectable())
224
StorageEngine *StorageEngine::findByName(Session& session, const string &predicate)
226
if (boost::iequals(predicate, DEFAULT_STRING))
227
return session.getDefaultStorageEngine();
229
EngineVector::iterator iter= find_if(vector_of_engines.begin(),
230
vector_of_engines.end(),
231
FindEngineByName(predicate));
232
if (iter != vector_of_engines.end())
234
StorageEngine *engine= *iter;
235
if (engine->is_user_selectable())
242
class StorageEngineCloseConnection : public unary_function<StorageEngine *, void>
246
StorageEngineCloseConnection(Session *session_arg) : session(session_arg) {}
248
there's no need to rollback here as all transactions must
249
be rolled back already
251
inline result_type operator() (argument_type engine)
253
if (*session->getEngineData(engine))
254
engine->close_connection(session);
260
don't bother to rollback here, it's done already
262
void StorageEngine::closeConnection(Session* session)
264
for_each(vector_of_engines.begin(), vector_of_engines.end(),
265
StorageEngineCloseConnection(session));
268
bool StorageEngine::flushLogs(StorageEngine *engine)
272
if (find_if(vector_of_engines.begin(), vector_of_engines.end(),
273
mem_fun(&StorageEngine::flush_logs))
274
!= vector_of_engines.begin())
279
if (engine->flush_logs())
285
class StorageEngineGetTableDefinition: public unary_function<StorageEngine *,bool>
288
const TableIdentifier &identifier;
289
message::Table &table_message;
293
StorageEngineGetTableDefinition(Session& session_arg,
294
const TableIdentifier &identifier_arg,
295
message::Table &table_message_arg,
297
session(session_arg),
298
identifier(identifier_arg),
299
table_message(table_message_arg),
302
result_type operator() (argument_type engine)
304
int ret= engine->doGetTableDefinition(session, identifier, table_message);
309
return err == EEXIST || err != ENOENT;
313
class StorageEngineDoesTableExist: public unary_function<StorageEngine *, bool>
316
const TableIdentifier &identifier;
319
StorageEngineDoesTableExist(Session& session_arg, const TableIdentifier &identifier_arg) :
320
session(session_arg),
321
identifier(identifier_arg)
324
result_type operator() (argument_type engine)
326
return engine->doDoesTableExist(session, identifier);
331
Utility method which hides some of the details of getTableDefinition()
333
bool plugin::StorageEngine::doesTableExist(Session &session,
334
const TableIdentifier &identifier,
335
bool include_temporary_tables)
337
if (include_temporary_tables)
339
if (session.doDoesTableExist(identifier))
343
EngineVector::iterator iter=
344
find_if(vector_of_engines.begin(), vector_of_engines.end(),
345
StorageEngineDoesTableExist(session, identifier));
347
if (iter == vector_of_engines.end())
355
bool plugin::StorageEngine::doDoesTableExist(Session&, const drizzled::TableIdentifier&)
357
cerr << " Engine was called for doDoesTableExist() and does not implement it: " << this->getName() << "\n";
363
Call this function in order to give the Cursor the possiblity
364
to ask engine if there are any new tables that should be written to disk
365
or any dropped tables that need to be removed from disk
367
int StorageEngine::getTableDefinition(Session& session,
368
const TableIdentifier &identifier,
369
message::Table &table_message,
370
bool include_temporary_tables)
374
if (include_temporary_tables)
376
if (session.doGetTableDefinition(identifier, table_message) == EEXIST)
380
EngineVector::iterator iter=
381
find_if(vector_of_engines.begin(), vector_of_engines.end(),
382
StorageEngineGetTableDefinition(session, identifier, table_message, err));
384
if (iter == vector_of_engines.end())
393
An interceptor to hijack the text of the error message without
394
setting an error in the thread. We need the text to present it
395
in the form of a warning to the user.
398
class Ha_delete_table_error_handler: public Internal_error_handler
401
Ha_delete_table_error_handler() : Internal_error_handler() {}
402
virtual bool handle_error(uint32_t sql_errno,
404
DRIZZLE_ERROR::enum_warning_level level,
406
char buff[DRIZZLE_ERRMSG_SIZE];
411
Ha_delete_table_error_handler::
412
handle_error(uint32_t ,
414
DRIZZLE_ERROR::enum_warning_level ,
417
/* Grab the error message */
418
strncpy(buff, message, sizeof(buff)-1);
423
returns ENOENT if the file doesn't exists.
425
int StorageEngine::dropTable(Session& session,
426
const TableIdentifier &identifier)
430
message::Table src_proto;
431
StorageEngine *engine;
433
error_proto= StorageEngine::getTableDefinition(session, identifier, src_proto);
435
if (error_proto == ER_CORRUPT_TABLE_DEFINITION)
437
string error_message;
439
error_message.append(const_cast<TableIdentifier &>(identifier).getSQLPath());
440
error_message.append(" : ");
441
error_message.append(src_proto.InitializationErrorString());
443
my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0), error_message.c_str());
445
return ER_CORRUPT_TABLE_DEFINITION;
448
engine= StorageEngine::findByName(session, src_proto.engine().name());
452
my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0), const_cast<TableIdentifier &>(identifier).getSQLPath().c_str());
454
return ER_CORRUPT_TABLE_DEFINITION;
457
error= StorageEngine::dropTable(session, *engine, identifier);
459
if (error_proto && error == 0)
465
int StorageEngine::dropTable(Session& session,
466
StorageEngine &engine,
467
const TableIdentifier &identifier)
471
engine.setTransactionReadWrite(session);
473
if (unlikely(plugin::EventObserver::beforeDropTable(session, identifier)))
475
error= ER_EVENT_OBSERVER_PLUGIN;
479
error= engine.doDropTable(session, identifier);
480
if (unlikely(plugin::EventObserver::afterDropTable(session, identifier, error)))
482
error= ER_EVENT_OBSERVER_PLUGIN;
492
Initiates table-file and calls appropriate database-creator.
499
int StorageEngine::createTable(Session &session,
500
const TableIdentifier &identifier,
501
message::Table& table_message)
505
TableShare share(identifier);
506
message::Table tmp_proto;
508
if (share.parse_table_proto(session, table_message) || share.open_table_from_share(&session, identifier, "", 0, 0, table))
510
// @note Error occured, we should probably do a little more here.
514
/* Check for legal operations against the Engine using the proto (if used) */
515
if (table_message.type() == message::Table::TEMPORARY &&
516
share.storage_engine->check_flag(HTON_BIT_TEMPORARY_NOT_SUPPORTED) == true)
518
error= HA_ERR_UNSUPPORTED;
520
else if (table_message.type() != message::Table::TEMPORARY &&
521
share.storage_engine->check_flag(HTON_BIT_TEMPORARY_ONLY) == true)
523
error= HA_ERR_UNSUPPORTED;
527
share.storage_engine->setTransactionReadWrite(session);
529
error= share.storage_engine->doCreateTable(session,
537
my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), const_cast<TableIdentifier &>(identifier).getSQLPath().c_str(), error);
540
table.delete_table();
546
Cursor *StorageEngine::getCursor(TableShare &share)
548
return create(share);
551
class AddTableIdentifier :
552
public unary_function<StorageEngine *, void>
554
CachedDirectory &directory;
555
const SchemaIdentifier &identifier;
556
TableIdentifiers &set_of_identifiers;
560
AddTableIdentifier(CachedDirectory &directory_arg, const SchemaIdentifier &identifier_arg, TableIdentifiers &of_names) :
561
directory(directory_arg),
562
identifier(identifier_arg),
563
set_of_identifiers(of_names)
567
result_type operator() (argument_type engine)
569
engine->doGetTableIdentifiers(directory, identifier, set_of_identifiers);
574
void StorageEngine::getIdentifiers(Session &session, const SchemaIdentifier &schema_identifier, TableIdentifiers &set_of_identifiers)
576
static SchemaIdentifier INFORMATION_SCHEMA_IDENTIFIER("information_schema");
577
static SchemaIdentifier DATA_DICTIONARY_IDENTIFIER("data_dictionary");
579
CachedDirectory directory(schema_identifier.getPath(), set_of_table_definition_ext);
581
if (schema_identifier == INFORMATION_SCHEMA_IDENTIFIER)
583
else if (schema_identifier == DATA_DICTIONARY_IDENTIFIER)
587
if (directory.fail())
589
errno= directory.getError();
591
my_error(ER_BAD_DB_ERROR, MYF(ME_BELL+ME_WAITTANG), const_cast<SchemaIdentifier &>(schema_identifier).getSQLPath().c_str());
593
my_error(ER_CANT_READ_DIR, MYF(ME_BELL+ME_WAITTANG), directory.getPath(), errno);
598
for_each(vector_of_engines.begin(), vector_of_engines.end(),
599
AddTableIdentifier(directory, schema_identifier, set_of_identifiers));
601
session.doGetTableIdentifiers(directory, schema_identifier, set_of_identifiers);
604
class DropTable: public unary_function<TableIdentifier&, bool>
607
StorageEngine *engine;
611
DropTable(Session &session_arg, StorageEngine *engine_arg) :
612
session(session_arg),
616
result_type operator() (argument_type identifier)
618
return engine->doDropTable(session, identifier) == 0;
622
/* This will later be converted to TableIdentifiers */
623
class DropTables: public unary_function<StorageEngine *, void>
626
TableIdentifiers &table_identifiers;
630
DropTables(Session &session_arg, TableIdentifiers &table_identifiers_arg) :
631
session(session_arg),
632
table_identifiers(table_identifiers_arg)
635
result_type operator() (argument_type engine)
637
// True returning from DropTable means the table has been successfully
638
// deleted, so it should be removed from the list of tables to drop
639
table_identifiers.erase(remove_if(table_identifiers.begin(),
640
table_identifiers.end(),
641
DropTable(session, engine)),
642
table_identifiers.end());
647
This only works for engines which use file based DFE.
649
Note-> Unlike MySQL, we do not, on purpose, delete files that do not match any engines.
651
void StorageEngine::removeLostTemporaryTables(Session &session, const char *directory)
653
CachedDirectory dir(directory, set_of_table_definition_ext);
654
TableIdentifiers table_identifiers;
658
errno= dir.getError();
659
my_error(ER_CANT_READ_DIR, MYF(0), directory, errno);
664
CachedDirectory::Entries files= dir.getEntries();
666
for (CachedDirectory::Entries::iterator fileIter= files.begin();
667
fileIter != files.end(); fileIter++)
671
CachedDirectory::Entry *entry= *fileIter;
673
/* We remove the file extension. */
674
length= entry->filename.length();
675
entry->filename.resize(length - DEFAULT_DEFINITION_FILE_EXT.length());
679
path+= entry->filename;
680
message::Table definition;
681
if (StorageEngine::readTableFile(path, definition))
683
TableIdentifier identifier(definition.schema(), definition.name(), path);
684
table_identifiers.push_back(identifier);
688
for_each(vector_of_engines.begin(), vector_of_engines.end(),
689
DropTables(session, table_identifiers));
692
Now we just clean up anything that might left over.
694
We rescan because some of what might have been there should
695
now be all nice and cleaned up.
697
set<string> all_exts= set_of_table_definition_ext;
699
for (EngineVector::iterator iter= vector_of_engines.begin();
700
iter != vector_of_engines.end() ; iter++)
702
for (const char **ext= (*iter)->bas_ext(); *ext ; ext++)
703
all_exts.insert(*ext);
706
CachedDirectory rescan(directory, all_exts);
708
files= rescan.getEntries();
709
for (CachedDirectory::Entries::iterator fileIter= files.begin();
710
fileIter != files.end(); fileIter++)
713
CachedDirectory::Entry *entry= *fileIter;
717
path+= entry->filename;
719
unlink(path.c_str());
725
Print error that we got from Cursor function.
728
In case of delete table it's only safe to use the following parts of
729
the 'table' structure:
730
- table->getShare()->path
733
void StorageEngine::print_error(int error, myf errflag, Table &table)
735
print_error(error, errflag, &table);
738
void StorageEngine::print_error(int error, myf errflag, Table *table)
740
int textno= ER_GET_ERRNO;
743
textno=ER_OPEN_AS_READONLY;
749
textno=ER_FILE_NOT_FOUND;
751
case HA_ERR_KEY_NOT_FOUND:
752
case HA_ERR_NO_ACTIVE_RECORD:
753
case HA_ERR_END_OF_FILE:
754
textno=ER_KEY_NOT_FOUND;
756
case HA_ERR_WRONG_MRG_TABLE_DEF:
757
textno=ER_WRONG_MRG_TABLE;
759
case HA_ERR_FOUND_DUPP_KEY:
762
uint32_t key_nr= table->get_dup_key(error);
763
if ((int) key_nr >= 0)
765
const char *err_msg= ER(ER_DUP_ENTRY_WITH_KEY_NAME);
767
print_keydup_error(key_nr, err_msg, *table);
774
case HA_ERR_FOREIGN_DUPLICATE_KEY:
777
uint32_t key_nr= table->get_dup_key(error);
778
if ((int) key_nr >= 0)
782
/* Write the key in the error message */
783
char key[MAX_KEY_LENGTH];
784
String str(key,sizeof(key),system_charset_info);
786
/* Table is opened and defined at this point */
787
key_unpack(&str,table,(uint32_t) key_nr);
788
max_length= (DRIZZLE_ERRMSG_SIZE-
789
(uint32_t) strlen(ER(ER_FOREIGN_DUPLICATE_KEY)));
790
if (str.length() >= max_length)
792
str.length(max_length-4);
793
str.append(STRING_WITH_LEN("..."));
795
my_error(ER_FOREIGN_DUPLICATE_KEY, MYF(0), table->getShare()->getTableName(),
796
str.c_ptr(), key_nr+1);
802
case HA_ERR_FOUND_DUPP_UNIQUE:
803
textno=ER_DUP_UNIQUE;
805
case HA_ERR_RECORD_CHANGED:
809
textno=ER_NOT_KEYFILE;
811
case HA_ERR_WRONG_IN_RECORD:
812
textno= ER_CRASHED_ON_USAGE;
814
case HA_ERR_CRASHED_ON_USAGE:
815
textno=ER_CRASHED_ON_USAGE;
817
case HA_ERR_NOT_A_TABLE:
820
case HA_ERR_CRASHED_ON_REPAIR:
821
textno=ER_CRASHED_ON_REPAIR;
823
case HA_ERR_OUT_OF_MEM:
824
textno=ER_OUT_OF_RESOURCES;
826
case HA_ERR_WRONG_COMMAND:
827
textno=ER_ILLEGAL_HA;
829
case HA_ERR_OLD_FILE:
830
textno=ER_OLD_KEYFILE;
832
case HA_ERR_UNSUPPORTED:
833
textno=ER_UNSUPPORTED_EXTENSION;
835
case HA_ERR_RECORD_FILE_FULL:
836
case HA_ERR_INDEX_FILE_FULL:
837
textno=ER_RECORD_FILE_FULL;
839
case HA_ERR_LOCK_WAIT_TIMEOUT:
840
textno=ER_LOCK_WAIT_TIMEOUT;
842
case HA_ERR_LOCK_TABLE_FULL:
843
textno=ER_LOCK_TABLE_FULL;
845
case HA_ERR_LOCK_DEADLOCK:
846
textno=ER_LOCK_DEADLOCK;
848
case HA_ERR_READ_ONLY_TRANSACTION:
849
textno=ER_READ_ONLY_TRANSACTION;
851
case HA_ERR_CANNOT_ADD_FOREIGN:
852
textno=ER_CANNOT_ADD_FOREIGN;
854
case HA_ERR_ROW_IS_REFERENCED:
857
get_error_message(error, &str);
858
my_error(ER_ROW_IS_REFERENCED_2, MYF(0), str.c_ptr_safe());
861
case HA_ERR_NO_REFERENCED_ROW:
864
get_error_message(error, &str);
865
my_error(ER_NO_REFERENCED_ROW_2, MYF(0), str.c_ptr_safe());
868
case HA_ERR_TABLE_DEF_CHANGED:
869
textno=ER_TABLE_DEF_CHANGED;
871
case HA_ERR_NO_SUCH_TABLE:
873
my_error(ER_NO_SUCH_TABLE, MYF(0), table->getShare()->getSchemaName(),
874
table->getShare()->getTableName());
876
case HA_ERR_RBR_LOGGING_FAILED:
877
textno= ER_BINLOG_ROW_LOGGING_FAILED;
879
case HA_ERR_DROP_INDEX_FK:
882
const char *ptr= "???";
883
uint32_t key_nr= table->get_dup_key(error);
884
if ((int) key_nr >= 0)
885
ptr= table->key_info[key_nr].name;
886
my_error(ER_DROP_INDEX_FK, MYF(0), ptr);
889
case HA_ERR_TABLE_NEEDS_UPGRADE:
890
textno=ER_TABLE_NEEDS_UPGRADE;
892
case HA_ERR_TABLE_READONLY:
893
textno= ER_OPEN_AS_READONLY;
895
case HA_ERR_AUTOINC_READ_FAILED:
896
textno= ER_AUTOINC_READ_FAILED;
898
case HA_ERR_AUTOINC_ERANGE:
899
textno= ER_WARN_DATA_OUT_OF_RANGE;
901
case HA_ERR_LOCK_OR_ACTIVE_TRANSACTION:
902
my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
903
ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
908
The error was "unknown" to this function.
909
Ask Cursor if it has got a message for this error
911
bool temporary= false;
913
temporary= get_error_message(error, &str);
916
const char* engine_name= getName().c_str();
918
my_error(ER_GET_TEMPORARY_ERRMSG, MYF(0), error, str.ptr(),
921
my_error(ER_GET_ERRMSG, MYF(0), error, str.ptr(), engine_name);
925
my_error(ER_GET_ERRNO,errflag,error);
930
my_error(textno, errflag, table->getShare()->getTableName(), error);
935
Return an error message specific to this Cursor.
937
@param error error code previously returned by Cursor
938
@param buf pointer to String where to add error message
941
Returns true if this is a temporary error
943
bool StorageEngine::get_error_message(int , String* )
949
void StorageEngine::print_keydup_error(uint32_t key_nr, const char *msg, Table &table)
951
/* Write the duplicated key in the error message */
952
char key[MAX_KEY_LENGTH];
953
String str(key,sizeof(key),system_charset_info);
955
if (key_nr == MAX_KEY)
958
str.copy("", 0, system_charset_info);
959
my_printf_error(ER_DUP_ENTRY, msg, MYF(0), str.c_ptr(), "*UNKNOWN*");
963
/* Table is opened and defined at this point */
964
key_unpack(&str, &table, (uint32_t) key_nr);
965
uint32_t max_length=DRIZZLE_ERRMSG_SIZE-(uint32_t) strlen(msg);
966
if (str.length() >= max_length)
968
str.length(max_length-4);
969
str.append(STRING_WITH_LEN("..."));
971
my_printf_error(ER_DUP_ENTRY, msg,
972
MYF(0), str.c_ptr(), table.key_info[key_nr].name);
977
int StorageEngine::deleteDefinitionFromPath(const TableIdentifier &identifier)
979
string path(identifier.getPath());
981
path.append(DEFAULT_DEFINITION_FILE_EXT);
983
return internal::my_delete(path.c_str(), MYF(0));
986
int StorageEngine::renameDefinitionFromPath(const TableIdentifier &dest, const TableIdentifier &src)
988
message::Table table_message;
989
string src_path(src.getPath());
990
string dest_path(dest.getPath());
992
src_path.append(DEFAULT_DEFINITION_FILE_EXT);
993
dest_path.append(DEFAULT_DEFINITION_FILE_EXT);
995
bool was_read= StorageEngine::readTableFile(src_path.c_str(), table_message);
1002
dest.copyToTableMessage(table_message);
1004
int error= StorageEngine::writeDefinitionFromPath(dest, table_message);
1008
if (unlink(src_path.c_str()))
1009
perror(src_path.c_str());
1015
int StorageEngine::writeDefinitionFromPath(const TableIdentifier &identifier, message::Table &table_message)
1017
char definition_file_tmp[FN_REFLEN];
1018
string file_name(identifier.getPath());
1020
file_name.append(DEFAULT_DEFINITION_FILE_EXT);
1022
snprintf(definition_file_tmp, sizeof(definition_file_tmp), "%sXXXXXX", file_name.c_str());
1024
int fd= mkstemp(definition_file_tmp);
1028
perror(definition_file_tmp);
1032
google::protobuf::io::ZeroCopyOutputStream* output=
1033
new google::protobuf::io::FileOutputStream(fd);
1038
success= table_message.SerializeToZeroCopyStream(output);
1047
my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
1048
table_message.InitializationErrorString().c_str());
1051
if (close(fd) == -1)
1052
perror(definition_file_tmp);
1054
if (unlink(definition_file_tmp) == -1)
1055
perror(definition_file_tmp);
1057
return ER_CORRUPT_TABLE_DEFINITION;
1062
if (close(fd) == -1)
1065
perror(definition_file_tmp);
1067
if (unlink(definition_file_tmp))
1068
perror(definition_file_tmp);
1073
if (rename(definition_file_tmp, file_name.c_str()) == -1)
1076
perror(definition_file_tmp);
1078
if (unlink(definition_file_tmp))
1079
perror(definition_file_tmp);
1087
class CanCreateTable: public unary_function<StorageEngine *, bool>
1089
const TableIdentifier &identifier;
1092
CanCreateTable(const TableIdentifier &identifier_arg) :
1093
identifier(identifier_arg)
1096
result_type operator() (argument_type engine)
1098
return not engine->doCanCreateTable(identifier);
1104
@note on success table can be created.
1106
bool StorageEngine::canCreateTable(const TableIdentifier &identifier)
1108
EngineVector::iterator iter=
1109
find_if(vector_of_engines.begin(), vector_of_engines.end(),
1110
CanCreateTable(identifier));
1112
if (iter == vector_of_engines.end())
1120
bool StorageEngine::readTableFile(const std::string &path, message::Table &table_message)
1122
fstream input(path.c_str(), ios::in | ios::binary);
1127
if (table_message.ParseFromIstream(&input))
1134
my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
1135
table_message.InitializationErrorString().empty() ? "": table_message.InitializationErrorString().c_str());
1140
perror(path.c_str());
1148
} /* namespace plugin */
1149
} /* namespace drizzled */