~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_table.cc

  • Committer: Monty Taylor
  • Date: 2011-02-13 17:26:39 UTC
  • mfrom: (2157.2.2 give-in-to-pkg-config)
  • mto: This revision was merged to the branch mainline in revision 2166.
  • Revision ID: mordred@inaugust.com-20110213172639-nhy7i72sfhoq13ms
Merged in pkg-config fixes.

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