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
31
#include <google/protobuf/io/zero_copy_stream.h>
32
#include <google/protobuf/io/zero_copy_stream_impl.h>
34
#include "drizzled/my_hash.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/plugin/authorization.h"
51
#include "drizzled/charset.h"
52
#include "drizzled/internal/my_sys.h"
53
#include "drizzled/db.h"
55
#include <drizzled/table_proto.h>
57
static bool shutdown_has_begun= false; // Once we put in the container for the vector/etc for engines this will go away.
67
static EngineVector vector_of_engines;
68
static EngineVector vector_of_schema_engines;
70
const std::string UNKNOWN_STRING("UNKNOWN");
71
const std::string DEFAULT_DEFINITION_FILE_EXT(".dfe");
73
static std::set<std::string> set_of_table_definition_ext;
75
StorageEngine::StorageEngine(const string name_arg,
76
const bitset<HTON_BIT_SIZE> &flags_arg)
77
: Plugin(name_arg, "StorageEngine"),
78
MonitoredInTransaction(), /* This gives the storage engine a "slot" or ID */
81
pthread_mutex_init(&proto_cache_mutex, NULL);
84
StorageEngine::~StorageEngine()
86
pthread_mutex_destroy(&proto_cache_mutex);
89
void StorageEngine::setTransactionReadWrite(Session& session)
91
TransactionContext &statement_ctx= session.transaction.stmt;
92
statement_ctx.markModifiedNonTransData();
95
int StorageEngine::doRenameTable(Session *,
100
for (const char **ext= bas_ext(); *ext ; ext++)
102
if (rename_file_ext(from, to, *ext))
104
if ((error=errno) != ENOENT)
114
Delete all files with extension from bas_ext().
116
@param name Base name of table
119
We assume that the Cursor may return more extensions than
120
was actually used for the file.
123
0 If we successfully deleted at least one file from base_ext and
124
didn't get any other errors than ENOENT
128
int StorageEngine::doDropTable(Session&,
129
const string &table_path)
132
int enoent_or_zero= ENOENT; // Error if no file was deleted
133
char buff[FN_REFLEN];
135
for (const char **ext= bas_ext(); *ext ; ext++)
137
internal::fn_format(buff, table_path.c_str(), "", *ext,
138
MY_UNPACK_FILENAME|MY_APPEND_EXT);
139
if (internal::my_delete_with_symlink(buff, MYF(0)))
141
if ((error= errno) != ENOENT)
145
enoent_or_zero= 0; // No error for ENOENT
146
error= enoent_or_zero;
151
const char *StorageEngine::checkLowercaseNames(const char *path,
154
if (flags.test(HTON_BIT_FILE_BASED))
157
/* Ensure that table Cursor get path in lower case */
158
if (tmp_path != path)
159
strcpy(tmp_path, path);
162
we only should turn into lowercase database/table part
163
so start the process after homedirectory
165
if (strstr(tmp_path, drizzle_tmpdir) == tmp_path)
166
my_casedn_str(files_charset_info, tmp_path + strlen(drizzle_tmpdir));
168
my_casedn_str(files_charset_info, tmp_path + drizzle_data_home_len);
174
bool StorageEngine::addPlugin(StorageEngine *engine)
177
vector_of_engines.push_back(engine);
179
if (engine->getTableDefinitionFileExtension().length())
181
assert(engine->getTableDefinitionFileExtension().length() == DEFAULT_DEFINITION_FILE_EXT.length());
182
set_of_table_definition_ext.insert(engine->getTableDefinitionFileExtension());
185
if (engine->check_flag(HTON_BIT_SCHEMA_DICTIONARY))
186
vector_of_schema_engines.push_back(engine);
191
void StorageEngine::removePlugin(StorageEngine *)
193
if (shutdown_has_begun == false)
195
vector_of_engines.clear();
196
vector_of_schema_engines.clear();
198
shutdown_has_begun= true;
202
class FindEngineByName
203
: public unary_function<StorageEngine *, bool>
207
explicit FindEngineByName(const string target_arg)
210
result_type operator() (argument_type engine)
212
string engine_name(engine->getName());
214
transform(engine_name.begin(), engine_name.end(),
215
engine_name.begin(), ::tolower);
216
return engine_name == target;
220
StorageEngine *StorageEngine::findByName(string find_str)
222
transform(find_str.begin(), find_str.end(),
223
find_str.begin(), ::tolower);
226
EngineVector::iterator iter= find_if(vector_of_engines.begin(),
227
vector_of_engines.end(),
228
FindEngineByName(find_str));
229
if (iter != vector_of_engines.end())
231
StorageEngine *engine= *iter;
232
if (engine->is_user_selectable())
239
StorageEngine *StorageEngine::findByName(Session& session,
243
transform(find_str.begin(), find_str.end(),
244
find_str.begin(), ::tolower);
246
if (find_str.compare("default") == 0)
247
return session.getDefaultStorageEngine();
249
EngineVector::iterator iter= find_if(vector_of_engines.begin(),
250
vector_of_engines.end(),
251
FindEngineByName(find_str));
252
if (iter != vector_of_engines.end())
254
StorageEngine *engine= *iter;
255
if (engine->is_user_selectable())
262
class StorageEngineCloseConnection
263
: public unary_function<StorageEngine *, void>
267
StorageEngineCloseConnection(Session *session_arg) : session(session_arg) {}
269
there's no need to rollback here as all transactions must
270
be rolled back already
272
inline result_type operator() (argument_type engine)
274
if (*session->getEngineData(engine))
275
engine->close_connection(session);
281
don't bother to rollback here, it's done already
283
void StorageEngine::closeConnection(Session* session)
285
for_each(vector_of_engines.begin(), vector_of_engines.end(),
286
StorageEngineCloseConnection(session));
289
bool StorageEngine::flushLogs(StorageEngine *engine)
293
if (find_if(vector_of_engines.begin(), vector_of_engines.end(),
294
mem_fun(&StorageEngine::flush_logs))
295
!= vector_of_engines.begin())
300
if (engine->flush_logs())
306
class StorageEngineGetTableDefinition: public unary_function<StorageEngine *,bool>
311
const char *table_name;
313
message::Table *table_message;
317
StorageEngineGetTableDefinition(Session& session_arg,
318
const char* path_arg,
320
const char *table_name_arg,
321
const bool is_tmp_arg,
322
message::Table *table_message_arg,
324
session(session_arg),
327
table_name(table_name_arg),
329
table_message(table_message_arg),
332
result_type operator() (argument_type engine)
334
int ret= engine->doGetTableDefinition(session,
344
return *err == EEXIST || *err != ENOENT;
349
Utility method which hides some of the details of getTableDefinition()
351
bool plugin::StorageEngine::doesTableExist(Session& session,
352
TableIdentifier &identifier,
353
bool include_temporary_tables)
355
return (plugin::StorageEngine::getTableDefinition(session, identifier, NULL, include_temporary_tables) == EEXIST);
359
Call this function in order to give the Cursor the possiblity
360
to ask engine if there are any new tables that should be written to disk
361
or any dropped tables that need to be removed from disk
363
int StorageEngine::getTableDefinition(Session& session,
364
TableIdentifier &identifier,
365
message::Table *table_message,
366
bool include_temporary_tables)
368
return getTableDefinition(session,
369
identifier.getPath(), identifier.getDBName(), identifier.getTableName(), identifier.isTmp(),
370
table_message, include_temporary_tables);
373
int StorageEngine::getTableDefinition(Session& session,
375
const char *schema_name,
376
const char *table_name,
378
message::Table *table_message,
379
bool include_temporary_tables)
383
if (include_temporary_tables)
385
if (session.doGetTableDefinition(path, schema_name, table_name, false, table_message) == EEXIST)
389
EngineVector::iterator iter=
390
find_if(vector_of_engines.begin(), vector_of_engines.end(),
391
StorageEngineGetTableDefinition(session, path, NULL, NULL, true, table_message, &err));
393
if (iter == vector_of_engines.end())
402
An interceptor to hijack the text of the error message without
403
setting an error in the thread. We need the text to present it
404
in the form of a warning to the user.
407
class Ha_delete_table_error_handler: public Internal_error_handler
410
Ha_delete_table_error_handler() : Internal_error_handler() {}
411
virtual bool handle_error(uint32_t sql_errno,
413
DRIZZLE_ERROR::enum_warning_level level,
415
char buff[DRIZZLE_ERRMSG_SIZE];
420
Ha_delete_table_error_handler::
421
handle_error(uint32_t ,
423
DRIZZLE_ERROR::enum_warning_level ,
426
/* Grab the error message */
427
strncpy(buff, message, sizeof(buff)-1);
432
public unary_function<StorageEngine *, void>
434
uint64_t &success_count;
435
TableIdentifier &identifier;
440
DropTable(Session &session_arg, TableIdentifier &arg, uint64_t &count_arg) :
441
success_count(count_arg),
447
result_type operator() (argument_type engine)
449
// @todo someday check that at least one engine said "true"
450
std::string path(identifier.getPath());
451
bool success= engine->doDropTable(session, path);
460
returns ENOENT if the file doesn't exists.
462
int StorageEngine::dropTable(Session& session,
463
TableIdentifier &identifier)
467
message::Table src_proto;
468
StorageEngine* engine;
470
error_proto= StorageEngine::getTableDefinition(session,
474
if (error_proto == ER_CORRUPT_TABLE_DEFINITION)
476
my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
477
src_proto.InitializationErrorString().c_str());
478
return ER_CORRUPT_TABLE_DEFINITION;
481
engine= StorageEngine::findByName(session, src_proto.engine().name());
485
std::string path(identifier.getPath());
486
engine->setTransactionReadWrite(session);
487
error= engine->doDropTable(session, path);
491
if (not engine->check_flag(HTON_BIT_HAS_DATA_DICTIONARY))
493
uint64_t counter; // @todo We need to refactor to check that.
495
for_each(vector_of_schema_engines.begin(), vector_of_schema_engines.end(),
496
DropTable(session, identifier, counter));
501
if (error_proto && error == 0)
508
Initiates table-file and calls appropriate database-creator.
515
@todo refactor to remove goto
517
int StorageEngine::createTable(Session& session,
518
TableIdentifier &identifier,
519
bool update_create_info,
520
message::Table& table_message)
524
TableShare share(identifier.getDBName(), 0, identifier.getTableName(), identifier.getPath());
525
message::Table tmp_proto;
527
if (parse_table_proto(session, table_message, &share))
530
if (open_table_from_share(&session, &share, "", 0, 0,
534
if (update_create_info)
535
table.updateCreateInfo(&table_message);
537
/* Check for legal operations against the Engine using the proto (if used) */
538
if (table_message.type() == message::Table::TEMPORARY &&
539
share.storage_engine->check_flag(HTON_BIT_TEMPORARY_NOT_SUPPORTED) == true)
541
error= HA_ERR_UNSUPPORTED;
544
else if (table_message.type() != message::Table::TEMPORARY &&
545
share.storage_engine->check_flag(HTON_BIT_TEMPORARY_ONLY) == true)
547
error= HA_ERR_UNSUPPORTED;
552
char name_buff[FN_REFLEN];
553
const char *table_name_arg;
555
table_name_arg= share.storage_engine->checkLowercaseNames(identifier.getPath(), name_buff);
557
if (not share.storage_engine->check_flag(HTON_BIT_HAS_DATA_DICTIONARY))
559
int protoerr= StorageEngine::writeDefinitionFromPath(identifier, table_message);
568
share.storage_engine->setTransactionReadWrite(session);
570
error= share.storage_engine->doCreateTable(&session,
579
if (not share.storage_engine->check_flag(HTON_BIT_HAS_DATA_DICTIONARY))
580
plugin::StorageEngine::deleteDefinitionFromPath(identifier);
582
my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), identifier.getSQLPath().c_str(), error);
585
table.closefrm(false);
588
share.free_table_share();
592
Cursor *StorageEngine::getCursor(TableShare &share, memory::Root *alloc)
594
return create(share, alloc);
598
TODO -> Remove this to force all engines to implement their own file. Solves the "we only looked at dfe" problem.
600
void StorageEngine::doGetTableNames(CachedDirectory&, string&, set<string>&)
604
public unary_function<StorageEngine *, void>
607
CachedDirectory& directory;
608
TableNameList &set_of_names;
612
AddTableName(CachedDirectory& directory_arg, const string& database_name, set<string>& of_names) :
613
directory(directory_arg),
614
set_of_names(of_names)
619
result_type operator() (argument_type engine)
621
engine->doGetTableNames(directory, db, set_of_names);
625
class AddSchemaNames :
626
public unary_function<StorageEngine *, void>
628
SchemaNameList &set_of_names;
632
AddSchemaNames(set<string>& of_names) :
633
set_of_names(of_names)
637
result_type operator() (argument_type engine)
639
engine->doGetSchemaNames(set_of_names);
643
void StorageEngine::getSchemaNames(SchemaNameList &set_of_names)
645
// Add hook here for engines to register schema.
646
for_each(vector_of_schema_engines.begin(), vector_of_schema_engines.end(),
647
AddSchemaNames(set_of_names));
649
plugin::Authorization::pruneSchemaNames(current_session->getSecurityContext(),
653
class StorageEngineGetSchemaDefinition: public unary_function<StorageEngine *, bool>
655
const std::string &schema_name;
656
message::Schema &schema_proto;
659
StorageEngineGetSchemaDefinition(const std::string &schema_name_arg,
660
message::Schema &schema_proto_arg) :
661
schema_name(schema_name_arg),
662
schema_proto(schema_proto_arg)
665
result_type operator() (argument_type engine)
667
return engine->doGetSchemaDefinition(schema_name, schema_proto);
672
Return value is "if parsed"
674
bool StorageEngine::getSchemaDefinition(const std::string &schema_name, message::Schema &proto)
678
EngineVector::iterator iter=
679
find_if(vector_of_schema_engines.begin(), vector_of_schema_engines.end(),
680
StorageEngineGetSchemaDefinition(schema_name, proto));
682
if (iter != vector_of_schema_engines.end())
690
bool StorageEngine::doesSchemaExist(const std::string &schema_name)
692
message::Schema proto;
694
return StorageEngine::getSchemaDefinition(schema_name, proto);
698
const CHARSET_INFO *StorageEngine::getSchemaCollation(const std::string &schema_name)
700
message::Schema schmema_proto;
703
found= StorageEngine::getSchemaDefinition(schema_name, schmema_proto);
705
if (found && schmema_proto.has_collation())
707
const string buffer= schmema_proto.collation();
708
const CHARSET_INFO* cs= get_charset_by_name(buffer.c_str());
712
errmsg_printf(ERRMSG_LVL_ERROR,
713
_("Error while loading database options: '%s':"), schema_name.c_str());
714
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_UNKNOWN_COLLATION), buffer.c_str());
716
return default_charset_info;
722
return default_charset_info;
726
public unary_function<StorageEngine *, void>
728
const drizzled::message::Schema &schema_message;
732
CreateSchema(const drizzled::message::Schema &arg) :
737
result_type operator() (argument_type engine)
739
// @todo eomeday check that at least one engine said "true"
740
(void)engine->doCreateSchema(schema_message);
744
bool StorageEngine::createSchema(const drizzled::message::Schema &schema_message)
746
// Add hook here for engines to register schema.
747
for_each(vector_of_schema_engines.begin(), vector_of_schema_engines.end(),
748
CreateSchema(schema_message));
754
public unary_function<StorageEngine *, void>
756
uint64_t &success_count;
757
const string &schema_name;
761
DropSchema(const string &arg, uint64_t &count_arg) :
762
success_count(count_arg),
767
result_type operator() (argument_type engine)
769
// @todo someday check that at least one engine said "true"
770
bool success= engine->doDropSchema(schema_name);
777
bool StorageEngine::dropSchema(const string &schema_name)
780
// Add hook here for engines to register schema.
781
for_each(vector_of_schema_engines.begin(), vector_of_schema_engines.end(),
782
DropSchema(schema_name, counter));
784
return counter ? true : false;
788
public unary_function<StorageEngine *, void>
790
uint64_t &success_count;
791
const drizzled::message::Schema &schema_message;
795
AlterSchema(const drizzled::message::Schema &arg, uint64_t &count_arg) :
796
success_count(count_arg),
801
result_type operator() (argument_type engine)
803
// @todo eomeday check that at least one engine said "true"
804
bool success= engine->doAlterSchema(schema_message);
811
bool StorageEngine::alterSchema(const drizzled::message::Schema &schema_message)
813
uint64_t success_count= 0;
815
for_each(vector_of_schema_engines.begin(), vector_of_schema_engines.end(),
816
AlterSchema(schema_message, success_count));
818
return success_count ? true : false;
822
void StorageEngine::getTableNames(const string &schema_name, TableNameList &set_of_names)
824
char tmp_path[FN_REFLEN];
826
build_table_filename(tmp_path, sizeof(tmp_path), schema_name.c_str(), "", false);
828
CachedDirectory directory(tmp_path, set_of_table_definition_ext);
830
if (not schema_name.compare("information_schema"))
832
else if (not schema_name.compare("data_dictionary"))
836
if (directory.fail())
838
errno= directory.getError();
840
my_error(ER_BAD_DB_ERROR, MYF(ME_BELL+ME_WAITTANG), schema_name.c_str());
842
my_error(ER_CANT_READ_DIR, MYF(ME_BELL+ME_WAITTANG), directory.getPath(), errno);
847
for_each(vector_of_engines.begin(), vector_of_engines.end(),
848
AddTableName(directory, schema_name, set_of_names));
850
Session *session= current_session;
852
session->doGetTableNames(directory, schema_name, set_of_names);
856
/* This will later be converted to TableIdentifiers */
857
class DropTables: public unary_function<StorageEngine *, void>
860
TableNameList &set_of_names;
864
DropTables(Session &session_arg, set<string>& of_names) :
865
session(session_arg),
866
set_of_names(of_names)
869
result_type operator() (argument_type engine)
872
for (TableNameList::iterator iter= set_of_names.begin();
873
iter != set_of_names.end();
876
int error= engine->doDropTable(session, *iter);
878
// On a return of zero we know we found and deleted the table. So we
879
// remove it from our search.
881
set_of_names.erase(iter);
887
This only works for engines which use file based DFE.
889
Note-> Unlike MySQL, we do not, on purpose, delete files that do not match any engines.
891
void StorageEngine::removeLostTemporaryTables(Session &session, const char *directory)
893
CachedDirectory dir(directory, set_of_table_definition_ext);
894
set<string> set_of_table_names;
898
errno= dir.getError();
899
my_error(ER_CANT_READ_DIR, MYF(0), directory, errno);
904
CachedDirectory::Entries files= dir.getEntries();
906
for (CachedDirectory::Entries::iterator fileIter= files.begin();
907
fileIter != files.end(); fileIter++)
911
CachedDirectory::Entry *entry= *fileIter;
913
/* We remove the file extension. */
914
length= entry->filename.length();
915
entry->filename.resize(length - DEFAULT_DEFINITION_FILE_EXT.length());
919
path+= entry->filename;
920
set_of_table_names.insert(path);
923
for_each(vector_of_engines.begin(), vector_of_engines.end(),
924
DropTables(session, set_of_table_names));
927
Now we just clean up anything that might left over.
929
We rescan because some of what might have been there should
930
now be all nice and cleaned up.
932
set<string> all_exts= set_of_table_definition_ext;
934
for (EngineVector::iterator iter= vector_of_engines.begin();
935
iter != vector_of_engines.end() ; iter++)
937
for (const char **ext= (*iter)->bas_ext(); *ext ; ext++)
938
all_exts.insert(*ext);
941
CachedDirectory rescan(directory, all_exts);
943
files= rescan.getEntries();
944
for (CachedDirectory::Entries::iterator fileIter= files.begin();
945
fileIter != files.end(); fileIter++)
948
CachedDirectory::Entry *entry= *fileIter;
952
path+= entry->filename;
954
unlink(path.c_str());
960
Print error that we got from Cursor function.
963
In case of delete table it's only safe to use the following parts of
964
the 'table' structure:
968
void StorageEngine::print_error(int error, myf errflag, Table &table)
970
print_error(error, errflag, &table);
973
void StorageEngine::print_error(int error, myf errflag, Table *table)
975
int textno= ER_GET_ERRNO;
978
textno=ER_OPEN_AS_READONLY;
984
textno=ER_FILE_NOT_FOUND;
986
case HA_ERR_KEY_NOT_FOUND:
987
case HA_ERR_NO_ACTIVE_RECORD:
988
case HA_ERR_END_OF_FILE:
989
textno=ER_KEY_NOT_FOUND;
991
case HA_ERR_WRONG_MRG_TABLE_DEF:
992
textno=ER_WRONG_MRG_TABLE;
994
case HA_ERR_FOUND_DUPP_KEY:
997
uint32_t key_nr= table->get_dup_key(error);
998
if ((int) key_nr >= 0)
1000
const char *err_msg= ER(ER_DUP_ENTRY_WITH_KEY_NAME);
1003
(table->key_info[0].key_part[0].field->flags &
1004
AUTO_INCREMENT_FLAG)
1005
&& (current_session)->lex->sql_command == SQLCOM_ALTER_TABLE)
1007
err_msg= ER(ER_DUP_ENTRY_AUTOINCREMENT_CASE);
1010
print_keydup_error(key_nr, err_msg, *table);
1016
case HA_ERR_FOREIGN_DUPLICATE_KEY:
1019
uint32_t key_nr= table->get_dup_key(error);
1020
if ((int) key_nr >= 0)
1022
uint32_t max_length;
1024
/* Write the key in the error message */
1025
char key[MAX_KEY_LENGTH];
1026
String str(key,sizeof(key),system_charset_info);
1028
/* Table is opened and defined at this point */
1029
key_unpack(&str,table,(uint32_t) key_nr);
1030
max_length= (DRIZZLE_ERRMSG_SIZE-
1031
(uint32_t) strlen(ER(ER_FOREIGN_DUPLICATE_KEY)));
1032
if (str.length() >= max_length)
1034
str.length(max_length-4);
1035
str.append(STRING_WITH_LEN("..."));
1037
my_error(ER_FOREIGN_DUPLICATE_KEY, MYF(0), table->s->table_name.str,
1038
str.c_ptr(), key_nr+1);
1044
case HA_ERR_FOUND_DUPP_UNIQUE:
1045
textno=ER_DUP_UNIQUE;
1047
case HA_ERR_RECORD_CHANGED:
1048
textno=ER_CHECKREAD;
1050
case HA_ERR_CRASHED:
1051
textno=ER_NOT_KEYFILE;
1053
case HA_ERR_WRONG_IN_RECORD:
1054
textno= ER_CRASHED_ON_USAGE;
1056
case HA_ERR_CRASHED_ON_USAGE:
1057
textno=ER_CRASHED_ON_USAGE;
1059
case HA_ERR_NOT_A_TABLE:
1062
case HA_ERR_CRASHED_ON_REPAIR:
1063
textno=ER_CRASHED_ON_REPAIR;
1065
case HA_ERR_OUT_OF_MEM:
1066
textno=ER_OUT_OF_RESOURCES;
1068
case HA_ERR_WRONG_COMMAND:
1069
textno=ER_ILLEGAL_HA;
1071
case HA_ERR_OLD_FILE:
1072
textno=ER_OLD_KEYFILE;
1074
case HA_ERR_UNSUPPORTED:
1075
textno=ER_UNSUPPORTED_EXTENSION;
1077
case HA_ERR_RECORD_FILE_FULL:
1078
case HA_ERR_INDEX_FILE_FULL:
1079
textno=ER_RECORD_FILE_FULL;
1081
case HA_ERR_LOCK_WAIT_TIMEOUT:
1082
textno=ER_LOCK_WAIT_TIMEOUT;
1084
case HA_ERR_LOCK_TABLE_FULL:
1085
textno=ER_LOCK_TABLE_FULL;
1087
case HA_ERR_LOCK_DEADLOCK:
1088
textno=ER_LOCK_DEADLOCK;
1090
case HA_ERR_READ_ONLY_TRANSACTION:
1091
textno=ER_READ_ONLY_TRANSACTION;
1093
case HA_ERR_CANNOT_ADD_FOREIGN:
1094
textno=ER_CANNOT_ADD_FOREIGN;
1096
case HA_ERR_ROW_IS_REFERENCED:
1099
get_error_message(error, &str);
1100
my_error(ER_ROW_IS_REFERENCED_2, MYF(0), str.c_ptr_safe());
1103
case HA_ERR_NO_REFERENCED_ROW:
1106
get_error_message(error, &str);
1107
my_error(ER_NO_REFERENCED_ROW_2, MYF(0), str.c_ptr_safe());
1110
case HA_ERR_TABLE_DEF_CHANGED:
1111
textno=ER_TABLE_DEF_CHANGED;
1113
case HA_ERR_NO_SUCH_TABLE:
1115
my_error(ER_NO_SUCH_TABLE, MYF(0), table->s->getSchemaName(),
1116
table->s->table_name.str);
1118
case HA_ERR_RBR_LOGGING_FAILED:
1119
textno= ER_BINLOG_ROW_LOGGING_FAILED;
1121
case HA_ERR_DROP_INDEX_FK:
1124
const char *ptr= "???";
1125
uint32_t key_nr= table->get_dup_key(error);
1126
if ((int) key_nr >= 0)
1127
ptr= table->key_info[key_nr].name;
1128
my_error(ER_DROP_INDEX_FK, MYF(0), ptr);
1131
case HA_ERR_TABLE_NEEDS_UPGRADE:
1132
textno=ER_TABLE_NEEDS_UPGRADE;
1134
case HA_ERR_TABLE_READONLY:
1135
textno= ER_OPEN_AS_READONLY;
1137
case HA_ERR_AUTOINC_READ_FAILED:
1138
textno= ER_AUTOINC_READ_FAILED;
1140
case HA_ERR_AUTOINC_ERANGE:
1141
textno= ER_WARN_DATA_OUT_OF_RANGE;
1143
case HA_ERR_LOCK_OR_ACTIVE_TRANSACTION:
1144
my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
1145
ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
1150
The error was "unknown" to this function.
1151
Ask Cursor if it has got a message for this error
1153
bool temporary= false;
1155
temporary= get_error_message(error, &str);
1156
if (!str.is_empty())
1158
const char* engine_name= getName().c_str();
1160
my_error(ER_GET_TEMPORARY_ERRMSG, MYF(0), error, str.ptr(),
1163
my_error(ER_GET_ERRMSG, MYF(0), error, str.ptr(), engine_name);
1167
my_error(ER_GET_ERRNO,errflag,error);
1172
my_error(textno, errflag, table->s->table_name.str, error);
1177
Return an error message specific to this Cursor.
1179
@param error error code previously returned by Cursor
1180
@param buf pointer to String where to add error message
1183
Returns true if this is a temporary error
1185
bool StorageEngine::get_error_message(int , String* )
1191
void StorageEngine::print_keydup_error(uint32_t key_nr, const char *msg, Table &table)
1193
/* Write the duplicated key in the error message */
1194
char key[MAX_KEY_LENGTH];
1195
String str(key,sizeof(key),system_charset_info);
1197
if (key_nr == MAX_KEY)
1199
/* Key is unknown */
1200
str.copy("", 0, system_charset_info);
1201
my_printf_error(ER_DUP_ENTRY, msg, MYF(0), str.c_ptr(), "*UNKNOWN*");
1205
/* Table is opened and defined at this point */
1206
key_unpack(&str, &table, (uint32_t) key_nr);
1207
uint32_t max_length=DRIZZLE_ERRMSG_SIZE-(uint32_t) strlen(msg);
1208
if (str.length() >= max_length)
1210
str.length(max_length-4);
1211
str.append(STRING_WITH_LEN("..."));
1213
my_printf_error(ER_DUP_ENTRY, msg,
1214
MYF(0), str.c_ptr(), table.key_info[key_nr].name);
1219
int StorageEngine::deleteDefinitionFromPath(TableIdentifier &identifier)
1221
string path(identifier.getPath());
1223
path.append(DEFAULT_DEFINITION_FILE_EXT);
1225
return internal::my_delete(path.c_str(), MYF(0));
1228
int StorageEngine::renameDefinitionFromPath(TableIdentifier &dest, TableIdentifier &src)
1230
string src_path(src.getPath());
1231
string dest_path(dest.getPath());
1233
src_path.append(DEFAULT_DEFINITION_FILE_EXT);
1234
dest_path.append(DEFAULT_DEFINITION_FILE_EXT);
1236
return internal::my_rename(src_path.c_str(), dest_path.c_str(), MYF(MY_WME));
1239
int StorageEngine::writeDefinitionFromPath(TableIdentifier &identifier, message::Table &table_message)
1241
string file_name(identifier.getPath());
1243
file_name.append(DEFAULT_DEFINITION_FILE_EXT);
1245
int fd= open(file_name.c_str(), O_RDWR|O_CREAT|O_TRUNC, internal::my_umask);
1250
google::protobuf::io::ZeroCopyOutputStream* output=
1251
new google::protobuf::io::FileOutputStream(fd);
1253
if (table_message.SerializeToZeroCopyStream(output) == false)
1265
class CanCreateTable: public unary_function<StorageEngine *, bool>
1267
const TableIdentifier &identifier;
1270
CanCreateTable(const TableIdentifier &identifier_arg) :
1271
identifier(identifier_arg)
1274
result_type operator() (argument_type engine)
1276
return not engine->doCanCreateTable(identifier);
1282
@note on success table can be created.
1284
bool StorageEngine::canCreateTable(drizzled::TableIdentifier &identifier)
1286
EngineVector::iterator iter=
1287
find_if(vector_of_engines.begin(), vector_of_engines.end(),
1288
CanCreateTable(identifier));
1290
if (iter == vector_of_engines.end())
1298
} /* namespace plugin */
1299
} /* namespace drizzled */