~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/plugin/storage_engine.cc

  • Committer: Prafulla Tekawade
  • Date: 2010-08-06 11:21:12 UTC
  • mto: (1711.1.21 build) (1725.1.1 build)
  • mto: This revision was merged to the branch mainline in revision 1714.
  • Revision ID: prafulla_t@users.sourceforge.net-20100806112112-7w5u0s3nx9u67nzt
Fix for Bug 586051

1. test_if_ref method which checks whether predicate is already evaluated
   due to ref/eq_ref access or not was incorrectly removing a predicate 
   that was not implicitly evaluated due to ref access (due to presence of filesort ?)
   It was field=NULL predicate.
   Such predicate should be kept and execution engine will filter out rows
   correctly. Removal of such predicate led to returning of rows which had
   NULL for join/predicate columns.
2. field COMP_OP NULL will always false for all fields except when COMP_OP
   is NULL-safe equality operator. Modified range optimizer to return zero
   row count in such cases.
   Query now does not even run. It returns zero result. As such Fix(1) is not
   required but we might hit that case in some other query (I have not tried it
   yet)
3. Fixed Field::val_str to print "NULL" for literal NULL instead of "0". It
   added lot of confusion while debugging.

Show diffs side-by-side

added added

removed removed

Lines of Context:
32
32
#include <google/protobuf/io/zero_copy_stream.h>
33
33
#include <google/protobuf/io/zero_copy_stream_impl.h>
34
34
 
 
35
#include "drizzled/my_hash.h"
35
36
#include "drizzled/cached_directory.h"
36
37
 
37
38
#include <drizzled/definitions.h>
54
55
#include <drizzled/table_proto.h>
55
56
#include <drizzled/plugin/event_observer.h>
56
57
 
57
 
#include <drizzled/table/shell.h>
58
 
 
59
 
#include "drizzled/message/cache.h"
60
 
 
61
 
#include <boost/algorithm/string/compare.hpp>
62
 
 
63
58
static bool shutdown_has_begun= false; // Once we put in the container for the vector/etc for engines this will go away.
64
59
 
 
60
using namespace std;
 
61
 
65
62
namespace drizzled
66
63
{
67
64
 
71
68
static EngineVector vector_of_engines;
72
69
static EngineVector vector_of_schema_engines;
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
 
82
78
  return vector_of_schema_engines;
83
79
}
84
80
 
85
 
StorageEngine::StorageEngine(const std::string name_arg,
86
 
                             const std::bitset<HTON_BIT_SIZE> &flags_arg) :
 
81
StorageEngine::StorageEngine(const string name_arg,
 
82
                             const bitset<HTON_BIT_SIZE> &flags_arg) :
87
83
  Plugin(name_arg, "StorageEngine"),
88
84
  MonitoredInTransaction(), /* This gives the storage engine a "slot" or ID */
89
85
  flags(flags_arg)
192
188
}
193
189
 
194
190
class FindEngineByName
195
 
  : public std::unary_function<StorageEngine *, bool>
 
191
  : public unary_function<StorageEngine *, bool>
196
192
{
197
 
  const std::string &predicate;
 
193
  const string &target;
198
194
 
199
195
public:
200
 
  explicit FindEngineByName(const std::string &target_arg) :
201
 
    predicate(target_arg)
 
196
  explicit FindEngineByName(const string &target_arg) :
 
197
    target(target_arg)
202
198
  {
203
199
  }
204
 
 
205
200
  result_type operator() (argument_type engine)
206
201
  {
207
 
    return boost::iequals(engine->getName(), predicate);
 
202
    string engine_name(engine->getName());
 
203
 
 
204
    transform(engine_name.begin(), engine_name.end(),
 
205
              engine_name.begin(), ::tolower);
 
206
    return engine_name == target;
208
207
  }
209
208
};
210
209
 
211
 
StorageEngine *StorageEngine::findByName(const std::string &predicate)
 
210
StorageEngine *StorageEngine::findByName(const string &find_str)
212
211
{
213
 
  EngineVector::iterator iter= std::find_if(vector_of_engines.begin(),
214
 
                                            vector_of_engines.end(),
215
 
                                            FindEngineByName(predicate));
 
212
  string search_string(find_str);
 
213
  transform(search_string.begin(), search_string.end(),
 
214
            search_string.begin(), ::tolower);
 
215
 
 
216
  
 
217
  EngineVector::iterator iter= find_if(vector_of_engines.begin(),
 
218
                                       vector_of_engines.end(),
 
219
                                       FindEngineByName(search_string));
216
220
  if (iter != vector_of_engines.end())
217
221
  {
218
222
    StorageEngine *engine= *iter;
223
227
  return NULL;
224
228
}
225
229
 
226
 
StorageEngine *StorageEngine::findByName(Session& session, const std::string &predicate)
 
230
StorageEngine *StorageEngine::findByName(Session& session, const string &find_str)
227
231
{
228
 
  if (boost::iequals(predicate, DEFAULT_STRING))
 
232
  string search_string(find_str);
 
233
  transform(search_string.begin(), search_string.end(),
 
234
            search_string.begin(), ::tolower);
 
235
 
 
236
  if (search_string.compare("default") == 0)
229
237
    return session.getDefaultStorageEngine();
230
238
 
231
 
  EngineVector::iterator iter= std::find_if(vector_of_engines.begin(),
232
 
                                            vector_of_engines.end(),
233
 
                                            FindEngineByName(predicate));
 
239
  EngineVector::iterator iter= find_if(vector_of_engines.begin(),
 
240
                                       vector_of_engines.end(),
 
241
                                       FindEngineByName(search_string));
234
242
  if (iter != vector_of_engines.end())
235
243
  {
236
244
    StorageEngine *engine= *iter;
241
249
  return NULL;
242
250
}
243
251
 
244
 
class StorageEngineCloseConnection : public std::unary_function<StorageEngine *, void>
 
252
class StorageEngineCloseConnection : public unary_function<StorageEngine *, void>
245
253
{
246
254
  Session *session;
247
255
public:
263
271
*/
264
272
void StorageEngine::closeConnection(Session* session)
265
273
{
266
 
  std::for_each(vector_of_engines.begin(), vector_of_engines.end(),
267
 
                StorageEngineCloseConnection(session));
 
274
  for_each(vector_of_engines.begin(), vector_of_engines.end(),
 
275
           StorageEngineCloseConnection(session));
268
276
}
269
277
 
270
278
bool StorageEngine::flushLogs(StorageEngine *engine)
271
279
{
272
280
  if (engine == NULL)
273
281
  {
274
 
    if (std::find_if(vector_of_engines.begin(), vector_of_engines.end(),
275
 
                     std::mem_fun(&StorageEngine::flush_logs))
 
282
    if (find_if(vector_of_engines.begin(), vector_of_engines.end(),
 
283
                mem_fun(&StorageEngine::flush_logs))
276
284
        != vector_of_engines.begin())
277
285
      return true;
278
286
  }
284
292
  return false;
285
293
}
286
294
 
287
 
class StorageEngineGetTableDefinition: public std::unary_function<StorageEngine *,bool>
 
295
class StorageEngineGetTableDefinition: public unary_function<StorageEngine *,bool>
288
296
{
289
297
  Session& session;
290
298
  const TableIdentifier &identifier;
312
320
  }
313
321
};
314
322
 
315
 
class StorageEngineDoesTableExist: public std::unary_function<StorageEngine *, bool>
 
323
class StorageEngineDoesTableExist: public unary_function<StorageEngine *, bool>
316
324
{
317
325
  Session& session;
318
326
  const TableIdentifier &identifier;
343
351
  }
344
352
 
345
353
  EngineVector::iterator iter=
346
 
    std::find_if(vector_of_engines.begin(), vector_of_engines.end(),
347
 
                 StorageEngineDoesTableExist(session, identifier));
 
354
    find_if(vector_of_engines.begin(), vector_of_engines.end(),
 
355
            StorageEngineDoesTableExist(session, identifier));
348
356
 
349
357
  if (iter == vector_of_engines.end())
350
358
  {
356
364
 
357
365
bool plugin::StorageEngine::doDoesTableExist(Session&, const drizzled::TableIdentifier&)
358
366
{
359
 
  std::cerr << " Engine was called for doDoesTableExist() and does not implement it: " << this->getName() << "\n";
 
367
  cerr << " Engine was called for doDoesTableExist() and does not implement it: " << this->getName() << "\n";
360
368
  assert(0);
361
369
  return false;
362
370
}
368
376
*/
369
377
int StorageEngine::getTableDefinition(Session& session,
370
378
                                      const TableIdentifier &identifier,
371
 
                                      message::table::shared_ptr &table_message,
 
379
                                      message::Table &table_message,
372
380
                                      bool include_temporary_tables)
373
381
{
374
382
  int err= ENOENT;
375
383
 
376
384
  if (include_temporary_tables)
377
385
  {
378
 
    Table *table= session.find_temporary_table(identifier);
379
 
    if (table)
380
 
    {
381
 
      table_message.reset(new message::Table(*table->getShare()->getTableProto()));
 
386
    if (session.doGetTableDefinition(identifier, table_message) == EEXIST)
382
387
      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;
 
388
  }
 
389
 
393
390
  EngineVector::iterator iter=
394
 
    std::find_if(vector_of_engines.begin(), vector_of_engines.end(),
395
 
                 StorageEngineGetTableDefinition(session, identifier, message, err));
 
391
    find_if(vector_of_engines.begin(), vector_of_engines.end(),
 
392
            StorageEngineGetTableDefinition(session, identifier, table_message, err));
396
393
 
397
394
  if (iter == vector_of_engines.end())
398
395
  {
399
396
    return ENOENT;
400
397
  }
401
 
  table_message.reset(new message::Table(message));
402
 
 
403
 
 drizzled::message::Cache::singleton().insert(identifier, table_message);
404
398
 
405
399
  return err;
406
400
}
443
437
{
444
438
  int error= 0;
445
439
  int error_proto;
446
 
  message::table::shared_ptr src_proto;
 
440
  message::Table src_proto;
447
441
  StorageEngine *engine;
448
442
 
449
443
  error_proto= StorageEngine::getTableDefinition(session, identifier, src_proto);
450
444
 
451
445
  if (error_proto == ER_CORRUPT_TABLE_DEFINITION)
452
446
  {
453
 
    std::string error_message;
454
 
    identifier.getSQLPath(error_message);
 
447
    string error_message;
455
448
 
 
449
    error_message.append(const_cast<TableIdentifier &>(identifier).getSQLPath());
456
450
    error_message.append(" : ");
457
 
    error_message.append(src_proto->InitializationErrorString());
 
451
    error_message.append(src_proto.InitializationErrorString());
458
452
 
459
453
    my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0), error_message.c_str());
460
454
 
461
455
    return ER_CORRUPT_TABLE_DEFINITION;
462
456
  }
463
457
 
464
 
  if (src_proto)
465
 
    engine= StorageEngine::findByName(session, src_proto->engine().name());
466
 
  else
467
 
    engine= StorageEngine::findByName(session, "");
 
458
  engine= StorageEngine::findByName(session, src_proto.engine().name());
468
459
 
469
460
  if (not engine)
470
461
  {
471
 
    std::string error_message;
472
 
    identifier.getSQLPath(error_message);
473
 
    my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0), error_message.c_str());
 
462
    my_error(ER_CORRUPT_TABLE_DEFINITION, MYF(0), const_cast<TableIdentifier &>(identifier).getSQLPath().c_str());
474
463
 
475
464
    return ER_CORRUPT_TABLE_DEFINITION;
476
465
  }
504
493
    }
505
494
  }
506
495
 
507
 
  drizzled::message::Cache::singleton().erase(identifier);
508
496
 
509
497
  return error;
510
498
}
523
511
                               message::Table& table_message)
524
512
{
525
513
  int error= 1;
 
514
  Table table;
526
515
  TableShare share(identifier);
527
 
  table::Shell table(share);
528
516
  message::Table tmp_proto;
529
517
 
530
518
  if (share.parse_table_proto(session, table_message) || share.open_table_from_share(&session, identifier, "", 0, 0, table))
556
544
 
557
545
    if (error)
558
546
    {
559
 
      std::string path;
560
 
      identifier.getSQLPath(path);
561
 
      my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), path.c_str(), error);
 
547
      my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), const_cast<TableIdentifier &>(identifier).getSQLPath().c_str(), error);
562
548
    }
563
549
 
564
550
    table.delete_table();
567
553
  return(error != 0);
568
554
}
569
555
 
570
 
Cursor *StorageEngine::getCursor(Table &arg)
 
556
Cursor *StorageEngine::getCursor(TableShare &share)
571
557
{
572
 
  return create(arg);
 
558
  return create(share);
573
559
}
574
560
 
575
561
class AddTableIdentifier : 
576
 
  public std::unary_function<StorageEngine *, void>
 
562
  public unary_function<StorageEngine *, void>
577
563
{
578
564
  CachedDirectory &directory;
579
565
  const SchemaIdentifier &identifier;
580
 
  TableIdentifier::vector &set_of_identifiers;
 
566
  TableIdentifiers &set_of_identifiers;
581
567
 
582
568
public:
583
569
 
584
 
  AddTableIdentifier(CachedDirectory &directory_arg, const SchemaIdentifier &identifier_arg, TableIdentifier::vector &of_names) :
 
570
  AddTableIdentifier(CachedDirectory &directory_arg, const SchemaIdentifier &identifier_arg, TableIdentifiers &of_names) :
585
571
    directory(directory_arg),
586
572
    identifier(identifier_arg),
587
573
    set_of_identifiers(of_names)
595
581
};
596
582
 
597
583
 
598
 
void StorageEngine::getIdentifiers(Session &session, const SchemaIdentifier &schema_identifier, TableIdentifier::vector &set_of_identifiers)
 
584
static SchemaIdentifier INFORMATION_SCHEMA_IDENTIFIER("information_schema");
 
585
static SchemaIdentifier DATA_DICTIONARY_IDENTIFIER("data_dictionary");
 
586
 
 
587
void StorageEngine::getIdentifiers(Session &session, const SchemaIdentifier &schema_identifier, TableIdentifiers &set_of_identifiers)
599
588
{
600
 
  static SchemaIdentifier INFORMATION_SCHEMA_IDENTIFIER("information_schema");
601
 
  static SchemaIdentifier DATA_DICTIONARY_IDENTIFIER("data_dictionary");
602
 
 
603
589
  CachedDirectory directory(schema_identifier.getPath(), set_of_table_definition_ext);
604
590
 
605
591
  if (schema_identifier == INFORMATION_SCHEMA_IDENTIFIER)
612
598
    {
613
599
      errno= directory.getError();
614
600
      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
 
      }
 
601
        my_error(ER_BAD_DB_ERROR, MYF(ME_BELL+ME_WAITTANG), const_cast<SchemaIdentifier &>(schema_identifier).getSQLPath().c_str());
620
602
      else
621
 
      {
622
603
        my_error(ER_CANT_READ_DIR, MYF(ME_BELL+ME_WAITTANG), directory.getPath(), errno);
623
 
      }
624
 
 
625
604
      return;
626
605
    }
627
606
  }
628
607
 
629
 
  std::for_each(vector_of_engines.begin(), vector_of_engines.end(),
630
 
                AddTableIdentifier(directory, schema_identifier, set_of_identifiers));
 
608
  for_each(vector_of_engines.begin(), vector_of_engines.end(),
 
609
           AddTableIdentifier(directory, schema_identifier, set_of_identifiers));
631
610
 
632
611
  session.doGetTableIdentifiers(directory, schema_identifier, set_of_identifiers);
633
612
}
634
613
 
635
 
class DropTable: public std::unary_function<TableIdentifier&, bool>
 
614
class DropTable: public unary_function<TableIdentifier&, bool>
636
615
{
637
616
  Session &session;
638
617
  StorageEngine *engine;
651
630
};
652
631
 
653
632
/* This will later be converted to TableIdentifiers */
654
 
class DropTables: public std::unary_function<StorageEngine *, void>
 
633
class DropTables: public unary_function<StorageEngine *, void>
655
634
{
656
635
  Session &session;
657
 
  TableIdentifier::vector &table_identifiers;
 
636
  TableIdentifiers &table_identifiers;
658
637
 
659
638
public:
660
639
 
661
 
  DropTables(Session &session_arg, TableIdentifier::vector &table_identifiers_arg) :
 
640
  DropTables(Session &session_arg, TableIdentifiers &table_identifiers_arg) :
662
641
    session(session_arg),
663
642
    table_identifiers(table_identifiers_arg)
664
643
  { }
667
646
  {
668
647
    // True returning from DropTable means the table has been successfully
669
648
    // 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)),
 
649
    table_identifiers.erase(remove_if(table_identifiers.begin(),
 
650
                                      table_identifiers.end(),
 
651
                                      DropTable(session, engine)),
673
652
                            table_identifiers.end());
674
653
  }
675
654
};
682
661
void StorageEngine::removeLostTemporaryTables(Session &session, const char *directory)
683
662
{
684
663
  CachedDirectory dir(directory, set_of_table_definition_ext);
685
 
  TableIdentifier::vector table_identifiers;
 
664
  TableIdentifiers table_identifiers;
686
665
 
687
666
  if (dir.fail())
688
667
  {
698
677
       fileIter != files.end(); fileIter++)
699
678
  {
700
679
    size_t length;
701
 
    std::string path;
 
680
    string path;
702
681
    CachedDirectory::Entry *entry= *fileIter;
703
682
 
704
683
    /* We remove the file extension. */
716
695
    }
717
696
  }
718
697
 
719
 
  std::for_each(vector_of_engines.begin(), vector_of_engines.end(),
720
 
                DropTables(session, table_identifiers));
721
 
 
 
698
  for_each(vector_of_engines.begin(), vector_of_engines.end(),
 
699
           DropTables(session, table_identifiers));
 
700
  
722
701
  /*
723
702
    Now we just clean up anything that might left over.
724
703
 
725
704
    We rescan because some of what might have been there should
726
705
    now be all nice and cleaned up.
727
706
  */
728
 
  std::set<std::string> all_exts= set_of_table_definition_ext;
 
707
  set<string> all_exts= set_of_table_definition_ext;
729
708
 
730
709
  for (EngineVector::iterator iter= vector_of_engines.begin();
731
710
       iter != vector_of_engines.end() ; iter++)
740
719
  for (CachedDirectory::Entries::iterator fileIter= files.begin();
741
720
       fileIter != files.end(); fileIter++)
742
721
  {
743
 
    std::string path;
 
722
    string path;
744
723
    CachedDirectory::Entry *entry= *fileIter;
745
724
 
746
725
    path+= directory;
1007
986
 
1008
987
int StorageEngine::deleteDefinitionFromPath(const TableIdentifier &identifier)
1009
988
{
1010
 
  std::string path(identifier.getPath());
 
989
  string path(identifier.getPath());
1011
990
 
1012
991
  path.append(DEFAULT_DEFINITION_FILE_EXT);
1013
992
 
1017
996
int StorageEngine::renameDefinitionFromPath(const TableIdentifier &dest, const TableIdentifier &src)
1018
997
{
1019
998
  message::Table table_message;
1020
 
  std::string src_path(src.getPath());
1021
 
  std::string dest_path(dest.getPath());
 
999
  string src_path(src.getPath());
 
1000
  string dest_path(dest.getPath());
1022
1001
 
1023
1002
  src_path.append(DEFAULT_DEFINITION_FILE_EXT);
1024
1003
  dest_path.append(DEFAULT_DEFINITION_FILE_EXT);
1046
1025
int StorageEngine::writeDefinitionFromPath(const TableIdentifier &identifier, message::Table &table_message)
1047
1026
{
1048
1027
  char definition_file_tmp[FN_REFLEN];
1049
 
  std::string file_name(identifier.getPath());
 
1028
  string file_name(identifier.getPath());
1050
1029
 
1051
1030
  file_name.append(DEFAULT_DEFINITION_FILE_EXT);
1052
1031
 
1065
1044
 
1066
1045
  bool success;
1067
1046
 
1068
 
  try
1069
 
  {
 
1047
  try {
1070
1048
    success= table_message.SerializeToZeroCopyStream(output);
1071
1049
  }
1072
1050
  catch (...)
1116
1094
  return 0;
1117
1095
}
1118
1096
 
1119
 
class CanCreateTable: public std::unary_function<StorageEngine *, bool>
 
1097
class CanCreateTable: public unary_function<StorageEngine *, bool>
1120
1098
{
1121
1099
  const TableIdentifier &identifier;
1122
1100
 
1138
1116
bool StorageEngine::canCreateTable(const TableIdentifier &identifier)
1139
1117
{
1140
1118
  EngineVector::iterator iter=
1141
 
    std::find_if(vector_of_engines.begin(), vector_of_engines.end(),
1142
 
                 CanCreateTable(identifier));
 
1119
    find_if(vector_of_engines.begin(), vector_of_engines.end(),
 
1120
            CanCreateTable(identifier));
1143
1121
 
1144
1122
  if (iter == vector_of_engines.end())
1145
1123
  {
1151
1129
 
1152
1130
bool StorageEngine::readTableFile(const std::string &path, message::Table &table_message)
1153
1131
{
1154
 
  std::fstream input(path.c_str(), std::ios::in | std::ios::binary);
 
1132
  fstream input(path.c_str(), ios::in | ios::binary);
1155
1133
 
1156
1134
  if (input.good())
1157
1135
  {