~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_table.cc

  • Committer: pcrews
  • Date: 2011-05-24 17:36:24 UTC
  • mfrom: (1099.4.232 drizzle)
  • Revision ID: pcrews@lucid32-20110524173624-mwr1bvq6fa1r01ao
Updated translations + 2011.05.18 tarball tag

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
 
16
16
/* drop and alter of tables */
17
17
 
18
 
#include "config.h"
 
18
#include <config.h>
19
19
#include <plugin/myisam/myisam.h>
20
20
#include <drizzled/show.h>
21
21
#include <drizzled/error.h>
22
22
#include <drizzled/gettext.h>
23
23
#include <drizzled/data_home.h>
24
24
#include <drizzled/sql_parse.h>
25
 
#include <drizzled/my_hash.h>
26
25
#include <drizzled/sql_lex.h>
27
26
#include <drizzled/session.h>
28
27
#include <drizzled/sql_base.h>
29
 
#include "drizzled/strfunc.h"
30
 
#include <drizzled/db.h>
31
28
#include <drizzled/lock.h>
32
29
#include <drizzled/unireg.h>
33
30
#include <drizzled/item/int.h>
34
31
#include <drizzled/item/empty_string.h>
35
32
#include <drizzled/transaction_services.h>
36
 
#include "drizzled/transaction_services.h"
 
33
#include <drizzled/transaction_services.h>
37
34
#include <drizzled/table_proto.h>
38
35
#include <drizzled/plugin/client.h>
39
36
#include <drizzled/identifier.h>
40
 
#include "drizzled/internal/m_string.h"
41
 
#include "drizzled/global_charset_info.h"
42
 
#include "drizzled/charset.h"
43
 
 
44
 
#include "drizzled/definition/cache.h"
45
 
 
46
 
 
47
 
#include "drizzled/statement/alter_table.h"
48
 
#include "drizzled/sql_table.h"
49
 
#include "drizzled/pthread_globals.h"
50
 
#include "drizzled/plugin/storage_engine.h"
 
37
#include <drizzled/internal/m_string.h>
 
38
#include <drizzled/charset.h>
 
39
#include <drizzled/definition/cache.h>
 
40
#include <drizzled/system_variables.h>
 
41
#include <drizzled/statement/alter_table.h>
 
42
#include <drizzled/sql_table.h>
 
43
#include <drizzled/pthread_globals.h>
 
44
#include <drizzled/typelib.h>
 
45
#include <drizzled/plugin/storage_engine.h>
 
46
#include <drizzled/diagnostics_area.h>
 
47
#include <drizzled/open_tables_state.h>
 
48
#include <drizzled/table/cache.h>
51
49
 
52
50
#include <algorithm>
53
51
#include <sstream>
56
54
 
57
55
using namespace std;
58
56
 
59
 
namespace drizzled
60
 
{
 
57
namespace drizzled {
61
58
 
62
59
bool is_primary_key(KeyInfo *key_info)
63
60
{
92
89
}
93
90
 
94
91
/*
95
 
  SYNOPSIS
96
 
    write_bin_log()
97
 
    session                           Thread object
98
 
    query                         Query to log
99
 
    query_length                  Length of query
100
 
 
101
 
  RETURN VALUES
102
 
    NONE
103
 
 
104
 
  DESCRIPTION
105
 
    Write the binlog if open, routine used in multiple places in this
106
 
    cursor
107
 
*/
108
 
 
109
 
void write_bin_log(Session *session, const std::string &query)
110
 
{
111
 
  TransactionServices &transaction_services= TransactionServices::singleton();
112
 
  transaction_services.rawStatement(*session, query);
113
 
}
114
 
 
115
 
/*
116
92
  Execute the drop of a normal or temporary table
117
93
 
118
94
  SYNOPSIS
143
119
                   bool drop_temporary)
144
120
{
145
121
  TableList *table;
146
 
  String wrong_tables;
 
122
  util::string::vector wrong_tables;
147
123
  int error= 0;
148
124
  bool foreign_key_error= false;
149
125
 
150
126
  do
151
127
  {
152
 
    boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex());
 
128
    boost::mutex::scoped_lock scopedLock(table::Cache::mutex());
153
129
 
154
130
    if (not drop_temporary && session->lock_table_names_exclusively(tables))
155
131
    {
163
139
    {
164
140
      identifier::Table tmp_identifier(table->getSchemaName(), table->getTableName());
165
141
 
166
 
      error= session->drop_temporary_table(tmp_identifier);
 
142
      error= session->open_tables.drop_temporary_table(tmp_identifier);
167
143
 
168
144
      switch (error) {
169
145
      case  0:
179
155
 
180
156
      if (drop_temporary == false)
181
157
      {
182
 
        Table *locked_table;
183
158
        abort_locked_tables(session, tmp_identifier);
184
 
        table::Cache::singleton().removeTable(session, tmp_identifier,
185
 
                                              RTFC_WAIT_OTHER_THREAD_FLAG |
186
 
                                              RTFC_CHECK_KILLED_FLAG);
 
159
        table::Cache::removeTable(*session, tmp_identifier, RTFC_WAIT_OTHER_THREAD_FLAG | RTFC_CHECK_KILLED_FLAG);
187
160
        /*
188
161
          If the table was used in lock tables, remember it so that
189
162
          unlock_table_names can free it
190
163
        */
191
 
        if ((locked_table= drop_locked_tables(session, tmp_identifier)))
 
164
        Table *locked_table= drop_locked_tables(session, tmp_identifier);
 
165
        if (locked_table)
192
166
          table->table= locked_table;
193
167
 
194
168
        if (session->getKilled())
199
173
      }
200
174
      identifier::Table identifier(table->getSchemaName(), table->getTableName(), table->getInternalTmpTable() ? message::Table::INTERNAL : message::Table::STANDARD);
201
175
 
 
176
      message::table::shared_ptr message= plugin::StorageEngine::getTableMessage(*session, identifier, true);
 
177
 
202
178
      if (drop_temporary || not plugin::StorageEngine::doesTableExist(*session, identifier))
203
179
      {
204
180
        // Table was not found on disk and table can't be created from engine
205
181
        if (if_exists)
 
182
        {
206
183
          push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
207
184
                              ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
208
185
                              table->getTableName());
 
186
        }
209
187
        else
210
188
        {
211
189
          error= 1;
218
196
        /* Generate transaction event ONLY when we successfully drop */ 
219
197
        if (plugin::StorageEngine::dropTable(*session, identifier, local_error))
220
198
        {
221
 
          TransactionServices &transaction_services= TransactionServices::singleton();
222
 
          transaction_services.dropTable(*session, identifier, if_exists);
 
199
          if (message) // If we have no definition, we don't know if the table should have been replicated
 
200
          {
 
201
            TransactionServices &transaction_services= TransactionServices::singleton();
 
202
            transaction_services.dropTable(*session, identifier, *message, if_exists);
 
203
          }
223
204
        }
224
205
        else
225
206
        {
240
221
 
241
222
      if (error)
242
223
      {
243
 
        if (wrong_tables.length())
244
 
          wrong_tables.append(',');
245
 
        wrong_tables.append(String(table->getTableName(), system_charset_info));
 
224
        wrong_tables.push_back(table->getTableName());
246
225
      }
247
226
    }
248
227
 
250
229
 
251
230
  } while (0);
252
231
 
253
 
  if (wrong_tables.length())
 
232
  if (wrong_tables.size())
254
233
  {
255
234
    if (not foreign_key_error)
256
235
    {
 
236
      std::string table_error;
 
237
 
 
238
      BOOST_FOREACH(util::string::vector::reference iter, wrong_tables)
 
239
      {
 
240
        table_error+= iter;
 
241
        table_error+= ',';
 
242
      }
 
243
      table_error.resize(table_error.size() -1);
 
244
 
257
245
      my_printf_error(ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), MYF(0),
258
 
                      wrong_tables.c_ptr());
 
246
                      table_error.c_str());
259
247
    }
260
248
    else
261
249
    {
338
326
{
339
327
public:
340
328
  string s;
341
 
  const CHARSET_INFO * const cs;
 
329
  const charset_info_st * const cs;
342
330
 
343
331
  typelib_set_member(const char* value, unsigned int length,
344
 
                     const CHARSET_INFO * const charset)
 
332
                     const charset_info_st * const charset)
345
333
    : s(value, length),
346
334
      cs(charset)
347
335
  {}
370
358
 
371
359
static bool check_duplicates_in_interval(const char *set_or_name,
372
360
                                         const char *name, TYPELIB *typelib,
373
 
                                         const CHARSET_INFO * const cs,
 
361
                                         const charset_info_st * const cs,
374
362
                                         unsigned int *dup_val_count)
375
363
{
376
364
  TYPELIB tmp= *typelib;
385
373
    tmp.type_names++;
386
374
    tmp.type_lengths++;
387
375
    tmp.count--;
388
 
    if (interval_set.find(typelib_set_member(*cur_value, *cur_length, cs)) != interval_set.end())
 
376
    if (interval_set.count(typelib_set_member(*cur_value, *cur_length, cs)))
389
377
    {
390
378
      my_error(ER_DUPLICATED_VALUE_IN_TYPE, MYF(0),
391
379
               name,*cur_value,set_or_name);
416
404
  RETURN VALUES
417
405
    void
418
406
*/
419
 
static void calculate_interval_lengths(const CHARSET_INFO * const cs,
 
407
static void calculate_interval_lengths(const charset_info_st * const cs,
420
408
                                       TYPELIB *interval,
421
409
                                       uint32_t *max_length,
422
410
                                       uint32_t *tot_length)
542
530
  int           timestamps= 0, timestamps_with_niladic= 0;
543
531
  int           dup_no;
544
532
  int           select_field_pos,auto_increment=0;
545
 
  List_iterator<CreateField> it(alter_info->create_list);
546
 
  List_iterator<CreateField> it2(alter_info->create_list);
 
533
  List<CreateField>::iterator it(alter_info->create_list.begin());
 
534
  List<CreateField>::iterator it2(alter_info->create_list.begin());
547
535
  uint32_t total_uneven_bit_length= 0;
548
536
 
549
537
  plugin::StorageEngine *engine= plugin::StorageEngine::findByName(create_proto.engine().name());
550
538
 
551
 
  select_field_pos= alter_info->create_list.elements - select_field_count;
 
539
  select_field_pos= alter_info->create_list.size() - select_field_count;
552
540
  null_fields=blob_columns=0;
553
541
  max_key_length= engine->max_key_length();
554
542
 
555
543
  for (int32_t field_no=0; (sql_field=it++) ; field_no++)
556
544
  {
557
 
    const CHARSET_INFO *save_cs;
 
545
    const charset_info_st *save_cs;
558
546
 
559
547
    /*
560
548
      Initialize length from its original value (number of characters),
619
607
    if (sql_field->sql_type == DRIZZLE_TYPE_ENUM)
620
608
    {
621
609
      size_t dummy;
622
 
      const CHARSET_INFO * const cs= sql_field->charset;
 
610
      const charset_info_st * const cs= sql_field->charset;
623
611
      TYPELIB *interval= sql_field->interval;
624
612
 
625
613
      /*
637
625
        interval= sql_field->interval= typelib(session->mem_root,
638
626
                                               sql_field->interval_list);
639
627
 
640
 
        List_iterator<String> int_it(sql_field->interval_list);
 
628
        List<String>::iterator int_it(sql_field->interval_list.begin());
641
629
        String conv, *tmp;
642
630
        char comma_buf[4];
643
631
        int comma_length= cs->cset->wc_mb(cs, ',', (unsigned char*) comma_buf,
651
639
          if (String::needs_conversion(tmp->length(), tmp->charset(),
652
640
                                       cs, &dummy))
653
641
          {
654
 
            size_t cnv_errs;
655
 
            conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs);
 
642
            conv.copy(tmp->ptr(), tmp->length(), cs);
656
643
            interval->type_names[i]= session->mem_root->strmake_root(conv.ptr(), conv.length());
657
644
            interval->type_lengths[i]= conv.length();
658
645
          }
663
650
          interval->type_lengths[i]= lengthsp;
664
651
          ((unsigned char *)interval->type_names[i])[lengthsp]= '\0';
665
652
        }
666
 
        sql_field->interval_list.empty(); // Don't need interval_list anymore
 
653
        sql_field->interval_list.clear(); // Don't need interval_list anymore
667
654
      }
668
655
 
669
656
      /* DRIZZLE_TYPE_ENUM */
686
673
          else /* not NULL */
687
674
          {
688
675
            def->length(cs->cset->lengthsp(cs, def->ptr(), def->length()));
689
 
            if (find_type2(interval, def->ptr(), def->length(), cs) == 0) /* not found */
 
676
            if (interval->find_type2(def->ptr(), def->length(), cs) == 0) /* not found */
690
677
            {
691
678
              my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
692
679
              return(true);
767
754
      (*db_options)|= HA_OPTION_PACK_RECORD;
768
755
    }
769
756
 
770
 
    it2.rewind();
 
757
    it2= alter_info->create_list.begin();
771
758
  }
772
759
 
773
760
  /* record_offset will be increased with 'length-of-null-bits' later */
774
761
  record_offset= 0;
775
762
  null_fields+= total_uneven_bit_length;
776
763
 
777
 
  it.rewind();
 
764
  it= alter_info->create_list.begin();
778
765
  while ((sql_field=it++))
779
766
  {
780
767
    assert(sql_field->charset != 0);
814
801
 
815
802
  /* Create keys */
816
803
 
817
 
  List_iterator<Key> key_iterator(alter_info->key_list);
818
 
  List_iterator<Key> key_iterator2(alter_info->key_list);
 
804
  List<Key>::iterator key_iterator(alter_info->key_list.begin());
 
805
  List<Key>::iterator key_iterator2(alter_info->key_list.begin());
819
806
  uint32_t key_parts=0, fk_key_count=0;
820
807
  bool primary_key=0,unique_key=0;
821
808
  Key *key, *key2;
845
832
                                       fk_key->update_opt,
846
833
                                       fk_key->match_opt);
847
834
 
848
 
      if (fk_key->ref_columns.elements &&
849
 
          fk_key->ref_columns.elements != fk_key->columns.elements)
 
835
      if (fk_key->ref_columns.size() &&
 
836
          fk_key->ref_columns.size() != fk_key->columns.size())
850
837
      {
851
838
        my_error(ER_WRONG_FK_DEF, MYF(0),
852
839
                 (fk_key->name.str ? fk_key->name.str :
858
845
    }
859
846
    (*key_count)++;
860
847
    tmp= engine->max_key_parts();
861
 
    if (key->columns.elements > tmp)
 
848
    if (key->columns.size() > tmp)
862
849
    {
863
850
      my_error(ER_TOO_MANY_KEY_PARTS,MYF(0),tmp);
864
851
      return(true);
865
852
    }
866
853
    if (check_identifier_name(&key->name, ER_TOO_LONG_IDENT))
867
854
      return(true);
868
 
    key_iterator2.rewind ();
 
855
    key_iterator2= alter_info->key_list.begin();
869
856
    if (key->type != Key::FOREIGN_KEY)
870
857
    {
871
858
      while ((key2 = key_iterator2++) != key)
882
869
          /* @todo issue warning message */
883
870
          /* mark that the generated key should be ignored */
884
871
          if (!key2->generated ||
885
 
              (key->generated && key->columns.elements <
886
 
               key2->columns.elements))
 
872
              (key->generated && key->columns.size() <
 
873
               key2->columns.size()))
887
874
            key->name.str= ignore_key;
888
875
          else
889
876
          {
890
877
            key2->name.str= ignore_key;
891
 
            key_parts-= key2->columns.elements;
 
878
            key_parts-= key2->columns.size();
892
879
            (*key_count)--;
893
880
          }
894
881
          break;
896
883
      }
897
884
    }
898
885
    if (key->name.str != ignore_key)
899
 
      key_parts+=key->columns.elements;
 
886
      key_parts+=key->columns.size();
900
887
    else
901
888
      (*key_count)--;
902
889
    if (key->name.str && !tmp_table && (key->type != Key::PRIMARY) &&
918
905
  if (!*key_info_buffer || ! key_part_info)
919
906
    return(true);                               // Out of memory
920
907
 
921
 
  key_iterator.rewind();
 
908
  key_iterator= alter_info->key_list.begin();
922
909
  key_number=0;
923
910
  for (; (key=key_iterator++) ; key_number++)
924
911
  {
949
936
    if (key->generated)
950
937
      key_info->flags|= HA_GENERATED_KEY;
951
938
 
952
 
    key_info->key_parts=(uint8_t) key->columns.elements;
 
939
    key_info->key_parts=(uint8_t) key->columns.size();
953
940
    key_info->key_part=key_part_info;
954
941
    key_info->usable_key_parts= key_number;
955
942
    key_info->algorithm= key->key_create_info.algorithm;
977
964
 
978
965
    message::Table::Field *protofield= NULL;
979
966
 
980
 
    List_iterator<Key_part_spec> cols(key->columns), cols2(key->columns);
 
967
    List<Key_part_spec>::iterator cols(key->columns.begin());
 
968
    List<Key_part_spec>::iterator cols2(key->columns.begin());
981
969
    for (uint32_t column_nr=0 ; (column=cols++) ; column_nr++)
982
970
    {
983
971
      uint32_t length;
984
972
      Key_part_spec *dup_column;
985
973
      int proto_field_nr= 0;
986
974
 
987
 
      it.rewind();
 
975
      it= alter_info->create_list.begin();
988
976
      field=0;
989
977
      while ((sql_field=it++) && ++proto_field_nr &&
990
978
             my_strcasecmp(system_charset_info,
1011
999
          return(true);
1012
1000
        }
1013
1001
      }
1014
 
      cols2.rewind();
 
1002
      cols2= key->columns.begin();
1015
1003
 
1016
1004
      if (create_proto.field_size() > 0)
1017
1005
        protofield= create_proto.mutable_field(proto_field_nr - 1);
1224
1212
                     (qsort_cmp) sort_keys);
1225
1213
 
1226
1214
  /* Check fields. */
1227
 
  it.rewind();
 
1215
  it= alter_info->create_list.begin();
1228
1216
  while ((sql_field=it++))
1229
1217
  {
1230
1218
    Field::utype type= (Field::utype) MTYP_TYPENR(sql_field->unireg_check);
1231
1219
 
1232
1220
    if (session->variables.sql_mode & MODE_NO_ZERO_DATE &&
1233
1221
        !sql_field->def &&
1234
 
        sql_field->sql_type == DRIZZLE_TYPE_TIMESTAMP &&
 
1222
        (sql_field->sql_type == DRIZZLE_TYPE_TIMESTAMP  or sql_field->sql_type == DRIZZLE_TYPE_MICROTIME) &&
1235
1223
        (sql_field->flags & NOT_NULL_FLAG) &&
1236
1224
        (type == Field::NONE || type == Field::TIMESTAMP_UN_FIELD))
1237
1225
    {
1348
1336
      /*
1349
1337
        @todo improve this error condition.
1350
1338
      */
1351
 
      if (definition::Cache::singleton().find(identifier.getKey()))
 
1339
      if (definition::Cache::find(identifier.getKey()))
1352
1340
      {
1353
1341
        my_error(ER_TABLE_EXISTS_ERROR, identifier);
1354
1342
 
1375
1363
    /* Open table and put in temporary table list */
1376
1364
    if (not (session->open_temporary_table(identifier)))
1377
1365
    {
1378
 
      (void) session->rm_temporary_table(identifier);
 
1366
      (void) session->open_tables.rm_temporary_table(identifier);
1379
1367
      return error;
1380
1368
    }
1381
1369
  }
1440
1428
  bool          error= true;
1441
1429
 
1442
1430
  /* Check for duplicate fields and check type of table to create */
1443
 
  if (not alter_info->create_list.elements)
 
1431
  if (not alter_info->create_list.size())
1444
1432
  {
1445
1433
    my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
1446
1434
               MYF(0));
1458
1446
                               &key_info_buffer, &key_count,
1459
1447
                               select_field_count))
1460
1448
  {
1461
 
    boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* CREATE TABLE (some confussion on naming, double check) */
 
1449
    boost::mutex::scoped_lock lock(table::Cache::mutex()); /* CREATE TABLE (some confussion on naming, double check) */
1462
1450
    error= locked_create_event(session,
1463
1451
                               identifier,
1464
1452
                               create_info,
1487
1475
                                 uint32_t select_field_count,
1488
1476
                                 bool is_if_not_exists)
1489
1477
{
1490
 
  Table *name_lock= NULL;
 
1478
  Table *name_lock= session->lock_table_name_if_not_cached(identifier);
1491
1479
  bool result;
1492
 
 
1493
 
  if (session->lock_table_name_if_not_cached(identifier, &name_lock))
1494
 
  {
1495
 
    result= true;
1496
 
  }
1497
 
  else if (name_lock == NULL)
 
1480
  if (name_lock == NULL)
1498
1481
  {
1499
1482
    if (is_if_not_exists)
1500
1483
    {
1524
1507
 
1525
1508
  if (name_lock)
1526
1509
  {
1527
 
    boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* Lock for removing name_lock during table create */
 
1510
    boost::mutex::scoped_lock lock(table::Cache::mutex()); /* Lock for removing name_lock during table create */
1528
1511
    session->unlink_open_table(name_lock);
1529
1512
  }
1530
1513
 
1635
1618
                   const identifier::Table &from,
1636
1619
                   const identifier::Table &to)
1637
1620
{
1638
 
  int error= 0;
1639
 
 
1640
 
  assert(base);
1641
 
 
1642
1621
  if (not plugin::StorageEngine::doesSchemaExist(to))
1643
1622
  {
1644
1623
    my_error(ER_NO_DB_ERROR, MYF(0), to.getSchemaName().c_str());
1645
1624
    return true;
1646
1625
  }
1647
1626
 
1648
 
  error= base->renameTable(session, from, to);
1649
 
 
 
1627
  int error= base->renameTable(session, from, to);
1650
1628
  if (error == HA_ERR_WRONG_COMMAND)
1651
 
  {
1652
1629
    my_error(ER_NOT_SUPPORTED_YET, MYF(0), "ALTER Table");
1653
 
  }
1654
1630
  else if (error)
1655
1631
  {
1656
 
    std::string from_path;
1657
 
    std::string to_path;
1658
 
 
1659
 
    from.getSQLPath(from_path);
1660
 
    to.getSQLPath(to_path);
1661
 
 
1662
 
    const char *from_identifier= from.isTmp() ? "#sql-temporary" : from_path.c_str();
1663
 
    const char *to_identifier= to.isTmp() ? "#sql-temporary" : to_path.c_str();
1664
 
 
1665
 
    my_error(ER_ERROR_ON_RENAME, MYF(0), from_identifier, to_identifier, error);
 
1632
    my_error(ER_ERROR_ON_RENAME, MYF(0), 
 
1633
                        from.isTmp() ? "#sql-temporary" : from.getSQLPath().c_str(), 
 
1634
                        to.isTmp() ? "#sql-temporary" : to.getSQLPath().c_str(), error);
1666
1635
  }
1667
 
 
1668
 
  return error ? true : false; 
 
1636
  return error; 
1669
1637
}
1670
1638
 
1671
1639
 
1684
1652
   the table is closed.
1685
1653
 
1686
1654
  PREREQUISITES
1687
 
    Lock on table::Cache::singleton().mutex()
 
1655
    Lock on table::Cache::mutex()
1688
1656
    Win32 clients must also have a WRITE LOCK on the table !
1689
1657
*/
1690
1658
 
1692
1660
                              enum ha_extra_function function)
1693
1661
{
1694
1662
 
1695
 
  safe_mutex_assert_owner(table::Cache::singleton().mutex().native_handle());
 
1663
  safe_mutex_assert_owner(table::Cache::mutex().native_handle());
1696
1664
 
1697
1665
  table->cursor->extra(function);
1698
1666
  /* Mark all tables that are in use as 'old' */
1700
1668
 
1701
1669
  /* Wait until all there are no other threads that has this table open */
1702
1670
  identifier::Table identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName());
1703
 
  table::Cache::singleton().removeTable(session, identifier, RTFC_WAIT_OTHER_THREAD_FLAG);
 
1671
  table::Cache::removeTable(*session, identifier, RTFC_WAIT_OTHER_THREAD_FLAG);
1704
1672
}
1705
1673
 
1706
1674
/*
1716
1684
    reopen the table.
1717
1685
 
1718
1686
  PREREQUISITES
1719
 
    Lock on table::Cache::singleton().mutex()
 
1687
    Lock on table::Cache::mutex()
1720
1688
    Win32 clients must also have a WRITE LOCK on the table !
1721
1689
*/
1722
1690
 
1725
1693
 
1726
1694
  wait_while_table_is_used(this, table, HA_EXTRA_FORCE_REOPEN);
1727
1695
  /* Close lock if this is not got with LOCK TABLES */
1728
 
  if (lock)
 
1696
  if (open_tables.lock)
1729
1697
  {
1730
 
    unlockTables(lock);
1731
 
    lock= NULL;                 // Start locked threads
 
1698
    unlockTables(open_tables.lock);
 
1699
    open_tables.lock= NULL;                     // Start locked threads
1732
1700
  }
1733
1701
  /* Close all copies of 'table'.  This also frees all LOCK TABLES lock */
1734
1702
  unlink_open_table(table);
1735
1703
 
1736
 
  /* When lock on table::Cache::singleton().mutex() is freed other threads can continue */
 
1704
  /* When lock on table::Cache::mutex() is freed other threads can continue */
1737
1705
  locking::broadcast_refresh();
1738
1706
}
1739
1707
 
1752
1720
                                                            HA_CHECK_OPT *))
1753
1721
{
1754
1722
  TableList *table;
1755
 
  Select_Lex *select= &session->lex->select_lex;
 
1723
  Select_Lex *select= &session->lex().select_lex;
1756
1724
  List<Item> field_list;
1757
1725
  Item *item;
1758
 
  LEX *lex= session->lex;
1759
1726
  int result_code= 0;
1760
1727
  TransactionServices &transaction_services= TransactionServices::singleton();
1761
 
  const CHARSET_INFO * const cs= system_charset_info;
 
1728
  const charset_info_st * const cs= system_charset_info;
1762
1729
 
1763
1730
  if (! session->endActiveTransaction())
1764
1731
    return 1;
 
1732
 
1765
1733
  field_list.push_back(item = new Item_empty_string("Table",
1766
1734
                                                    NAME_CHAR_LEN * 2,
1767
1735
                                                    cs));
1777
1745
 
1778
1746
  for (table= tables; table; table= table->next_local)
1779
1747
  {
1780
 
    char table_name[NAME_LEN*2+2];
 
1748
    identifier::Table table_identifier(table->getSchemaName(), table->getTableName());
1781
1749
    bool fatal_error=0;
1782
1750
 
1783
 
    snprintf(table_name, sizeof(table_name), "%s.%s", table->getSchemaName(), table->getTableName());
 
1751
    std::string table_name = table_identifier.getSQLPath();
 
1752
 
1784
1753
    table->lock_type= lock_type;
1785
1754
    /* open only one table from local list of command */
1786
1755
    {
1795
1764
        so it have to be prepared.
1796
1765
        @todo Investigate if we can put extra tables into argument instead of using lex->query_tables
1797
1766
      */
1798
 
      lex->query_tables= table;
1799
 
      lex->query_tables_last= &table->next_global;
1800
 
      lex->query_tables_own_last= 0;
 
1767
      session->lex().query_tables= table;
 
1768
      session->lex().query_tables_last= &table->next_global;
 
1769
      session->lex().query_tables_own_last= 0;
1801
1770
      session->no_warnings_for_error= 0;
1802
1771
 
1803
1772
      session->openTablesLock(table);
1816
1785
    */
1817
1786
    if (!table->table)
1818
1787
    {
1819
 
      if (!session->warn_list.elements)
 
1788
      if (!session->main_da().m_warn_list.size())
1820
1789
        push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1821
1790
                     ER_CHECK_NO_SUCH_TABLE, ER(ER_CHECK_NO_SUCH_TABLE));
1822
1791
      result_code= HA_ADMIN_CORRUPT;
1827
1796
    {
1828
1797
      char buff[FN_REFLEN + DRIZZLE_ERRMSG_SIZE];
1829
1798
      uint32_t length;
1830
 
      session->getClient()->store(table_name);
 
1799
      session->getClient()->store(table_name.c_str());
1831
1800
      session->getClient()->store(operator_name);
1832
1801
      session->getClient()->store(STRING_WITH_LEN("error"));
1833
1802
      length= snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY),
1834
 
                       table_name);
 
1803
                       table_name.c_str());
1835
1804
      session->getClient()->store(buff, length);
1836
1805
      transaction_services.autocommitOrRollback(*session, false);
1837
1806
      session->endTransaction(COMMIT);
1838
1807
      session->close_thread_tables();
1839
 
      lex->reset_query_tables_list(false);
 
1808
      session->lex().reset_query_tables_list(false);
1840
1809
      table->table=0;                           // For query cache
1841
1810
      if (session->getClient()->flush())
1842
1811
        goto err;
1846
1815
    /* Close all instances of the table to allow repair to rename files */
1847
1816
    if (lock_type == TL_WRITE && table->table->getShare()->getVersion())
1848
1817
    {
1849
 
      table::Cache::singleton().mutex().lock(); /* Lock type is TL_WRITE and we lock to repair the table */
1850
 
      const char *old_message=session->enter_cond(COND_refresh, table::Cache::singleton().mutex(),
 
1818
      table::Cache::mutex().lock(); /* Lock type is TL_WRITE and we lock to repair the table */
 
1819
      const char *old_message=session->enter_cond(COND_refresh, table::Cache::mutex(),
1851
1820
                                                  "Waiting to get writelock");
1852
1821
      session->abortLock(table->table);
1853
1822
      identifier::Table identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
1854
 
      table::Cache::singleton().removeTable(session, identifier, RTFC_WAIT_OTHER_THREAD_FLAG | RTFC_CHECK_KILLED_FLAG);
 
1823
      table::Cache::removeTable(*session, identifier, RTFC_WAIT_OTHER_THREAD_FLAG | RTFC_CHECK_KILLED_FLAG);
1855
1824
      session->exit_cond(old_message);
1856
1825
      if (session->getKilled())
1857
1826
        goto err;
1862
1831
 
1863
1832
send_result:
1864
1833
 
1865
 
    lex->cleanup_after_one_table_open();
 
1834
    session->lex().cleanup_after_one_table_open();
1866
1835
    session->clear_error();  // these errors shouldn't get client
1867
1836
    {
1868
 
      List_iterator_fast<DRIZZLE_ERROR> it(session->warn_list);
 
1837
      List<DRIZZLE_ERROR>::iterator it(session->main_da().m_warn_list.begin());
1869
1838
      DRIZZLE_ERROR *err;
1870
1839
      while ((err= it++))
1871
1840
      {
1872
 
        session->getClient()->store(table_name);
 
1841
        session->getClient()->store(table_name.c_str());
1873
1842
        session->getClient()->store(operator_name);
1874
1843
        session->getClient()->store(warning_level_names[err->level].str,
1875
1844
                               warning_level_names[err->level].length);
1879
1848
      }
1880
1849
      drizzle_reset_errors(session, true);
1881
1850
    }
1882
 
    session->getClient()->store(table_name);
 
1851
    session->getClient()->store(table_name.c_str());
1883
1852
    session->getClient()->store(operator_name);
1884
1853
 
1885
1854
    switch (result_code) {
1951
1920
        }
1952
1921
        else
1953
1922
        {
1954
 
          boost::unique_lock<boost::mutex> lock(table::Cache::singleton().mutex());
1955
 
          identifier::Table identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
1956
 
          table::Cache::singleton().removeTable(session, identifier, RTFC_NO_FLAG);
 
1923
          boost::unique_lock<boost::mutex> lock(table::Cache::mutex());
 
1924
          identifier::Table identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
 
1925
          table::Cache::removeTable(*session, identifier, RTFC_NO_FLAG);
1957
1926
        }
1958
1927
      }
1959
1928
    }
1983
1952
    Altough exclusive name-lock on target table protects us from concurrent
1984
1953
    DML and DDL operations on it we still want to wrap .FRM creation and call
1985
1954
    to plugin::StorageEngine::createTable() in critical section protected by
1986
 
    table::Cache::singleton().mutex() in order to provide minimal atomicity against operations which
 
1955
    table::Cache::mutex() in order to provide minimal atomicity against operations which
1987
1956
    disregard name-locks, like I_S implementation, for example. This is a
1988
1957
    temporary and should not be copied. Instead we should fix our code to
1989
1958
    always honor name-locks.
1990
1959
 
1991
 
    Also some engines (e.g. NDB cluster) require that table::Cache::singleton().mutex() should be held
 
1960
    Also some engines (e.g. NDB cluster) require that table::Cache::mutex() should be held
1992
1961
    during the call to plugin::StorageEngine::createTable().
1993
1962
    See bug #28614 for more info.
1994
1963
  */
1995
1964
static bool create_table_wrapper(Session &session,
1996
1965
                                 const message::Table& create_table_proto,
1997
 
                                 identifier::Table::const_reference destination_identifier,
1998
 
                                 identifier::Table::const_reference source_identifier,
 
1966
                                 const identifier::Table& destination_identifier,
 
1967
                                 const identifier::Table& source_identifier,
1999
1968
                                 bool is_engine_set)
2000
1969
{
2001
1970
  // We require an additional table message because during parsing we used
2002
1971
  // a "new" message and it will not have all of the information that the
2003
1972
  // source table message would have.
2004
1973
  message::Table new_table_message;
2005
 
  drizzled::error_t error;
2006
1974
 
2007
 
  message::table::shared_ptr source_table_message= plugin::StorageEngine::getTableMessage(session, source_identifier, error);
 
1975
  message::table::shared_ptr source_table_message= plugin::StorageEngine::getTableMessage(session, source_identifier);
2008
1976
 
2009
1977
  if (not source_table_message)
2010
1978
  {
2084
2052
*/
2085
2053
 
2086
2054
bool create_like_table(Session* session,
2087
 
                       identifier::Table::const_reference destination_identifier,
2088
 
                       identifier::Table::const_reference source_identifier,
 
2055
                       const identifier::Table& destination_identifier,
 
2056
                       const identifier::Table& source_identifier,
2089
2057
                       message::Table &create_table_proto,
2090
2058
                       bool is_if_not_exists,
2091
2059
                       bool is_engine_set)
2101
2069
  */
2102
2070
  if (destination_identifier.isTmp())
2103
2071
  {
2104
 
    if (session->find_temporary_table(destination_identifier))
 
2072
    if (session->open_tables.find_temporary_table(destination_identifier))
2105
2073
    {
2106
2074
      table_exists= true;
2107
2075
    }
2114
2082
                                             is_engine_set);
2115
2083
      if (not was_created) // This is pretty paranoid, but we assume something might not clean up after itself
2116
2084
      {
2117
 
        (void) session->rm_temporary_table(destination_identifier, true);
 
2085
        (void) session->open_tables.rm_temporary_table(destination_identifier, true);
2118
2086
      }
2119
2087
      else if (not session->open_temporary_table(destination_identifier))
2120
2088
      {
2121
2089
        // We created, but we can't open... also, a hack.
2122
 
        (void) session->rm_temporary_table(destination_identifier, true);
 
2090
        (void) session->open_tables.rm_temporary_table(destination_identifier, true);
2123
2091
      }
2124
2092
      else
2125
2093
      {
2129
2097
  }
2130
2098
  else // Standard table which will require locks.
2131
2099
  {
2132
 
    Table *name_lock= 0;
2133
 
 
2134
 
    if (session->lock_table_name_if_not_cached(destination_identifier, &name_lock))
2135
 
    {
2136
 
      if (name_lock)
2137
 
      {
2138
 
        boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* unlink open tables for create table like*/
2139
 
        session->unlink_open_table(name_lock);
2140
 
      }
2141
 
 
2142
 
      return res;
2143
 
    }
2144
 
 
 
2100
    Table *name_lock= session->lock_table_name_if_not_cached(destination_identifier);
2145
2101
    if (not name_lock)
2146
2102
    {
2147
2103
      table_exists= true;
2154
2110
    {
2155
2111
      bool was_created;
2156
2112
      {
2157
 
        boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* We lock for CREATE TABLE LIKE to copy table definition */
 
2113
        boost::mutex::scoped_lock lock(table::Cache::mutex()); /* We lock for CREATE TABLE LIKE to copy table definition */
2158
2114
        was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
2159
2115
                                          source_identifier, is_engine_set);
2160
2116
      }
2173
2129
 
2174
2130
    if (name_lock)
2175
2131
    {
2176
 
      boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* unlink open tables for create table like*/
 
2132
      boost::mutex::scoped_lock lock(table::Cache::mutex()); /* unlink open tables for create table like*/
2177
2133
      session->unlink_open_table(name_lock);
2178
2134
    }
2179
2135
  }