~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_table.cc

  • Committer: Brian Aker
  • Date: 2010-11-19 00:00:46 UTC
  • mto: (1945.2.1 quick)
  • mto: This revision was merged to the branch mainline in revision 1944.
  • Revision ID: brian@tangent.org-20101119000046-iajnd847tmo595ts
Fix style issue around table for message (though this is imperfect,...)

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>
26
26
#include <drizzled/sql_lex.h>
27
27
#include <drizzled/session.h>
28
28
#include <drizzled/sql_base.h>
29
 
#include <drizzled/strfunc.h>
 
29
#include "drizzled/strfunc.h"
 
30
#include <drizzled/db.h>
30
31
#include <drizzled/lock.h>
31
32
#include <drizzled/unireg.h>
32
33
#include <drizzled/item/int.h>
33
34
#include <drizzled/item/empty_string.h>
34
35
#include <drizzled/transaction_services.h>
35
 
#include <drizzled/transaction_services.h>
 
36
#include "drizzled/transaction_services.h"
36
37
#include <drizzled/table_proto.h>
37
38
#include <drizzled/plugin/client.h>
38
39
#include <drizzled/identifier.h>
39
 
#include <drizzled/internal/m_string.h>
40
 
#include <drizzled/global_charset_info.h>
41
 
#include <drizzled/charset.h>
42
 
 
43
 
#include <drizzled/definition/cache.h>
44
 
 
45
 
#include <drizzled/statement/alter_table.h>
46
 
#include <drizzled/sql_table.h>
47
 
#include <drizzled/pthread_globals.h>
48
 
#include <drizzled/typelib.h>
49
 
#include <drizzled/plugin/storage_engine.h>
 
40
#include "drizzled/internal/m_string.h"
 
41
#include "drizzled/global_charset_info.h"
 
42
#include "drizzled/charset.h"
 
43
 
 
44
 
 
45
#include "drizzled/statement/alter_table.h"
 
46
#include "drizzled/sql_table.h"
 
47
#include "drizzled/pthread_globals.h"
50
48
 
51
49
#include <algorithm>
52
50
#include <sstream>
58
56
namespace drizzled
59
57
{
60
58
 
 
59
extern pid_t current_pid;
 
60
 
61
61
bool is_primary_key(KeyInfo *key_info)
62
62
{
63
63
  static const char * primary_key_name="PRIMARY";
85
85
    let's fetch the database default character set and
86
86
    apply it to the table.
87
87
  */
88
 
  identifier::Schema identifier(db);
 
88
  SchemaIdentifier identifier(db);
89
89
  if (create_info->default_table_charset == NULL)
90
90
    create_info->default_table_charset= plugin::StorageEngine::getSchemaCollation(identifier);
91
91
}
108
108
void write_bin_log(Session *session, const std::string &query)
109
109
{
110
110
  TransactionServices &transaction_services= TransactionServices::singleton();
111
 
  transaction_services.rawStatement(*session, query);
 
111
  transaction_services.rawStatement(session, query);
112
112
}
113
113
 
114
114
/*
115
115
  Execute the drop of a normal or temporary table
116
116
 
117
117
  SYNOPSIS
118
 
    rm_table_part2()
 
118
    mysql_rm_table_part2()
119
119
    session                     Thread Cursor
120
120
    tables              Tables to drop
121
121
    if_exists           If set, don't give an error if table doesn't exists.
138
138
   -1   Thread was killed
139
139
*/
140
140
 
141
 
int rm_table_part2(Session *session, TableList *tables, bool if_exists,
142
 
                   bool drop_temporary)
 
141
int mysql_rm_table_part2(Session *session, TableList *tables, bool if_exists,
 
142
                         bool drop_temporary)
143
143
{
144
144
  TableList *table;
145
 
  util::string::vector wrong_tables;
 
145
  String wrong_tables;
146
146
  int error= 0;
147
147
  bool foreign_key_error= false;
148
148
 
149
 
  do
150
 
  {
151
 
    boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex());
152
 
 
153
 
    if (not drop_temporary && session->lock_table_names_exclusively(tables))
154
 
    {
155
 
      return 1;
156
 
    }
157
 
 
158
 
    /* Don't give warnings for not found errors, as we already generate notes */
159
 
    session->no_warnings_for_error= 1;
160
 
 
161
 
    for (table= tables; table; table= table->next_local)
162
 
    {
163
 
      identifier::Table tmp_identifier(table->getSchemaName(), table->getTableName());
164
 
 
165
 
      error= session->drop_temporary_table(tmp_identifier);
166
 
 
167
 
      switch (error) {
168
 
      case  0:
169
 
        // removed temporary table
170
 
        continue;
171
 
      case -1:
 
149
  LOCK_open.lock(); /* Part 2 of rm a table */
 
150
 
 
151
  if (not drop_temporary && session->lock_table_names_exclusively(tables))
 
152
  {
 
153
    LOCK_open.unlock();
 
154
    return 1;
 
155
  }
 
156
 
 
157
  /* Don't give warnings for not found errors, as we already generate notes */
 
158
  session->no_warnings_for_error= 1;
 
159
 
 
160
  for (table= tables; table; table= table->next_local)
 
161
  {
 
162
    TableIdentifier tmp_identifier(table->getSchemaName(), table->getTableName());
 
163
 
 
164
    error= session->drop_temporary_table(tmp_identifier);
 
165
 
 
166
    switch (error) {
 
167
    case  0:
 
168
      // removed temporary table
 
169
      continue;
 
170
    case -1:
 
171
      error= 1;
 
172
      goto err_with_placeholders;
 
173
    default:
 
174
      // temporary table not found
 
175
      error= 0;
 
176
    }
 
177
 
 
178
    if (drop_temporary == false)
 
179
    {
 
180
      Table *locked_table;
 
181
      abort_locked_tables(session, tmp_identifier);
 
182
      table::Cache::singleton().removeTable(session, tmp_identifier,
 
183
                                            RTFC_WAIT_OTHER_THREAD_FLAG |
 
184
                                            RTFC_CHECK_KILLED_FLAG);
 
185
      /*
 
186
        If the table was used in lock tables, remember it so that
 
187
        unlock_table_names can free it
 
188
      */
 
189
      if ((locked_table= drop_locked_tables(session, tmp_identifier)))
 
190
        table->table= locked_table;
 
191
 
 
192
      if (session->getKilled())
 
193
      {
 
194
        error= -1;
 
195
        goto err_with_placeholders;
 
196
      }
 
197
    }
 
198
    TableIdentifier identifier(table->getSchemaName(), table->getTableName(), table->getInternalTmpTable() ? message::Table::INTERNAL : message::Table::STANDARD);
 
199
 
 
200
    if (drop_temporary || not plugin::StorageEngine::doesTableExist(*session, identifier))
 
201
    {
 
202
      // Table was not found on disk and table can't be created from engine
 
203
      if (if_exists)
 
204
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
205
                            ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
 
206
                            table->getTableName());
 
207
      else
172
208
        error= 1;
173
 
        break;
174
 
      default:
175
 
        // temporary table not found
 
209
    }
 
210
    else
 
211
    {
 
212
      error= plugin::StorageEngine::dropTable(*session, identifier);
 
213
 
 
214
      if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) && if_exists)
 
215
      {
176
216
        error= 0;
177
 
      }
178
 
 
179
 
      if (drop_temporary == false)
180
 
      {
181
 
        Table *locked_table;
182
 
        abort_locked_tables(session, tmp_identifier);
183
 
        table::Cache::singleton().removeTable(session, tmp_identifier,
184
 
                                              RTFC_WAIT_OTHER_THREAD_FLAG |
185
 
                                              RTFC_CHECK_KILLED_FLAG);
186
 
        /*
187
 
          If the table was used in lock tables, remember it so that
188
 
          unlock_table_names can free it
189
 
        */
190
 
        if ((locked_table= drop_locked_tables(session, tmp_identifier)))
191
 
          table->table= locked_table;
192
 
 
193
 
        if (session->getKilled())
194
 
        {
195
 
          error= -1;
196
 
          break;
197
 
        }
198
 
      }
199
 
      identifier::Table identifier(table->getSchemaName(), table->getTableName(), table->getInternalTmpTable() ? message::Table::INTERNAL : message::Table::STANDARD);
200
 
 
201
 
      message::table::shared_ptr message= plugin::StorageEngine::getTableMessage(*session, identifier, true);
202
 
 
203
 
      if (drop_temporary || not plugin::StorageEngine::doesTableExist(*session, identifier))
204
 
      {
205
 
        // Table was not found on disk and table can't be created from engine
206
 
        if (if_exists)
207
 
        {
208
 
          push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
209
 
                              ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
210
 
                              table->getTableName());
211
 
        }
212
 
        else
213
 
        {
214
 
          error= 1;
215
 
        }
216
 
      }
217
 
      else
218
 
      {
219
 
        drizzled::error_t local_error;
220
 
 
221
 
        /* Generate transaction event ONLY when we successfully drop */ 
222
 
        if (plugin::StorageEngine::dropTable(*session, identifier, local_error))
223
 
        {
224
 
          if (message) // If we have no definition, we don't know if the table should have been replicated
225
 
          {
226
 
            TransactionServices &transaction_services= TransactionServices::singleton();
227
 
            transaction_services.dropTable(*session, identifier, *message, if_exists);
228
 
          }
229
 
        }
230
 
        else
231
 
        {
232
 
          if (local_error == HA_ERR_NO_SUCH_TABLE and if_exists)
233
 
          {
234
 
            error= 0;
235
 
            session->clear_error();
236
 
          }
237
 
 
238
 
          if (local_error == HA_ERR_ROW_IS_REFERENCED)
239
 
          {
240
 
            /* the table is referenced by a foreign key constraint */
241
 
            foreign_key_error= true;
242
 
          }
243
 
          error= local_error;
244
 
        }
245
 
      }
246
 
 
247
 
      if (error)
248
 
      {
249
 
        wrong_tables.push_back(table->getTableName());
250
 
      }
251
 
    }
252
 
 
253
 
    tables->unlock_table_names();
254
 
 
255
 
  } while (0);
256
 
 
257
 
  if (wrong_tables.size())
 
217
        session->clear_error();
 
218
      }
 
219
 
 
220
      if (error == HA_ERR_ROW_IS_REFERENCED)
 
221
      {
 
222
        /* the table is referenced by a foreign key constraint */
 
223
        foreign_key_error= true;
 
224
      }
 
225
    }
 
226
 
 
227
    if (error == 0 || (if_exists && foreign_key_error == false))
 
228
    {
 
229
      TransactionServices &transaction_services= TransactionServices::singleton();
 
230
      transaction_services.dropTable(session, string(table->getSchemaName()), string(table->getTableName()), if_exists);
 
231
    }
 
232
 
 
233
    if (error)
 
234
    {
 
235
      if (wrong_tables.length())
 
236
        wrong_tables.append(',');
 
237
      wrong_tables.append(String(table->getTableName(), system_charset_info));
 
238
    }
 
239
  }
 
240
  /*
 
241
    It's safe to unlock LOCK_open: we have an exclusive lock
 
242
    on the table name.
 
243
  */
 
244
  LOCK_open.unlock();
 
245
  error= 0;
 
246
 
 
247
  if (wrong_tables.length())
258
248
  {
259
249
    if (not foreign_key_error)
260
250
    {
261
 
      std::string table_error;
262
 
 
263
 
      for (util::string::vector::iterator iter= wrong_tables.begin();
264
 
           iter != wrong_tables.end();
265
 
           iter++)
266
 
      {
267
 
        table_error+= *iter;
268
 
        table_error+= ',';
269
 
      }
270
 
      table_error.resize(table_error.size() -1);
271
 
 
272
251
      my_printf_error(ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), MYF(0),
273
 
                      table_error.c_str());
 
252
                      wrong_tables.c_ptr());
274
253
    }
275
254
    else
276
255
    {
279
258
    error= 1;
280
259
  }
281
260
 
 
261
  LOCK_open.lock(); /* final bit in rm table lock */
 
262
 
 
263
err_with_placeholders:
 
264
  tables->unlock_table_names();
 
265
  LOCK_open.unlock();
282
266
  session->no_warnings_for_error= 0;
283
267
 
284
268
  return error;
285
269
}
286
270
 
 
271
 
 
272
/*
 
273
  Quickly remove a table.
 
274
 
 
275
  SYNOPSIS
 
276
    quick_rm_table()
 
277
      base                      The plugin::StorageEngine handle.
 
278
      db                        The database name.
 
279
      table_name                The table name.
 
280
      is_tmp                    If the table is temp.
 
281
 
 
282
  RETURN
 
283
    0           OK
 
284
    != 0        Error
 
285
*/
 
286
bool quick_rm_table(Session& session,
 
287
                    TableIdentifier &identifier)
 
288
{
 
289
  return (plugin::StorageEngine::dropTable(session, identifier));
 
290
}
 
291
 
287
292
/*
288
293
  Sort keys in the following order:
289
294
  - PRIMARY KEY
483
488
    sql_field->length= 8; // Unireg field length
484
489
    (*blob_columns)++;
485
490
    break;
486
 
 
 
491
  case DRIZZLE_TYPE_VARCHAR:
 
492
    break;
487
493
  case DRIZZLE_TYPE_ENUM:
488
 
    {
489
 
      if (check_duplicates_in_interval("ENUM",
490
 
                                       sql_field->field_name,
491
 
                                       sql_field->interval,
492
 
                                       sql_field->charset,
493
 
                                       &dup_val_count))
494
 
      {
495
 
        return 1;
496
 
      }
497
 
    }
498
 
    break;
499
 
 
500
 
  case DRIZZLE_TYPE_MICROTIME:
 
494
    if (check_duplicates_in_interval("ENUM",
 
495
                                     sql_field->field_name,
 
496
                                     sql_field->interval,
 
497
                                     sql_field->charset,
 
498
                                     &dup_val_count))
 
499
      return 1;
 
500
    break;
 
501
  case DRIZZLE_TYPE_DATE:  // Rest of string types
 
502
  case DRIZZLE_TYPE_DATETIME:
 
503
  case DRIZZLE_TYPE_NULL:
 
504
    break;
 
505
  case DRIZZLE_TYPE_DECIMAL:
 
506
    break;
501
507
  case DRIZZLE_TYPE_TIMESTAMP:
502
508
    /* We should replace old TIMESTAMP fields with their newer analogs */
503
509
    if (sql_field->unireg_check == Field::TIMESTAMP_OLD_FIELD)
513
519
      }
514
520
    }
515
521
    else if (sql_field->unireg_check != Field::NONE)
516
 
    {
517
522
      (*timestamps_with_niladic)++;
518
 
    }
519
523
 
520
524
    (*timestamps)++;
521
 
 
522
 
    break;
523
 
 
524
 
  case DRIZZLE_TYPE_BOOLEAN:
525
 
  case DRIZZLE_TYPE_DATE:  // Rest of string types
526
 
  case DRIZZLE_TYPE_DATETIME:
527
 
  case DRIZZLE_TYPE_DECIMAL:
528
 
  case DRIZZLE_TYPE_DOUBLE:
529
 
  case DRIZZLE_TYPE_LONG:
530
 
  case DRIZZLE_TYPE_LONGLONG:
531
 
  case DRIZZLE_TYPE_NULL:
532
 
  case DRIZZLE_TYPE_TIME:
533
 
  case DRIZZLE_TYPE_UUID:
534
 
  case DRIZZLE_TYPE_VARCHAR:
 
525
    /* fall-through */
 
526
  default:
535
527
    break;
536
528
  }
537
529
 
538
530
  return 0;
539
531
}
540
532
 
541
 
static int prepare_create_table(Session *session,
542
 
                                HA_CREATE_INFO *create_info,
543
 
                                message::Table &create_proto,
544
 
                                AlterInfo *alter_info,
545
 
                                bool tmp_table,
546
 
                                uint32_t *db_options,
547
 
                                KeyInfo **key_info_buffer,
548
 
                                uint32_t *key_count,
549
 
                                int select_field_count)
 
533
static int mysql_prepare_create_table(Session *session,
 
534
                                      HA_CREATE_INFO *create_info,
 
535
                                      message::Table &create_proto,
 
536
                                      AlterInfo *alter_info,
 
537
                                      bool tmp_table,
 
538
                                      uint32_t *db_options,
 
539
                                      KeyInfo **key_info_buffer,
 
540
                                      uint32_t *key_count,
 
541
                                      int select_field_count)
550
542
{
551
543
  const char    *key_name;
552
544
  CreateField   *sql_field,*dup_field;
555
547
  KeyInfo               *key_info;
556
548
  KeyPartInfo *key_part_info;
557
549
  int           timestamps= 0, timestamps_with_niladic= 0;
558
 
  int           dup_no;
 
550
  int           field_no,dup_no;
559
551
  int           select_field_pos,auto_increment=0;
560
 
  List<CreateField>::iterator it(alter_info->create_list.begin());
561
 
  List<CreateField>::iterator it2(alter_info->create_list.begin());
 
552
  List_iterator<CreateField> it(alter_info->create_list);
 
553
  List_iterator<CreateField> it2(alter_info->create_list);
562
554
  uint32_t total_uneven_bit_length= 0;
563
555
 
564
556
  plugin::StorageEngine *engine= plugin::StorageEngine::findByName(create_proto.engine().name());
567
559
  null_fields=blob_columns=0;
568
560
  max_key_length= engine->max_key_length();
569
561
 
570
 
  for (int32_t field_no=0; (sql_field=it++) ; field_no++)
 
562
  for (field_no=0; (sql_field=it++) ; field_no++)
571
563
  {
572
564
    const CHARSET_INFO *save_cs;
573
565
 
577
569
      executing a prepared statement for the second time.
578
570
    */
579
571
    sql_field->length= sql_field->char_length;
580
 
 
581
572
    if (!sql_field->charset)
582
573
      sql_field->charset= create_info->default_table_charset;
583
 
 
584
574
    /*
585
575
      table_charset is set in ALTER Table if we want change character set
586
576
      for all varchar/char columns.
652
642
        interval= sql_field->interval= typelib(session->mem_root,
653
643
                                               sql_field->interval_list);
654
644
 
655
 
        List<String>::iterator int_it(sql_field->interval_list.begin());
 
645
        List_iterator<String> int_it(sql_field->interval_list);
656
646
        String conv, *tmp;
657
647
        char comma_buf[4];
658
648
        int comma_length= cs->cset->wc_mb(cs, ',', (unsigned char*) comma_buf,
678
668
          interval->type_lengths[i]= lengthsp;
679
669
          ((unsigned char *)interval->type_names[i])[lengthsp]= '\0';
680
670
        }
681
 
        sql_field->interval_list.clear(); // Don't need interval_list anymore
 
671
        sql_field->interval_list.empty(); // Don't need interval_list anymore
682
672
      }
683
673
 
684
674
      /* DRIZZLE_TYPE_ENUM */
701
691
          else /* not NULL */
702
692
          {
703
693
            def->length(cs->cset->lengthsp(cs, def->ptr(), def->length()));
704
 
            if (interval->find_type2(def->ptr(), def->length(), cs) == 0) /* not found */
 
694
            if (find_type2(interval, def->ptr(), def->length(), cs) == 0) /* not found */
705
695
            {
706
696
              my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
707
697
              return(true);
778
768
    if (not create_proto.engine().name().compare("MyISAM") &&
779
769
        ((sql_field->flags & BLOB_FLAG) ||
780
770
         (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR)))
781
 
    {
782
771
      (*db_options)|= HA_OPTION_PACK_RECORD;
783
 
    }
784
 
 
785
 
    it2= alter_info->create_list.begin();
 
772
    it2.rewind();
786
773
  }
787
774
 
788
775
  /* record_offset will be increased with 'length-of-null-bits' later */
789
776
  record_offset= 0;
790
777
  null_fields+= total_uneven_bit_length;
791
778
 
792
 
  it= alter_info->create_list.begin();
 
779
  it.rewind();
793
780
  while ((sql_field=it++))
794
781
  {
795
782
    assert(sql_field->charset != 0);
829
816
 
830
817
  /* Create keys */
831
818
 
832
 
  List<Key>::iterator key_iterator(alter_info->key_list.begin());
833
 
  List<Key>::iterator key_iterator2(alter_info->key_list.begin());
 
819
  List_iterator<Key> key_iterator(alter_info->key_list);
 
820
  List_iterator<Key> key_iterator2(alter_info->key_list);
834
821
  uint32_t key_parts=0, fk_key_count=0;
835
822
  bool primary_key=0,unique_key=0;
836
823
  Key *key, *key2;
880
867
    }
881
868
    if (check_identifier_name(&key->name, ER_TOO_LONG_IDENT))
882
869
      return(true);
883
 
    key_iterator2= alter_info->key_list.begin();
 
870
    key_iterator2.rewind ();
884
871
    if (key->type != Key::FOREIGN_KEY)
885
872
    {
886
873
      while ((key2 = key_iterator2++) != key)
933
920
  if (!*key_info_buffer || ! key_part_info)
934
921
    return(true);                               // Out of memory
935
922
 
936
 
  key_iterator= alter_info->key_list.begin();
 
923
  key_iterator.rewind();
937
924
  key_number=0;
938
925
  for (; (key=key_iterator++) ; key_number++)
939
926
  {
992
979
 
993
980
    message::Table::Field *protofield= NULL;
994
981
 
995
 
    List<Key_part_spec>::iterator cols(key->columns.begin());
996
 
    List<Key_part_spec>::iterator cols2(key->columns.begin());
 
982
    List_iterator<Key_part_spec> cols(key->columns), cols2(key->columns);
997
983
    for (uint32_t column_nr=0 ; (column=cols++) ; column_nr++)
998
984
    {
999
985
      uint32_t length;
1000
986
      Key_part_spec *dup_column;
1001
987
      int proto_field_nr= 0;
1002
988
 
1003
 
      it= alter_info->create_list.begin();
 
989
      it.rewind();
1004
990
      field=0;
1005
991
      while ((sql_field=it++) && ++proto_field_nr &&
1006
992
             my_strcasecmp(system_charset_info,
1007
993
                           column->field_name.str,
1008
994
                           sql_field->field_name))
1009
 
      {
1010
995
        field++;
1011
 
      }
1012
 
 
1013
996
      if (!sql_field)
1014
997
      {
1015
998
        my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name.str);
1016
999
        return(true);
1017
1000
      }
1018
 
 
1019
1001
      while ((dup_column= cols2++) != column)
1020
1002
      {
1021
1003
        if (!my_strcasecmp(system_charset_info,
1027
1009
          return(true);
1028
1010
        }
1029
1011
      }
1030
 
      cols2= key->columns.begin();
 
1012
      cols2.rewind();
1031
1013
 
1032
1014
      if (create_proto.field_size() > 0)
1033
1015
        protofield= create_proto.mutable_field(proto_field_nr - 1);
1048
1030
            return true;
1049
1031
          }
1050
1032
        }
1051
 
 
1052
1033
        if (! (sql_field->flags & NOT_NULL_FLAG))
1053
1034
        {
1054
1035
          if (key->type == Key::PRIMARY)
1061
1042
            {
1062
1043
              message::Table::Field::FieldConstraints *constraints;
1063
1044
              constraints= protofield->mutable_constraints();
1064
 
              constraints->set_is_notnull(true);
 
1045
              constraints->set_is_nullable(false);
1065
1046
            }
1066
1047
 
1067
1048
          }
1075
1056
            }
1076
1057
          }
1077
1058
        }
1078
 
 
1079
1059
        if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
1080
1060
        {
1081
1061
          if (column_nr == 0 || (engine->check_flag(HTON_BIT_AUTO_PART_KEY)))
1200
1180
        key_info->name=(char*) key_name;
1201
1181
      }
1202
1182
    }
1203
 
 
1204
1183
    if (!key_info->name || check_column_name(key_info->name))
1205
1184
    {
1206
1185
      my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key_info->name);
1207
1186
      return(true);
1208
1187
    }
1209
 
 
1210
1188
    if (!(key_info->flags & HA_NULL_PART_KEY))
1211
 
    {
1212
1189
      unique_key=1;
1213
 
    }
1214
 
 
1215
1190
    key_info->key_length=(uint16_t) key_length;
1216
 
 
1217
1191
    if (key_length > max_key_length)
1218
1192
    {
1219
1193
      my_error(ER_TOO_LONG_KEY,MYF(0),max_key_length);
1220
1194
      return(true);
1221
1195
    }
1222
 
 
1223
1196
    key_info++;
1224
1197
  }
1225
 
 
1226
1198
  if (!unique_key && !primary_key &&
1227
1199
      (engine->check_flag(HTON_BIT_REQUIRE_PRIMARY_KEY)))
1228
1200
  {
1229
1201
    my_message(ER_REQUIRES_PRIMARY_KEY, ER(ER_REQUIRES_PRIMARY_KEY), MYF(0));
1230
1202
    return(true);
1231
1203
  }
1232
 
 
1233
1204
  if (auto_increment > 0)
1234
1205
  {
1235
1206
    my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
1240
1211
                     (qsort_cmp) sort_keys);
1241
1212
 
1242
1213
  /* Check fields. */
1243
 
  it= alter_info->create_list.begin();
 
1214
  it.rewind();
1244
1215
  while ((sql_field=it++))
1245
1216
  {
1246
1217
    Field::utype type= (Field::utype) MTYP_TYPENR(sql_field->unireg_check);
1247
1218
 
1248
1219
    if (session->variables.sql_mode & MODE_NO_ZERO_DATE &&
1249
1220
        !sql_field->def &&
1250
 
        (sql_field->sql_type == DRIZZLE_TYPE_TIMESTAMP  or sql_field->sql_type == DRIZZLE_TYPE_MICROTIME) &&
 
1221
        sql_field->sql_type == DRIZZLE_TYPE_TIMESTAMP &&
1251
1222
        (sql_field->flags & NOT_NULL_FLAG) &&
1252
1223
        (type == Field::NONE || type == Field::TIMESTAMP_UN_FIELD))
1253
1224
    {
1311
1282
}
1312
1283
 
1313
1284
static bool locked_create_event(Session *session,
1314
 
                                const identifier::Table &identifier,
 
1285
                                TableIdentifier &identifier,
1315
1286
                                HA_CREATE_INFO *create_info,
1316
1287
                                message::Table &table_proto,
1317
1288
                                AlterInfo *alter_info,
1346
1317
        return error;
1347
1318
      }
1348
1319
 
1349
 
      my_error(ER_TABLE_EXISTS_ERROR, identifier);
1350
 
 
 
1320
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getSQLPath().c_str());
1351
1321
      return error;
1352
1322
    }
1353
1323
 
1364
1334
      /*
1365
1335
        @todo improve this error condition.
1366
1336
      */
1367
 
      if (definition::Cache::singleton().find(identifier.getKey()))
 
1337
      if (TableShare::getShare(identifier))
1368
1338
      {
1369
 
        my_error(ER_TABLE_EXISTS_ERROR, identifier);
1370
 
 
 
1339
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getSQLPath().c_str());
1371
1340
        return error;
1372
1341
      }
1373
1342
    }
1405
1374
  if (table_proto.type() == message::Table::STANDARD && not internal_tmp_table)
1406
1375
  {
1407
1376
    TransactionServices &transaction_services= TransactionServices::singleton();
1408
 
    transaction_services.createTable(*session, table_proto);
 
1377
    transaction_services.createTable(session, table_proto);
1409
1378
  }
1410
1379
 
1411
1380
  return false;
1418
1387
  Create a table
1419
1388
 
1420
1389
  SYNOPSIS
1421
 
    create_table_no_lock()
 
1390
    mysql_create_table_no_lock()
1422
1391
    session                     Thread object
1423
1392
    db                  Database
1424
1393
    table_name          Table name
1434
1403
 
1435
1404
    Note that this function assumes that caller already have taken
1436
1405
    name-lock on table being created or used some other way to ensure
1437
 
    that concurrent operations won't intervene. create_table()
 
1406
    that concurrent operations won't intervene. mysql_create_table()
1438
1407
    is a wrapper that can be used for this.
1439
1408
 
1440
1409
  RETURN VALUES
1442
1411
    true  error
1443
1412
*/
1444
1413
 
1445
 
bool create_table_no_lock(Session *session,
1446
 
                                const identifier::Table &identifier,
 
1414
bool mysql_create_table_no_lock(Session *session,
 
1415
                                TableIdentifier &identifier,
1447
1416
                                HA_CREATE_INFO *create_info,
1448
1417
                                message::Table &table_proto,
1449
1418
                                AlterInfo *alter_info,
1468
1437
  set_table_default_charset(create_info, identifier.getSchemaName().c_str());
1469
1438
 
1470
1439
  /* Build a Table object to pass down to the engine, and the do the actual create. */
1471
 
  if (not prepare_create_table(session, create_info, table_proto, alter_info,
1472
 
                               internal_tmp_table,
1473
 
                               &db_options,
1474
 
                               &key_info_buffer, &key_count,
1475
 
                               select_field_count))
 
1440
  if (not mysql_prepare_create_table(session, create_info, table_proto, alter_info,
 
1441
                                     internal_tmp_table,
 
1442
                                     &db_options,
 
1443
                                     &key_info_buffer, &key_count,
 
1444
                                     select_field_count))
1476
1445
  {
1477
 
    boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* CREATE TABLE (some confussion on naming, double check) */
 
1446
    boost_unique_lock_t lock(LOCK_open); /* CREATE TABLE (some confussion on naming, double check) */
1478
1447
    error= locked_create_event(session,
1479
1448
                               identifier,
1480
1449
                               create_info,
1495
1464
  @note the following two methods implement create [temporary] table.
1496
1465
*/
1497
1466
static bool drizzle_create_table(Session *session,
1498
 
                                 const identifier::Table &identifier,
 
1467
                                 TableIdentifier &identifier,
1499
1468
                                 HA_CREATE_INFO *create_info,
1500
1469
                                 message::Table &table_proto,
1501
1470
                                 AlterInfo *alter_info,
1522
1491
    }
1523
1492
    else
1524
1493
    {
1525
 
      my_error(ER_TABLE_EXISTS_ERROR, identifier);
 
1494
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getSQLPath().c_str());
1526
1495
      result= true;
1527
1496
    }
1528
1497
  }
1529
1498
  else
1530
1499
  {
1531
 
    result= create_table_no_lock(session,
 
1500
    result= mysql_create_table_no_lock(session,
1532
1501
                                       identifier,
1533
1502
                                       create_info,
1534
1503
                                       table_proto,
1540
1509
 
1541
1510
  if (name_lock)
1542
1511
  {
1543
 
    boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* Lock for removing name_lock during table create */
 
1512
    boost_unique_lock_t lock(LOCK_open); /* Lock for removing name_lock during table create */
1544
1513
    session->unlink_open_table(name_lock);
1545
1514
  }
1546
1515
 
1549
1518
 
1550
1519
 
1551
1520
/*
1552
 
  Database locking aware wrapper for create_table_no_lock(),
 
1521
  Database locking aware wrapper for mysql_create_table_no_lock(),
1553
1522
*/
1554
 
bool create_table(Session *session,
1555
 
                        const identifier::Table &identifier,
 
1523
bool mysql_create_table(Session *session,
 
1524
                        TableIdentifier &identifier,
1556
1525
                        HA_CREATE_INFO *create_info,
1557
1526
                        message::Table &table_proto,
1558
1527
                        AlterInfo *alter_info,
1562
1531
{
1563
1532
  if (identifier.isTmp())
1564
1533
  {
1565
 
    return create_table_no_lock(session,
 
1534
    return mysql_create_table_no_lock(session,
1566
1535
                                      identifier,
1567
1536
                                      create_info,
1568
1537
                                      table_proto,
1632
1601
  Rename a table.
1633
1602
 
1634
1603
  SYNOPSIS
1635
 
    rename_table()
 
1604
    mysql_rename_table()
1636
1605
      session
1637
1606
      base                      The plugin::StorageEngine handle.
1638
1607
      old_db                    The old database name.
1646
1615
*/
1647
1616
 
1648
1617
bool
1649
 
rename_table(Session &session,
 
1618
mysql_rename_table(Session &session,
1650
1619
                   plugin::StorageEngine *base,
1651
 
                   const identifier::Table &from,
1652
 
                   const identifier::Table &to)
 
1620
                   TableIdentifier &from,
 
1621
                   TableIdentifier &to)
1653
1622
{
1654
1623
  int error= 0;
1655
1624
 
1669
1638
  }
1670
1639
  else if (error)
1671
1640
  {
1672
 
    std::string from_path;
1673
 
    std::string to_path;
1674
 
 
1675
 
    from.getSQLPath(from_path);
1676
 
    to.getSQLPath(to_path);
1677
 
 
1678
 
    const char *from_identifier= from.isTmp() ? "#sql-temporary" : from_path.c_str();
1679
 
    const char *to_identifier= to.isTmp() ? "#sql-temporary" : to_path.c_str();
 
1641
    const char *from_identifier= from.isTmp() ? "#sql-temporary" : from.getSQLPath().c_str();
 
1642
    const char *to_identifier= to.isTmp() ? "#sql-temporary" : to.getSQLPath().c_str();
1680
1643
 
1681
1644
    my_error(ER_ERROR_ON_RENAME, MYF(0), from_identifier, to_identifier, error);
1682
1645
  }
1700
1663
   the table is closed.
1701
1664
 
1702
1665
  PREREQUISITES
1703
 
    Lock on table::Cache::singleton().mutex()
 
1666
    Lock on LOCK_open
1704
1667
    Win32 clients must also have a WRITE LOCK on the table !
1705
1668
*/
1706
1669
 
1708
1671
                              enum ha_extra_function function)
1709
1672
{
1710
1673
 
1711
 
  safe_mutex_assert_owner(table::Cache::singleton().mutex().native_handle());
 
1674
  safe_mutex_assert_owner(LOCK_open.native_handle());
1712
1675
 
1713
1676
  table->cursor->extra(function);
1714
1677
  /* Mark all tables that are in use as 'old' */
1715
1678
  session->abortLock(table);    /* end threads waiting on lock */
1716
1679
 
1717
1680
  /* Wait until all there are no other threads that has this table open */
1718
 
  identifier::Table identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName());
 
1681
  TableIdentifier identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName());
1719
1682
  table::Cache::singleton().removeTable(session, identifier, RTFC_WAIT_OTHER_THREAD_FLAG);
1720
1683
}
1721
1684
 
1732
1695
    reopen the table.
1733
1696
 
1734
1697
  PREREQUISITES
1735
 
    Lock on table::Cache::singleton().mutex()
 
1698
    Lock on LOCK_open
1736
1699
    Win32 clients must also have a WRITE LOCK on the table !
1737
1700
*/
1738
1701
 
1749
1712
  /* Close all copies of 'table'.  This also frees all LOCK TABLES lock */
1750
1713
  unlink_open_table(table);
1751
1714
 
1752
 
  /* When lock on table::Cache::singleton().mutex() is freed other threads can continue */
 
1715
  /* When lock on LOCK_open is freed other threads can continue */
1753
1716
  locking::broadcast_refresh();
1754
1717
}
1755
1718
 
1759
1722
    true  Message should be sent by caller
1760
1723
          (admin operation or network communication failed)
1761
1724
*/
1762
 
static bool admin_table(Session* session, TableList* tables,
 
1725
static bool mysql_admin_table(Session* session, TableList* tables,
1763
1726
                              HA_CHECK_OPT* check_opt,
1764
1727
                              const char *operator_name,
1765
1728
                              thr_lock_type lock_type,
1768
1731
                                                            HA_CHECK_OPT *))
1769
1732
{
1770
1733
  TableList *table;
1771
 
  Select_Lex *select= &session->getLex()->select_lex;
 
1734
  Select_Lex *select= &session->lex->select_lex;
1772
1735
  List<Item> field_list;
1773
1736
  Item *item;
 
1737
  LEX *lex= session->lex;
1774
1738
  int result_code= 0;
1775
1739
  TransactionServices &transaction_services= TransactionServices::singleton();
1776
1740
  const CHARSET_INFO * const cs= system_charset_info;
1777
1741
 
1778
1742
  if (! session->endActiveTransaction())
1779
1743
    return 1;
1780
 
 
1781
1744
  field_list.push_back(item = new Item_empty_string("Table",
1782
1745
                                                    NAME_CHAR_LEN * 2,
1783
1746
                                                    cs));
1788
1751
  item->maybe_null = 1;
1789
1752
  field_list.push_back(item = new Item_empty_string("Msg_text", 255, cs));
1790
1753
  item->maybe_null = 1;
1791
 
  if (session->getClient()->sendFields(&field_list))
 
1754
  if (session->client->sendFields(&field_list))
1792
1755
    return true;
1793
1756
 
1794
1757
  for (table= tables; table; table= table->next_local)
1795
1758
  {
1796
 
    identifier::Table table_identifier(table->getSchemaName(), table->getTableName());
1797
 
    std::string table_name;
 
1759
    char table_name[NAME_LEN*2+2];
1798
1760
    bool fatal_error=0;
1799
1761
 
1800
 
    table_identifier.getSQLPath(table_name);
1801
 
 
 
1762
    snprintf(table_name, sizeof(table_name), "%s.%s", table->getSchemaName(), table->getTableName());
1802
1763
    table->lock_type= lock_type;
1803
1764
    /* open only one table from local list of command */
1804
1765
    {
1813
1774
        so it have to be prepared.
1814
1775
        @todo Investigate if we can put extra tables into argument instead of using lex->query_tables
1815
1776
      */
1816
 
      session->getLex()->query_tables= table;
1817
 
      session->getLex()->query_tables_last= &table->next_global;
1818
 
      session->getLex()->query_tables_own_last= 0;
 
1777
      lex->query_tables= table;
 
1778
      lex->query_tables_last= &table->next_global;
 
1779
      lex->query_tables_own_last= 0;
1819
1780
      session->no_warnings_for_error= 0;
1820
1781
 
1821
1782
      session->openTablesLock(table);
1845
1806
    {
1846
1807
      char buff[FN_REFLEN + DRIZZLE_ERRMSG_SIZE];
1847
1808
      uint32_t length;
1848
 
      session->getClient()->store(table_name.c_str());
1849
 
      session->getClient()->store(operator_name);
1850
 
      session->getClient()->store(STRING_WITH_LEN("error"));
 
1809
      session->client->store(table_name);
 
1810
      session->client->store(operator_name);
 
1811
      session->client->store(STRING_WITH_LEN("error"));
1851
1812
      length= snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY),
1852
 
                       table_name.c_str());
1853
 
      session->getClient()->store(buff, length);
1854
 
      transaction_services.autocommitOrRollback(*session, false);
 
1813
                       table_name);
 
1814
      session->client->store(buff, length);
 
1815
      transaction_services.autocommitOrRollback(session, false);
1855
1816
      session->endTransaction(COMMIT);
1856
1817
      session->close_thread_tables();
1857
 
      session->getLex()->reset_query_tables_list(false);
 
1818
      lex->reset_query_tables_list(false);
1858
1819
      table->table=0;                           // For query cache
1859
 
      if (session->getClient()->flush())
 
1820
      if (session->client->flush())
1860
1821
        goto err;
1861
1822
      continue;
1862
1823
    }
1864
1825
    /* Close all instances of the table to allow repair to rename files */
1865
1826
    if (lock_type == TL_WRITE && table->table->getShare()->getVersion())
1866
1827
    {
1867
 
      table::Cache::singleton().mutex().lock(); /* Lock type is TL_WRITE and we lock to repair the table */
1868
 
      const char *old_message=session->enter_cond(COND_refresh, table::Cache::singleton().mutex(),
 
1828
      LOCK_open.lock(); /* Lock type is TL_WRITE and we lock to repair the table */
 
1829
      const char *old_message=session->enter_cond(COND_refresh, LOCK_open,
1869
1830
                                                  "Waiting to get writelock");
1870
1831
      session->abortLock(table->table);
1871
 
      identifier::Table identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
 
1832
      TableIdentifier identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
1872
1833
      table::Cache::singleton().removeTable(session, identifier, RTFC_WAIT_OTHER_THREAD_FLAG | RTFC_CHECK_KILLED_FLAG);
1873
1834
      session->exit_cond(old_message);
1874
1835
      if (session->getKilled())
1880
1841
 
1881
1842
send_result:
1882
1843
 
1883
 
    session->getLex()->cleanup_after_one_table_open();
 
1844
    lex->cleanup_after_one_table_open();
1884
1845
    session->clear_error();  // these errors shouldn't get client
1885
1846
    {
1886
 
      List<DRIZZLE_ERROR>::iterator it(session->warn_list.begin());
 
1847
      List_iterator_fast<DRIZZLE_ERROR> it(session->warn_list);
1887
1848
      DRIZZLE_ERROR *err;
1888
1849
      while ((err= it++))
1889
1850
      {
1890
 
        session->getClient()->store(table_name.c_str());
1891
 
        session->getClient()->store(operator_name);
1892
 
        session->getClient()->store(warning_level_names[err->level].str,
 
1851
        session->client->store(table_name);
 
1852
        session->client->store(operator_name);
 
1853
        session->client->store(warning_level_names[err->level].str,
1893
1854
                               warning_level_names[err->level].length);
1894
 
        session->getClient()->store(err->msg);
1895
 
        if (session->getClient()->flush())
 
1855
        session->client->store(err->msg);
 
1856
        if (session->client->flush())
1896
1857
          goto err;
1897
1858
      }
1898
1859
      drizzle_reset_errors(session, true);
1899
1860
    }
1900
 
    session->getClient()->store(table_name.c_str());
1901
 
    session->getClient()->store(operator_name);
 
1861
    session->client->store(table_name);
 
1862
    session->client->store(operator_name);
1902
1863
 
1903
1864
    switch (result_code) {
1904
1865
    case HA_ADMIN_NOT_IMPLEMENTED:
1906
1867
        char buf[ERRMSGSIZE+20];
1907
1868
        uint32_t length=snprintf(buf, ERRMSGSIZE,
1908
1869
                             ER(ER_CHECK_NOT_IMPLEMENTED), operator_name);
1909
 
        session->getClient()->store(STRING_WITH_LEN("note"));
1910
 
        session->getClient()->store(buf, length);
 
1870
        session->client->store(STRING_WITH_LEN("note"));
 
1871
        session->client->store(buf, length);
1911
1872
      }
1912
1873
      break;
1913
1874
 
1914
1875
    case HA_ADMIN_OK:
1915
 
      session->getClient()->store(STRING_WITH_LEN("status"));
1916
 
      session->getClient()->store(STRING_WITH_LEN("OK"));
 
1876
      session->client->store(STRING_WITH_LEN("status"));
 
1877
      session->client->store(STRING_WITH_LEN("OK"));
1917
1878
      break;
1918
1879
 
1919
1880
    case HA_ADMIN_FAILED:
1920
 
      session->getClient()->store(STRING_WITH_LEN("status"));
1921
 
      session->getClient()->store(STRING_WITH_LEN("Operation failed"));
 
1881
      session->client->store(STRING_WITH_LEN("status"));
 
1882
      session->client->store(STRING_WITH_LEN("Operation failed"));
1922
1883
      break;
1923
1884
 
1924
1885
    case HA_ADMIN_REJECT:
1925
 
      session->getClient()->store(STRING_WITH_LEN("status"));
1926
 
      session->getClient()->store(STRING_WITH_LEN("Operation need committed state"));
 
1886
      session->client->store(STRING_WITH_LEN("status"));
 
1887
      session->client->store(STRING_WITH_LEN("Operation need committed state"));
1927
1888
      open_for_modify= false;
1928
1889
      break;
1929
1890
 
1930
1891
    case HA_ADMIN_ALREADY_DONE:
1931
 
      session->getClient()->store(STRING_WITH_LEN("status"));
1932
 
      session->getClient()->store(STRING_WITH_LEN("Table is already up to date"));
 
1892
      session->client->store(STRING_WITH_LEN("status"));
 
1893
      session->client->store(STRING_WITH_LEN("Table is already up to date"));
1933
1894
      break;
1934
1895
 
1935
1896
    case HA_ADMIN_CORRUPT:
1936
 
      session->getClient()->store(STRING_WITH_LEN("error"));
1937
 
      session->getClient()->store(STRING_WITH_LEN("Corrupt"));
 
1897
      session->client->store(STRING_WITH_LEN("error"));
 
1898
      session->client->store(STRING_WITH_LEN("Corrupt"));
1938
1899
      fatal_error=1;
1939
1900
      break;
1940
1901
 
1941
1902
    case HA_ADMIN_INVALID:
1942
 
      session->getClient()->store(STRING_WITH_LEN("error"));
1943
 
      session->getClient()->store(STRING_WITH_LEN("Invalid argument"));
 
1903
      session->client->store(STRING_WITH_LEN("error"));
 
1904
      session->client->store(STRING_WITH_LEN("Invalid argument"));
1944
1905
      break;
1945
1906
 
1946
1907
    default:                            // Probably HA_ADMIN_INTERNAL_ERROR
1949
1910
        uint32_t length=snprintf(buf, ERRMSGSIZE,
1950
1911
                             _("Unknown - internal error %d during operation"),
1951
1912
                             result_code);
1952
 
        session->getClient()->store(STRING_WITH_LEN("error"));
1953
 
        session->getClient()->store(buf, length);
 
1913
        session->client->store(STRING_WITH_LEN("error"));
 
1914
        session->client->store(buf, length);
1954
1915
        fatal_error=1;
1955
1916
        break;
1956
1917
      }
1969
1930
        }
1970
1931
        else
1971
1932
        {
1972
 
          boost::unique_lock<boost::mutex> lock(table::Cache::singleton().mutex());
1973
 
          identifier::Table identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
 
1933
          boost::unique_lock<boost::mutex> lock(LOCK_open);
 
1934
          TableIdentifier identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
1974
1935
          table::Cache::singleton().removeTable(session, identifier, RTFC_NO_FLAG);
1975
1936
        }
1976
1937
      }
1977
1938
    }
1978
 
    transaction_services.autocommitOrRollback(*session, false);
 
1939
    transaction_services.autocommitOrRollback(session, false);
1979
1940
    session->endTransaction(COMMIT);
1980
1941
    session->close_thread_tables();
1981
1942
    table->table=0;                             // For query cache
1982
 
    if (session->getClient()->flush())
 
1943
    if (session->client->flush())
1983
1944
      goto err;
1984
1945
  }
1985
1946
 
1987
1948
  return(false);
1988
1949
 
1989
1950
err:
1990
 
  transaction_services.autocommitOrRollback(*session, true);
 
1951
  transaction_services.autocommitOrRollback(session, true);
1991
1952
  session->endTransaction(ROLLBACK);
1992
1953
  session->close_thread_tables();                       // Shouldn't be needed
1993
1954
  if (table)
2001
1962
    Altough exclusive name-lock on target table protects us from concurrent
2002
1963
    DML and DDL operations on it we still want to wrap .FRM creation and call
2003
1964
    to plugin::StorageEngine::createTable() in critical section protected by
2004
 
    table::Cache::singleton().mutex() in order to provide minimal atomicity against operations which
 
1965
    LOCK_open in order to provide minimal atomicity against operations which
2005
1966
    disregard name-locks, like I_S implementation, for example. This is a
2006
1967
    temporary and should not be copied. Instead we should fix our code to
2007
1968
    always honor name-locks.
2008
1969
 
2009
 
    Also some engines (e.g. NDB cluster) require that table::Cache::singleton().mutex() should be held
 
1970
    Also some engines (e.g. NDB cluster) require that LOCK_open should be held
2010
1971
    during the call to plugin::StorageEngine::createTable().
2011
1972
    See bug #28614 for more info.
2012
1973
  */
2013
 
static bool create_table_wrapper(Session &session,
2014
 
                                 const message::Table& create_table_proto,
2015
 
                                 identifier::Table::const_reference destination_identifier,
2016
 
                                 identifier::Table::const_reference source_identifier,
 
1974
static bool create_table_wrapper(Session &session, const message::Table& create_table_proto,
 
1975
                                 TableIdentifier &destination_identifier,
 
1976
                                 TableIdentifier &src_table,
2017
1977
                                 bool is_engine_set)
2018
1978
{
2019
 
  // We require an additional table message because during parsing we used
2020
 
  // a "new" message and it will not have all of the information that the
2021
 
  // source table message would have.
2022
 
  message::Table new_table_message;
2023
 
 
2024
 
  message::table::shared_ptr source_table_message= plugin::StorageEngine::getTableMessage(session, source_identifier);
2025
 
 
2026
 
  if (not source_table_message)
2027
 
  {
2028
 
    my_error(ER_TABLE_UNKNOWN, source_identifier);
2029
 
    return false;
2030
 
  }
2031
 
 
2032
 
  new_table_message.CopyFrom(*source_table_message);
 
1979
  int protoerr= EEXIST;
 
1980
  message::Table new_proto;
 
1981
  message::table::shared_ptr src_proto;
 
1982
 
 
1983
  protoerr= plugin::StorageEngine::getTableDefinition(session,
 
1984
                                                      src_table,
 
1985
                                                      src_proto);
 
1986
  new_proto.CopyFrom(*src_proto);
2033
1987
 
2034
1988
  if (destination_identifier.isTmp())
2035
1989
  {
2036
 
    new_table_message.set_type(message::Table::TEMPORARY);
 
1990
    new_proto.set_type(message::Table::TEMPORARY);
2037
1991
  }
2038
1992
  else
2039
1993
  {
2040
 
    new_table_message.set_type(message::Table::STANDARD);
 
1994
    new_proto.set_type(message::Table::STANDARD);
2041
1995
  }
2042
1996
 
2043
1997
  if (is_engine_set)
2044
1998
  {
2045
 
    new_table_message.mutable_engine()->set_name(create_table_proto.engine().name());
 
1999
    new_proto.mutable_engine()->set_name(create_table_proto.engine().name());
2046
2000
  }
2047
2001
 
2048
2002
  { // We now do a selective copy of elements on to the new table.
2049
 
    new_table_message.set_name(create_table_proto.name());
2050
 
    new_table_message.set_schema(create_table_proto.schema());
2051
 
    new_table_message.set_catalog(create_table_proto.catalog());
 
2003
    new_proto.set_name(create_table_proto.name());
 
2004
    new_proto.set_schema(create_table_proto.schema());
 
2005
    new_proto.set_catalog(create_table_proto.catalog());
2052
2006
  }
2053
2007
 
2054
 
  /* Fix names of foreign keys being added */
2055
 
  for (int32_t j= 0; j < new_table_message.fk_constraint_size(); j++)
 
2008
  if (protoerr && protoerr != EEXIST)
2056
2009
  {
2057
 
    if (new_table_message.fk_constraint(j).has_name())
2058
 
    {
2059
 
      std::string name(new_table_message.name());
2060
 
      char number[20];
2061
 
 
2062
 
      name.append("_ibfk_");
2063
 
      snprintf(number, sizeof(number), "%d", j+1);
2064
 
      name.append(number);
2065
 
 
2066
 
      message::Table::ForeignKeyConstraint *pfkey= new_table_message.mutable_fk_constraint(j);
2067
 
      pfkey->set_name(name);
2068
 
    }
 
2010
    if (errno == ENOENT)
 
2011
      my_error(ER_BAD_DB_ERROR,MYF(0), destination_identifier.getSchemaName().c_str());
 
2012
    else
 
2013
      my_error(ER_CANT_CREATE_FILE, MYF(0), destination_identifier.getPath().c_str(), errno);
 
2014
 
 
2015
    return false;
2069
2016
  }
2070
2017
 
2071
2018
  /*
2072
2019
    As mysql_truncate don't work on a new table at this stage of
2073
 
    creation, instead create the table directly (for both normal and temporary tables).
 
2020
    creation, instead create the table directly (for both normal
 
2021
    and temporary tables).
2074
2022
  */
2075
 
  bool success= plugin::StorageEngine::createTable(session,
2076
 
                                                   destination_identifier,
2077
 
                                                   new_table_message);
 
2023
  int err= plugin::StorageEngine::createTable(session,
 
2024
                                              destination_identifier,
 
2025
                                              new_proto);
2078
2026
 
2079
 
  if (success && not destination_identifier.isTmp())
 
2027
  if (err == false && not destination_identifier.isTmp())
2080
2028
  {
2081
2029
    TransactionServices &transaction_services= TransactionServices::singleton();
2082
 
    transaction_services.createTable(session, new_table_message);
 
2030
    transaction_services.createTable(&session, new_proto);
2083
2031
  }
2084
2032
 
2085
 
  return success;
 
2033
  return err ? false : true;
2086
2034
}
2087
2035
 
2088
2036
/*
2089
2037
  Create a table identical to the specified table
2090
2038
 
2091
2039
  SYNOPSIS
2092
 
    create_like_table()
 
2040
    mysql_create_like_table()
2093
2041
    session             Thread object
2094
2042
    table       Table list element for target table
2095
2043
    src_table   Table list element for source table
2100
2048
    true  error
2101
2049
*/
2102
2050
 
2103
 
bool create_like_table(Session* session,
2104
 
                       identifier::Table::const_reference destination_identifier,
2105
 
                       identifier::Table::const_reference source_identifier,
2106
 
                       message::Table &create_table_proto,
2107
 
                       bool is_if_not_exists,
2108
 
                       bool is_engine_set)
 
2051
bool mysql_create_like_table(Session* session,
 
2052
                             TableIdentifier &destination_identifier,
 
2053
                             TableList* table, TableList* src_table,
 
2054
                             message::Table &create_table_proto,
 
2055
                             bool is_if_not_exists,
 
2056
                             bool is_engine_set)
2109
2057
{
2110
2058
  bool res= true;
2111
 
  bool table_exists= false;
 
2059
  uint32_t not_used;
 
2060
 
 
2061
  /*
 
2062
    By opening source table we guarantee that it exists and no concurrent
 
2063
    DDL operation will mess with it. Later we also take an exclusive
 
2064
    name-lock on target table name, which makes copying of .frm cursor,
 
2065
    call to plugin::StorageEngine::createTable() and binlogging atomic
 
2066
    against concurrent DML and DDL operations on target table.
 
2067
    Thus by holding both these "locks" we ensure that our statement is
 
2068
    properly isolated from all concurrent operations which matter.
 
2069
  */
 
2070
  if (session->open_tables_from_list(&src_table, &not_used))
 
2071
    return true;
 
2072
 
 
2073
  TableIdentifier src_identifier(src_table->table->getShare()->getSchemaName(),
 
2074
                                 src_table->table->getShare()->getTableName(), src_table->table->getShare()->getType());
 
2075
 
 
2076
 
2112
2077
 
2113
2078
  /*
2114
2079
    Check that destination tables does not exist. Note that its name
2116
2081
 
2117
2082
    For temporary tables we don't aim to grab locks.
2118
2083
  */
 
2084
  bool table_exists= false;
2119
2085
  if (destination_identifier.isTmp())
2120
2086
  {
2121
2087
    if (session->find_temporary_table(destination_identifier))
2124
2090
    }
2125
2091
    else
2126
2092
    {
2127
 
      bool was_created= create_table_wrapper(*session,
2128
 
                                             create_table_proto,
2129
 
                                             destination_identifier,
2130
 
                                             source_identifier,
2131
 
                                             is_engine_set);
 
2093
      bool was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
 
2094
                                             src_identifier, is_engine_set);
2132
2095
      if (not was_created) // This is pretty paranoid, but we assume something might not clean up after itself
2133
2096
      {
2134
2097
        (void) session->rm_temporary_table(destination_identifier, true);
2152
2115
    {
2153
2116
      if (name_lock)
2154
2117
      {
2155
 
        boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* unlink open tables for create table like*/
 
2118
        boost_unique_lock_t lock(LOCK_open); /* unlink open tables for create table like*/
2156
2119
        session->unlink_open_table(name_lock);
2157
2120
      }
2158
2121
 
2171
2134
    {
2172
2135
      bool was_created;
2173
2136
      {
2174
 
        boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* We lock for CREATE TABLE LIKE to copy table definition */
 
2137
        boost_unique_lock_t lock(LOCK_open); /* We lock for CREATE TABLE LIKE to copy table definition */
2175
2138
        was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
2176
 
                                          source_identifier, is_engine_set);
 
2139
                                               src_identifier, is_engine_set);
2177
2140
      }
2178
2141
 
2179
2142
      // So we blew the creation of the table, and we scramble to clean up
2180
2143
      // anything that might have been created (read... it is a hack)
2181
2144
      if (not was_created)
2182
2145
      {
2183
 
        plugin::StorageEngine::dropTable(*session, destination_identifier);
 
2146
        quick_rm_table(*session, destination_identifier);
2184
2147
      } 
2185
2148
      else
2186
2149
      {
2190
2153
 
2191
2154
    if (name_lock)
2192
2155
    {
2193
 
      boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* unlink open tables for create table like*/
 
2156
      boost_unique_lock_t lock(LOCK_open); /* unlink open tables for create table like*/
2194
2157
      session->unlink_open_table(name_lock);
2195
2158
    }
2196
2159
  }
2201
2164
    {
2202
2165
      char warn_buff[DRIZZLE_ERRMSG_SIZE];
2203
2166
      snprintf(warn_buff, sizeof(warn_buff),
2204
 
               ER(ER_TABLE_EXISTS_ERROR), destination_identifier.getTableName().c_str());
 
2167
               ER(ER_TABLE_EXISTS_ERROR), table->getTableName());
2205
2168
      push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
2206
 
                   ER_TABLE_EXISTS_ERROR, warn_buff);
2207
 
      return false;
2208
 
    }
2209
 
 
2210
 
    my_error(ER_TABLE_EXISTS_ERROR, destination_identifier);
2211
 
 
2212
 
    return true;
 
2169
                   ER_TABLE_EXISTS_ERROR,warn_buff);
 
2170
      res= false;
 
2171
    }
 
2172
    else
 
2173
    {
 
2174
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table->getTableName());
 
2175
    }
2213
2176
  }
2214
2177
 
2215
 
  return res;
 
2178
  return(res);
2216
2179
}
2217
2180
 
2218
2181
 
2219
 
bool analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
 
2182
bool mysql_analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
2220
2183
{
2221
2184
  thr_lock_type lock_type = TL_READ_NO_INSERT;
2222
2185
 
2223
 
  return(admin_table(session, tables, check_opt,
 
2186
  return(mysql_admin_table(session, tables, check_opt,
2224
2187
                                "analyze", lock_type, true,
2225
2188
                                &Cursor::ha_analyze));
2226
2189
}
2227
2190
 
2228
2191
 
2229
 
bool check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
 
2192
bool mysql_check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
2230
2193
{
2231
2194
  thr_lock_type lock_type = TL_READ_NO_INSERT;
2232
2195
 
2233
 
  return(admin_table(session, tables, check_opt,
 
2196
  return(mysql_admin_table(session, tables, check_opt,
2234
2197
                                "check", lock_type,
2235
2198
                                false,
2236
2199
                                &Cursor::ha_check));