~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/plugin/storage_engine.cc

  • Committer: pawel
  • Date: 2010-03-29 20:16:08 UTC
  • mto: This revision was merged to the branch mainline in revision 1428.
  • Revision ID: pawel@paw-20100329201608-ndqnc736k47uvy3s
changed function-like defines into functions in some files

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
 
48
47
#include "drizzled/xid.h"
49
48
#include "drizzled/sql_table.h"
50
49
#include "drizzled/global_charset_info.h"
 
50
#include "drizzled/plugin/authorization.h"
51
51
#include "drizzled/charset.h"
52
52
#include "drizzled/internal/my_sys.h"
53
53
#include "drizzled/db.h"
66
66
 
67
67
static EngineVector vector_of_engines;
68
68
static EngineVector vector_of_schema_engines;
 
69
static EngineVector vector_of_data_dictionary;
69
70
 
70
71
const std::string UNKNOWN_STRING("UNKNOWN");
71
72
const std::string DEFAULT_DEFINITION_FILE_EXT(".dfe");
72
73
 
73
74
static std::set<std::string> set_of_table_definition_ext;
74
75
 
75
 
EngineVector &StorageEngine::getSchemaEngines()
76
 
{
77
 
  return vector_of_schema_engines;
78
 
}
79
 
 
80
76
StorageEngine::StorageEngine(const string name_arg,
81
 
                             const bitset<HTON_BIT_SIZE> &flags_arg) :
82
 
  Plugin(name_arg, "StorageEngine"),
83
 
  MonitoredInTransaction(), /* This gives the storage engine a "slot" or ID */
84
 
  flags(flags_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)
85
81
{
 
82
  pthread_mutex_init(&proto_cache_mutex, NULL);
86
83
}
87
84
 
88
85
StorageEngine::~StorageEngine()
89
86
{
 
87
  pthread_mutex_destroy(&proto_cache_mutex);
90
88
}
91
89
 
92
90
void StorageEngine::setTransactionReadWrite(Session& session)
95
93
  statement_ctx.markModifiedNonTransData();
96
94
}
97
95
 
98
 
 
99
 
int StorageEngine::renameTable(Session &session, TableIdentifier &from, TableIdentifier &to)
 
96
int StorageEngine::doRenameTable(Session *,
 
97
                                 const char *from,
 
98
                                 const char *to)
100
99
{
101
 
  setTransactionReadWrite(session);
102
 
 
103
 
  return doRenameTable(session, from, to);
 
100
  int error= 0;
 
101
  for (const char **ext= bas_ext(); *ext ; ext++)
 
102
  {
 
103
    if (rename_file_ext(from, to, *ext))
 
104
    {
 
105
      if ((error=errno) != ENOENT)
 
106
        break;
 
107
      error= 0;
 
108
    }
 
109
  }
 
110
  return error;
104
111
}
105
112
 
 
113
 
106
114
/**
107
115
  Delete all files with extension from bas_ext().
108
116
 
135
143
        break;
136
144
    }
137
145
    else
138
 
    {
139
146
      enoent_or_zero= 0;                        // No error for ENOENT
140
 
    }
141
 
 
142
147
    error= enoent_or_zero;
143
148
  }
144
149
  return error;
158
163
  if (engine->check_flag(HTON_BIT_SCHEMA_DICTIONARY))
159
164
    vector_of_schema_engines.push_back(engine);
160
165
 
 
166
  if (engine->check_flag(HTON_BIT_HAS_DATA_DICTIONARY))
 
167
    vector_of_data_dictionary.push_back(engine);
 
168
 
161
169
  return false;
162
170
}
163
171
 
167
175
  {
168
176
    vector_of_engines.clear();
169
177
    vector_of_schema_engines.clear();
 
178
    vector_of_data_dictionary.clear();
170
179
 
171
180
    shutdown_has_begun= true;
172
181
  }
175
184
class FindEngineByName
176
185
  : public unary_function<StorageEngine *, bool>
177
186
{
178
 
  const string &target;
179
 
 
 
187
  const string target;
180
188
public:
181
 
  explicit FindEngineByName(const string &target_arg) :
182
 
    target(target_arg)
183
 
  {
184
 
  }
 
189
  explicit FindEngineByName(const string target_arg)
 
190
    : target(target_arg)
 
191
  {}
185
192
  result_type operator() (argument_type engine)
186
193
  {
187
194
    string engine_name(engine->getName());
192
199
  }
193
200
};
194
201
 
195
 
StorageEngine *StorageEngine::findByName(const string &find_str)
 
202
StorageEngine *StorageEngine::findByName(string find_str)
196
203
{
197
 
  string search_string(find_str);
198
 
  transform(search_string.begin(), search_string.end(),
199
 
            search_string.begin(), ::tolower);
 
204
  transform(find_str.begin(), find_str.end(),
 
205
            find_str.begin(), ::tolower);
200
206
 
201
207
  
202
208
  EngineVector::iterator iter= find_if(vector_of_engines.begin(),
203
209
                                       vector_of_engines.end(),
204
 
                                       FindEngineByName(search_string));
 
210
                                       FindEngineByName(find_str));
205
211
  if (iter != vector_of_engines.end())
206
212
  {
207
213
    StorageEngine *engine= *iter;
212
218
  return NULL;
213
219
}
214
220
 
215
 
StorageEngine *StorageEngine::findByName(Session& session, const string &find_str)
 
221
StorageEngine *StorageEngine::findByName(Session& session, string find_str)
216
222
{
217
 
  string search_string(find_str);
218
 
  transform(search_string.begin(), search_string.end(),
219
 
            search_string.begin(), ::tolower);
 
223
  
 
224
  transform(find_str.begin(), find_str.end(),
 
225
            find_str.begin(), ::tolower);
220
226
 
221
 
  if (search_string.compare("default") == 0)
 
227
  if (find_str.compare("default") == 0)
222
228
    return session.getDefaultStorageEngine();
223
229
 
224
230
  EngineVector::iterator iter= find_if(vector_of_engines.begin(),
225
231
                                       vector_of_engines.end(),
226
 
                                       FindEngineByName(search_string));
 
232
                                       FindEngineByName(find_str));
227
233
  if (iter != vector_of_engines.end())
228
234
  {
229
235
    StorageEngine *engine= *iter;
234
240
  return NULL;
235
241
}
236
242
 
237
 
class StorageEngineCloseConnection : public unary_function<StorageEngine *, void>
 
243
class StorageEngineCloseConnection
 
244
: public unary_function<StorageEngine *, void>
238
245
{
239
246
  Session *session;
240
247
public:
296
303
 
297
304
  result_type operator() (argument_type engine)
298
305
  {
299
 
    int ret= engine->doGetTableDefinition(session, identifier, table_message);
 
306
    int ret= engine->doGetTableDefinition(session,
 
307
                                          identifier,
 
308
                                          table_message);
300
309
 
301
310
    if (ret != ENOENT)
302
311
      err= ret;
336
345
  }
337
346
 
338
347
  EngineVector::iterator iter=
339
 
    find_if(vector_of_engines.begin(), vector_of_engines.end(),
 
348
    find_if(vector_of_data_dictionary.begin(), vector_of_data_dictionary.end(),
340
349
            StorageEngineDoesTableExist(session, identifier));
341
350
 
342
 
  if (iter == vector_of_engines.end())
 
351
  if (iter == vector_of_data_dictionary.end())
343
352
  {
344
353
    return false;
345
354
  }
414
423
  return true;
415
424
}
416
425
 
 
426
class DropTable : 
 
427
  public unary_function<StorageEngine *, void>
 
428
{
 
429
  uint64_t &success_count;
 
430
  TableIdentifier &identifier;
 
431
  Session &session;
 
432
 
 
433
public:
 
434
 
 
435
  DropTable(Session &session_arg, TableIdentifier &arg, uint64_t &count_arg) :
 
436
    success_count(count_arg),
 
437
    identifier(arg),
 
438
    session(session_arg)
 
439
  {
 
440
  }
 
441
 
 
442
  result_type operator() (argument_type engine)
 
443
  {
 
444
    bool success= engine->doDropTable(session, identifier);
 
445
 
 
446
    if (success)
 
447
      success_count++;
 
448
  }
 
449
};
 
450
 
 
451
 
417
452
/**
418
453
   returns ENOENT if the file doesn't exists.
419
454
*/
423
458
  int error= 0;
424
459
  int error_proto;
425
460
  message::Table src_proto;
426
 
  StorageEngine *engine;
 
461
  StorageEngine* engine;
427
462
 
428
463
  error_proto= StorageEngine::getTableDefinition(session, identifier, src_proto);
429
464
 
430
465
  if (error_proto == ER_CORRUPT_TABLE_DEFINITION)
431
466
  {
432
 
    string error_message;
433
 
 
434
 
    error_message.append(identifier.getSQLPath());
435
 
    error_message.append(" : ");
436
 
    error_message.append(src_proto.InitializationErrorString());
437
 
 
438
 
    my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0), error_message.c_str());
439
 
 
 
467
    my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
 
468
             src_proto.InitializationErrorString().c_str());
440
469
    return ER_CORRUPT_TABLE_DEFINITION;
441
470
  }
442
471
 
443
472
  engine= StorageEngine::findByName(session, src_proto.engine().name());
444
473
 
445
 
  if (not engine)
 
474
  if (engine)
446
475
  {
447
 
    my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0), identifier.getSQLPath().c_str());
448
 
 
449
 
    return ER_CORRUPT_TABLE_DEFINITION;
 
476
    std::string path(identifier.getPath());
 
477
    engine->setTransactionReadWrite(session);
 
478
    error= engine->doDropTable(session, identifier);
 
479
 
 
480
    if (not error)
 
481
    {
 
482
      if (not engine->check_flag(HTON_BIT_HAS_DATA_DICTIONARY))
 
483
      {
 
484
        uint64_t counter; // @todo We need to refactor to check that.
 
485
 
 
486
        for_each(vector_of_schema_engines.begin(), vector_of_schema_engines.end(),
 
487
                 DropTable(session, identifier, counter));
 
488
      }
 
489
    }
450
490
  }
451
491
 
452
 
  error= StorageEngine::dropTable(session, *engine, identifier);
453
 
 
454
492
  if (error_proto && error == 0)
455
493
    return 0;
456
494
 
457
495
  return error;
458
496
}
459
497
 
460
 
int StorageEngine::dropTable(Session& session,
461
 
                             StorageEngine &engine,
462
 
                             TableIdentifier &identifier)
463
 
{
464
 
  int error;
465
 
 
466
 
  engine.setTransactionReadWrite(session);
467
 
  error= engine.doDropTable(session, identifier);
468
 
 
469
 
  return error;
470
 
}
471
 
 
472
 
 
473
498
/**
474
499
  Initiates table-file and calls appropriate database-creator.
475
500
 
477
502
   0  ok
478
503
  @retval
479
504
   1  error
 
505
 
 
506
   @todo refactor to remove goto
480
507
*/
481
 
int StorageEngine::createTable(Session &session,
 
508
int StorageEngine::createTable(Session& session,
482
509
                               TableIdentifier &identifier,
483
510
                               bool update_create_info,
484
511
                               message::Table& table_message)
485
512
{
486
513
  int error= 1;
487
514
  Table table;
488
 
  TableShare share(identifier.getSchemaName().c_str(), 0, identifier.getTableName().c_str(), identifier.getPath().c_str());
 
515
  TableShare share(identifier.getDBName().c_str(), 0, identifier.getTableName().c_str(), identifier.getPath().c_str());
489
516
  message::Table tmp_proto;
490
517
 
491
 
  if (parse_table_proto(session, table_message, &share) || open_table_from_share(&session, &share, "", 0, 0, &table))
492
 
  { 
493
 
    // @note Error occured, we should probably do a little more here.
494
 
  }
495
 
  else
496
 
  {
497
 
    if (update_create_info)
498
 
      table.updateCreateInfo(&table_message);
499
 
 
500
 
    /* Check for legal operations against the Engine using the proto (if used) */
501
 
    if (table_message.type() == message::Table::TEMPORARY &&
502
 
        share.storage_engine->check_flag(HTON_BIT_TEMPORARY_NOT_SUPPORTED) == true)
503
 
    {
504
 
      error= HA_ERR_UNSUPPORTED;
505
 
    }
506
 
    else if (table_message.type() != message::Table::TEMPORARY &&
507
 
             share.storage_engine->check_flag(HTON_BIT_TEMPORARY_ONLY) == true)
508
 
    {
509
 
      error= HA_ERR_UNSUPPORTED;
510
 
    }
511
 
    else
512
 
    {
513
 
      share.storage_engine->setTransactionReadWrite(session);
514
 
 
515
 
      error= share.storage_engine->doCreateTable(session,
516
 
                                                 table,
517
 
                                                 identifier,
518
 
                                                 table_message);
519
 
    }
520
 
 
521
 
    if (error)
522
 
    {
523
 
      my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), identifier.getSQLPath().c_str(), error);
524
 
    }
525
 
 
526
 
    table.closefrm(false);
527
 
  }
528
 
 
 
518
  if (parse_table_proto(session, table_message, &share))
 
519
    goto err;
 
520
 
 
521
  if (open_table_from_share(&session, &share, "", 0, 0,
 
522
                            &table))
 
523
    goto err;
 
524
 
 
525
  if (update_create_info)
 
526
    table.updateCreateInfo(&table_message);
 
527
 
 
528
  /* Check for legal operations against the Engine using the proto (if used) */
 
529
  if (table_message.type() == message::Table::TEMPORARY &&
 
530
      share.storage_engine->check_flag(HTON_BIT_TEMPORARY_NOT_SUPPORTED) == true)
 
531
  {
 
532
    error= HA_ERR_UNSUPPORTED;
 
533
    goto err2;
 
534
  }
 
535
  else if (table_message.type() != message::Table::TEMPORARY &&
 
536
           share.storage_engine->check_flag(HTON_BIT_TEMPORARY_ONLY) == true)
 
537
  {
 
538
    error= HA_ERR_UNSUPPORTED;
 
539
    goto err2;
 
540
  }
 
541
 
 
542
  {
 
543
    if (not share.storage_engine->check_flag(HTON_BIT_HAS_DATA_DICTIONARY))
 
544
    {
 
545
      int protoerr= StorageEngine::writeDefinitionFromPath(identifier, table_message);
 
546
 
 
547
      if (protoerr)
 
548
      {
 
549
        error= protoerr;
 
550
        goto err2;
 
551
      }
 
552
    }
 
553
 
 
554
    share.storage_engine->setTransactionReadWrite(session);
 
555
 
 
556
    error= share.storage_engine->doCreateTable(&session,
 
557
                                               table,
 
558
                                               identifier,
 
559
                                               table_message);
 
560
  }
 
561
 
 
562
err2:
 
563
  if (error)
 
564
  {
 
565
    if (not share.storage_engine->check_flag(HTON_BIT_HAS_DATA_DICTIONARY))
 
566
      plugin::StorageEngine::deleteDefinitionFromPath(identifier);
 
567
 
 
568
    my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), identifier.getSQLPath().c_str(), error);
 
569
  }
 
570
 
 
571
  table.closefrm(false);
 
572
 
 
573
err:
529
574
  share.free_table_share();
530
575
  return(error != 0);
531
576
}
535
580
  return create(share, alloc);
536
581
}
537
582
 
 
583
/**
 
584
  TODO -> Remove this to force all engines to implement their own file. Solves the "we only looked at dfe" problem.
 
585
*/
 
586
void StorageEngine::doGetTableNames(CachedDirectory&, string&, set<string>&)
 
587
{ }
 
588
 
538
589
class AddTableName : 
539
590
  public unary_function<StorageEngine *, void>
540
591
{
541
 
  CachedDirectory &directory;
542
 
  SchemaIdentifier &identifier;
 
592
  string db;
 
593
  CachedDirectory& directory;
543
594
  TableNameList &set_of_names;
544
595
 
545
596
public:
546
597
 
547
 
  AddTableName(CachedDirectory &directory_arg, SchemaIdentifier &identifier_arg, set<string>& of_names) :
548
 
    directory(directory_arg),
549
 
    identifier(identifier_arg),
550
 
    set_of_names(of_names)
551
 
  {
552
 
  }
553
 
 
554
 
  result_type operator() (argument_type engine)
555
 
  {
556
 
    engine->doGetTableNames(directory, identifier, set_of_names);
557
 
  }
558
 
};
559
 
 
560
 
class AddTableIdentifier : 
561
 
  public unary_function<StorageEngine *, void>
562
 
{
563
 
  CachedDirectory &directory;
564
 
  SchemaIdentifier &identifier;
565
 
  TableIdentifiers &set_of_identifiers;
566
 
 
567
 
public:
568
 
 
569
 
  AddTableIdentifier(CachedDirectory &directory_arg, SchemaIdentifier &identifier_arg, TableIdentifiers &of_names) :
570
 
    directory(directory_arg),
571
 
    identifier(identifier_arg),
572
 
    set_of_identifiers(of_names)
573
 
  {
574
 
  }
575
 
 
576
 
  result_type operator() (argument_type engine)
577
 
  {
578
 
    engine->doGetTableIdentifiers(directory, identifier, set_of_identifiers);
579
 
  }
580
 
};
581
 
 
582
 
 
583
 
static SchemaIdentifier INFORMATION_SCHEMA_IDENTIFIER("information_schema");
584
 
static SchemaIdentifier DATA_DICTIONARY_IDENTIFIER("data_dictionary");
585
 
 
586
 
void StorageEngine::getTableNames(Session &session, SchemaIdentifier &schema_identifier, TableNameList &set_of_names)
587
 
{
588
 
  CachedDirectory directory(schema_identifier.getPath(), set_of_table_definition_ext);
589
 
 
590
 
  if (schema_identifier == INFORMATION_SCHEMA_IDENTIFIER)
591
 
  { }
592
 
  else if (schema_identifier == DATA_DICTIONARY_IDENTIFIER)
593
 
  { }
594
 
  else
595
 
  {
596
 
    if (directory.fail())
597
 
    {
598
 
      errno= directory.getError();
599
 
      if (errno == ENOENT)
600
 
        my_error(ER_BAD_DB_ERROR, MYF(ME_BELL+ME_WAITTANG), schema_identifier.getSQLPath().c_str());
601
 
      else
602
 
        my_error(ER_CANT_READ_DIR, MYF(ME_BELL+ME_WAITTANG), directory.getPath(), errno);
603
 
      return;
604
 
    }
605
 
  }
606
 
 
607
 
  for_each(vector_of_engines.begin(), vector_of_engines.end(),
608
 
           AddTableName(directory, schema_identifier, set_of_names));
609
 
 
610
 
  session.doGetTableNames(directory, schema_identifier, set_of_names);
611
 
}
612
 
 
613
 
void StorageEngine::getTableIdentifiers(Session &session, SchemaIdentifier &schema_identifier, TableIdentifiers &set_of_identifiers)
614
 
{
615
 
  CachedDirectory directory(schema_identifier.getPath(), set_of_table_definition_ext);
616
 
 
617
 
  if (schema_identifier == INFORMATION_SCHEMA_IDENTIFIER)
618
 
  { }
619
 
  else if (schema_identifier == DATA_DICTIONARY_IDENTIFIER)
620
 
  { }
621
 
  else
622
 
  {
623
 
    if (directory.fail())
624
 
    {
625
 
      errno= directory.getError();
626
 
      if (errno == ENOENT)
627
 
        my_error(ER_BAD_DB_ERROR, MYF(ME_BELL+ME_WAITTANG), schema_identifier.getSQLPath().c_str());
628
 
      else
629
 
        my_error(ER_CANT_READ_DIR, MYF(ME_BELL+ME_WAITTANG), directory.getPath(), errno);
630
 
      return;
631
 
    }
632
 
  }
633
 
 
634
 
  for_each(vector_of_engines.begin(), vector_of_engines.end(),
635
 
           AddTableIdentifier(directory, schema_identifier, set_of_identifiers));
636
 
 
637
 
  session.doGetTableIdentifiers(directory, schema_identifier, set_of_identifiers);
 
598
  AddTableName(CachedDirectory& directory_arg, const string& database_name, set<string>& of_names) :
 
599
    directory(directory_arg),
 
600
    set_of_names(of_names)
 
601
  {
 
602
    db= database_name;
 
603
  }
 
604
 
 
605
  result_type operator() (argument_type engine)
 
606
  {
 
607
    engine->doGetTableNames(directory, db, set_of_names);
 
608
  }
 
609
};
 
610
 
 
611
class AddSchemaNames : 
 
612
  public unary_function<StorageEngine *, void>
 
613
{
 
614
  SchemaNameList &set_of_names;
 
615
 
 
616
public:
 
617
 
 
618
  AddSchemaNames(set<string>& of_names) :
 
619
    set_of_names(of_names)
 
620
  {
 
621
  }
 
622
 
 
623
  result_type operator() (argument_type engine)
 
624
  {
 
625
    engine->doGetSchemaNames(set_of_names);
 
626
  }
 
627
};
 
628
 
 
629
void StorageEngine::getSchemaNames(SchemaNameList &set_of_names)
 
630
{
 
631
  // Add hook here for engines to register schema.
 
632
  for_each(vector_of_schema_engines.begin(), vector_of_schema_engines.end(),
 
633
           AddSchemaNames(set_of_names));
 
634
 
 
635
  plugin::Authorization::pruneSchemaNames(current_session->getSecurityContext(),
 
636
                                          set_of_names);
 
637
}
 
638
 
 
639
class StorageEngineGetSchemaDefinition: public unary_function<StorageEngine *, bool>
 
640
{
 
641
  const std::string &schema_name;
 
642
  message::Schema &schema_proto;
 
643
 
 
644
public:
 
645
  StorageEngineGetSchemaDefinition(const std::string &schema_name_arg,
 
646
                                  message::Schema &schema_proto_arg) :
 
647
    schema_name(schema_name_arg),
 
648
    schema_proto(schema_proto_arg) 
 
649
  { }
 
650
 
 
651
  result_type operator() (argument_type engine)
 
652
  {
 
653
    return engine->doGetSchemaDefinition(schema_name, schema_proto);
 
654
  }
 
655
};
 
656
 
 
657
/*
 
658
  Return value is "if parsed"
 
659
*/
 
660
bool StorageEngine::getSchemaDefinition(const std::string &schema_name, message::Schema &proto)
 
661
{
 
662
  proto.Clear();
 
663
 
 
664
  EngineVector::iterator iter=
 
665
    find_if(vector_of_schema_engines.begin(), vector_of_schema_engines.end(),
 
666
            StorageEngineGetSchemaDefinition(schema_name, proto));
 
667
 
 
668
  if (iter != vector_of_schema_engines.end())
 
669
  {
 
670
    return true;
 
671
  }
 
672
 
 
673
  return false;
 
674
}
 
675
 
 
676
bool StorageEngine::doesSchemaExist(const std::string &schema_name)
 
677
{
 
678
  message::Schema proto;
 
679
 
 
680
  return StorageEngine::getSchemaDefinition(schema_name, proto);
 
681
}
 
682
 
 
683
 
 
684
const CHARSET_INFO *StorageEngine::getSchemaCollation(const std::string &schema_name)
 
685
{
 
686
  message::Schema schmema_proto;
 
687
  bool found;
 
688
 
 
689
  found= StorageEngine::getSchemaDefinition(schema_name, schmema_proto);
 
690
 
 
691
  if (found && schmema_proto.has_collation())
 
692
  {
 
693
    const string buffer= schmema_proto.collation();
 
694
    const CHARSET_INFO* cs= get_charset_by_name(buffer.c_str());
 
695
 
 
696
    if (not cs)
 
697
    {
 
698
      errmsg_printf(ERRMSG_LVL_ERROR,
 
699
                    _("Error while loading database options: '%s':"), schema_name.c_str());
 
700
      errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_UNKNOWN_COLLATION), buffer.c_str());
 
701
 
 
702
      return default_charset_info;
 
703
    }
 
704
 
 
705
    return cs;
 
706
  }
 
707
 
 
708
  return default_charset_info;
 
709
}
 
710
 
 
711
class CreateSchema : 
 
712
  public unary_function<StorageEngine *, void>
 
713
{
 
714
  const drizzled::message::Schema &schema_message;
 
715
 
 
716
public:
 
717
 
 
718
  CreateSchema(const drizzled::message::Schema &arg) :
 
719
    schema_message(arg)
 
720
  {
 
721
  }
 
722
 
 
723
  result_type operator() (argument_type engine)
 
724
  {
 
725
    // @todo eomeday check that at least one engine said "true"
 
726
    (void)engine->doCreateSchema(schema_message);
 
727
  }
 
728
};
 
729
 
 
730
bool StorageEngine::createSchema(const drizzled::message::Schema &schema_message)
 
731
{
 
732
  // Add hook here for engines to register schema.
 
733
  for_each(vector_of_schema_engines.begin(), vector_of_schema_engines.end(),
 
734
           CreateSchema(schema_message));
 
735
 
 
736
  return true;
 
737
}
 
738
 
 
739
class DropSchema : 
 
740
  public unary_function<StorageEngine *, void>
 
741
{
 
742
  uint64_t &success_count;
 
743
  const string &schema_name;
 
744
 
 
745
public:
 
746
 
 
747
  DropSchema(const string &arg, uint64_t &count_arg) :
 
748
    success_count(count_arg),
 
749
    schema_name(arg)
 
750
  {
 
751
  }
 
752
 
 
753
  result_type operator() (argument_type engine)
 
754
  {
 
755
    // @todo someday check that at least one engine said "true"
 
756
    bool success= engine->doDropSchema(schema_name);
 
757
 
 
758
    if (success)
 
759
      success_count++;
 
760
  }
 
761
};
 
762
 
 
763
bool StorageEngine::dropSchema(const string &schema_name)
 
764
{
 
765
  uint64_t counter= 0;
 
766
  // Add hook here for engines to register schema.
 
767
  for_each(vector_of_schema_engines.begin(), vector_of_schema_engines.end(),
 
768
           DropSchema(schema_name, counter));
 
769
 
 
770
  return counter ? true : false;
 
771
}
 
772
 
 
773
class AlterSchema : 
 
774
  public unary_function<StorageEngine *, void>
 
775
{
 
776
  uint64_t &success_count;
 
777
  const drizzled::message::Schema &schema_message;
 
778
 
 
779
public:
 
780
 
 
781
  AlterSchema(const drizzled::message::Schema &arg, uint64_t &count_arg) :
 
782
    success_count(count_arg),
 
783
    schema_message(arg)
 
784
  {
 
785
  }
 
786
 
 
787
  result_type operator() (argument_type engine)
 
788
  {
 
789
    // @todo eomeday check that at least one engine said "true"
 
790
    bool success= engine->doAlterSchema(schema_message);
 
791
 
 
792
    if (success)
 
793
      success_count++;
 
794
  }
 
795
};
 
796
 
 
797
bool StorageEngine::alterSchema(const drizzled::message::Schema &schema_message)
 
798
{
 
799
  uint64_t success_count= 0;
 
800
 
 
801
  for_each(vector_of_schema_engines.begin(), vector_of_schema_engines.end(),
 
802
           AlterSchema(schema_message, success_count));
 
803
 
 
804
  return success_count ? true : false;
 
805
}
 
806
 
 
807
 
 
808
void StorageEngine::getTableNames(const string &schema_name, TableNameList &set_of_names)
 
809
{
 
810
  string tmp_path;
 
811
 
 
812
  build_table_filename(tmp_path, schema_name.c_str(), "", false);
 
813
 
 
814
  CachedDirectory directory(tmp_path, set_of_table_definition_ext);
 
815
 
 
816
  if (not schema_name.compare("information_schema"))
 
817
  { }
 
818
  else if (not schema_name.compare("data_dictionary"))
 
819
  { }
 
820
  else
 
821
  {
 
822
    if (directory.fail())
 
823
    {
 
824
      errno= directory.getError();
 
825
      if (errno == ENOENT)
 
826
        my_error(ER_BAD_DB_ERROR, MYF(ME_BELL+ME_WAITTANG), schema_name.c_str());
 
827
      else
 
828
        my_error(ER_CANT_READ_DIR, MYF(ME_BELL+ME_WAITTANG), directory.getPath(), errno);
 
829
      return;
 
830
    }
 
831
  }
 
832
 
 
833
  for_each(vector_of_engines.begin(), vector_of_engines.end(),
 
834
           AddTableName(directory, schema_name, set_of_names));
 
835
 
 
836
  Session *session= current_session;
 
837
 
 
838
  session->doGetTableNames(directory, schema_name, set_of_names);
 
839
 
638
840
}
639
841
 
640
842
/* This will later be converted to TableIdentifiers */
641
843
class DropTables: public unary_function<StorageEngine *, void>
642
844
{
643
845
  Session &session;
644
 
  TableIdentifierList &table_identifiers;
 
846
  TableNameList &set_of_names;
645
847
 
646
848
public:
647
849
 
648
 
  DropTables(Session &session_arg, TableIdentifierList &table_identifiers_arg) :
 
850
  DropTables(Session &session_arg, set<string>& of_names) :
649
851
    session(session_arg),
650
 
    table_identifiers(table_identifiers_arg)
 
852
    set_of_names(of_names)
651
853
  { }
652
854
 
653
855
  result_type operator() (argument_type engine)
654
856
  {
655
 
    for (TableIdentifierList::iterator iter= table_identifiers.begin();
656
 
         iter != table_identifiers.end();
 
857
    for (TableNameList::iterator iter= set_of_names.begin();
 
858
         iter != set_of_names.end();
657
859
         iter++)
658
860
    {
659
 
      int error= engine->doDropTable(session, const_cast<TableIdentifier&>(*iter));
 
861
      TableIdentifier dummy((*iter).c_str());
 
862
      int error= engine->doDropTable(session, dummy);
660
863
 
661
864
      // On a return of zero we know we found and deleted the table. So we
662
865
      // remove it from our search.
663
866
      if (not error)
664
 
        table_identifiers.erase(iter);
 
867
        set_of_names.erase(iter);
665
868
    }
666
869
  }
667
870
};
674
877
void StorageEngine::removeLostTemporaryTables(Session &session, const char *directory)
675
878
{
676
879
  CachedDirectory dir(directory, set_of_table_definition_ext);
677
 
  TableIdentifierList table_identifiers;
 
880
  set<string> set_of_table_names;
678
881
 
679
882
  if (dir.fail())
680
883
  {
700
903
    path+= directory;
701
904
    path+= FN_LIBCHAR;
702
905
    path+= entry->filename;
703
 
    message::Table definition;
704
 
    if (StorageEngine::readTableFile(path, definition))
705
 
    {
706
 
      TableIdentifier identifier(definition.schema(), definition.name(), path);
707
 
      table_identifiers.push_back(identifier);
708
 
    }
 
906
    set_of_table_names.insert(path);
709
907
  }
710
908
 
711
909
  for_each(vector_of_engines.begin(), vector_of_engines.end(),
712
 
           DropTables(session, table_identifiers));
 
910
           DropTables(session, set_of_table_names));
713
911
  
714
912
  /*
715
913
    Now we just clean up anything that might left over.
1015
1213
 
1016
1214
int StorageEngine::renameDefinitionFromPath(TableIdentifier &dest, TableIdentifier &src)
1017
1215
{
1018
 
  message::Table table_message;
1019
1216
  string src_path(src.getPath());
1020
1217
  string dest_path(dest.getPath());
1021
1218
 
1022
1219
  src_path.append(DEFAULT_DEFINITION_FILE_EXT);
1023
1220
  dest_path.append(DEFAULT_DEFINITION_FILE_EXT);
1024
1221
 
1025
 
  bool was_read= StorageEngine::readTableFile(src_path.c_str(), table_message);
1026
 
 
1027
 
  if (not was_read)
1028
 
  {
1029
 
    return ENOENT;
1030
 
  }
1031
 
 
1032
 
  dest.copyToTableMessage(table_message);
1033
 
 
1034
 
  int error= StorageEngine::writeDefinitionFromPath(dest, table_message);
1035
 
 
1036
 
  if (not error)
1037
 
  {
1038
 
    if (unlink(src_path.c_str()))
1039
 
      perror(src_path.c_str());
1040
 
  }
1041
 
 
1042
 
  return error;
 
1222
  return internal::my_rename(src_path.c_str(), dest_path.c_str(), MYF(MY_WME));
1043
1223
}
1044
1224
 
1045
1225
int StorageEngine::writeDefinitionFromPath(TableIdentifier &identifier, message::Table &table_message)
1046
1226
{
1047
 
  char definition_file_tmp[FN_REFLEN];
1048
1227
  string file_name(identifier.getPath());
1049
1228
 
1050
1229
  file_name.append(DEFAULT_DEFINITION_FILE_EXT);
1051
1230
 
1052
 
  snprintf(definition_file_tmp, sizeof(definition_file_tmp), "%sXXXXXX", file_name.c_str());
1053
 
 
1054
 
  int fd= mkstemp(definition_file_tmp);
 
1231
  int fd= open(file_name.c_str(), O_RDWR|O_CREAT|O_TRUNC, internal::my_umask);
1055
1232
 
1056
1233
  if (fd == -1)
1057
 
  {
1058
 
    perror(definition_file_tmp);
1059
1234
    return errno;
1060
 
  }
1061
1235
 
1062
1236
  google::protobuf::io::ZeroCopyOutputStream* output=
1063
1237
    new google::protobuf::io::FileOutputStream(fd);
1064
1238
 
1065
 
  if (not table_message.SerializeToZeroCopyStream(output))
 
1239
  if (table_message.SerializeToZeroCopyStream(output) == false)
1066
1240
  {
1067
 
    my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
1068
 
             table_message.InitializationErrorString().c_str());
1069
1241
    delete output;
1070
 
 
1071
 
    if (close(fd) == -1)
1072
 
      perror(definition_file_tmp);
1073
 
 
1074
 
    if (unlink(definition_file_tmp) == -1)
1075
 
      perror(definition_file_tmp);
1076
 
 
1077
 
    return ER_CORRUPT_TABLE_DEFINITION;
 
1242
    close(fd);
 
1243
    return errno;
1078
1244
  }
1079
1245
 
1080
1246
  delete output;
1081
 
 
1082
 
  if (close(fd) == -1)
1083
 
  {
1084
 
    int error= errno;
1085
 
    perror(definition_file_tmp);
1086
 
 
1087
 
    if (unlink(definition_file_tmp))
1088
 
      perror(definition_file_tmp);
1089
 
 
1090
 
    return error;
1091
 
  }
1092
 
 
1093
 
  if (rename(definition_file_tmp, file_name.c_str()) == -1)
1094
 
  {
1095
 
    int error= errno;
1096
 
    perror(definition_file_tmp);
1097
 
 
1098
 
    if (unlink(definition_file_tmp))
1099
 
      perror(definition_file_tmp);
1100
 
 
1101
 
    return error;
1102
 
  }
1103
 
 
 
1247
  close(fd);
1104
1248
  return 0;
1105
1249
}
1106
1250
 
1107
1251
class CanCreateTable: public unary_function<StorageEngine *, bool>
1108
1252
{
1109
 
  TableIdentifier &identifier;
 
1253
  const TableIdentifier &identifier;
1110
1254
 
1111
1255
public:
1112
 
  CanCreateTable(TableIdentifier &identifier_arg) :
 
1256
  CanCreateTable(const TableIdentifier &identifier_arg) :
1113
1257
    identifier(identifier_arg)
1114
1258
  { }
1115
1259
 
1137
1281
  return false;
1138
1282
}
1139
1283
 
1140
 
bool StorageEngine::readTableFile(const std::string &path, message::Table &table_message)
1141
 
{
1142
 
  fstream input(path.c_str(), ios::in | ios::binary);
1143
 
 
1144
 
  if (input.good())
1145
 
  {
1146
 
    if (table_message.ParseFromIstream(&input))
1147
 
    {
1148
 
      return true;
1149
 
    }
1150
 
 
1151
 
    my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0),
1152
 
             table_message.InitializationErrorString().c_str());
1153
 
  }
1154
 
  else
1155
 
  {
1156
 
    perror(path.c_str());
1157
 
  }
1158
 
 
1159
 
  return false;
1160
 
}
1161
 
 
1162
 
 
1163
 
 
1164
1284
} /* namespace plugin */
1165
1285
} /* namespace drizzled */