~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_table.cc

  • Committer: lbieber
  • Date: 2010-10-06 16:34:16 UTC
  • mfrom: (1816.1.3 build)
  • Revision ID: lbieber@orisndriz08-20101006163416-ea0sl59qgpglk21y
Merge Monty - Change the requirement from either libinnodb to libhaildb. Also, tied it to version 2.2
Merge Andrew - fix bug 650935: remove --compress from all clients
Merge Andrew - fix bug 653471: Add -A to drizzle client
Merge Travis - 621861 = To change C structs to C++ classes in Drizzle

Show diffs side-by-side

added added

removed removed

Lines of Context:
41
41
#include "drizzled/global_charset_info.h"
42
42
#include "drizzled/charset.h"
43
43
 
44
 
#include "drizzled/definition/cache.h"
45
 
 
46
44
 
47
45
#include "drizzled/statement/alter_table.h"
48
46
#include "drizzled/sql_table.h"
49
47
#include "drizzled/pthread_globals.h"
50
 
#include "drizzled/plugin/storage_engine.h"
51
48
 
52
49
#include <algorithm>
53
50
#include <sstream>
59
56
namespace drizzled
60
57
{
61
58
 
 
59
extern pid_t current_pid;
 
60
 
62
61
bool is_primary_key(KeyInfo *key_info)
63
62
{
64
63
  static const char * primary_key_name="PRIMARY";
86
85
    let's fetch the database default character set and
87
86
    apply it to the table.
88
87
  */
89
 
  identifier::Schema identifier(db);
 
88
  SchemaIdentifier identifier(db);
90
89
  if (create_info->default_table_charset == NULL)
91
90
    create_info->default_table_charset= plugin::StorageEngine::getSchemaCollation(identifier);
92
91
}
106
105
    cursor
107
106
*/
108
107
 
109
 
void write_bin_log(Session *session, const std::string &query)
 
108
void write_bin_log(Session *session,
 
109
                   char const *query)
110
110
{
111
111
  TransactionServices &transaction_services= TransactionServices::singleton();
112
 
  transaction_services.rawStatement(*session, query);
 
112
  transaction_services.rawStatement(session, query);
113
113
}
114
114
 
115
115
/*
116
116
  Execute the drop of a normal or temporary table
117
117
 
118
118
  SYNOPSIS
119
 
    rm_table_part2()
 
119
    mysql_rm_table_part2()
120
120
    session                     Thread Cursor
121
121
    tables              Tables to drop
122
122
    if_exists           If set, don't give an error if table doesn't exists.
139
139
   -1   Thread was killed
140
140
*/
141
141
 
142
 
int rm_table_part2(Session *session, TableList *tables, bool if_exists,
143
 
                   bool drop_temporary)
 
142
int mysql_rm_table_part2(Session *session, TableList *tables, bool if_exists,
 
143
                         bool drop_temporary)
144
144
{
145
145
  TableList *table;
146
146
  String wrong_tables;
147
147
  int error= 0;
148
148
  bool foreign_key_error= false;
149
149
 
150
 
  do
151
 
  {
152
 
    boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex());
153
 
 
154
 
    if (not drop_temporary && session->lock_table_names_exclusively(tables))
155
 
    {
156
 
      return 1;
157
 
    }
158
 
 
159
 
    /* Don't give warnings for not found errors, as we already generate notes */
160
 
    session->no_warnings_for_error= 1;
161
 
 
162
 
    for (table= tables; table; table= table->next_local)
163
 
    {
164
 
      identifier::Table tmp_identifier(table->getSchemaName(), table->getTableName());
165
 
 
166
 
      error= session->drop_temporary_table(tmp_identifier);
167
 
 
168
 
      switch (error) {
169
 
      case  0:
170
 
        // removed temporary table
171
 
        continue;
172
 
      case -1:
 
150
  LOCK_open.lock(); /* Part 2 of rm a table */
 
151
 
 
152
  /*
 
153
    If we have the table in the definition cache, we don't have to check the
 
154
    .frm cursor to find if the table is a normal table (not view) and what
 
155
    engine to use.
 
156
  */
 
157
 
 
158
  for (table= tables; table; table= table->next_local)
 
159
  {
 
160
    TableIdentifier identifier(table->db, table->table_name);
 
161
    TableShare *share;
 
162
    table->setDbType(NULL);
 
163
 
 
164
    if ((share= TableShare::getShare(identifier)))
 
165
    {
 
166
      table->setDbType(share->db_type());
 
167
    }
 
168
  }
 
169
 
 
170
  if (not drop_temporary && lock_table_names_exclusively(session, tables))
 
171
  {
 
172
    LOCK_open.unlock();
 
173
    return 1;
 
174
  }
 
175
 
 
176
  /* Don't give warnings for not found errors, as we already generate notes */
 
177
  session->no_warnings_for_error= 1;
 
178
 
 
179
  for (table= tables; table; table= table->next_local)
 
180
  {
 
181
    char *db=table->db;
 
182
 
 
183
    error= session->drop_temporary_table(table);
 
184
 
 
185
    switch (error) {
 
186
    case  0:
 
187
      // removed temporary table
 
188
      continue;
 
189
    case -1:
 
190
      error= 1;
 
191
      goto err_with_placeholders;
 
192
    default:
 
193
      // temporary table not found
 
194
      error= 0;
 
195
    }
 
196
 
 
197
    if (drop_temporary == false)
 
198
    {
 
199
      Table *locked_table;
 
200
      TableIdentifier identifier(db, table->table_name);
 
201
      abort_locked_tables(session, identifier);
 
202
      remove_table_from_cache(session, identifier,
 
203
                              RTFC_WAIT_OTHER_THREAD_FLAG |
 
204
                              RTFC_CHECK_KILLED_FLAG);
 
205
      /*
 
206
        If the table was used in lock tables, remember it so that
 
207
        unlock_table_names can free it
 
208
      */
 
209
      if ((locked_table= drop_locked_tables(session, identifier)))
 
210
        table->table= locked_table;
 
211
 
 
212
      if (session->killed)
 
213
      {
 
214
        error= -1;
 
215
        goto err_with_placeholders;
 
216
      }
 
217
    }
 
218
    TableIdentifier identifier(db, table->table_name, table->getInternalTmpTable() ? message::Table::INTERNAL : message::Table::STANDARD);
 
219
 
 
220
    if (drop_temporary || not plugin::StorageEngine::doesTableExist(*session, identifier))
 
221
    {
 
222
      // Table was not found on disk and table can't be created from engine
 
223
      if (if_exists)
 
224
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
225
                            ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
 
226
                            table->table_name);
 
227
      else
173
228
        error= 1;
174
 
        break;
175
 
      default:
176
 
        // temporary table not found
 
229
    }
 
230
    else
 
231
    {
 
232
      error= plugin::StorageEngine::dropTable(*session, identifier);
 
233
 
 
234
      if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) && if_exists)
 
235
      {
177
236
        error= 0;
178
 
      }
179
 
 
180
 
      if (drop_temporary == false)
181
 
      {
182
 
        Table *locked_table;
183
 
        abort_locked_tables(session, tmp_identifier);
184
 
        table::Cache::singleton().removeTable(session, tmp_identifier,
185
 
                                              RTFC_WAIT_OTHER_THREAD_FLAG |
186
 
                                              RTFC_CHECK_KILLED_FLAG);
187
 
        /*
188
 
          If the table was used in lock tables, remember it so that
189
 
          unlock_table_names can free it
190
 
        */
191
 
        if ((locked_table= drop_locked_tables(session, tmp_identifier)))
192
 
          table->table= locked_table;
193
 
 
194
 
        if (session->getKilled())
195
 
        {
196
 
          error= -1;
197
 
          break;
198
 
        }
199
 
      }
200
 
      identifier::Table identifier(table->getSchemaName(), table->getTableName(), table->getInternalTmpTable() ? message::Table::INTERNAL : message::Table::STANDARD);
201
 
 
202
 
      if (drop_temporary || not plugin::StorageEngine::doesTableExist(*session, identifier))
203
 
      {
204
 
        // Table was not found on disk and table can't be created from engine
205
 
        if (if_exists)
206
 
          push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
207
 
                              ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
208
 
                              table->getTableName());
209
 
        else
210
 
        {
211
 
          error= 1;
212
 
        }
213
 
      }
214
 
      else
215
 
      {
216
 
        drizzled::error_t local_error;
217
 
 
218
 
        /* Generate transaction event ONLY when we successfully drop */ 
219
 
        if (plugin::StorageEngine::dropTable(*session, identifier, local_error))
220
 
        {
221
 
          TransactionServices &transaction_services= TransactionServices::singleton();
222
 
          transaction_services.dropTable(*session, identifier, if_exists);
223
 
        }
224
 
        else
225
 
        {
226
 
          if (local_error == HA_ERR_NO_SUCH_TABLE and if_exists)
227
 
          {
228
 
            error= 0;
229
 
            session->clear_error();
230
 
          }
231
 
 
232
 
          if (local_error == HA_ERR_ROW_IS_REFERENCED)
233
 
          {
234
 
            /* the table is referenced by a foreign key constraint */
235
 
            foreign_key_error= true;
236
 
          }
237
 
          error= local_error;
238
 
        }
239
 
      }
240
 
 
241
 
      if (error)
242
 
      {
243
 
        if (wrong_tables.length())
244
 
          wrong_tables.append(',');
245
 
        wrong_tables.append(String(table->getTableName(), system_charset_info));
246
 
      }
247
 
    }
248
 
 
249
 
    tables->unlock_table_names();
250
 
 
251
 
  } while (0);
 
237
        session->clear_error();
 
238
      }
 
239
 
 
240
      if (error == HA_ERR_ROW_IS_REFERENCED)
 
241
      {
 
242
        /* the table is referenced by a foreign key constraint */
 
243
        foreign_key_error= true;
 
244
      }
 
245
    }
 
246
 
 
247
    if (error == 0 || (if_exists && foreign_key_error == false))
 
248
    {
 
249
      TransactionServices &transaction_services= TransactionServices::singleton();
 
250
      transaction_services.dropTable(session, string(db), string(table->table_name), if_exists);
 
251
    }
 
252
 
 
253
    if (error)
 
254
    {
 
255
      if (wrong_tables.length())
 
256
        wrong_tables.append(',');
 
257
      wrong_tables.append(String(table->table_name,system_charset_info));
 
258
    }
 
259
  }
 
260
  /*
 
261
    It's safe to unlock LOCK_open: we have an exclusive lock
 
262
    on the table name.
 
263
  */
 
264
  LOCK_open.unlock();
 
265
  error= 0;
252
266
 
253
267
  if (wrong_tables.length())
254
268
  {
264
278
    error= 1;
265
279
  }
266
280
 
 
281
  LOCK_open.lock(); /* final bit in rm table lock */
 
282
 
 
283
err_with_placeholders:
 
284
  unlock_table_names(tables, NULL);
 
285
  LOCK_open.unlock();
267
286
  session->no_warnings_for_error= 0;
268
287
 
269
288
  return error;
270
289
}
271
290
 
 
291
 
 
292
/*
 
293
  Quickly remove a table.
 
294
 
 
295
  SYNOPSIS
 
296
    quick_rm_table()
 
297
      base                      The plugin::StorageEngine handle.
 
298
      db                        The database name.
 
299
      table_name                The table name.
 
300
      is_tmp                    If the table is temp.
 
301
 
 
302
  RETURN
 
303
    0           OK
 
304
    != 0        Error
 
305
*/
 
306
bool quick_rm_table(Session& session,
 
307
                    TableIdentifier &identifier)
 
308
{
 
309
  return (plugin::StorageEngine::dropTable(session, identifier));
 
310
}
 
311
 
272
312
/*
273
313
  Sort keys in the following order:
274
314
  - PRIMARY KEY
468
508
    sql_field->length= 8; // Unireg field length
469
509
    (*blob_columns)++;
470
510
    break;
471
 
 
 
511
  case DRIZZLE_TYPE_VARCHAR:
 
512
    break;
472
513
  case DRIZZLE_TYPE_ENUM:
473
 
    {
474
 
      if (check_duplicates_in_interval("ENUM",
475
 
                                       sql_field->field_name,
476
 
                                       sql_field->interval,
477
 
                                       sql_field->charset,
478
 
                                       &dup_val_count))
479
 
      {
480
 
        return 1;
481
 
      }
482
 
    }
483
 
    break;
484
 
 
485
 
  case DRIZZLE_TYPE_MICROTIME:
 
514
    if (check_duplicates_in_interval("ENUM",
 
515
                                     sql_field->field_name,
 
516
                                     sql_field->interval,
 
517
                                     sql_field->charset,
 
518
                                     &dup_val_count))
 
519
      return 1;
 
520
    break;
 
521
  case DRIZZLE_TYPE_DATE:  // Rest of string types
 
522
  case DRIZZLE_TYPE_DATETIME:
 
523
  case DRIZZLE_TYPE_NULL:
 
524
    break;
 
525
  case DRIZZLE_TYPE_DECIMAL:
 
526
    break;
486
527
  case DRIZZLE_TYPE_TIMESTAMP:
487
528
    /* We should replace old TIMESTAMP fields with their newer analogs */
488
529
    if (sql_field->unireg_check == Field::TIMESTAMP_OLD_FIELD)
498
539
      }
499
540
    }
500
541
    else if (sql_field->unireg_check != Field::NONE)
501
 
    {
502
542
      (*timestamps_with_niladic)++;
503
 
    }
504
543
 
505
544
    (*timestamps)++;
506
 
 
507
 
    break;
508
 
 
509
 
  case DRIZZLE_TYPE_BOOLEAN:
510
 
  case DRIZZLE_TYPE_DATE:  // Rest of string types
511
 
  case DRIZZLE_TYPE_DATETIME:
512
 
  case DRIZZLE_TYPE_DECIMAL:
513
 
  case DRIZZLE_TYPE_DOUBLE:
514
 
  case DRIZZLE_TYPE_LONG:
515
 
  case DRIZZLE_TYPE_LONGLONG:
516
 
  case DRIZZLE_TYPE_NULL:
517
 
  case DRIZZLE_TYPE_TIME:
518
 
  case DRIZZLE_TYPE_UUID:
519
 
  case DRIZZLE_TYPE_VARCHAR:
 
545
    /* fall-through */
 
546
  default:
520
547
    break;
521
548
  }
522
549
 
523
550
  return 0;
524
551
}
525
552
 
526
 
static int prepare_create_table(Session *session,
527
 
                                HA_CREATE_INFO *create_info,
528
 
                                message::Table &create_proto,
529
 
                                AlterInfo *alter_info,
530
 
                                bool tmp_table,
531
 
                                uint32_t *db_options,
532
 
                                KeyInfo **key_info_buffer,
533
 
                                uint32_t *key_count,
534
 
                                int select_field_count)
 
553
static int mysql_prepare_create_table(Session *session,
 
554
                                      HA_CREATE_INFO *create_info,
 
555
                                      message::Table &create_proto,
 
556
                                      AlterInfo *alter_info,
 
557
                                      bool tmp_table,
 
558
                                      uint32_t *db_options,
 
559
                                      KeyInfo **key_info_buffer,
 
560
                                      uint32_t *key_count,
 
561
                                      int select_field_count)
535
562
{
536
563
  const char    *key_name;
537
564
  CreateField   *sql_field,*dup_field;
540
567
  KeyInfo               *key_info;
541
568
  KeyPartInfo *key_part_info;
542
569
  int           timestamps= 0, timestamps_with_niladic= 0;
543
 
  int           dup_no;
 
570
  int           field_no,dup_no;
544
571
  int           select_field_pos,auto_increment=0;
545
572
  List_iterator<CreateField> it(alter_info->create_list);
546
573
  List_iterator<CreateField> it2(alter_info->create_list);
552
579
  null_fields=blob_columns=0;
553
580
  max_key_length= engine->max_key_length();
554
581
 
555
 
  for (int32_t field_no=0; (sql_field=it++) ; field_no++)
 
582
  for (field_no=0; (sql_field=it++) ; field_no++)
556
583
  {
557
584
    const CHARSET_INFO *save_cs;
558
585
 
562
589
      executing a prepared statement for the second time.
563
590
    */
564
591
    sql_field->length= sql_field->char_length;
565
 
 
566
592
    if (!sql_field->charset)
567
593
      sql_field->charset= create_info->default_table_charset;
568
 
 
569
594
    /*
570
595
      table_charset is set in ALTER Table if we want change character set
571
596
      for all varchar/char columns.
618
643
 
619
644
    if (sql_field->sql_type == DRIZZLE_TYPE_ENUM)
620
645
    {
621
 
      size_t dummy;
 
646
      uint32_t dummy;
622
647
      const CHARSET_INFO * const cs= sql_field->charset;
623
648
      TYPELIB *interval= sql_field->interval;
624
649
 
651
676
          if (String::needs_conversion(tmp->length(), tmp->charset(),
652
677
                                       cs, &dummy))
653
678
          {
654
 
            size_t cnv_errs;
 
679
            uint32_t cnv_errs;
655
680
            conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs);
656
681
            interval->type_names[i]= session->mem_root->strmake_root(conv.ptr(), conv.length());
657
682
            interval->type_lengths[i]= conv.length();
693
718
            }
694
719
          }
695
720
        }
696
 
        uint32_t new_dummy;
697
 
        calculate_interval_lengths(cs, interval, &field_length, &new_dummy);
 
721
        calculate_interval_lengths(cs, interval, &field_length, &dummy);
698
722
        sql_field->length= field_length;
699
723
      }
700
724
      set_if_smaller(sql_field->length, (uint32_t)MAX_FIELD_WIDTH-1);
763
787
    if (not create_proto.engine().name().compare("MyISAM") &&
764
788
        ((sql_field->flags & BLOB_FLAG) ||
765
789
         (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR)))
766
 
    {
767
790
      (*db_options)|= HA_OPTION_PACK_RECORD;
768
 
    }
769
 
 
770
791
    it2.rewind();
771
792
  }
772
793
 
990
1011
             my_strcasecmp(system_charset_info,
991
1012
                           column->field_name.str,
992
1013
                           sql_field->field_name))
993
 
      {
994
1014
        field++;
995
 
      }
996
 
 
997
1015
      if (!sql_field)
998
1016
      {
999
1017
        my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name.str);
1000
1018
        return(true);
1001
1019
      }
1002
 
 
1003
1020
      while ((dup_column= cols2++) != column)
1004
1021
      {
1005
1022
        if (!my_strcasecmp(system_charset_info,
1032
1049
            return true;
1033
1050
          }
1034
1051
        }
1035
 
 
1036
1052
        if (! (sql_field->flags & NOT_NULL_FLAG))
1037
1053
        {
1038
1054
          if (key->type == Key::PRIMARY)
1045
1061
            {
1046
1062
              message::Table::Field::FieldConstraints *constraints;
1047
1063
              constraints= protofield->mutable_constraints();
1048
 
              constraints->set_is_notnull(true);
 
1064
              constraints->set_is_nullable(false);
1049
1065
            }
1050
1066
 
1051
1067
          }
1059
1075
            }
1060
1076
          }
1061
1077
        }
1062
 
 
1063
1078
        if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
1064
1079
        {
1065
1080
          if (column_nr == 0 || (engine->check_flag(HTON_BIT_AUTO_PART_KEY)))
1184
1199
        key_info->name=(char*) key_name;
1185
1200
      }
1186
1201
    }
1187
 
 
1188
1202
    if (!key_info->name || check_column_name(key_info->name))
1189
1203
    {
1190
1204
      my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key_info->name);
1191
1205
      return(true);
1192
1206
    }
1193
 
 
1194
1207
    if (!(key_info->flags & HA_NULL_PART_KEY))
1195
 
    {
1196
1208
      unique_key=1;
1197
 
    }
1198
 
 
1199
1209
    key_info->key_length=(uint16_t) key_length;
1200
 
 
1201
1210
    if (key_length > max_key_length)
1202
1211
    {
1203
1212
      my_error(ER_TOO_LONG_KEY,MYF(0),max_key_length);
1204
1213
      return(true);
1205
1214
    }
1206
 
 
1207
1215
    key_info++;
1208
1216
  }
1209
 
 
1210
1217
  if (!unique_key && !primary_key &&
1211
1218
      (engine->check_flag(HTON_BIT_REQUIRE_PRIMARY_KEY)))
1212
1219
  {
1213
1220
    my_message(ER_REQUIRES_PRIMARY_KEY, ER(ER_REQUIRES_PRIMARY_KEY), MYF(0));
1214
1221
    return(true);
1215
1222
  }
1216
 
 
1217
1223
  if (auto_increment > 0)
1218
1224
  {
1219
1225
    my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
1295
1301
}
1296
1302
 
1297
1303
static bool locked_create_event(Session *session,
1298
 
                                const identifier::Table &identifier,
 
1304
                                TableIdentifier &identifier,
1299
1305
                                HA_CREATE_INFO *create_info,
1300
1306
                                message::Table &table_proto,
1301
1307
                                AlterInfo *alter_info,
1330
1336
        return error;
1331
1337
      }
1332
1338
 
1333
 
      my_error(ER_TABLE_EXISTS_ERROR, identifier);
1334
 
 
 
1339
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getSQLPath().c_str());
1335
1340
      return error;
1336
1341
    }
1337
1342
 
1348
1353
      /*
1349
1354
        @todo improve this error condition.
1350
1355
      */
1351
 
      if (definition::Cache::singleton().find(identifier.getKey()))
 
1356
      if (TableShare::getShare(identifier))
1352
1357
      {
1353
 
        my_error(ER_TABLE_EXISTS_ERROR, identifier);
1354
 
 
 
1358
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getSQLPath().c_str());
1355
1359
        return error;
1356
1360
      }
1357
1361
    }
1389
1393
  if (table_proto.type() == message::Table::STANDARD && not internal_tmp_table)
1390
1394
  {
1391
1395
    TransactionServices &transaction_services= TransactionServices::singleton();
1392
 
    transaction_services.createTable(*session, table_proto);
 
1396
    transaction_services.createTable(session, table_proto);
1393
1397
  }
1394
1398
 
1395
1399
  return false;
1402
1406
  Create a table
1403
1407
 
1404
1408
  SYNOPSIS
1405
 
    create_table_no_lock()
 
1409
    mysql_create_table_no_lock()
1406
1410
    session                     Thread object
1407
1411
    db                  Database
1408
1412
    table_name          Table name
1418
1422
 
1419
1423
    Note that this function assumes that caller already have taken
1420
1424
    name-lock on table being created or used some other way to ensure
1421
 
    that concurrent operations won't intervene. create_table()
 
1425
    that concurrent operations won't intervene. mysql_create_table()
1422
1426
    is a wrapper that can be used for this.
1423
1427
 
1424
1428
  RETURN VALUES
1426
1430
    true  error
1427
1431
*/
1428
1432
 
1429
 
bool create_table_no_lock(Session *session,
1430
 
                                const identifier::Table &identifier,
 
1433
bool mysql_create_table_no_lock(Session *session,
 
1434
                                TableIdentifier &identifier,
1431
1435
                                HA_CREATE_INFO *create_info,
1432
1436
                                message::Table &table_proto,
1433
1437
                                AlterInfo *alter_info,
1452
1456
  set_table_default_charset(create_info, identifier.getSchemaName().c_str());
1453
1457
 
1454
1458
  /* Build a Table object to pass down to the engine, and the do the actual create. */
1455
 
  if (not prepare_create_table(session, create_info, table_proto, alter_info,
1456
 
                               internal_tmp_table,
1457
 
                               &db_options,
1458
 
                               &key_info_buffer, &key_count,
1459
 
                               select_field_count))
 
1459
  if (not mysql_prepare_create_table(session, create_info, table_proto, alter_info,
 
1460
                                 internal_tmp_table,
 
1461
                                 &db_options,
 
1462
                                 &key_info_buffer, &key_count,
 
1463
                                 select_field_count))
1460
1464
  {
1461
 
    boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* CREATE TABLE (some confussion on naming, double check) */
 
1465
    boost::mutex::scoped_lock lock(LOCK_open); /* CREATE TABLE (some confussion on naming, double check) */
1462
1466
    error= locked_create_event(session,
1463
1467
                               identifier,
1464
1468
                               create_info,
1479
1483
  @note the following two methods implement create [temporary] table.
1480
1484
*/
1481
1485
static bool drizzle_create_table(Session *session,
1482
 
                                 const identifier::Table &identifier,
 
1486
                                 TableIdentifier &identifier,
1483
1487
                                 HA_CREATE_INFO *create_info,
1484
1488
                                 message::Table &table_proto,
1485
1489
                                 AlterInfo *alter_info,
1506
1510
    }
1507
1511
    else
1508
1512
    {
1509
 
      my_error(ER_TABLE_EXISTS_ERROR, identifier);
 
1513
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getSQLPath().c_str());
1510
1514
      result= true;
1511
1515
    }
1512
1516
  }
1513
1517
  else
1514
1518
  {
1515
 
    result= create_table_no_lock(session,
 
1519
    result= mysql_create_table_no_lock(session,
1516
1520
                                       identifier,
1517
1521
                                       create_info,
1518
1522
                                       table_proto,
1524
1528
 
1525
1529
  if (name_lock)
1526
1530
  {
1527
 
    boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* Lock for removing name_lock during table create */
 
1531
    boost::mutex::scoped_lock lock(LOCK_open); /* Lock for removing name_lock during table create */
1528
1532
    session->unlink_open_table(name_lock);
1529
1533
  }
1530
1534
 
1533
1537
 
1534
1538
 
1535
1539
/*
1536
 
  Database locking aware wrapper for create_table_no_lock(),
 
1540
  Database locking aware wrapper for mysql_create_table_no_lock(),
1537
1541
*/
1538
 
bool create_table(Session *session,
1539
 
                        const identifier::Table &identifier,
 
1542
bool mysql_create_table(Session *session,
 
1543
                        TableIdentifier &identifier,
1540
1544
                        HA_CREATE_INFO *create_info,
1541
1545
                        message::Table &table_proto,
1542
1546
                        AlterInfo *alter_info,
1546
1550
{
1547
1551
  if (identifier.isTmp())
1548
1552
  {
1549
 
    return create_table_no_lock(session,
 
1553
    return mysql_create_table_no_lock(session,
1550
1554
                                      identifier,
1551
1555
                                      create_info,
1552
1556
                                      table_proto,
1616
1620
  Rename a table.
1617
1621
 
1618
1622
  SYNOPSIS
1619
 
    rename_table()
 
1623
    mysql_rename_table()
1620
1624
      session
1621
1625
      base                      The plugin::StorageEngine handle.
1622
1626
      old_db                    The old database name.
1630
1634
*/
1631
1635
 
1632
1636
bool
1633
 
rename_table(Session &session,
 
1637
mysql_rename_table(Session &session,
1634
1638
                   plugin::StorageEngine *base,
1635
 
                   const identifier::Table &from,
1636
 
                   const identifier::Table &to)
 
1639
                   TableIdentifier &from,
 
1640
                   TableIdentifier &to)
1637
1641
{
1638
1642
  int error= 0;
1639
1643
 
1653
1657
  }
1654
1658
  else if (error)
1655
1659
  {
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();
 
1660
    const char *from_identifier= from.isTmp() ? "#sql-temporary" : from.getSQLPath().c_str();
 
1661
    const char *to_identifier= to.isTmp() ? "#sql-temporary" : to.getSQLPath().c_str();
1664
1662
 
1665
1663
    my_error(ER_ERROR_ON_RENAME, MYF(0), from_identifier, to_identifier, error);
1666
1664
  }
1684
1682
   the table is closed.
1685
1683
 
1686
1684
  PREREQUISITES
1687
 
    Lock on table::Cache::singleton().mutex()
 
1685
    Lock on LOCK_open
1688
1686
    Win32 clients must also have a WRITE LOCK on the table !
1689
1687
*/
1690
1688
 
1692
1690
                              enum ha_extra_function function)
1693
1691
{
1694
1692
 
1695
 
  safe_mutex_assert_owner(table::Cache::singleton().mutex().native_handle());
 
1693
  safe_mutex_assert_owner(LOCK_open.native_handle());
1696
1694
 
1697
1695
  table->cursor->extra(function);
1698
1696
  /* Mark all tables that are in use as 'old' */
1699
 
  session->abortLock(table);    /* end threads waiting on lock */
 
1697
  mysql_lock_abort(session, table);     /* end threads waiting on lock */
1700
1698
 
1701
1699
  /* Wait until all there are no other threads that has this table open */
1702
 
  identifier::Table identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName());
1703
 
  table::Cache::singleton().removeTable(session, identifier, RTFC_WAIT_OTHER_THREAD_FLAG);
 
1700
  TableIdentifier identifier(table->getMutableShare()->getSchemaName(), table->getMutableShare()->getTableName());
 
1701
  remove_table_from_cache(session, identifier, RTFC_WAIT_OTHER_THREAD_FLAG);
1704
1702
}
1705
1703
 
1706
1704
/*
1716
1714
    reopen the table.
1717
1715
 
1718
1716
  PREREQUISITES
1719
 
    Lock on table::Cache::singleton().mutex()
 
1717
    Lock on LOCK_open
1720
1718
    Win32 clients must also have a WRITE LOCK on the table !
1721
1719
*/
1722
1720
 
1727
1725
  /* Close lock if this is not got with LOCK TABLES */
1728
1726
  if (lock)
1729
1727
  {
1730
 
    unlockTables(lock);
 
1728
    mysql_unlock_tables(this, lock);
1731
1729
    lock= NULL;                 // Start locked threads
1732
1730
  }
1733
1731
  /* Close all copies of 'table'.  This also frees all LOCK TABLES lock */
1734
1732
  unlink_open_table(table);
1735
1733
 
1736
 
  /* When lock on table::Cache::singleton().mutex() is freed other threads can continue */
1737
 
  locking::broadcast_refresh();
 
1734
  /* When lock on LOCK_open is freed other threads can continue */
 
1735
  broadcast_refresh();
1738
1736
}
1739
1737
 
1740
1738
/*
1743
1741
    true  Message should be sent by caller
1744
1742
          (admin operation or network communication failed)
1745
1743
*/
1746
 
static bool admin_table(Session* session, TableList* tables,
 
1744
static bool mysql_admin_table(Session* session, TableList* tables,
1747
1745
                              HA_CHECK_OPT* check_opt,
1748
1746
                              const char *operator_name,
1749
1747
                              thr_lock_type lock_type,
1772
1770
  item->maybe_null = 1;
1773
1771
  field_list.push_back(item = new Item_empty_string("Msg_text", 255, cs));
1774
1772
  item->maybe_null = 1;
1775
 
  if (session->getClient()->sendFields(&field_list))
 
1773
  if (session->client->sendFields(&field_list))
1776
1774
    return true;
1777
1775
 
1778
1776
  for (table= tables; table; table= table->next_local)
1779
1777
  {
1780
1778
    char table_name[NAME_LEN*2+2];
 
1779
    char* db = table->db;
1781
1780
    bool fatal_error=0;
1782
1781
 
1783
 
    snprintf(table_name, sizeof(table_name), "%s.%s", table->getSchemaName(), table->getTableName());
 
1782
    snprintf(table_name, sizeof(table_name), "%s.%s",db,table->table_name);
1784
1783
    table->lock_type= lock_type;
1785
1784
    /* open only one table from local list of command */
1786
1785
    {
1827
1826
    {
1828
1827
      char buff[FN_REFLEN + DRIZZLE_ERRMSG_SIZE];
1829
1828
      uint32_t length;
1830
 
      session->getClient()->store(table_name);
1831
 
      session->getClient()->store(operator_name);
1832
 
      session->getClient()->store(STRING_WITH_LEN("error"));
 
1829
      session->client->store(table_name);
 
1830
      session->client->store(operator_name);
 
1831
      session->client->store(STRING_WITH_LEN("error"));
1833
1832
      length= snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY),
1834
1833
                       table_name);
1835
 
      session->getClient()->store(buff, length);
1836
 
      transaction_services.autocommitOrRollback(*session, false);
 
1834
      session->client->store(buff, length);
 
1835
      transaction_services.autocommitOrRollback(session, false);
1837
1836
      session->endTransaction(COMMIT);
1838
1837
      session->close_thread_tables();
1839
1838
      lex->reset_query_tables_list(false);
1840
1839
      table->table=0;                           // For query cache
1841
 
      if (session->getClient()->flush())
 
1840
      if (session->client->flush())
1842
1841
        goto err;
1843
1842
      continue;
1844
1843
    }
1846
1845
    /* Close all instances of the table to allow repair to rename files */
1847
1846
    if (lock_type == TL_WRITE && table->table->getShare()->getVersion())
1848
1847
    {
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(),
 
1848
      LOCK_open.lock(); /* Lock type is TL_WRITE and we lock to repair the table */
 
1849
      const char *old_message=session->enter_cond(COND_refresh, LOCK_open,
1851
1850
                                                  "Waiting to get writelock");
1852
 
      session->abortLock(table->table);
1853
 
      identifier::Table identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
1854
 
      table::Cache::singleton().removeTable(session, identifier, RTFC_WAIT_OTHER_THREAD_FLAG | RTFC_CHECK_KILLED_FLAG);
 
1851
      mysql_lock_abort(session,table->table);
 
1852
      TableIdentifier identifier(table->table->getMutableShare()->getSchemaName(), table->table->getMutableShare()->getTableName());
 
1853
      remove_table_from_cache(session, identifier,
 
1854
                              RTFC_WAIT_OTHER_THREAD_FLAG |
 
1855
                              RTFC_CHECK_KILLED_FLAG);
1855
1856
      session->exit_cond(old_message);
1856
 
      if (session->getKilled())
 
1857
      if (session->killed)
1857
1858
        goto err;
1858
1859
      open_for_modify= 0;
1859
1860
    }
1869
1870
      DRIZZLE_ERROR *err;
1870
1871
      while ((err= it++))
1871
1872
      {
1872
 
        session->getClient()->store(table_name);
1873
 
        session->getClient()->store(operator_name);
1874
 
        session->getClient()->store(warning_level_names[err->level].str,
 
1873
        session->client->store(table_name);
 
1874
        session->client->store(operator_name);
 
1875
        session->client->store(warning_level_names[err->level].str,
1875
1876
                               warning_level_names[err->level].length);
1876
 
        session->getClient()->store(err->msg);
1877
 
        if (session->getClient()->flush())
 
1877
        session->client->store(err->msg);
 
1878
        if (session->client->flush())
1878
1879
          goto err;
1879
1880
      }
1880
1881
      drizzle_reset_errors(session, true);
1881
1882
    }
1882
 
    session->getClient()->store(table_name);
1883
 
    session->getClient()->store(operator_name);
 
1883
    session->client->store(table_name);
 
1884
    session->client->store(operator_name);
1884
1885
 
1885
1886
    switch (result_code) {
1886
1887
    case HA_ADMIN_NOT_IMPLEMENTED:
1888
1889
        char buf[ERRMSGSIZE+20];
1889
1890
        uint32_t length=snprintf(buf, ERRMSGSIZE,
1890
1891
                             ER(ER_CHECK_NOT_IMPLEMENTED), operator_name);
1891
 
        session->getClient()->store(STRING_WITH_LEN("note"));
1892
 
        session->getClient()->store(buf, length);
 
1892
        session->client->store(STRING_WITH_LEN("note"));
 
1893
        session->client->store(buf, length);
1893
1894
      }
1894
1895
      break;
1895
1896
 
1896
1897
    case HA_ADMIN_OK:
1897
 
      session->getClient()->store(STRING_WITH_LEN("status"));
1898
 
      session->getClient()->store(STRING_WITH_LEN("OK"));
 
1898
      session->client->store(STRING_WITH_LEN("status"));
 
1899
      session->client->store(STRING_WITH_LEN("OK"));
1899
1900
      break;
1900
1901
 
1901
1902
    case HA_ADMIN_FAILED:
1902
 
      session->getClient()->store(STRING_WITH_LEN("status"));
1903
 
      session->getClient()->store(STRING_WITH_LEN("Operation failed"));
 
1903
      session->client->store(STRING_WITH_LEN("status"));
 
1904
      session->client->store(STRING_WITH_LEN("Operation failed"));
1904
1905
      break;
1905
1906
 
1906
1907
    case HA_ADMIN_REJECT:
1907
 
      session->getClient()->store(STRING_WITH_LEN("status"));
1908
 
      session->getClient()->store(STRING_WITH_LEN("Operation need committed state"));
 
1908
      session->client->store(STRING_WITH_LEN("status"));
 
1909
      session->client->store(STRING_WITH_LEN("Operation need committed state"));
1909
1910
      open_for_modify= false;
1910
1911
      break;
1911
1912
 
1912
1913
    case HA_ADMIN_ALREADY_DONE:
1913
 
      session->getClient()->store(STRING_WITH_LEN("status"));
1914
 
      session->getClient()->store(STRING_WITH_LEN("Table is already up to date"));
 
1914
      session->client->store(STRING_WITH_LEN("status"));
 
1915
      session->client->store(STRING_WITH_LEN("Table is already up to date"));
1915
1916
      break;
1916
1917
 
1917
1918
    case HA_ADMIN_CORRUPT:
1918
 
      session->getClient()->store(STRING_WITH_LEN("error"));
1919
 
      session->getClient()->store(STRING_WITH_LEN("Corrupt"));
 
1919
      session->client->store(STRING_WITH_LEN("error"));
 
1920
      session->client->store(STRING_WITH_LEN("Corrupt"));
1920
1921
      fatal_error=1;
1921
1922
      break;
1922
1923
 
1923
1924
    case HA_ADMIN_INVALID:
1924
 
      session->getClient()->store(STRING_WITH_LEN("error"));
1925
 
      session->getClient()->store(STRING_WITH_LEN("Invalid argument"));
 
1925
      session->client->store(STRING_WITH_LEN("error"));
 
1926
      session->client->store(STRING_WITH_LEN("Invalid argument"));
1926
1927
      break;
1927
1928
 
1928
1929
    default:                            // Probably HA_ADMIN_INTERNAL_ERROR
1931
1932
        uint32_t length=snprintf(buf, ERRMSGSIZE,
1932
1933
                             _("Unknown - internal error %d during operation"),
1933
1934
                             result_code);
1934
 
        session->getClient()->store(STRING_WITH_LEN("error"));
1935
 
        session->getClient()->store(buf, length);
 
1935
        session->client->store(STRING_WITH_LEN("error"));
 
1936
        session->client->store(buf, length);
1936
1937
        fatal_error=1;
1937
1938
        break;
1938
1939
      }
1951
1952
        }
1952
1953
        else
1953
1954
        {
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);
 
1955
          boost::mutex::scoped_lock lock(LOCK_open);
 
1956
          TableIdentifier identifier(table->table->getMutableShare()->getSchemaName(), table->table->getMutableShare()->getTableName());
 
1957
          remove_table_from_cache(session, identifier, RTFC_NO_FLAG);
1957
1958
        }
1958
1959
      }
1959
1960
    }
1960
 
    transaction_services.autocommitOrRollback(*session, false);
 
1961
    transaction_services.autocommitOrRollback(session, false);
1961
1962
    session->endTransaction(COMMIT);
1962
1963
    session->close_thread_tables();
1963
1964
    table->table=0;                             // For query cache
1964
 
    if (session->getClient()->flush())
 
1965
    if (session->client->flush())
1965
1966
      goto err;
1966
1967
  }
1967
1968
 
1969
1970
  return(false);
1970
1971
 
1971
1972
err:
1972
 
  transaction_services.autocommitOrRollback(*session, true);
 
1973
  transaction_services.autocommitOrRollback(session, true);
1973
1974
  session->endTransaction(ROLLBACK);
1974
1975
  session->close_thread_tables();                       // Shouldn't be needed
1975
1976
  if (table)
1983
1984
    Altough exclusive name-lock on target table protects us from concurrent
1984
1985
    DML and DDL operations on it we still want to wrap .FRM creation and call
1985
1986
    to plugin::StorageEngine::createTable() in critical section protected by
1986
 
    table::Cache::singleton().mutex() in order to provide minimal atomicity against operations which
 
1987
    LOCK_open in order to provide minimal atomicity against operations which
1987
1988
    disregard name-locks, like I_S implementation, for example. This is a
1988
1989
    temporary and should not be copied. Instead we should fix our code to
1989
1990
    always honor name-locks.
1990
1991
 
1991
 
    Also some engines (e.g. NDB cluster) require that table::Cache::singleton().mutex() should be held
 
1992
    Also some engines (e.g. NDB cluster) require that LOCK_open should be held
1992
1993
    during the call to plugin::StorageEngine::createTable().
1993
1994
    See bug #28614 for more info.
1994
1995
  */
1995
 
static bool create_table_wrapper(Session &session,
1996
 
                                 const message::Table& create_table_proto,
1997
 
                                 identifier::Table::const_reference destination_identifier,
1998
 
                                 identifier::Table::const_reference source_identifier,
 
1996
static bool create_table_wrapper(Session &session, const message::Table& create_table_proto,
 
1997
                                 TableIdentifier &destination_identifier,
 
1998
                                 TableIdentifier &src_table,
1999
1999
                                 bool is_engine_set)
2000
2000
{
2001
 
  // We require an additional table message because during parsing we used
2002
 
  // a "new" message and it will not have all of the information that the
2003
 
  // source table message would have.
2004
 
  message::Table new_table_message;
2005
 
  drizzled::error_t error;
2006
 
 
2007
 
  message::table::shared_ptr source_table_message= plugin::StorageEngine::getTableMessage(session, source_identifier, error);
2008
 
 
2009
 
  if (not source_table_message)
2010
 
  {
2011
 
    my_error(ER_TABLE_UNKNOWN, source_identifier);
2012
 
    return false;
2013
 
  }
2014
 
 
2015
 
  new_table_message.CopyFrom(*source_table_message);
 
2001
  int protoerr= EEXIST;
 
2002
  message::Table new_proto;
 
2003
  message::Table src_proto;
 
2004
 
 
2005
  protoerr= plugin::StorageEngine::getTableDefinition(session,
 
2006
                                                      src_table,
 
2007
                                                      src_proto);
 
2008
  new_proto.CopyFrom(src_proto);
2016
2009
 
2017
2010
  if (destination_identifier.isTmp())
2018
2011
  {
2019
 
    new_table_message.set_type(message::Table::TEMPORARY);
 
2012
    new_proto.set_type(message::Table::TEMPORARY);
2020
2013
  }
2021
2014
  else
2022
2015
  {
2023
 
    new_table_message.set_type(message::Table::STANDARD);
 
2016
    new_proto.set_type(message::Table::STANDARD);
2024
2017
  }
2025
2018
 
2026
2019
  if (is_engine_set)
2027
2020
  {
2028
 
    new_table_message.mutable_engine()->set_name(create_table_proto.engine().name());
 
2021
    new_proto.mutable_engine()->set_name(create_table_proto.engine().name());
2029
2022
  }
2030
2023
 
2031
2024
  { // We now do a selective copy of elements on to the new table.
2032
 
    new_table_message.set_name(create_table_proto.name());
2033
 
    new_table_message.set_schema(create_table_proto.schema());
2034
 
    new_table_message.set_catalog(create_table_proto.catalog());
 
2025
    new_proto.set_name(create_table_proto.name());
 
2026
    new_proto.set_schema(create_table_proto.schema());
 
2027
    new_proto.set_catalog(create_table_proto.catalog());
2035
2028
  }
2036
2029
 
2037
 
  /* Fix names of foreign keys being added */
2038
 
  for (int32_t j= 0; j < new_table_message.fk_constraint_size(); j++)
 
2030
  if (protoerr && protoerr != EEXIST)
2039
2031
  {
2040
 
    if (new_table_message.fk_constraint(j).has_name())
2041
 
    {
2042
 
      std::string name(new_table_message.name());
2043
 
      char number[20];
2044
 
 
2045
 
      name.append("_ibfk_");
2046
 
      snprintf(number, sizeof(number), "%d", j+1);
2047
 
      name.append(number);
2048
 
 
2049
 
      message::Table::ForeignKeyConstraint *pfkey= new_table_message.mutable_fk_constraint(j);
2050
 
      pfkey->set_name(name);
2051
 
    }
 
2032
    if (errno == ENOENT)
 
2033
      my_error(ER_BAD_DB_ERROR,MYF(0), destination_identifier.getSchemaName().c_str());
 
2034
    else
 
2035
      my_error(ER_CANT_CREATE_FILE, MYF(0), destination_identifier.getPath().c_str(), errno);
 
2036
 
 
2037
    return false;
2052
2038
  }
2053
2039
 
2054
2040
  /*
2055
2041
    As mysql_truncate don't work on a new table at this stage of
2056
 
    creation, instead create the table directly (for both normal and temporary tables).
 
2042
    creation, instead create the table directly (for both normal
 
2043
    and temporary tables).
2057
2044
  */
2058
 
  bool success= plugin::StorageEngine::createTable(session,
2059
 
                                                   destination_identifier,
2060
 
                                                   new_table_message);
 
2045
  int err= plugin::StorageEngine::createTable(session,
 
2046
                                              destination_identifier,
 
2047
                                              new_proto);
2061
2048
 
2062
 
  if (success && not destination_identifier.isTmp())
 
2049
  if (err == false && not destination_identifier.isTmp())
2063
2050
  {
2064
2051
    TransactionServices &transaction_services= TransactionServices::singleton();
2065
 
    transaction_services.createTable(session, new_table_message);
 
2052
    transaction_services.createTable(&session, new_proto);
2066
2053
  }
2067
2054
 
2068
 
  return success;
 
2055
  return err ? false : true;
2069
2056
}
2070
2057
 
2071
2058
/*
2072
2059
  Create a table identical to the specified table
2073
2060
 
2074
2061
  SYNOPSIS
2075
 
    create_like_table()
 
2062
    mysql_create_like_table()
2076
2063
    session             Thread object
2077
2064
    table       Table list element for target table
2078
2065
    src_table   Table list element for source table
2083
2070
    true  error
2084
2071
*/
2085
2072
 
2086
 
bool create_like_table(Session* session,
2087
 
                       identifier::Table::const_reference destination_identifier,
2088
 
                       identifier::Table::const_reference source_identifier,
2089
 
                       message::Table &create_table_proto,
2090
 
                       bool is_if_not_exists,
2091
 
                       bool is_engine_set)
 
2073
bool mysql_create_like_table(Session* session,
 
2074
                             TableIdentifier &destination_identifier,
 
2075
                             TableList* table, TableList* src_table,
 
2076
                             message::Table &create_table_proto,
 
2077
                             bool is_if_not_exists,
 
2078
                             bool is_engine_set)
2092
2079
{
 
2080
  char *db= table->db;
 
2081
  char *table_name= table->table_name;
2093
2082
  bool res= true;
2094
 
  bool table_exists= false;
 
2083
  uint32_t not_used;
 
2084
 
 
2085
  /*
 
2086
    By opening source table we guarantee that it exists and no concurrent
 
2087
    DDL operation will mess with it. Later we also take an exclusive
 
2088
    name-lock on target table name, which makes copying of .frm cursor,
 
2089
    call to plugin::StorageEngine::createTable() and binlogging atomic
 
2090
    against concurrent DML and DDL operations on target table.
 
2091
    Thus by holding both these "locks" we ensure that our statement is
 
2092
    properly isolated from all concurrent operations which matter.
 
2093
  */
 
2094
  if (session->open_tables_from_list(&src_table, &not_used))
 
2095
    return true;
 
2096
 
 
2097
  TableIdentifier src_identifier(src_table->table->getMutableShare()->getSchemaName(),
 
2098
                                 src_table->table->getMutableShare()->getTableName(), src_table->table->getMutableShare()->getType());
 
2099
 
 
2100
 
2095
2101
 
2096
2102
  /*
2097
2103
    Check that destination tables does not exist. Note that its name
2099
2105
 
2100
2106
    For temporary tables we don't aim to grab locks.
2101
2107
  */
 
2108
  bool table_exists= false;
2102
2109
  if (destination_identifier.isTmp())
2103
2110
  {
2104
 
    if (session->find_temporary_table(destination_identifier))
 
2111
    if (session->find_temporary_table(db, table_name))
2105
2112
    {
2106
2113
      table_exists= true;
2107
2114
    }
2108
2115
    else
2109
2116
    {
2110
 
      bool was_created= create_table_wrapper(*session,
2111
 
                                             create_table_proto,
2112
 
                                             destination_identifier,
2113
 
                                             source_identifier,
2114
 
                                             is_engine_set);
 
2117
      bool was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
 
2118
                                             src_identifier, is_engine_set);
2115
2119
      if (not was_created) // This is pretty paranoid, but we assume something might not clean up after itself
2116
2120
      {
2117
2121
        (void) session->rm_temporary_table(destination_identifier, true);
2135
2139
    {
2136
2140
      if (name_lock)
2137
2141
      {
2138
 
        boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* unlink open tables for create table like*/
 
2142
        boost::mutex::scoped_lock lock(LOCK_open); /* unlink open tables for create table like*/
2139
2143
        session->unlink_open_table(name_lock);
2140
2144
      }
2141
2145
 
2154
2158
    {
2155
2159
      bool was_created;
2156
2160
      {
2157
 
        boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* We lock for CREATE TABLE LIKE to copy table definition */
 
2161
        boost::mutex::scoped_lock lock(LOCK_open); /* We lock for CREATE TABLE LIKE to copy table definition */
2158
2162
        was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
2159
 
                                          source_identifier, is_engine_set);
 
2163
                                               src_identifier, is_engine_set);
2160
2164
      }
2161
2165
 
2162
2166
      // So we blew the creation of the table, and we scramble to clean up
2163
2167
      // anything that might have been created (read... it is a hack)
2164
2168
      if (not was_created)
2165
2169
      {
2166
 
        plugin::StorageEngine::dropTable(*session, destination_identifier);
 
2170
        quick_rm_table(*session, destination_identifier);
2167
2171
      } 
2168
2172
      else
2169
2173
      {
2173
2177
 
2174
2178
    if (name_lock)
2175
2179
    {
2176
 
      boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* unlink open tables for create table like*/
 
2180
      boost::mutex::scoped_lock lock(LOCK_open); /* unlink open tables for create table like*/
2177
2181
      session->unlink_open_table(name_lock);
2178
2182
    }
2179
2183
  }
2184
2188
    {
2185
2189
      char warn_buff[DRIZZLE_ERRMSG_SIZE];
2186
2190
      snprintf(warn_buff, sizeof(warn_buff),
2187
 
               ER(ER_TABLE_EXISTS_ERROR), destination_identifier.getTableName().c_str());
 
2191
               ER(ER_TABLE_EXISTS_ERROR), table_name);
2188
2192
      push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
2189
 
                   ER_TABLE_EXISTS_ERROR, warn_buff);
2190
 
      return false;
2191
 
    }
2192
 
 
2193
 
    my_error(ER_TABLE_EXISTS_ERROR, destination_identifier);
2194
 
 
2195
 
    return true;
 
2193
                   ER_TABLE_EXISTS_ERROR,warn_buff);
 
2194
      res= false;
 
2195
    }
 
2196
    else
 
2197
    {
 
2198
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
 
2199
    }
2196
2200
  }
2197
2201
 
2198
 
  return res;
 
2202
  return(res);
2199
2203
}
2200
2204
 
2201
2205
 
2202
 
bool analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
 
2206
bool mysql_analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
2203
2207
{
2204
2208
  thr_lock_type lock_type = TL_READ_NO_INSERT;
2205
2209
 
2206
 
  return(admin_table(session, tables, check_opt,
 
2210
  return(mysql_admin_table(session, tables, check_opt,
2207
2211
                                "analyze", lock_type, true,
2208
2212
                                &Cursor::ha_analyze));
2209
2213
}
2210
2214
 
2211
2215
 
2212
 
bool check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
 
2216
bool mysql_check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
2213
2217
{
2214
2218
  thr_lock_type lock_type = TL_READ_NO_INSERT;
2215
2219
 
2216
 
  return(admin_table(session, tables, check_opt,
 
2220
  return(mysql_admin_table(session, tables, check_opt,
2217
2221
                                "check", lock_type,
2218
2222
                                false,
2219
2223
                                &Cursor::ha_check));