75
73
static std::set<std::string> set_of_table_definition_ext;
77
75
StorageEngine::StorageEngine(const string name_arg,
78
const bitset<HTON_BIT_SIZE> &flags_arg) :
79
Plugin(name_arg, "StorageEngine"),
80
MonitoredInTransaction(), /* This gives the storage engine a "slot" or ID */
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);
85
84
StorageEngine::~StorageEngine()
86
pthread_mutex_destroy(&proto_cache_mutex);
89
89
void StorageEngine::setTransactionReadWrite(Session& session)
92
92
statement_ctx.markModifiedNonTransData();
96
int StorageEngine::renameTable(Session &session, TableIdentifier &from, TableIdentifier &to)
95
int StorageEngine::doRenameTable(Session *,
98
setTransactionReadWrite(session);
100
return doRenameTable(session, from, to);
100
for (const char **ext= bas_ext(); *ext ; ext++)
102
if (rename_file_ext(from, to, *ext))
104
if ((error=errno) != ENOENT)
104
114
Delete all files with extension from bas_ext().
125
135
for (const char **ext= bas_ext(); *ext ; ext++)
127
internal::fn_format(buff, identifier.getPath().c_str(), "", *ext,
128
MY_UNPACK_FILENAME|MY_APPEND_EXT);
137
internal::fn_format(buff, table_path.c_str(), "", *ext,
138
MY_UNPACK_FILENAME|MY_APPEND_EXT);
129
139
if (internal::my_delete_with_symlink(buff, MYF(0)))
131
141
if ((error= errno) != ENOENT)
136
145
enoent_or_zero= 0; // No error for ENOENT
139
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);
144
174
bool StorageEngine::addPlugin(StorageEngine *engine)
196
StorageEngine *StorageEngine::findByName(const string &find_str)
220
StorageEngine *StorageEngine::findByName(string find_str)
198
string search_string(find_str);
199
transform(search_string.begin(), search_string.end(),
200
search_string.begin(), ::tolower);
222
transform(find_str.begin(), find_str.end(),
223
find_str.begin(), ::tolower);
203
226
EngineVector::iterator iter= find_if(vector_of_engines.begin(),
204
227
vector_of_engines.end(),
205
FindEngineByName(search_string));
228
FindEngineByName(find_str));
206
229
if (iter != vector_of_engines.end())
208
231
StorageEngine *engine= *iter;
216
StorageEngine *StorageEngine::findByName(Session& session, const string &find_str)
239
StorageEngine *StorageEngine::findByName(Session& session,
218
string search_string(find_str);
219
transform(search_string.begin(), search_string.end(),
220
search_string.begin(), ::tolower);
243
transform(find_str.begin(), find_str.end(),
244
find_str.begin(), ::tolower);
222
if (search_string.compare("default") == 0)
246
if (find_str.compare("default") == 0)
223
247
return session.getDefaultStorageEngine();
225
249
EngineVector::iterator iter= find_if(vector_of_engines.begin(),
226
250
vector_of_engines.end(),
227
FindEngineByName(search_string));
251
FindEngineByName(find_str));
228
252
if (iter != vector_of_engines.end())
230
254
StorageEngine *engine= *iter;
281
306
class StorageEngineGetTableDefinition: public unary_function<StorageEngine *,bool>
283
308
Session& session;
284
TableIdentifier &identifier;
285
message::Table &table_message;
311
const char *table_name;
313
message::Table *table_message;
289
317
StorageEngineGetTableDefinition(Session& session_arg,
290
TableIdentifier &identifier_arg,
291
message::Table &table_message_arg,
318
const char* path_arg,
320
const char *table_name_arg,
321
const bool is_tmp_arg,
322
message::Table *table_message_arg,
293
324
session(session_arg),
294
identifier(identifier_arg),
327
table_name(table_name_arg),
295
329
table_message(table_message_arg),
298
332
result_type operator() (argument_type engine)
300
int ret= engine->doGetTableDefinition(session, identifier, table_message);
334
int ret= engine->doGetTableDefinition(session,
302
341
if (ret != ENOENT)
305
return err == EEXIST || err != ENOENT;
309
class StorageEngineDoesTableExist: public unary_function<StorageEngine *, bool>
312
TableIdentifier &identifier;
315
StorageEngineDoesTableExist(Session& session_arg, TableIdentifier &identifier_arg) :
316
session(session_arg),
317
identifier(identifier_arg)
320
result_type operator() (argument_type engine)
322
return engine->doDoesTableExist(session, identifier);
344
return *err == EEXIST || *err != ENOENT;
327
349
Utility method which hides some of the details of getTableDefinition()
329
bool plugin::StorageEngine::doesTableExist(Session &session,
351
bool plugin::StorageEngine::doesTableExist(Session& session,
330
352
TableIdentifier &identifier,
331
353
bool include_temporary_tables)
333
if (include_temporary_tables)
335
if (session.doDoesTableExist(identifier))
339
EngineVector::iterator iter=
340
find_if(vector_of_data_dictionary.begin(), vector_of_data_dictionary.end(),
341
StorageEngineDoesTableExist(session, identifier));
343
if (iter == vector_of_data_dictionary.end())
351
bool plugin::StorageEngine::doDoesTableExist(Session&, TableIdentifier&)
353
cerr << " Engine was called for doDoesTableExist() and does not implement it: " << this->getName() << "\n";
355
return (plugin::StorageEngine::getTableDefinition(session, identifier, NULL, include_temporary_tables) == EEXIST);
363
363
int StorageEngine::getTableDefinition(Session& session,
364
364
TableIdentifier &identifier,
365
message::Table &table_message,
365
message::Table *table_message,
366
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)
370
383
if (include_temporary_tables)
372
if (session.doGetTableDefinition(identifier, table_message) == EEXIST)
385
if (session.doGetTableDefinition(path, schema_name, table_name, false, table_message) == EEXIST)
376
389
EngineVector::iterator iter=
377
390
find_if(vector_of_engines.begin(), vector_of_engines.end(),
378
StorageEngineGetTableDefinition(session, identifier, table_message, err));
391
StorageEngineGetTableDefinition(session, path, NULL, NULL, true, table_message, &err));
380
393
if (iter == vector_of_engines.end())
452
467
message::Table src_proto;
453
StorageEngine *engine;
468
StorageEngine* engine;
455
error_proto= StorageEngine::getTableDefinition(session, identifier, src_proto);
470
error_proto= StorageEngine::getTableDefinition(session,
457
474
if (error_proto == ER_CORRUPT_TABLE_DEFINITION)
459
string error_message;
461
error_message.append(identifier.getSQLPath());
462
error_message.append(" : ");
463
error_message.append(src_proto.InitializationErrorString());
465
my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0), error_message.c_str());
476
my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
477
src_proto.InitializationErrorString().c_str());
467
478
return ER_CORRUPT_TABLE_DEFINITION;
474
error= StorageEngine::dropTable(session, *engine, identifier);
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));
477
501
if (error_proto && error == 0)
483
int StorageEngine::dropTable(Session& session,
484
StorageEngine &engine,
485
TableIdentifier &identifier)
489
engine.setTransactionReadWrite(session);
490
error= engine.doDropTable(session, identifier);
494
if (not engine.check_flag(HTON_BIT_HAS_DATA_DICTIONARY))
496
uint64_t counter; // @todo We need to refactor to check that.
498
for_each(vector_of_schema_engines.begin(), vector_of_schema_engines.end(),
499
DropTable(session, identifier, counter));
507
508
Initiates table-file and calls appropriate database-creator.
515
@todo refactor to remove goto
514
int StorageEngine::createTable(Session &session,
517
int StorageEngine::createTable(Session& session,
515
518
TableIdentifier &identifier,
516
519
bool update_create_info,
517
520
message::Table& table_message)
521
TableShare share(identifier.getDBName().c_str(), 0, identifier.getTableName().c_str(), identifier.getPath().c_str());
524
TableShare share(identifier.getDBName(), 0, identifier.getTableName(), identifier.getPath());
522
525
message::Table tmp_proto;
524
if (parse_table_proto(session, table_message, &share) || open_table_from_share(&session, &share, "", 0, 0, &table))
526
// @note Error occured, we should probably do a little more here.
530
if (update_create_info)
531
table.updateCreateInfo(&table_message);
533
/* Check for legal operations against the Engine using the proto (if used) */
534
if (table_message.type() == message::Table::TEMPORARY &&
535
share.storage_engine->check_flag(HTON_BIT_TEMPORARY_NOT_SUPPORTED) == true)
537
error= HA_ERR_UNSUPPORTED;
539
else if (table_message.type() != message::Table::TEMPORARY &&
540
share.storage_engine->check_flag(HTON_BIT_TEMPORARY_ONLY) == true)
542
error= HA_ERR_UNSUPPORTED;
546
bool do_create= true;
547
if (not share.storage_engine->check_flag(HTON_BIT_HAS_DATA_DICTIONARY))
549
int protoerr= StorageEngine::writeDefinitionFromPath(identifier, table_message);
560
share.storage_engine->setTransactionReadWrite(session);
562
error= share.storage_engine->doCreateTable(&session,
571
if (not share.storage_engine->check_flag(HTON_BIT_HAS_DATA_DICTIONARY))
572
plugin::StorageEngine::deleteDefinitionFromPath(identifier);
574
my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), identifier.getSQLPath().c_str(), error);
577
table.closefrm(false);
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);
580
588
share.free_table_share();
581
589
return(error != 0);
645
653
class StorageEngineGetSchemaDefinition: public unary_function<StorageEngine *, bool>
647
std::string schema_name;
655
const std::string &schema_name;
648
656
message::Schema &schema_proto;
651
StorageEngineGetSchemaDefinition(const std::string schema_name_arg,
659
StorageEngineGetSchemaDefinition(const std::string &schema_name_arg,
652
660
message::Schema &schema_proto_arg) :
653
661
schema_name(schema_name_arg),
654
662
schema_proto(schema_proto_arg)
656
transform(schema_name.begin(), schema_name.end(),
657
schema_name.begin(), ::tolower);
660
665
result_type operator() (argument_type engine)
864
857
class DropTables: public unary_function<StorageEngine *, void>
866
859
Session &session;
867
TableIdentifierList &table_identifiers;
860
TableNameList &set_of_names;
871
DropTables(Session &session_arg, TableIdentifierList &table_identifiers_arg) :
864
DropTables(Session &session_arg, set<string>& of_names) :
872
865
session(session_arg),
873
table_identifiers(table_identifiers_arg)
866
set_of_names(of_names)
876
869
result_type operator() (argument_type engine)
878
for (TableIdentifierList::iterator iter= table_identifiers.begin();
879
iter != table_identifiers.end();
872
for (TableNameList::iterator iter= set_of_names.begin();
873
iter != set_of_names.end();
882
int error= engine->doDropTable(session, const_cast<TableIdentifier&>(*iter));
876
int error= engine->doDropTable(session, *iter);
884
878
// On a return of zero we know we found and deleted the table. So we
885
879
// remove it from our search.
887
table_identifiers.erase(iter);
881
set_of_names.erase(iter);
923
917
path+= directory;
924
918
path+= FN_LIBCHAR;
925
919
path+= entry->filename;
926
message::Table definition;
927
if (StorageEngine::readTableFile(path, definition))
929
TableIdentifier identifier(definition.schema(), definition.name(), path);
930
table_identifiers.push_back(identifier);
920
set_of_table_names.insert(path);
934
923
for_each(vector_of_engines.begin(), vector_of_engines.end(),
935
DropTables(session, table_identifiers));
924
DropTables(session, set_of_table_names));
938
927
Now we just clean up anything that might left over.
1239
1228
int StorageEngine::renameDefinitionFromPath(TableIdentifier &dest, TableIdentifier &src)
1241
message::Table table_message;
1242
1230
string src_path(src.getPath());
1243
1231
string dest_path(dest.getPath());
1245
1233
src_path.append(DEFAULT_DEFINITION_FILE_EXT);
1246
1234
dest_path.append(DEFAULT_DEFINITION_FILE_EXT);
1248
bool was_read= StorageEngine::readTableFile(src_path.c_str(), table_message);
1255
dest.copyToTableMessage(table_message);
1257
int error= StorageEngine::writeDefinitionFromPath(dest, table_message);
1261
if (unlink(src_path.c_str()))
1262
perror(src_path.c_str());
1236
return internal::my_rename(src_path.c_str(), dest_path.c_str(), MYF(MY_WME));
1268
1239
int StorageEngine::writeDefinitionFromPath(TableIdentifier &identifier, message::Table &table_message)
1270
char definition_file_tmp[FN_REFLEN];
1271
1241
string file_name(identifier.getPath());
1273
1243
file_name.append(DEFAULT_DEFINITION_FILE_EXT);
1275
snprintf(definition_file_tmp, sizeof(definition_file_tmp), "%s.%sXXXXXX", file_name.c_str(), DEFAULT_DEFINITION_FILE_EXT.c_str());
1277
int fd= mkstemp(definition_file_tmp);
1245
int fd= open(file_name.c_str(), O_RDWR|O_CREAT|O_TRUNC, internal::my_umask);
1281
perror(definition_file_tmp);
1285
1250
google::protobuf::io::ZeroCopyOutputStream* output=
1286
1251
new google::protobuf::io::FileOutputStream(fd);
1288
if (not table_message.SerializeToZeroCopyStream(output))
1253
if (table_message.SerializeToZeroCopyStream(output) == false)
1290
my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
1291
table_message.InitializationErrorString().c_str());
1294
if (close(fd) == -1)
1295
perror(definition_file_tmp);
1297
if (unlink(definition_file_tmp) == -1)
1298
perror(definition_file_tmp);
1300
return ER_CORRUPT_TABLE_DEFINITION;
1305
if (close(fd) == -1)
1308
perror(definition_file_tmp);
1310
if (unlink(definition_file_tmp))
1311
perror(definition_file_tmp);
1316
if (rename(definition_file_tmp, file_name.c_str()) == -1)
1319
perror(definition_file_tmp);
1321
if (unlink(definition_file_tmp))
1322
perror(definition_file_tmp);