~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_table.cc

  • Committer: Brian Aker
  • Date: 2010-12-07 09:12:12 UTC
  • mto: This revision was merged to the branch mainline in revision 1985.
  • Revision ID: brian@tangent.org-20101207091212-1m0w20tck6z7632m
This is a fix for bug lp:686197

Show diffs side-by-side

added added

removed removed

Lines of Context:
47
47
#include "drizzled/statement/alter_table.h"
48
48
#include "drizzled/sql_table.h"
49
49
#include "drizzled/pthread_globals.h"
50
 
#include "drizzled/plugin/storage_engine.h"
51
50
 
52
51
#include <algorithm>
53
52
#include <sstream>
59
58
namespace drizzled
60
59
{
61
60
 
 
61
extern pid_t current_pid;
 
62
 
62
63
bool is_primary_key(KeyInfo *key_info)
63
64
{
64
65
  static const char * primary_key_name="PRIMARY";
86
87
    let's fetch the database default character set and
87
88
    apply it to the table.
88
89
  */
89
 
  identifier::Schema identifier(db);
 
90
  SchemaIdentifier identifier(db);
90
91
  if (create_info->default_table_charset == NULL)
91
92
    create_info->default_table_charset= plugin::StorageEngine::getSchemaCollation(identifier);
92
93
}
109
110
void write_bin_log(Session *session, const std::string &query)
110
111
{
111
112
  TransactionServices &transaction_services= TransactionServices::singleton();
112
 
  transaction_services.rawStatement(*session, query);
 
113
  transaction_services.rawStatement(session, query);
113
114
}
114
115
 
115
116
/*
116
117
  Execute the drop of a normal or temporary table
117
118
 
118
119
  SYNOPSIS
119
 
    rm_table_part2()
 
120
    mysql_rm_table_part2()
120
121
    session                     Thread Cursor
121
122
    tables              Tables to drop
122
123
    if_exists           If set, don't give an error if table doesn't exists.
139
140
   -1   Thread was killed
140
141
*/
141
142
 
142
 
int rm_table_part2(Session *session, TableList *tables, bool if_exists,
143
 
                   bool drop_temporary)
 
143
int mysql_rm_table_part2(Session *session, TableList *tables, bool if_exists,
 
144
                         bool drop_temporary)
144
145
{
145
146
  TableList *table;
146
147
  String wrong_tables;
147
148
  int error= 0;
148
149
  bool foreign_key_error= false;
149
150
 
150
 
  do
151
151
  {
152
 
    boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex());
 
152
    table::Cache::singleton().mutex().lock(); /* Part 2 of rm a table */
153
153
 
154
154
    if (not drop_temporary && session->lock_table_names_exclusively(tables))
155
155
    {
 
156
      table::Cache::singleton().mutex().unlock();
156
157
      return 1;
157
158
    }
158
159
 
161
162
 
162
163
    for (table= tables; table; table= table->next_local)
163
164
    {
164
 
      identifier::Table tmp_identifier(table->getSchemaName(), table->getTableName());
 
165
      TableIdentifier tmp_identifier(table->getSchemaName(), table->getTableName());
165
166
 
166
167
      error= session->drop_temporary_table(tmp_identifier);
167
168
 
171
172
        continue;
172
173
      case -1:
173
174
        error= 1;
174
 
        break;
 
175
        goto err_with_placeholders;
175
176
      default:
176
177
        // temporary table not found
177
178
        error= 0;
194
195
        if (session->getKilled())
195
196
        {
196
197
          error= -1;
197
 
          break;
 
198
          goto err_with_placeholders;
198
199
        }
199
200
      }
200
 
      identifier::Table identifier(table->getSchemaName(), table->getTableName(), table->getInternalTmpTable() ? message::Table::INTERNAL : message::Table::STANDARD);
 
201
      TableIdentifier identifier(table->getSchemaName(), table->getTableName(), table->getInternalTmpTable() ? message::Table::INTERNAL : message::Table::STANDARD);
201
202
 
202
203
      if (drop_temporary || not plugin::StorageEngine::doesTableExist(*session, identifier))
203
204
      {
207
208
                              ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
208
209
                              table->getTableName());
209
210
        else
210
 
        {
211
211
          error= 1;
212
 
        }
213
212
      }
214
213
      else
215
214
      {
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
 
        }
 
215
        error= plugin::StorageEngine::dropTable(*session, identifier);
 
216
 
 
217
        if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) && if_exists)
 
218
        {
 
219
          error= 0;
 
220
          session->clear_error();
 
221
        }
 
222
 
 
223
        if (error == HA_ERR_ROW_IS_REFERENCED)
 
224
        {
 
225
          /* the table is referenced by a foreign key constraint */
 
226
          foreign_key_error= true;
 
227
        }
 
228
      }
 
229
 
 
230
      if (error == 0 || (if_exists && foreign_key_error == false))
 
231
      {
 
232
        TransactionServices &transaction_services= TransactionServices::singleton();
 
233
        transaction_services.dropTable(session, string(table->getSchemaName()), string(table->getTableName()), if_exists);
239
234
      }
240
235
 
241
236
      if (error)
245
240
        wrong_tables.append(String(table->getTableName(), system_charset_info));
246
241
      }
247
242
    }
248
 
 
249
 
    tables->unlock_table_names();
250
 
 
251
 
  } while (0);
 
243
    /*
 
244
      It's safe to unlock table::Cache::singleton().mutex(): we have an exclusive lock
 
245
      on the table name.
 
246
    */
 
247
    table::Cache::singleton().mutex().unlock();
 
248
  }
 
249
  error= 0;
252
250
 
253
251
  if (wrong_tables.length())
254
252
  {
264
262
    error= 1;
265
263
  }
266
264
 
 
265
  table::Cache::singleton().mutex().lock(); /* final bit in rm table lock */
 
266
 
 
267
err_with_placeholders:
 
268
  tables->unlock_table_names();
 
269
  table::Cache::singleton().mutex().unlock();
267
270
  session->no_warnings_for_error= 0;
268
271
 
269
272
  return error;
468
471
    sql_field->length= 8; // Unireg field length
469
472
    (*blob_columns)++;
470
473
    break;
471
 
 
 
474
  case DRIZZLE_TYPE_VARCHAR:
 
475
    break;
472
476
  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:
 
477
    if (check_duplicates_in_interval("ENUM",
 
478
                                     sql_field->field_name,
 
479
                                     sql_field->interval,
 
480
                                     sql_field->charset,
 
481
                                     &dup_val_count))
 
482
      return 1;
 
483
    break;
 
484
  case DRIZZLE_TYPE_DATE:  // Rest of string types
 
485
  case DRIZZLE_TYPE_DATETIME:
 
486
  case DRIZZLE_TYPE_NULL:
 
487
    break;
 
488
  case DRIZZLE_TYPE_DECIMAL:
 
489
    break;
486
490
  case DRIZZLE_TYPE_TIMESTAMP:
487
491
    /* We should replace old TIMESTAMP fields with their newer analogs */
488
492
    if (sql_field->unireg_check == Field::TIMESTAMP_OLD_FIELD)
498
502
      }
499
503
    }
500
504
    else if (sql_field->unireg_check != Field::NONE)
501
 
    {
502
505
      (*timestamps_with_niladic)++;
503
 
    }
504
506
 
505
507
    (*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:
 
508
    /* fall-through */
 
509
  default:
520
510
    break;
521
511
  }
522
512
 
523
513
  return 0;
524
514
}
525
515
 
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)
 
516
static int mysql_prepare_create_table(Session *session,
 
517
                                      HA_CREATE_INFO *create_info,
 
518
                                      message::Table &create_proto,
 
519
                                      AlterInfo *alter_info,
 
520
                                      bool tmp_table,
 
521
                                      uint32_t *db_options,
 
522
                                      KeyInfo **key_info_buffer,
 
523
                                      uint32_t *key_count,
 
524
                                      int select_field_count)
535
525
{
536
526
  const char    *key_name;
537
527
  CreateField   *sql_field,*dup_field;
540
530
  KeyInfo               *key_info;
541
531
  KeyPartInfo *key_part_info;
542
532
  int           timestamps= 0, timestamps_with_niladic= 0;
543
 
  int           dup_no;
 
533
  int           field_no,dup_no;
544
534
  int           select_field_pos,auto_increment=0;
545
535
  List_iterator<CreateField> it(alter_info->create_list);
546
536
  List_iterator<CreateField> it2(alter_info->create_list);
552
542
  null_fields=blob_columns=0;
553
543
  max_key_length= engine->max_key_length();
554
544
 
555
 
  for (int32_t field_no=0; (sql_field=it++) ; field_no++)
 
545
  for (field_no=0; (sql_field=it++) ; field_no++)
556
546
  {
557
547
    const CHARSET_INFO *save_cs;
558
548
 
562
552
      executing a prepared statement for the second time.
563
553
    */
564
554
    sql_field->length= sql_field->char_length;
565
 
 
566
555
    if (!sql_field->charset)
567
556
      sql_field->charset= create_info->default_table_charset;
568
 
 
569
557
    /*
570
558
      table_charset is set in ALTER Table if we want change character set
571
559
      for all varchar/char columns.
763
751
    if (not create_proto.engine().name().compare("MyISAM") &&
764
752
        ((sql_field->flags & BLOB_FLAG) ||
765
753
         (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR)))
766
 
    {
767
754
      (*db_options)|= HA_OPTION_PACK_RECORD;
768
 
    }
769
 
 
770
755
    it2.rewind();
771
756
  }
772
757
 
990
975
             my_strcasecmp(system_charset_info,
991
976
                           column->field_name.str,
992
977
                           sql_field->field_name))
993
 
      {
994
978
        field++;
995
 
      }
996
 
 
997
979
      if (!sql_field)
998
980
      {
999
981
        my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name.str);
1000
982
        return(true);
1001
983
      }
1002
 
 
1003
984
      while ((dup_column= cols2++) != column)
1004
985
      {
1005
986
        if (!my_strcasecmp(system_charset_info,
1032
1013
            return true;
1033
1014
          }
1034
1015
        }
1035
 
 
1036
1016
        if (! (sql_field->flags & NOT_NULL_FLAG))
1037
1017
        {
1038
1018
          if (key->type == Key::PRIMARY)
1045
1025
            {
1046
1026
              message::Table::Field::FieldConstraints *constraints;
1047
1027
              constraints= protofield->mutable_constraints();
1048
 
              constraints->set_is_notnull(true);
 
1028
              constraints->set_is_nullable(false);
1049
1029
            }
1050
1030
 
1051
1031
          }
1059
1039
            }
1060
1040
          }
1061
1041
        }
1062
 
 
1063
1042
        if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
1064
1043
        {
1065
1044
          if (column_nr == 0 || (engine->check_flag(HTON_BIT_AUTO_PART_KEY)))
1184
1163
        key_info->name=(char*) key_name;
1185
1164
      }
1186
1165
    }
1187
 
 
1188
1166
    if (!key_info->name || check_column_name(key_info->name))
1189
1167
    {
1190
1168
      my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key_info->name);
1191
1169
      return(true);
1192
1170
    }
1193
 
 
1194
1171
    if (!(key_info->flags & HA_NULL_PART_KEY))
1195
 
    {
1196
1172
      unique_key=1;
1197
 
    }
1198
 
 
1199
1173
    key_info->key_length=(uint16_t) key_length;
1200
 
 
1201
1174
    if (key_length > max_key_length)
1202
1175
    {
1203
1176
      my_error(ER_TOO_LONG_KEY,MYF(0),max_key_length);
1204
1177
      return(true);
1205
1178
    }
1206
 
 
1207
1179
    key_info++;
1208
1180
  }
1209
 
 
1210
1181
  if (!unique_key && !primary_key &&
1211
1182
      (engine->check_flag(HTON_BIT_REQUIRE_PRIMARY_KEY)))
1212
1183
  {
1213
1184
    my_message(ER_REQUIRES_PRIMARY_KEY, ER(ER_REQUIRES_PRIMARY_KEY), MYF(0));
1214
1185
    return(true);
1215
1186
  }
1216
 
 
1217
1187
  if (auto_increment > 0)
1218
1188
  {
1219
1189
    my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
1295
1265
}
1296
1266
 
1297
1267
static bool locked_create_event(Session *session,
1298
 
                                const identifier::Table &identifier,
 
1268
                                const TableIdentifier &identifier,
1299
1269
                                HA_CREATE_INFO *create_info,
1300
1270
                                message::Table &table_proto,
1301
1271
                                AlterInfo *alter_info,
1330
1300
        return error;
1331
1301
      }
1332
1302
 
1333
 
      my_error(ER_TABLE_EXISTS_ERROR, identifier);
 
1303
      std::string path;
 
1304
      identifier.getSQLPath(path);
 
1305
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
1334
1306
 
1335
1307
      return error;
1336
1308
    }
1350
1322
      */
1351
1323
      if (definition::Cache::singleton().find(identifier.getKey()))
1352
1324
      {
1353
 
        my_error(ER_TABLE_EXISTS_ERROR, identifier);
 
1325
        std::string path;
 
1326
        identifier.getSQLPath(path);
 
1327
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
1354
1328
 
1355
1329
        return error;
1356
1330
      }
1389
1363
  if (table_proto.type() == message::Table::STANDARD && not internal_tmp_table)
1390
1364
  {
1391
1365
    TransactionServices &transaction_services= TransactionServices::singleton();
1392
 
    transaction_services.createTable(*session, table_proto);
 
1366
    transaction_services.createTable(session, table_proto);
1393
1367
  }
1394
1368
 
1395
1369
  return false;
1402
1376
  Create a table
1403
1377
 
1404
1378
  SYNOPSIS
1405
 
    create_table_no_lock()
 
1379
    mysql_create_table_no_lock()
1406
1380
    session                     Thread object
1407
1381
    db                  Database
1408
1382
    table_name          Table name
1418
1392
 
1419
1393
    Note that this function assumes that caller already have taken
1420
1394
    name-lock on table being created or used some other way to ensure
1421
 
    that concurrent operations won't intervene. create_table()
 
1395
    that concurrent operations won't intervene. mysql_create_table()
1422
1396
    is a wrapper that can be used for this.
1423
1397
 
1424
1398
  RETURN VALUES
1426
1400
    true  error
1427
1401
*/
1428
1402
 
1429
 
bool create_table_no_lock(Session *session,
1430
 
                                const identifier::Table &identifier,
 
1403
bool mysql_create_table_no_lock(Session *session,
 
1404
                                const TableIdentifier &identifier,
1431
1405
                                HA_CREATE_INFO *create_info,
1432
1406
                                message::Table &table_proto,
1433
1407
                                AlterInfo *alter_info,
1452
1426
  set_table_default_charset(create_info, identifier.getSchemaName().c_str());
1453
1427
 
1454
1428
  /* 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))
 
1429
  if (not mysql_prepare_create_table(session, create_info, table_proto, alter_info,
 
1430
                                     internal_tmp_table,
 
1431
                                     &db_options,
 
1432
                                     &key_info_buffer, &key_count,
 
1433
                                     select_field_count))
1460
1434
  {
1461
1435
    boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* CREATE TABLE (some confussion on naming, double check) */
1462
1436
    error= locked_create_event(session,
1479
1453
  @note the following two methods implement create [temporary] table.
1480
1454
*/
1481
1455
static bool drizzle_create_table(Session *session,
1482
 
                                 const identifier::Table &identifier,
 
1456
                                 const TableIdentifier &identifier,
1483
1457
                                 HA_CREATE_INFO *create_info,
1484
1458
                                 message::Table &table_proto,
1485
1459
                                 AlterInfo *alter_info,
1506
1480
    }
1507
1481
    else
1508
1482
    {
1509
 
      my_error(ER_TABLE_EXISTS_ERROR, identifier);
 
1483
      std::string path;
 
1484
      identifier.getSQLPath(path);
 
1485
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
1510
1486
      result= true;
1511
1487
    }
1512
1488
  }
1513
1489
  else
1514
1490
  {
1515
 
    result= create_table_no_lock(session,
 
1491
    result= mysql_create_table_no_lock(session,
1516
1492
                                       identifier,
1517
1493
                                       create_info,
1518
1494
                                       table_proto,
1533
1509
 
1534
1510
 
1535
1511
/*
1536
 
  Database locking aware wrapper for create_table_no_lock(),
 
1512
  Database locking aware wrapper for mysql_create_table_no_lock(),
1537
1513
*/
1538
 
bool create_table(Session *session,
1539
 
                        const identifier::Table &identifier,
 
1514
bool mysql_create_table(Session *session,
 
1515
                        const TableIdentifier &identifier,
1540
1516
                        HA_CREATE_INFO *create_info,
1541
1517
                        message::Table &table_proto,
1542
1518
                        AlterInfo *alter_info,
1546
1522
{
1547
1523
  if (identifier.isTmp())
1548
1524
  {
1549
 
    return create_table_no_lock(session,
 
1525
    return mysql_create_table_no_lock(session,
1550
1526
                                      identifier,
1551
1527
                                      create_info,
1552
1528
                                      table_proto,
1616
1592
  Rename a table.
1617
1593
 
1618
1594
  SYNOPSIS
1619
 
    rename_table()
 
1595
    mysql_rename_table()
1620
1596
      session
1621
1597
      base                      The plugin::StorageEngine handle.
1622
1598
      old_db                    The old database name.
1630
1606
*/
1631
1607
 
1632
1608
bool
1633
 
rename_table(Session &session,
 
1609
mysql_rename_table(Session &session,
1634
1610
                   plugin::StorageEngine *base,
1635
 
                   const identifier::Table &from,
1636
 
                   const identifier::Table &to)
 
1611
                   const TableIdentifier &from,
 
1612
                   const TableIdentifier &to)
1637
1613
{
1638
1614
  int error= 0;
1639
1615
 
1699
1675
  session->abortLock(table);    /* end threads waiting on lock */
1700
1676
 
1701
1677
  /* Wait until all there are no other threads that has this table open */
1702
 
  identifier::Table identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName());
 
1678
  TableIdentifier identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName());
1703
1679
  table::Cache::singleton().removeTable(session, identifier, RTFC_WAIT_OTHER_THREAD_FLAG);
1704
1680
}
1705
1681
 
1743
1719
    true  Message should be sent by caller
1744
1720
          (admin operation or network communication failed)
1745
1721
*/
1746
 
static bool admin_table(Session* session, TableList* tables,
 
1722
static bool mysql_admin_table(Session* session, TableList* tables,
1747
1723
                              HA_CHECK_OPT* check_opt,
1748
1724
                              const char *operator_name,
1749
1725
                              thr_lock_type lock_type,
1772
1748
  item->maybe_null = 1;
1773
1749
  field_list.push_back(item = new Item_empty_string("Msg_text", 255, cs));
1774
1750
  item->maybe_null = 1;
1775
 
  if (session->getClient()->sendFields(&field_list))
 
1751
  if (session->client->sendFields(&field_list))
1776
1752
    return true;
1777
1753
 
1778
1754
  for (table= tables; table; table= table->next_local)
1827
1803
    {
1828
1804
      char buff[FN_REFLEN + DRIZZLE_ERRMSG_SIZE];
1829
1805
      uint32_t length;
1830
 
      session->getClient()->store(table_name);
1831
 
      session->getClient()->store(operator_name);
1832
 
      session->getClient()->store(STRING_WITH_LEN("error"));
 
1806
      session->client->store(table_name);
 
1807
      session->client->store(operator_name);
 
1808
      session->client->store(STRING_WITH_LEN("error"));
1833
1809
      length= snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY),
1834
1810
                       table_name);
1835
 
      session->getClient()->store(buff, length);
1836
 
      transaction_services.autocommitOrRollback(*session, false);
 
1811
      session->client->store(buff, length);
 
1812
      transaction_services.autocommitOrRollback(session, false);
1837
1813
      session->endTransaction(COMMIT);
1838
1814
      session->close_thread_tables();
1839
1815
      lex->reset_query_tables_list(false);
1840
1816
      table->table=0;                           // For query cache
1841
 
      if (session->getClient()->flush())
 
1817
      if (session->client->flush())
1842
1818
        goto err;
1843
1819
      continue;
1844
1820
    }
1850
1826
      const char *old_message=session->enter_cond(COND_refresh, table::Cache::singleton().mutex(),
1851
1827
                                                  "Waiting to get writelock");
1852
1828
      session->abortLock(table->table);
1853
 
      identifier::Table identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
 
1829
      TableIdentifier identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
1854
1830
      table::Cache::singleton().removeTable(session, identifier, RTFC_WAIT_OTHER_THREAD_FLAG | RTFC_CHECK_KILLED_FLAG);
1855
1831
      session->exit_cond(old_message);
1856
1832
      if (session->getKilled())
1869
1845
      DRIZZLE_ERROR *err;
1870
1846
      while ((err= it++))
1871
1847
      {
1872
 
        session->getClient()->store(table_name);
1873
 
        session->getClient()->store(operator_name);
1874
 
        session->getClient()->store(warning_level_names[err->level].str,
 
1848
        session->client->store(table_name);
 
1849
        session->client->store(operator_name);
 
1850
        session->client->store(warning_level_names[err->level].str,
1875
1851
                               warning_level_names[err->level].length);
1876
 
        session->getClient()->store(err->msg);
1877
 
        if (session->getClient()->flush())
 
1852
        session->client->store(err->msg);
 
1853
        if (session->client->flush())
1878
1854
          goto err;
1879
1855
      }
1880
1856
      drizzle_reset_errors(session, true);
1881
1857
    }
1882
 
    session->getClient()->store(table_name);
1883
 
    session->getClient()->store(operator_name);
 
1858
    session->client->store(table_name);
 
1859
    session->client->store(operator_name);
1884
1860
 
1885
1861
    switch (result_code) {
1886
1862
    case HA_ADMIN_NOT_IMPLEMENTED:
1888
1864
        char buf[ERRMSGSIZE+20];
1889
1865
        uint32_t length=snprintf(buf, ERRMSGSIZE,
1890
1866
                             ER(ER_CHECK_NOT_IMPLEMENTED), operator_name);
1891
 
        session->getClient()->store(STRING_WITH_LEN("note"));
1892
 
        session->getClient()->store(buf, length);
 
1867
        session->client->store(STRING_WITH_LEN("note"));
 
1868
        session->client->store(buf, length);
1893
1869
      }
1894
1870
      break;
1895
1871
 
1896
1872
    case HA_ADMIN_OK:
1897
 
      session->getClient()->store(STRING_WITH_LEN("status"));
1898
 
      session->getClient()->store(STRING_WITH_LEN("OK"));
 
1873
      session->client->store(STRING_WITH_LEN("status"));
 
1874
      session->client->store(STRING_WITH_LEN("OK"));
1899
1875
      break;
1900
1876
 
1901
1877
    case HA_ADMIN_FAILED:
1902
 
      session->getClient()->store(STRING_WITH_LEN("status"));
1903
 
      session->getClient()->store(STRING_WITH_LEN("Operation failed"));
 
1878
      session->client->store(STRING_WITH_LEN("status"));
 
1879
      session->client->store(STRING_WITH_LEN("Operation failed"));
1904
1880
      break;
1905
1881
 
1906
1882
    case HA_ADMIN_REJECT:
1907
 
      session->getClient()->store(STRING_WITH_LEN("status"));
1908
 
      session->getClient()->store(STRING_WITH_LEN("Operation need committed state"));
 
1883
      session->client->store(STRING_WITH_LEN("status"));
 
1884
      session->client->store(STRING_WITH_LEN("Operation need committed state"));
1909
1885
      open_for_modify= false;
1910
1886
      break;
1911
1887
 
1912
1888
    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"));
 
1889
      session->client->store(STRING_WITH_LEN("status"));
 
1890
      session->client->store(STRING_WITH_LEN("Table is already up to date"));
1915
1891
      break;
1916
1892
 
1917
1893
    case HA_ADMIN_CORRUPT:
1918
 
      session->getClient()->store(STRING_WITH_LEN("error"));
1919
 
      session->getClient()->store(STRING_WITH_LEN("Corrupt"));
 
1894
      session->client->store(STRING_WITH_LEN("error"));
 
1895
      session->client->store(STRING_WITH_LEN("Corrupt"));
1920
1896
      fatal_error=1;
1921
1897
      break;
1922
1898
 
1923
1899
    case HA_ADMIN_INVALID:
1924
 
      session->getClient()->store(STRING_WITH_LEN("error"));
1925
 
      session->getClient()->store(STRING_WITH_LEN("Invalid argument"));
 
1900
      session->client->store(STRING_WITH_LEN("error"));
 
1901
      session->client->store(STRING_WITH_LEN("Invalid argument"));
1926
1902
      break;
1927
1903
 
1928
1904
    default:                            // Probably HA_ADMIN_INTERNAL_ERROR
1931
1907
        uint32_t length=snprintf(buf, ERRMSGSIZE,
1932
1908
                             _("Unknown - internal error %d during operation"),
1933
1909
                             result_code);
1934
 
        session->getClient()->store(STRING_WITH_LEN("error"));
1935
 
        session->getClient()->store(buf, length);
 
1910
        session->client->store(STRING_WITH_LEN("error"));
 
1911
        session->client->store(buf, length);
1936
1912
        fatal_error=1;
1937
1913
        break;
1938
1914
      }
1952
1928
        else
1953
1929
        {
1954
1930
          boost::unique_lock<boost::mutex> lock(table::Cache::singleton().mutex());
1955
 
          identifier::Table identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
 
1931
          TableIdentifier identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
1956
1932
          table::Cache::singleton().removeTable(session, identifier, RTFC_NO_FLAG);
1957
1933
        }
1958
1934
      }
1959
1935
    }
1960
 
    transaction_services.autocommitOrRollback(*session, false);
 
1936
    transaction_services.autocommitOrRollback(session, false);
1961
1937
    session->endTransaction(COMMIT);
1962
1938
    session->close_thread_tables();
1963
1939
    table->table=0;                             // For query cache
1964
 
    if (session->getClient()->flush())
 
1940
    if (session->client->flush())
1965
1941
      goto err;
1966
1942
  }
1967
1943
 
1969
1945
  return(false);
1970
1946
 
1971
1947
err:
1972
 
  transaction_services.autocommitOrRollback(*session, true);
 
1948
  transaction_services.autocommitOrRollback(session, true);
1973
1949
  session->endTransaction(ROLLBACK);
1974
1950
  session->close_thread_tables();                       // Shouldn't be needed
1975
1951
  if (table)
1992
1968
    during the call to plugin::StorageEngine::createTable().
1993
1969
    See bug #28614 for more info.
1994
1970
  */
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,
 
1971
static bool create_table_wrapper(Session &session, const message::Table& create_table_proto,
 
1972
                                 const TableIdentifier &destination_identifier,
 
1973
                                 const TableIdentifier &src_table,
1999
1974
                                 bool is_engine_set)
2000
1975
{
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);
 
1976
  int protoerr= EEXIST;
 
1977
  message::Table new_proto;
 
1978
  message::table::shared_ptr src_proto;
 
1979
 
 
1980
  protoerr= plugin::StorageEngine::getTableDefinition(session,
 
1981
                                                      src_table,
 
1982
                                                      src_proto);
 
1983
  new_proto.CopyFrom(*src_proto);
2016
1984
 
2017
1985
  if (destination_identifier.isTmp())
2018
1986
  {
2019
 
    new_table_message.set_type(message::Table::TEMPORARY);
 
1987
    new_proto.set_type(message::Table::TEMPORARY);
2020
1988
  }
2021
1989
  else
2022
1990
  {
2023
 
    new_table_message.set_type(message::Table::STANDARD);
 
1991
    new_proto.set_type(message::Table::STANDARD);
2024
1992
  }
2025
1993
 
2026
1994
  if (is_engine_set)
2027
1995
  {
2028
 
    new_table_message.mutable_engine()->set_name(create_table_proto.engine().name());
 
1996
    new_proto.mutable_engine()->set_name(create_table_proto.engine().name());
2029
1997
  }
2030
1998
 
2031
1999
  { // 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());
 
2000
    new_proto.set_name(create_table_proto.name());
 
2001
    new_proto.set_schema(create_table_proto.schema());
 
2002
    new_proto.set_catalog(create_table_proto.catalog());
2035
2003
  }
2036
2004
 
2037
 
  /* Fix names of foreign keys being added */
2038
 
  for (int32_t j= 0; j < new_table_message.fk_constraint_size(); j++)
 
2005
  if (protoerr && protoerr != EEXIST)
2039
2006
  {
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
 
    }
 
2007
    if (errno == ENOENT)
 
2008
      my_error(ER_BAD_DB_ERROR,MYF(0), destination_identifier.getSchemaName().c_str());
 
2009
    else
 
2010
      my_error(ER_CANT_CREATE_FILE, MYF(0), destination_identifier.getPath().c_str(), errno);
 
2011
 
 
2012
    return false;
2052
2013
  }
2053
2014
 
2054
2015
  /*
2055
2016
    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).
 
2017
    creation, instead create the table directly (for both normal
 
2018
    and temporary tables).
2057
2019
  */
2058
 
  bool success= plugin::StorageEngine::createTable(session,
2059
 
                                                   destination_identifier,
2060
 
                                                   new_table_message);
 
2020
  int err= plugin::StorageEngine::createTable(session,
 
2021
                                              destination_identifier,
 
2022
                                              new_proto);
2061
2023
 
2062
 
  if (success && not destination_identifier.isTmp())
 
2024
  if (err == false && not destination_identifier.isTmp())
2063
2025
  {
2064
2026
    TransactionServices &transaction_services= TransactionServices::singleton();
2065
 
    transaction_services.createTable(session, new_table_message);
 
2027
    transaction_services.createTable(&session, new_proto);
2066
2028
  }
2067
2029
 
2068
 
  return success;
 
2030
  return err ? false : true;
2069
2031
}
2070
2032
 
2071
2033
/*
2072
2034
  Create a table identical to the specified table
2073
2035
 
2074
2036
  SYNOPSIS
2075
 
    create_like_table()
 
2037
    mysql_create_like_table()
2076
2038
    session             Thread object
2077
2039
    table       Table list element for target table
2078
2040
    src_table   Table list element for source table
2083
2045
    true  error
2084
2046
*/
2085
2047
 
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)
 
2048
bool mysql_create_like_table(Session* session,
 
2049
                             const TableIdentifier &destination_identifier,
 
2050
                             TableList* table, TableList* src_table,
 
2051
                             message::Table &create_table_proto,
 
2052
                             bool is_if_not_exists,
 
2053
                             bool is_engine_set)
2092
2054
{
2093
2055
  bool res= true;
2094
 
  bool table_exists= false;
 
2056
  uint32_t not_used;
 
2057
 
 
2058
  /*
 
2059
    By opening source table we guarantee that it exists and no concurrent
 
2060
    DDL operation will mess with it. Later we also take an exclusive
 
2061
    name-lock on target table name, which makes copying of .frm cursor,
 
2062
    call to plugin::StorageEngine::createTable() and binlogging atomic
 
2063
    against concurrent DML and DDL operations on target table.
 
2064
    Thus by holding both these "locks" we ensure that our statement is
 
2065
    properly isolated from all concurrent operations which matter.
 
2066
  */
 
2067
  if (session->open_tables_from_list(&src_table, &not_used))
 
2068
    return true;
 
2069
 
 
2070
  TableIdentifier src_identifier(src_table->table->getShare()->getSchemaName(),
 
2071
                                 src_table->table->getShare()->getTableName(), src_table->table->getShare()->getType());
 
2072
 
 
2073
 
2095
2074
 
2096
2075
  /*
2097
2076
    Check that destination tables does not exist. Note that its name
2099
2078
 
2100
2079
    For temporary tables we don't aim to grab locks.
2101
2080
  */
 
2081
  bool table_exists= false;
2102
2082
  if (destination_identifier.isTmp())
2103
2083
  {
2104
2084
    if (session->find_temporary_table(destination_identifier))
2107
2087
    }
2108
2088
    else
2109
2089
    {
2110
 
      bool was_created= create_table_wrapper(*session,
2111
 
                                             create_table_proto,
2112
 
                                             destination_identifier,
2113
 
                                             source_identifier,
2114
 
                                             is_engine_set);
 
2090
      bool was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
 
2091
                                             src_identifier, is_engine_set);
2115
2092
      if (not was_created) // This is pretty paranoid, but we assume something might not clean up after itself
2116
2093
      {
2117
2094
        (void) session->rm_temporary_table(destination_identifier, true);
2156
2133
      {
2157
2134
        boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* We lock for CREATE TABLE LIKE to copy table definition */
2158
2135
        was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
2159
 
                                          source_identifier, is_engine_set);
 
2136
                                               src_identifier, is_engine_set);
2160
2137
      }
2161
2138
 
2162
2139
      // So we blew the creation of the table, and we scramble to clean up
2184
2161
    {
2185
2162
      char warn_buff[DRIZZLE_ERRMSG_SIZE];
2186
2163
      snprintf(warn_buff, sizeof(warn_buff),
2187
 
               ER(ER_TABLE_EXISTS_ERROR), destination_identifier.getTableName().c_str());
 
2164
               ER(ER_TABLE_EXISTS_ERROR), table->getTableName());
2188
2165
      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;
 
2166
                   ER_TABLE_EXISTS_ERROR,warn_buff);
 
2167
      res= false;
 
2168
    }
 
2169
    else
 
2170
    {
 
2171
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table->getTableName());
 
2172
    }
2196
2173
  }
2197
2174
 
2198
 
  return res;
 
2175
  return(res);
2199
2176
}
2200
2177
 
2201
2178
 
2202
 
bool analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
 
2179
bool mysql_analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
2203
2180
{
2204
2181
  thr_lock_type lock_type = TL_READ_NO_INSERT;
2205
2182
 
2206
 
  return(admin_table(session, tables, check_opt,
 
2183
  return(mysql_admin_table(session, tables, check_opt,
2207
2184
                                "analyze", lock_type, true,
2208
2185
                                &Cursor::ha_analyze));
2209
2186
}
2210
2187
 
2211
2188
 
2212
 
bool check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
 
2189
bool mysql_check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
2213
2190
{
2214
2191
  thr_lock_type lock_type = TL_READ_NO_INSERT;
2215
2192
 
2216
 
  return(admin_table(session, tables, check_opt,
 
2193
  return(mysql_admin_table(session, tables, check_opt,
2217
2194
                                "check", lock_type,
2218
2195
                                false,
2219
2196
                                &Cursor::ha_check));