~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/plugin/storage_engine.cc

  • Committer: Siddharth Prakash Singh
  • Date: 2010-03-26 17:24:57 UTC
  • mto: This revision was merged to the branch mainline in revision 1425.
  • Revision ID: spsneo@spsneo-laptop-20100326172457-vni09y22ktvvefmn
some more sprintf --> snprintf

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
#include <string>
26
26
#include <vector>
27
27
#include <set>
28
 
#include <fstream>
29
28
#include <algorithm>
30
29
#include <functional>
31
30
 
32
31
#include <google/protobuf/io/zero_copy_stream.h>
33
32
#include <google/protobuf/io/zero_copy_stream_impl.h>
34
33
 
 
34
#include "drizzled/my_hash.h"
35
35
#include "drizzled/cached_directory.h"
36
36
 
37
37
#include <drizzled/definitions.h>
47
47
#include "drizzled/xid.h"
48
48
#include "drizzled/sql_table.h"
49
49
#include "drizzled/global_charset_info.h"
 
50
#include "drizzled/plugin/authorization.h"
50
51
#include "drizzled/charset.h"
51
52
#include "drizzled/internal/my_sys.h"
52
53
#include "drizzled/db.h"
53
54
 
54
55
#include <drizzled/table_proto.h>
55
 
#include <drizzled/plugin/event_observer.h>
56
 
 
57
 
#include <drizzled/table/shell.h>
58
 
 
59
 
#include "drizzled/message/cache.h"
60
 
 
61
 
#include <boost/algorithm/string/compare.hpp>
62
56
 
63
57
static bool shutdown_has_begun= false; // Once we put in the container for the vector/etc for engines this will go away.
64
58
 
 
59
using namespace std;
 
60
 
65
61
namespace drizzled
66
62
{
67
63
 
70
66
 
71
67
static EngineVector vector_of_engines;
72
68
static EngineVector vector_of_schema_engines;
 
69
static EngineVector vector_of_data_dictionary;
73
70
 
74
 
const std::string DEFAULT_STRING("default");
75
71
const std::string UNKNOWN_STRING("UNKNOWN");
76
72
const std::string DEFAULT_DEFINITION_FILE_EXT(".dfe");
77
73
 
78
74
static std::set<std::string> set_of_table_definition_ext;
79
75
 
80
 
EngineVector &StorageEngine::getSchemaEngines()
81
 
{
82
 
  return vector_of_schema_engines;
83
 
}
84
 
 
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 */
89
 
  flags(flags_arg)
90
 
{
 
76
StorageEngine::StorageEngine(const string name_arg,
 
77
                             const bitset<HTON_BIT_SIZE> &flags_arg)
 
78
    : Plugin(name_arg, "StorageEngine"),
 
79
      MonitoredInTransaction(), /* This gives the storage engine a "slot" or ID */
 
80
      flags(flags_arg)
 
81
{
 
82
  pthread_mutex_init(&proto_cache_mutex, NULL);
91
83
}
92
84
 
93
85
StorageEngine::~StorageEngine()
94
86
{
 
87
  pthread_mutex_destroy(&proto_cache_mutex);
95
88
}
96
89
 
97
90
void StorageEngine::setTransactionReadWrite(Session& session)
100
93
  statement_ctx.markModifiedNonTransData();
101
94
}
102
95
 
103
 
 
104
 
int StorageEngine::renameTable(Session &session, const TableIdentifier &from, const TableIdentifier &to)
 
96
int StorageEngine::doRenameTable(Session *,
 
97
                                 const char *from,
 
98
                                 const char *to)
105
99
{
106
 
  int error;
107
 
  setTransactionReadWrite(session);
108
 
 
109
 
  if (unlikely(plugin::EventObserver::beforeRenameTable(session, from, to)))
110
 
  {
111
 
    error= ER_EVENT_OBSERVER_PLUGIN;
112
 
  }
113
 
  else
114
 
  {
115
 
    error =  doRenameTable(session, from, to);
116
 
    if (unlikely(plugin::EventObserver::afterRenameTable(session, from, to, error)))
 
100
  int error= 0;
 
101
  for (const char **ext= bas_ext(); *ext ; ext++)
 
102
  {
 
103
    if (rename_file_ext(from, to, *ext))
117
104
    {
118
 
      error= ER_EVENT_OBSERVER_PLUGIN;
 
105
      if ((error=errno) != ENOENT)
 
106
        break;
 
107
      error= 0;
119
108
    }
120
109
  }
121
 
  
122
110
  return error;
123
111
}
124
112
 
 
113
 
125
114
/**
126
115
  Delete all files with extension from bas_ext().
127
116
 
137
126
  @retval
138
127
    !0  Error
139
128
*/
140
 
int StorageEngine::doDropTable(Session&, const TableIdentifier &identifier)
 
129
int StorageEngine::doDropTable(Session&, TableIdentifier &identifier)
141
130
                               
142
131
{
143
132
  int error= 0;
151
140
    if (internal::my_delete_with_symlink(buff, MYF(0)))
152
141
    {
153
142
      if ((error= errno) != ENOENT)
154
 
        break;
 
143
        break;
155
144
    }
156
145
    else
157
 
    {
158
146
      enoent_or_zero= 0;                        // No error for ENOENT
159
 
    }
160
 
 
161
147
    error= enoent_or_zero;
162
148
  }
163
149
  return error;
177
163
  if (engine->check_flag(HTON_BIT_SCHEMA_DICTIONARY))
178
164
    vector_of_schema_engines.push_back(engine);
179
165
 
 
166
  if (engine->check_flag(HTON_BIT_HAS_DATA_DICTIONARY))
 
167
    vector_of_data_dictionary.push_back(engine);
 
168
 
180
169
  return false;
181
170
}
182
171
 
186
175
  {
187
176
    vector_of_engines.clear();
188
177
    vector_of_schema_engines.clear();
 
178
    vector_of_data_dictionary.clear();
189
179
 
190
180
    shutdown_has_begun= true;
191
181
  }
192
182
}
193
183
 
194
184
class FindEngineByName
195
 
  : public std::unary_function<StorageEngine *, bool>
 
185
  : public unary_function<StorageEngine *, bool>
196
186
{
197
 
  const std::string &predicate;
198
 
 
 
187
  const string target;
199
188
public:
200
 
  explicit FindEngineByName(const std::string &target_arg) :
201
 
    predicate(target_arg)
202
 
  {
203
 
  }
204
 
 
 
189
  explicit FindEngineByName(const string target_arg)
 
190
    : target(target_arg)
 
191
  {}
205
192
  result_type operator() (argument_type engine)
206
193
  {
207
 
    return boost::iequals(engine->getName(), predicate);
 
194
    string engine_name(engine->getName());
 
195
 
 
196
    transform(engine_name.begin(), engine_name.end(),
 
197
              engine_name.begin(), ::tolower);
 
198
    return engine_name == target;
208
199
  }
209
200
};
210
201
 
211
 
StorageEngine *StorageEngine::findByName(const std::string &predicate)
 
202
StorageEngine *StorageEngine::findByName(string find_str)
212
203
{
213
 
  EngineVector::iterator iter= std::find_if(vector_of_engines.begin(),
214
 
                                            vector_of_engines.end(),
215
 
                                            FindEngineByName(predicate));
 
204
  transform(find_str.begin(), find_str.end(),
 
205
            find_str.begin(), ::tolower);
 
206
 
 
207
  
 
208
  EngineVector::iterator iter= find_if(vector_of_engines.begin(),
 
209
                                       vector_of_engines.end(),
 
210
                                       FindEngineByName(find_str));
216
211
  if (iter != vector_of_engines.end())
217
212
  {
218
213
    StorageEngine *engine= *iter;
223
218
  return NULL;
224
219
}
225
220
 
226
 
StorageEngine *StorageEngine::findByName(Session& session, const std::string &predicate)
 
221
StorageEngine *StorageEngine::findByName(Session& session,
 
222
                                                         string find_str)
227
223
{
228
 
  if (boost::iequals(predicate, DEFAULT_STRING))
 
224
  
 
225
  transform(find_str.begin(), find_str.end(),
 
226
            find_str.begin(), ::tolower);
 
227
 
 
228
  if (find_str.compare("default") == 0)
229
229
    return session.getDefaultStorageEngine();
230
230
 
231
 
  EngineVector::iterator iter= std::find_if(vector_of_engines.begin(),
232
 
                                            vector_of_engines.end(),
233
 
                                            FindEngineByName(predicate));
 
231
  EngineVector::iterator iter= find_if(vector_of_engines.begin(),
 
232
                                       vector_of_engines.end(),
 
233
                                       FindEngineByName(find_str));
234
234
  if (iter != vector_of_engines.end())
235
235
  {
236
236
    StorageEngine *engine= *iter;
241
241
  return NULL;
242
242
}
243
243
 
244
 
class StorageEngineCloseConnection : public std::unary_function<StorageEngine *, void>
 
244
class StorageEngineCloseConnection
 
245
: public unary_function<StorageEngine *, void>
245
246
{
246
247
  Session *session;
247
248
public:
263
264
*/
264
265
void StorageEngine::closeConnection(Session* session)
265
266
{
266
 
  std::for_each(vector_of_engines.begin(), vector_of_engines.end(),
267
 
                StorageEngineCloseConnection(session));
 
267
  for_each(vector_of_engines.begin(), vector_of_engines.end(),
 
268
           StorageEngineCloseConnection(session));
268
269
}
269
270
 
270
271
bool StorageEngine::flushLogs(StorageEngine *engine)
271
272
{
272
273
  if (engine == NULL)
273
274
  {
274
 
    if (std::find_if(vector_of_engines.begin(), vector_of_engines.end(),
275
 
                     std::mem_fun(&StorageEngine::flush_logs))
 
275
    if (find_if(vector_of_engines.begin(), vector_of_engines.end(),
 
276
                mem_fun(&StorageEngine::flush_logs))
276
277
        != vector_of_engines.begin())
277
278
      return true;
278
279
  }
284
285
  return false;
285
286
}
286
287
 
287
 
class StorageEngineGetTableDefinition: public std::unary_function<StorageEngine *,bool>
 
288
class StorageEngineGetTableDefinition: public unary_function<StorageEngine *,bool>
288
289
{
289
290
  Session& session;
290
 
  const TableIdentifier &identifier;
 
291
  TableIdentifier &identifier;
291
292
  message::Table &table_message;
292
 
  int &err;
 
293
  int *err;
293
294
 
294
295
public:
295
296
  StorageEngineGetTableDefinition(Session& session_arg,
296
 
                                  const TableIdentifier &identifier_arg,
 
297
                                  TableIdentifier &identifier_arg,
297
298
                                  message::Table &table_message_arg,
298
 
                                  int &err_arg) :
 
299
                                  int *err_arg) :
299
300
    session(session_arg), 
300
301
    identifier(identifier_arg),
301
302
    table_message(table_message_arg), 
303
304
 
304
305
  result_type operator() (argument_type engine)
305
306
  {
306
 
    int ret= engine->doGetTableDefinition(session, identifier, table_message);
 
307
    int ret= engine->doGetTableDefinition(session,
 
308
                                          identifier,
 
309
                                          table_message);
307
310
 
308
311
    if (ret != ENOENT)
309
 
      err= ret;
 
312
      *err= ret;
310
313
 
311
 
    return err == EEXIST || err != ENOENT;
 
314
    return *err == EEXIST || *err != ENOENT;
312
315
  }
313
316
};
314
317
 
315
 
class StorageEngineDoesTableExist: public std::unary_function<StorageEngine *, bool>
 
318
class StorageEngineDoesTableExist: public unary_function<StorageEngine *, bool>
316
319
{
317
320
  Session& session;
318
 
  const TableIdentifier &identifier;
 
321
  TableIdentifier &identifier;
319
322
 
320
323
public:
321
 
  StorageEngineDoesTableExist(Session& session_arg, const TableIdentifier &identifier_arg) :
 
324
  StorageEngineDoesTableExist(Session& session_arg, TableIdentifier &identifier_arg) :
322
325
    session(session_arg), 
323
326
    identifier(identifier_arg) 
324
327
  { }
333
336
  Utility method which hides some of the details of getTableDefinition()
334
337
*/
335
338
bool plugin::StorageEngine::doesTableExist(Session &session,
336
 
                                           const TableIdentifier &identifier,
 
339
                                           TableIdentifier &identifier,
337
340
                                           bool include_temporary_tables)
338
341
{
339
342
  if (include_temporary_tables)
343
346
  }
344
347
 
345
348
  EngineVector::iterator iter=
346
 
    std::find_if(vector_of_engines.begin(), vector_of_engines.end(),
347
 
                 StorageEngineDoesTableExist(session, identifier));
 
349
    find_if(vector_of_data_dictionary.begin(), vector_of_data_dictionary.end(),
 
350
            StorageEngineDoesTableExist(session, identifier));
348
351
 
349
 
  if (iter == vector_of_engines.end())
 
352
  if (iter == vector_of_data_dictionary.end())
350
353
  {
351
354
    return false;
352
355
  }
354
357
  return true;
355
358
}
356
359
 
357
 
bool plugin::StorageEngine::doDoesTableExist(Session&, const drizzled::TableIdentifier&)
 
360
bool plugin::StorageEngine::doDoesTableExist(Session&, TableIdentifier&)
358
361
{
359
 
  std::cerr << " Engine was called for doDoesTableExist() and does not implement it: " << this->getName() << "\n";
 
362
  cerr << " Engine was called for doDoesTableExist() and does not implement it: " << this->getName() << "\n";
360
363
  assert(0);
361
364
  return false;
362
365
}
367
370
  or any dropped tables that need to be removed from disk
368
371
*/
369
372
int StorageEngine::getTableDefinition(Session& session,
370
 
                                      const TableIdentifier &identifier,
371
 
                                      message::table::shared_ptr &table_message,
 
373
                                      TableIdentifier &identifier,
 
374
                                      message::Table &table_message,
372
375
                                      bool include_temporary_tables)
373
376
{
374
377
  int err= ENOENT;
375
378
 
376
379
  if (include_temporary_tables)
377
380
  {
378
 
    Table *table= session.find_temporary_table(identifier);
379
 
    if (table)
380
 
    {
381
 
      table_message.reset(new message::Table(*table->getShare()->getTableProto()));
 
381
    if (session.doGetTableDefinition(identifier, table_message) == EEXIST)
382
382
      return EEXIST;
383
 
    }
384
 
  }
385
 
 
386
 
  drizzled::message::table::shared_ptr table_ptr;
387
 
  if ((table_ptr= drizzled::message::Cache::singleton().find(identifier)))
388
 
  {
389
 
    table_message= table_ptr;
390
 
  }
391
 
 
392
 
  message::Table message;
 
383
  }
 
384
 
393
385
  EngineVector::iterator iter=
394
 
    std::find_if(vector_of_engines.begin(), vector_of_engines.end(),
395
 
                 StorageEngineGetTableDefinition(session, identifier, message, err));
 
386
    find_if(vector_of_engines.begin(), vector_of_engines.end(),
 
387
            StorageEngineGetTableDefinition(session, identifier, table_message, &err));
396
388
 
397
389
  if (iter == vector_of_engines.end())
398
390
  {
399
391
    return ENOENT;
400
392
  }
401
 
  table_message.reset(new message::Table(message));
402
 
 
403
 
 drizzled::message::Cache::singleton().insert(identifier, table_message);
404
393
 
405
394
  return err;
406
395
}
435
424
  return true;
436
425
}
437
426
 
 
427
class DropTable : 
 
428
  public unary_function<StorageEngine *, void>
 
429
{
 
430
  uint64_t &success_count;
 
431
  TableIdentifier &identifier;
 
432
  Session &session;
 
433
 
 
434
public:
 
435
 
 
436
  DropTable(Session &session_arg, TableIdentifier &arg, uint64_t &count_arg) :
 
437
    success_count(count_arg),
 
438
    identifier(arg),
 
439
    session(session_arg)
 
440
  {
 
441
  }
 
442
 
 
443
  result_type operator() (argument_type engine)
 
444
  {
 
445
    // @todo someday check that at least one engine said "true"
 
446
    std::string path(identifier.getPath());
 
447
    bool success= engine->doDropTable(session, identifier, path);
 
448
 
 
449
    if (success)
 
450
      success_count++;
 
451
  }
 
452
};
 
453
 
 
454
 
438
455
/**
439
456
   returns ENOENT if the file doesn't exists.
440
457
*/
441
458
int StorageEngine::dropTable(Session& session,
442
 
                             const TableIdentifier &identifier)
 
459
                             TableIdentifier &identifier)
443
460
{
444
461
  int error= 0;
445
462
  int error_proto;
446
 
  message::table::shared_ptr src_proto;
447
 
  StorageEngine *engine;
 
463
  message::Table src_proto;
 
464
  StorageEngine* engine;
448
465
 
449
466
  error_proto= StorageEngine::getTableDefinition(session, identifier, src_proto);
450
467
 
451
468
  if (error_proto == ER_CORRUPT_TABLE_DEFINITION)
452
469
  {
453
 
    std::string error_message;
454
 
    identifier.getSQLPath(error_message);
455
 
 
456
 
    error_message.append(" : ");
457
 
    error_message.append(src_proto->InitializationErrorString());
458
 
 
459
 
    my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0), error_message.c_str());
460
 
 
 
470
    my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
 
471
             src_proto.InitializationErrorString().c_str());
461
472
    return ER_CORRUPT_TABLE_DEFINITION;
462
473
  }
463
474
 
464
 
  if (src_proto)
465
 
    engine= StorageEngine::findByName(session, src_proto->engine().name());
466
 
  else
467
 
    engine= StorageEngine::findByName(session, "");
 
475
  engine= StorageEngine::findByName(session, src_proto.engine().name());
468
476
 
469
 
  if (not engine)
 
477
  if (engine)
470
478
  {
471
 
    std::string error_message;
472
 
    identifier.getSQLPath(error_message);
473
 
    my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0), error_message.c_str());
474
 
 
475
 
    return ER_CORRUPT_TABLE_DEFINITION;
 
479
    std::string path(identifier.getPath());
 
480
    engine->setTransactionReadWrite(session);
 
481
    error= engine->doDropTable(session, identifier, path);
 
482
 
 
483
    if (not error)
 
484
    {
 
485
      if (not engine->check_flag(HTON_BIT_HAS_DATA_DICTIONARY))
 
486
      {
 
487
        uint64_t counter; // @todo We need to refactor to check that.
 
488
 
 
489
        for_each(vector_of_schema_engines.begin(), vector_of_schema_engines.end(),
 
490
                 DropTable(session, identifier, counter));
 
491
      }
 
492
    }
476
493
  }
477
494
 
478
 
  error= StorageEngine::dropTable(session, *engine, identifier);
479
 
 
480
495
  if (error_proto && error == 0)
481
496
    return 0;
482
497
 
483
498
  return error;
484
499
}
485
500
 
486
 
int StorageEngine::dropTable(Session& session,
487
 
                             StorageEngine &engine,
488
 
                             const TableIdentifier &identifier)
489
 
{
490
 
  int error;
491
 
 
492
 
  engine.setTransactionReadWrite(session);
493
 
  
494
 
  if (unlikely(plugin::EventObserver::beforeDropTable(session, identifier)))
495
 
  {
496
 
    error= ER_EVENT_OBSERVER_PLUGIN;
497
 
  }
498
 
  else
499
 
  {
500
 
    error= engine.doDropTable(session, identifier);
501
 
    if (unlikely(plugin::EventObserver::afterDropTable(session, identifier, error)))
502
 
    {
503
 
      error= ER_EVENT_OBSERVER_PLUGIN;
504
 
    }
505
 
  }
506
 
 
507
 
  drizzled::message::Cache::singleton().erase(identifier);
508
 
 
509
 
  return error;
510
 
}
511
 
 
512
 
 
513
501
/**
514
502
  Initiates table-file and calls appropriate database-creator.
515
503
 
517
505
   0  ok
518
506
  @retval
519
507
   1  error
 
508
 
 
509
   @todo refactor to remove goto
520
510
*/
521
 
int StorageEngine::createTable(Session &session,
522
 
                               const TableIdentifier &identifier,
 
511
int StorageEngine::createTable(Session& session,
 
512
                               TableIdentifier &identifier,
 
513
                               bool update_create_info,
523
514
                               message::Table& table_message)
524
515
{
525
516
  int error= 1;
526
 
  TableShare share(identifier);
527
 
  table::Shell table(share);
 
517
  Table table;
 
518
  TableShare share(identifier.getDBName().c_str(), 0, identifier.getTableName().c_str(), identifier.getPath().c_str());
528
519
  message::Table tmp_proto;
529
520
 
530
 
  if (share.parse_table_proto(session, table_message) || share.open_table_from_share(&session, identifier, "", 0, 0, table))
531
 
  { 
532
 
    // @note Error occured, we should probably do a little more here.
533
 
  }
534
 
  else
535
 
  {
536
 
    /* Check for legal operations against the Engine using the proto (if used) */
537
 
    if (table_message.type() == message::Table::TEMPORARY &&
538
 
        share.storage_engine->check_flag(HTON_BIT_TEMPORARY_NOT_SUPPORTED) == true)
539
 
    {
540
 
      error= HA_ERR_UNSUPPORTED;
541
 
    }
542
 
    else if (table_message.type() != message::Table::TEMPORARY &&
543
 
             share.storage_engine->check_flag(HTON_BIT_TEMPORARY_ONLY) == true)
544
 
    {
545
 
      error= HA_ERR_UNSUPPORTED;
546
 
    }
547
 
    else
548
 
    {
549
 
      share.storage_engine->setTransactionReadWrite(session);
550
 
 
551
 
      error= share.storage_engine->doCreateTable(session,
552
 
                                                 table,
553
 
                                                 identifier,
554
 
                                                 table_message);
555
 
    }
556
 
 
557
 
    if (error)
558
 
    {
559
 
      std::string path;
560
 
      identifier.getSQLPath(path);
561
 
      my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), path.c_str(), error);
562
 
    }
563
 
 
564
 
    table.delete_table();
565
 
  }
566
 
 
 
521
  if (parse_table_proto(session, table_message, &share))
 
522
    goto err;
 
523
 
 
524
  if (open_table_from_share(&session, &share, "", 0, 0,
 
525
                            &table))
 
526
    goto err;
 
527
 
 
528
  if (update_create_info)
 
529
    table.updateCreateInfo(&table_message);
 
530
 
 
531
  /* Check for legal operations against the Engine using the proto (if used) */
 
532
  if (table_message.type() == message::Table::TEMPORARY &&
 
533
      share.storage_engine->check_flag(HTON_BIT_TEMPORARY_NOT_SUPPORTED) == true)
 
534
  {
 
535
    error= HA_ERR_UNSUPPORTED;
 
536
    goto err2;
 
537
  }
 
538
  else if (table_message.type() != message::Table::TEMPORARY &&
 
539
           share.storage_engine->check_flag(HTON_BIT_TEMPORARY_ONLY) == true)
 
540
  {
 
541
    error= HA_ERR_UNSUPPORTED;
 
542
    goto err2;
 
543
  }
 
544
 
 
545
  {
 
546
    if (not share.storage_engine->check_flag(HTON_BIT_HAS_DATA_DICTIONARY))
 
547
    {
 
548
      int protoerr= StorageEngine::writeDefinitionFromPath(identifier, table_message);
 
549
 
 
550
      if (protoerr)
 
551
      {
 
552
        error= protoerr;
 
553
        goto err2;
 
554
      }
 
555
    }
 
556
 
 
557
    share.storage_engine->setTransactionReadWrite(session);
 
558
 
 
559
    error= share.storage_engine->doCreateTable(&session,
 
560
                                               table,
 
561
                                               identifier,
 
562
                                               table_message);
 
563
  }
 
564
 
 
565
err2:
 
566
  if (error)
 
567
  {
 
568
    if (not share.storage_engine->check_flag(HTON_BIT_HAS_DATA_DICTIONARY))
 
569
      plugin::StorageEngine::deleteDefinitionFromPath(identifier);
 
570
 
 
571
    my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), identifier.getSQLPath().c_str(), error);
 
572
  }
 
573
 
 
574
  table.closefrm(false);
 
575
 
 
576
err:
 
577
  share.free_table_share();
567
578
  return(error != 0);
568
579
}
569
580
 
570
 
Cursor *StorageEngine::getCursor(Table &arg)
 
581
Cursor *StorageEngine::getCursor(TableShare &share, memory::Root *alloc)
571
582
{
572
 
  return create(arg);
 
583
  return create(share, alloc);
573
584
}
574
585
 
575
 
class AddTableIdentifier : 
576
 
  public std::unary_function<StorageEngine *, void>
 
586
/**
 
587
  TODO -> Remove this to force all engines to implement their own file. Solves the "we only looked at dfe" problem.
 
588
*/
 
589
void StorageEngine::doGetTableNames(CachedDirectory&, string&, set<string>&)
 
590
{ }
 
591
 
 
592
class AddTableName : 
 
593
  public unary_function<StorageEngine *, void>
577
594
{
578
 
  CachedDirectory &directory;
579
 
  const SchemaIdentifier &identifier;
580
 
  TableIdentifier::vector &set_of_identifiers;
 
595
  string db;
 
596
  CachedDirectory& directory;
 
597
  TableNameList &set_of_names;
581
598
 
582
599
public:
583
600
 
584
 
  AddTableIdentifier(CachedDirectory &directory_arg, const SchemaIdentifier &identifier_arg, TableIdentifier::vector &of_names) :
 
601
  AddTableName(CachedDirectory& directory_arg, const string& database_name, set<string>& of_names) :
585
602
    directory(directory_arg),
586
 
    identifier(identifier_arg),
587
 
    set_of_identifiers(of_names)
588
 
  {
589
 
  }
590
 
 
591
 
  result_type operator() (argument_type engine)
592
 
  {
593
 
    engine->doGetTableIdentifiers(directory, identifier, set_of_identifiers);
594
 
  }
595
 
};
596
 
 
597
 
 
598
 
void StorageEngine::getIdentifiers(Session &session, const SchemaIdentifier &schema_identifier, TableIdentifier::vector &set_of_identifiers)
599
 
{
600
 
  static SchemaIdentifier INFORMATION_SCHEMA_IDENTIFIER("information_schema");
601
 
  static SchemaIdentifier DATA_DICTIONARY_IDENTIFIER("data_dictionary");
602
 
 
603
 
  CachedDirectory directory(schema_identifier.getPath(), set_of_table_definition_ext);
604
 
 
605
 
  if (schema_identifier == INFORMATION_SCHEMA_IDENTIFIER)
606
 
  { }
607
 
  else if (schema_identifier == DATA_DICTIONARY_IDENTIFIER)
 
603
    set_of_names(of_names)
 
604
  {
 
605
    db= database_name;
 
606
  }
 
607
 
 
608
  result_type operator() (argument_type engine)
 
609
  {
 
610
    engine->doGetTableNames(directory, db, set_of_names);
 
611
  }
 
612
};
 
613
 
 
614
class AddSchemaNames : 
 
615
  public unary_function<StorageEngine *, void>
 
616
{
 
617
  SchemaNameList &set_of_names;
 
618
 
 
619
public:
 
620
 
 
621
  AddSchemaNames(set<string>& of_names) :
 
622
    set_of_names(of_names)
 
623
  {
 
624
  }
 
625
 
 
626
  result_type operator() (argument_type engine)
 
627
  {
 
628
    engine->doGetSchemaNames(set_of_names);
 
629
  }
 
630
};
 
631
 
 
632
void StorageEngine::getSchemaNames(SchemaNameList &set_of_names)
 
633
{
 
634
  // Add hook here for engines to register schema.
 
635
  for_each(vector_of_schema_engines.begin(), vector_of_schema_engines.end(),
 
636
           AddSchemaNames(set_of_names));
 
637
 
 
638
  plugin::Authorization::pruneSchemaNames(current_session->getSecurityContext(),
 
639
                                          set_of_names);
 
640
}
 
641
 
 
642
class StorageEngineGetSchemaDefinition: public unary_function<StorageEngine *, bool>
 
643
{
 
644
  const std::string &schema_name;
 
645
  message::Schema &schema_proto;
 
646
 
 
647
public:
 
648
  StorageEngineGetSchemaDefinition(const std::string &schema_name_arg,
 
649
                                  message::Schema &schema_proto_arg) :
 
650
    schema_name(schema_name_arg),
 
651
    schema_proto(schema_proto_arg) 
 
652
  { }
 
653
 
 
654
  result_type operator() (argument_type engine)
 
655
  {
 
656
    return engine->doGetSchemaDefinition(schema_name, schema_proto);
 
657
  }
 
658
};
 
659
 
 
660
/*
 
661
  Return value is "if parsed"
 
662
*/
 
663
bool StorageEngine::getSchemaDefinition(const std::string &schema_name, message::Schema &proto)
 
664
{
 
665
  proto.Clear();
 
666
 
 
667
  EngineVector::iterator iter=
 
668
    find_if(vector_of_schema_engines.begin(), vector_of_schema_engines.end(),
 
669
            StorageEngineGetSchemaDefinition(schema_name, proto));
 
670
 
 
671
  if (iter != vector_of_schema_engines.end())
 
672
  {
 
673
    return true;
 
674
  }
 
675
 
 
676
  return false;
 
677
}
 
678
 
 
679
bool StorageEngine::doesSchemaExist(const std::string &schema_name)
 
680
{
 
681
  message::Schema proto;
 
682
 
 
683
  return StorageEngine::getSchemaDefinition(schema_name, proto);
 
684
}
 
685
 
 
686
 
 
687
const CHARSET_INFO *StorageEngine::getSchemaCollation(const std::string &schema_name)
 
688
{
 
689
  message::Schema schmema_proto;
 
690
  bool found;
 
691
 
 
692
  found= StorageEngine::getSchemaDefinition(schema_name, schmema_proto);
 
693
 
 
694
  if (found && schmema_proto.has_collation())
 
695
  {
 
696
    const string buffer= schmema_proto.collation();
 
697
    const CHARSET_INFO* cs= get_charset_by_name(buffer.c_str());
 
698
 
 
699
    if (not cs)
 
700
    {
 
701
      errmsg_printf(ERRMSG_LVL_ERROR,
 
702
                    _("Error while loading database options: '%s':"), schema_name.c_str());
 
703
      errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_UNKNOWN_COLLATION), buffer.c_str());
 
704
 
 
705
      return default_charset_info;
 
706
    }
 
707
 
 
708
    return cs;
 
709
  }
 
710
 
 
711
  return default_charset_info;
 
712
}
 
713
 
 
714
class CreateSchema : 
 
715
  public unary_function<StorageEngine *, void>
 
716
{
 
717
  const drizzled::message::Schema &schema_message;
 
718
 
 
719
public:
 
720
 
 
721
  CreateSchema(const drizzled::message::Schema &arg) :
 
722
    schema_message(arg)
 
723
  {
 
724
  }
 
725
 
 
726
  result_type operator() (argument_type engine)
 
727
  {
 
728
    // @todo eomeday check that at least one engine said "true"
 
729
    (void)engine->doCreateSchema(schema_message);
 
730
  }
 
731
};
 
732
 
 
733
bool StorageEngine::createSchema(const drizzled::message::Schema &schema_message)
 
734
{
 
735
  // Add hook here for engines to register schema.
 
736
  for_each(vector_of_schema_engines.begin(), vector_of_schema_engines.end(),
 
737
           CreateSchema(schema_message));
 
738
 
 
739
  return true;
 
740
}
 
741
 
 
742
class DropSchema : 
 
743
  public unary_function<StorageEngine *, void>
 
744
{
 
745
  uint64_t &success_count;
 
746
  const string &schema_name;
 
747
 
 
748
public:
 
749
 
 
750
  DropSchema(const string &arg, uint64_t &count_arg) :
 
751
    success_count(count_arg),
 
752
    schema_name(arg)
 
753
  {
 
754
  }
 
755
 
 
756
  result_type operator() (argument_type engine)
 
757
  {
 
758
    // @todo someday check that at least one engine said "true"
 
759
    bool success= engine->doDropSchema(schema_name);
 
760
 
 
761
    if (success)
 
762
      success_count++;
 
763
  }
 
764
};
 
765
 
 
766
bool StorageEngine::dropSchema(const string &schema_name)
 
767
{
 
768
  uint64_t counter= 0;
 
769
  // Add hook here for engines to register schema.
 
770
  for_each(vector_of_schema_engines.begin(), vector_of_schema_engines.end(),
 
771
           DropSchema(schema_name, counter));
 
772
 
 
773
  return counter ? true : false;
 
774
}
 
775
 
 
776
class AlterSchema : 
 
777
  public unary_function<StorageEngine *, void>
 
778
{
 
779
  uint64_t &success_count;
 
780
  const drizzled::message::Schema &schema_message;
 
781
 
 
782
public:
 
783
 
 
784
  AlterSchema(const drizzled::message::Schema &arg, uint64_t &count_arg) :
 
785
    success_count(count_arg),
 
786
    schema_message(arg)
 
787
  {
 
788
  }
 
789
 
 
790
  result_type operator() (argument_type engine)
 
791
  {
 
792
    // @todo eomeday check that at least one engine said "true"
 
793
    bool success= engine->doAlterSchema(schema_message);
 
794
 
 
795
    if (success)
 
796
      success_count++;
 
797
  }
 
798
};
 
799
 
 
800
bool StorageEngine::alterSchema(const drizzled::message::Schema &schema_message)
 
801
{
 
802
  uint64_t success_count= 0;
 
803
 
 
804
  for_each(vector_of_schema_engines.begin(), vector_of_schema_engines.end(),
 
805
           AlterSchema(schema_message, success_count));
 
806
 
 
807
  return success_count ? true : false;
 
808
}
 
809
 
 
810
 
 
811
void StorageEngine::getTableNames(const string &schema_name, TableNameList &set_of_names)
 
812
{
 
813
  string tmp_path;
 
814
 
 
815
  build_table_filename(tmp_path, schema_name.c_str(), "", false);
 
816
 
 
817
  CachedDirectory directory(tmp_path, set_of_table_definition_ext);
 
818
 
 
819
  if (not schema_name.compare("information_schema"))
 
820
  { }
 
821
  else if (not schema_name.compare("data_dictionary"))
608
822
  { }
609
823
  else
610
824
  {
612
826
    {
613
827
      errno= directory.getError();
614
828
      if (errno == ENOENT)
615
 
      {
616
 
        std::string path;
617
 
        schema_identifier.getSQLPath(path);
618
 
        my_error(ER_BAD_DB_ERROR, MYF(ME_BELL+ME_WAITTANG), path.c_str());
619
 
      }
 
829
        my_error(ER_BAD_DB_ERROR, MYF(ME_BELL+ME_WAITTANG), schema_name.c_str());
620
830
      else
621
 
      {
622
831
        my_error(ER_CANT_READ_DIR, MYF(ME_BELL+ME_WAITTANG), directory.getPath(), errno);
623
 
      }
624
 
 
625
832
      return;
626
833
    }
627
834
  }
628
835
 
629
 
  std::for_each(vector_of_engines.begin(), vector_of_engines.end(),
630
 
                AddTableIdentifier(directory, schema_identifier, set_of_identifiers));
631
 
 
632
 
  session.doGetTableIdentifiers(directory, schema_identifier, set_of_identifiers);
 
836
  for_each(vector_of_engines.begin(), vector_of_engines.end(),
 
837
           AddTableName(directory, schema_name, set_of_names));
 
838
 
 
839
  Session *session= current_session;
 
840
 
 
841
  session->doGetTableNames(directory, schema_name, set_of_names);
 
842
 
633
843
}
634
844
 
635
 
class DropTable: public std::unary_function<TableIdentifier&, bool>
636
 
{
637
 
  Session &session;
638
 
  StorageEngine *engine;
639
 
 
640
 
public:
641
 
 
642
 
  DropTable(Session &session_arg, StorageEngine *engine_arg) :
643
 
    session(session_arg),
644
 
    engine(engine_arg)
645
 
  { }
646
 
 
647
 
  result_type operator() (argument_type identifier)
648
 
  {
649
 
    return engine->doDropTable(session, identifier) == 0;
650
 
  } 
651
 
};
652
 
 
653
845
/* This will later be converted to TableIdentifiers */
654
 
class DropTables: public std::unary_function<StorageEngine *, void>
 
846
class DropTables: public unary_function<StorageEngine *, void>
655
847
{
656
848
  Session &session;
657
 
  TableIdentifier::vector &table_identifiers;
 
849
  TableNameList &set_of_names;
658
850
 
659
851
public:
660
852
 
661
 
  DropTables(Session &session_arg, TableIdentifier::vector &table_identifiers_arg) :
 
853
  DropTables(Session &session_arg, set<string>& of_names) :
662
854
    session(session_arg),
663
 
    table_identifiers(table_identifiers_arg)
 
855
    set_of_names(of_names)
664
856
  { }
665
857
 
666
858
  result_type operator() (argument_type engine)
667
859
  {
668
 
    // True returning from DropTable means the table has been successfully
669
 
    // deleted, so it should be removed from the list of tables to drop
670
 
    table_identifiers.erase(std::remove_if(table_identifiers.begin(),
671
 
                                           table_identifiers.end(),
672
 
                                           DropTable(session, engine)),
673
 
                            table_identifiers.end());
 
860
    for (TableNameList::iterator iter= set_of_names.begin();
 
861
         iter != set_of_names.end();
 
862
         iter++)
 
863
    {
 
864
      TableIdentifier dummy((*iter).c_str());
 
865
      int error= engine->doDropTable(session, dummy, *iter);
 
866
 
 
867
      // On a return of zero we know we found and deleted the table. So we
 
868
      // remove it from our search.
 
869
      if (not error)
 
870
        set_of_names.erase(iter);
 
871
    }
674
872
  }
675
873
};
676
874
 
682
880
void StorageEngine::removeLostTemporaryTables(Session &session, const char *directory)
683
881
{
684
882
  CachedDirectory dir(directory, set_of_table_definition_ext);
685
 
  TableIdentifier::vector table_identifiers;
 
883
  set<string> set_of_table_names;
686
884
 
687
885
  if (dir.fail())
688
886
  {
698
896
       fileIter != files.end(); fileIter++)
699
897
  {
700
898
    size_t length;
701
 
    std::string path;
 
899
    string path;
702
900
    CachedDirectory::Entry *entry= *fileIter;
703
901
 
704
902
    /* We remove the file extension. */
708
906
    path+= directory;
709
907
    path+= FN_LIBCHAR;
710
908
    path+= entry->filename;
711
 
    message::Table definition;
712
 
    if (StorageEngine::readTableFile(path, definition))
713
 
    {
714
 
      TableIdentifier identifier(definition.schema(), definition.name(), path);
715
 
      table_identifiers.push_back(identifier);
716
 
    }
 
909
    set_of_table_names.insert(path);
717
910
  }
718
911
 
719
 
  std::for_each(vector_of_engines.begin(), vector_of_engines.end(),
720
 
                DropTables(session, table_identifiers));
721
 
 
 
912
  for_each(vector_of_engines.begin(), vector_of_engines.end(),
 
913
           DropTables(session, set_of_table_names));
 
914
  
722
915
  /*
723
916
    Now we just clean up anything that might left over.
724
917
 
725
918
    We rescan because some of what might have been there should
726
919
    now be all nice and cleaned up.
727
920
  */
728
 
  std::set<std::string> all_exts= set_of_table_definition_ext;
 
921
  set<string> all_exts= set_of_table_definition_ext;
729
922
 
730
923
  for (EngineVector::iterator iter= vector_of_engines.begin();
731
924
       iter != vector_of_engines.end() ; iter++)
740
933
  for (CachedDirectory::Entries::iterator fileIter= files.begin();
741
934
       fileIter != files.end(); fileIter++)
742
935
  {
743
 
    std::string path;
 
936
    string path;
744
937
    CachedDirectory::Entry *entry= *fileIter;
745
938
 
746
939
    path+= directory;
758
951
  @note
759
952
    In case of delete table it's only safe to use the following parts of
760
953
    the 'table' structure:
761
 
    - table->getShare()->path
 
954
    - table->s->path
762
955
    - table->alias
763
956
*/
764
957
void StorageEngine::print_error(int error, myf errflag, Table &table)
795
988
    {
796
989
      const char *err_msg= ER(ER_DUP_ENTRY_WITH_KEY_NAME);
797
990
 
 
991
      if (key_nr == 0 &&
 
992
          (table->key_info[0].key_part[0].field->flags &
 
993
           AUTO_INCREMENT_FLAG)
 
994
          && (current_session)->lex->sql_command == SQLCOM_ALTER_TABLE)
 
995
      {
 
996
        err_msg= ER(ER_DUP_ENTRY_AUTOINCREMENT_CASE);
 
997
      }
 
998
 
798
999
      print_keydup_error(key_nr, err_msg, *table);
799
 
 
800
1000
      return;
801
1001
    }
802
1002
    textno=ER_DUP_KEY;
823
1023
        str.length(max_length-4);
824
1024
        str.append(STRING_WITH_LEN("..."));
825
1025
      }
826
 
      my_error(ER_FOREIGN_DUPLICATE_KEY, MYF(0), table->getShare()->getTableName(),
 
1026
      my_error(ER_FOREIGN_DUPLICATE_KEY, MYF(0), table->s->table_name.str,
827
1027
        str.c_ptr(), key_nr+1);
828
1028
      return;
829
1029
    }
901
1101
    break;
902
1102
  case HA_ERR_NO_SUCH_TABLE:
903
1103
    assert(table);
904
 
    my_error(ER_NO_SUCH_TABLE, MYF(0), table->getShare()->getSchemaName(),
905
 
             table->getShare()->getTableName());
 
1104
    my_error(ER_NO_SUCH_TABLE, MYF(0), table->s->getSchemaName(),
 
1105
             table->s->table_name.str);
906
1106
    return;
907
1107
  case HA_ERR_RBR_LOGGING_FAILED:
908
1108
    textno= ER_BINLOG_ROW_LOGGING_FAILED;
958
1158
      return;
959
1159
    }
960
1160
  }
961
 
  my_error(textno, errflag, table->getShare()->getTableName(), error);
 
1161
  my_error(textno, errflag, table->s->table_name.str, error);
962
1162
}
963
1163
 
964
1164
 
1005
1205
}
1006
1206
 
1007
1207
 
1008
 
int StorageEngine::deleteDefinitionFromPath(const TableIdentifier &identifier)
 
1208
int StorageEngine::deleteDefinitionFromPath(TableIdentifier &identifier)
1009
1209
{
1010
 
  std::string path(identifier.getPath());
 
1210
  string path(identifier.getPath());
1011
1211
 
1012
1212
  path.append(DEFAULT_DEFINITION_FILE_EXT);
1013
1213
 
1014
1214
  return internal::my_delete(path.c_str(), MYF(0));
1015
1215
}
1016
1216
 
1017
 
int StorageEngine::renameDefinitionFromPath(const TableIdentifier &dest, const TableIdentifier &src)
 
1217
int StorageEngine::renameDefinitionFromPath(TableIdentifier &dest, TableIdentifier &src)
1018
1218
{
1019
 
  message::Table table_message;
1020
 
  std::string src_path(src.getPath());
1021
 
  std::string dest_path(dest.getPath());
 
1219
  string src_path(src.getPath());
 
1220
  string dest_path(dest.getPath());
1022
1221
 
1023
1222
  src_path.append(DEFAULT_DEFINITION_FILE_EXT);
1024
1223
  dest_path.append(DEFAULT_DEFINITION_FILE_EXT);
1025
1224
 
1026
 
  bool was_read= StorageEngine::readTableFile(src_path.c_str(), table_message);
1027
 
 
1028
 
  if (not was_read)
1029
 
  {
1030
 
    return ENOENT;
1031
 
  }
1032
 
 
1033
 
  dest.copyToTableMessage(table_message);
1034
 
 
1035
 
  int error= StorageEngine::writeDefinitionFromPath(dest, table_message);
1036
 
 
1037
 
  if (not error)
1038
 
  {
1039
 
    if (unlink(src_path.c_str()))
1040
 
      perror(src_path.c_str());
1041
 
  }
1042
 
 
1043
 
  return error;
 
1225
  return internal::my_rename(src_path.c_str(), dest_path.c_str(), MYF(MY_WME));
1044
1226
}
1045
1227
 
1046
 
int StorageEngine::writeDefinitionFromPath(const TableIdentifier &identifier, message::Table &table_message)
 
1228
int StorageEngine::writeDefinitionFromPath(TableIdentifier &identifier, message::Table &table_message)
1047
1229
{
1048
 
  char definition_file_tmp[FN_REFLEN];
1049
 
  std::string file_name(identifier.getPath());
 
1230
  string file_name(identifier.getPath());
1050
1231
 
1051
1232
  file_name.append(DEFAULT_DEFINITION_FILE_EXT);
1052
1233
 
1053
 
  snprintf(definition_file_tmp, sizeof(definition_file_tmp), "%sXXXXXX", file_name.c_str());
1054
 
 
1055
 
  int fd= mkstemp(definition_file_tmp);
 
1234
  int fd= open(file_name.c_str(), O_RDWR|O_CREAT|O_TRUNC, internal::my_umask);
1056
1235
 
1057
1236
  if (fd == -1)
1058
 
  {
1059
 
    perror(definition_file_tmp);
1060
1237
    return errno;
1061
 
  }
1062
1238
 
1063
1239
  google::protobuf::io::ZeroCopyOutputStream* output=
1064
1240
    new google::protobuf::io::FileOutputStream(fd);
1065
1241
 
1066
 
  bool success;
1067
 
 
1068
 
  try
1069
 
  {
1070
 
    success= table_message.SerializeToZeroCopyStream(output);
1071
 
  }
1072
 
  catch (...)
1073
 
  {
1074
 
    success= false;
1075
 
  }
1076
 
 
1077
 
  if (not success)
1078
 
  {
1079
 
    my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
1080
 
             table_message.InitializationErrorString().c_str());
 
1242
  if (table_message.SerializeToZeroCopyStream(output) == false)
 
1243
  {
1081
1244
    delete output;
1082
 
 
1083
 
    if (close(fd) == -1)
1084
 
      perror(definition_file_tmp);
1085
 
 
1086
 
    if (unlink(definition_file_tmp) == -1)
1087
 
      perror(definition_file_tmp);
1088
 
 
1089
 
    return ER_CORRUPT_TABLE_DEFINITION;
 
1245
    close(fd);
 
1246
    return errno;
1090
1247
  }
1091
1248
 
1092
1249
  delete output;
1093
 
 
1094
 
  if (close(fd) == -1)
1095
 
  {
1096
 
    int error= errno;
1097
 
    perror(definition_file_tmp);
1098
 
 
1099
 
    if (unlink(definition_file_tmp))
1100
 
      perror(definition_file_tmp);
1101
 
 
1102
 
    return error;
1103
 
  }
1104
 
 
1105
 
  if (rename(definition_file_tmp, file_name.c_str()) == -1)
1106
 
  {
1107
 
    int error= errno;
1108
 
    perror(definition_file_tmp);
1109
 
 
1110
 
    if (unlink(definition_file_tmp))
1111
 
      perror(definition_file_tmp);
1112
 
 
1113
 
    return error;
1114
 
  }
1115
 
 
 
1250
  close(fd);
1116
1251
  return 0;
1117
1252
}
1118
1253
 
1119
 
class CanCreateTable: public std::unary_function<StorageEngine *, bool>
 
1254
class CanCreateTable: public unary_function<StorageEngine *, bool>
1120
1255
{
1121
1256
  const TableIdentifier &identifier;
1122
1257
 
1135
1270
/**
1136
1271
  @note on success table can be created.
1137
1272
*/
1138
 
bool StorageEngine::canCreateTable(const TableIdentifier &identifier)
 
1273
bool StorageEngine::canCreateTable(drizzled::TableIdentifier &identifier)
1139
1274
{
1140
1275
  EngineVector::iterator iter=
1141
 
    std::find_if(vector_of_engines.begin(), vector_of_engines.end(),
1142
 
                 CanCreateTable(identifier));
 
1276
    find_if(vector_of_engines.begin(), vector_of_engines.end(),
 
1277
            CanCreateTable(identifier));
1143
1278
 
1144
1279
  if (iter == vector_of_engines.end())
1145
1280
  {
1149
1284
  return false;
1150
1285
}
1151
1286
 
1152
 
bool StorageEngine::readTableFile(const std::string &path, message::Table &table_message)
1153
 
{
1154
 
  std::fstream input(path.c_str(), std::ios::in | std::ios::binary);
1155
 
 
1156
 
  if (input.good())
1157
 
  {
1158
 
    try {
1159
 
      if (table_message.ParseFromIstream(&input))
1160
 
      {
1161
 
        return true;
1162
 
      }
1163
 
    }
1164
 
    catch (...)
1165
 
    {
1166
 
      my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
1167
 
               table_message.InitializationErrorString().empty() ? "": table_message.InitializationErrorString().c_str());
1168
 
    }
1169
 
  }
1170
 
  else
1171
 
  {
1172
 
    perror(path.c_str());
1173
 
  }
1174
 
 
1175
 
  return false;
1176
 
}
1177
 
 
1178
 
 
1179
 
 
1180
1287
} /* namespace plugin */
1181
1288
} /* namespace drizzled */