~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_table.cc

  • Committer: Lee Bieber
  • Date: 2011-01-05 19:01:18 UTC
  • mfrom: (2053.2.3 trunk-bug-696188)
  • Revision ID: kalebral@gmail.com-20110105190118-kiq5sez67rvi4kl7
Merge Andrew - fix bug 696188: error handling for drizzle client stdin replacement problems

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
 
16
16
/* drop and alter of tables */
17
17
 
18
 
#include <config.h>
 
18
#include "config.h"
19
19
#include <plugin/myisam/myisam.h>
20
20
#include <drizzled/show.h>
21
21
#include <drizzled/error.h>
26
26
#include <drizzled/sql_lex.h>
27
27
#include <drizzled/session.h>
28
28
#include <drizzled/sql_base.h>
29
 
#include <drizzled/strfunc.h>
 
29
#include "drizzled/strfunc.h"
 
30
#include <drizzled/db.h>
30
31
#include <drizzled/lock.h>
31
32
#include <drizzled/unireg.h>
32
33
#include <drizzled/item/int.h>
33
34
#include <drizzled/item/empty_string.h>
34
35
#include <drizzled/transaction_services.h>
35
 
#include <drizzled/transaction_services.h>
 
36
#include "drizzled/transaction_services.h"
36
37
#include <drizzled/table_proto.h>
37
38
#include <drizzled/plugin/client.h>
38
39
#include <drizzled/identifier.h>
39
 
#include <drizzled/internal/m_string.h>
40
 
#include <drizzled/global_charset_info.h>
41
 
#include <drizzled/charset.h>
42
 
 
43
 
#include <drizzled/definition/cache.h>
44
 
 
45
 
#include <drizzled/statement/alter_table.h>
46
 
#include <drizzled/sql_table.h>
47
 
#include <drizzled/pthread_globals.h>
48
 
#include <drizzled/typelib.h>
49
 
#include <drizzled/plugin/storage_engine.h>
 
40
#include "drizzled/internal/m_string.h"
 
41
#include "drizzled/global_charset_info.h"
 
42
#include "drizzled/charset.h"
 
43
 
 
44
#include "drizzled/definition/cache.h"
 
45
 
 
46
 
 
47
#include "drizzled/statement/alter_table.h"
 
48
#include "drizzled/sql_table.h"
 
49
#include "drizzled/pthread_globals.h"
50
50
 
51
51
#include <algorithm>
52
52
#include <sstream>
58
58
namespace drizzled
59
59
{
60
60
 
 
61
extern pid_t current_pid;
 
62
 
61
63
bool is_primary_key(KeyInfo *key_info)
62
64
{
63
65
  static const char * primary_key_name="PRIMARY";
85
87
    let's fetch the database default character set and
86
88
    apply it to the table.
87
89
  */
88
 
  identifier::Schema identifier(db);
 
90
  SchemaIdentifier identifier(db);
89
91
  if (create_info->default_table_charset == NULL)
90
92
    create_info->default_table_charset= plugin::StorageEngine::getSchemaCollation(identifier);
91
93
}
108
110
void write_bin_log(Session *session, const std::string &query)
109
111
{
110
112
  TransactionServices &transaction_services= TransactionServices::singleton();
111
 
  transaction_services.rawStatement(*session, query);
 
113
  transaction_services.rawStatement(session, query);
112
114
}
113
115
 
114
116
/*
139
141
*/
140
142
 
141
143
int rm_table_part2(Session *session, TableList *tables, bool if_exists,
142
 
                   bool drop_temporary)
 
144
                         bool drop_temporary)
143
145
{
144
146
  TableList *table;
145
 
  util::string::vector wrong_tables;
 
147
  String wrong_tables;
146
148
  int error= 0;
147
149
  bool foreign_key_error= false;
148
150
 
149
 
  do
150
151
  {
151
 
    boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex());
 
152
    table::Cache::singleton().mutex().lock(); /* Part 2 of rm a table */
152
153
 
153
154
    if (not drop_temporary && session->lock_table_names_exclusively(tables))
154
155
    {
 
156
      table::Cache::singleton().mutex().unlock();
155
157
      return 1;
156
158
    }
157
159
 
160
162
 
161
163
    for (table= tables; table; table= table->next_local)
162
164
    {
163
 
      identifier::Table tmp_identifier(table->getSchemaName(), table->getTableName());
 
165
      TableIdentifier tmp_identifier(table->getSchemaName(), table->getTableName());
164
166
 
165
167
      error= session->drop_temporary_table(tmp_identifier);
166
168
 
170
172
        continue;
171
173
      case -1:
172
174
        error= 1;
173
 
        break;
 
175
        goto err_with_placeholders;
174
176
      default:
175
177
        // temporary table not found
176
178
        error= 0;
193
195
        if (session->getKilled())
194
196
        {
195
197
          error= -1;
196
 
          break;
 
198
          goto err_with_placeholders;
197
199
        }
198
200
      }
199
 
      identifier::Table identifier(table->getSchemaName(), table->getTableName(), table->getInternalTmpTable() ? message::Table::INTERNAL : message::Table::STANDARD);
200
 
 
201
 
      message::table::shared_ptr message= plugin::StorageEngine::getTableMessage(*session, identifier, true);
 
201
      TableIdentifier identifier(table->getSchemaName(), table->getTableName(), table->getInternalTmpTable() ? message::Table::INTERNAL : message::Table::STANDARD);
202
202
 
203
203
      if (drop_temporary || not plugin::StorageEngine::doesTableExist(*session, identifier))
204
204
      {
205
205
        // Table was not found on disk and table can't be created from engine
206
206
        if (if_exists)
207
 
        {
208
207
          push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
209
208
                              ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
210
209
                              table->getTableName());
211
 
        }
212
210
        else
213
 
        {
214
211
          error= 1;
215
 
        }
216
212
      }
217
213
      else
218
214
      {
219
 
        drizzled::error_t local_error;
 
215
        error= plugin::StorageEngine::dropTable(*session, identifier);
220
216
 
221
217
        /* Generate transaction event ONLY when we successfully drop */ 
222
 
        if (plugin::StorageEngine::dropTable(*session, identifier, local_error))
223
 
        {
224
 
          if (message) // If we have no definition, we don't know if the table should have been replicated
225
 
          {
226
 
            TransactionServices &transaction_services= TransactionServices::singleton();
227
 
            transaction_services.dropTable(*session, identifier, *message, if_exists);
228
 
          }
229
 
        }
230
 
        else
231
 
        {
232
 
          if (local_error == HA_ERR_NO_SUCH_TABLE and if_exists)
233
 
          {
234
 
            error= 0;
235
 
            session->clear_error();
236
 
          }
237
 
 
238
 
          if (local_error == HA_ERR_ROW_IS_REFERENCED)
239
 
          {
240
 
            /* the table is referenced by a foreign key constraint */
241
 
            foreign_key_error= true;
242
 
          }
243
 
          error= local_error;
 
218
        if (error == 0)
 
219
        {
 
220
          TransactionServices &transaction_services= TransactionServices::singleton();
 
221
          transaction_services.dropTable(session, identifier, if_exists);
 
222
        }
 
223
 
 
224
        if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) && if_exists)
 
225
        {
 
226
          error= 0;
 
227
          session->clear_error();
 
228
        }
 
229
 
 
230
        if (error == HA_ERR_ROW_IS_REFERENCED)
 
231
        {
 
232
          /* the table is referenced by a foreign key constraint */
 
233
          foreign_key_error= true;
244
234
        }
245
235
      }
246
236
 
247
237
      if (error)
248
238
      {
249
 
        wrong_tables.push_back(table->getTableName());
 
239
        if (wrong_tables.length())
 
240
          wrong_tables.append(',');
 
241
        wrong_tables.append(String(table->getTableName(), system_charset_info));
250
242
      }
251
243
    }
252
 
 
253
 
    tables->unlock_table_names();
254
 
 
255
 
  } while (0);
256
 
 
257
 
  if (wrong_tables.size())
 
244
    /*
 
245
      It's safe to unlock table::Cache::singleton().mutex(): we have an exclusive lock
 
246
      on the table name.
 
247
    */
 
248
    table::Cache::singleton().mutex().unlock();
 
249
  }
 
250
  error= 0;
 
251
 
 
252
  if (wrong_tables.length())
258
253
  {
259
254
    if (not foreign_key_error)
260
255
    {
261
 
      std::string table_error;
262
 
 
263
 
      for (util::string::vector::iterator iter= wrong_tables.begin();
264
 
           iter != wrong_tables.end();
265
 
           iter++)
266
 
      {
267
 
        table_error+= *iter;
268
 
        table_error+= ',';
269
 
      }
270
 
      table_error.resize(table_error.size() -1);
271
 
 
272
256
      my_printf_error(ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), MYF(0),
273
 
                      table_error.c_str());
 
257
                      wrong_tables.c_ptr());
274
258
    }
275
259
    else
276
260
    {
279
263
    error= 1;
280
264
  }
281
265
 
 
266
  table::Cache::singleton().mutex().lock(); /* final bit in rm table lock */
 
267
 
 
268
err_with_placeholders:
 
269
  tables->unlock_table_names();
 
270
  table::Cache::singleton().mutex().unlock();
282
271
  session->no_warnings_for_error= 0;
283
272
 
284
273
  return error;
483
472
    sql_field->length= 8; // Unireg field length
484
473
    (*blob_columns)++;
485
474
    break;
486
 
 
 
475
  case DRIZZLE_TYPE_VARCHAR:
 
476
    break;
487
477
  case DRIZZLE_TYPE_ENUM:
488
 
    {
489
 
      if (check_duplicates_in_interval("ENUM",
490
 
                                       sql_field->field_name,
491
 
                                       sql_field->interval,
492
 
                                       sql_field->charset,
493
 
                                       &dup_val_count))
494
 
      {
495
 
        return 1;
496
 
      }
497
 
    }
498
 
    break;
499
 
 
500
 
  case DRIZZLE_TYPE_MICROTIME:
 
478
    if (check_duplicates_in_interval("ENUM",
 
479
                                     sql_field->field_name,
 
480
                                     sql_field->interval,
 
481
                                     sql_field->charset,
 
482
                                     &dup_val_count))
 
483
      return 1;
 
484
    break;
 
485
  case DRIZZLE_TYPE_DATE:  // Rest of string types
 
486
  case DRIZZLE_TYPE_TIME:
 
487
  case DRIZZLE_TYPE_DATETIME:
 
488
  case DRIZZLE_TYPE_NULL:
 
489
    break;
 
490
  case DRIZZLE_TYPE_DECIMAL:
 
491
    break;
501
492
  case DRIZZLE_TYPE_TIMESTAMP:
502
493
    /* We should replace old TIMESTAMP fields with their newer analogs */
503
494
    if (sql_field->unireg_check == Field::TIMESTAMP_OLD_FIELD)
513
504
      }
514
505
    }
515
506
    else if (sql_field->unireg_check != Field::NONE)
516
 
    {
517
507
      (*timestamps_with_niladic)++;
518
 
    }
519
508
 
520
509
    (*timestamps)++;
521
 
 
522
 
    break;
523
 
 
524
 
  case DRIZZLE_TYPE_BOOLEAN:
525
 
  case DRIZZLE_TYPE_DATE:  // Rest of string types
526
 
  case DRIZZLE_TYPE_DATETIME:
527
 
  case DRIZZLE_TYPE_DECIMAL:
528
 
  case DRIZZLE_TYPE_DOUBLE:
529
 
  case DRIZZLE_TYPE_LONG:
530
 
  case DRIZZLE_TYPE_LONGLONG:
531
 
  case DRIZZLE_TYPE_NULL:
532
 
  case DRIZZLE_TYPE_TIME:
533
 
  case DRIZZLE_TYPE_UUID:
534
 
  case DRIZZLE_TYPE_VARCHAR:
 
510
    /* fall-through */
 
511
  default:
535
512
    break;
536
513
  }
537
514
 
539
516
}
540
517
 
541
518
static int prepare_create_table(Session *session,
542
 
                                HA_CREATE_INFO *create_info,
543
 
                                message::Table &create_proto,
544
 
                                AlterInfo *alter_info,
545
 
                                bool tmp_table,
546
 
                                uint32_t *db_options,
547
 
                                KeyInfo **key_info_buffer,
548
 
                                uint32_t *key_count,
549
 
                                int select_field_count)
 
519
                                      HA_CREATE_INFO *create_info,
 
520
                                      message::Table &create_proto,
 
521
                                      AlterInfo *alter_info,
 
522
                                      bool tmp_table,
 
523
                                      uint32_t *db_options,
 
524
                                      KeyInfo **key_info_buffer,
 
525
                                      uint32_t *key_count,
 
526
                                      int select_field_count)
550
527
{
551
528
  const char    *key_name;
552
529
  CreateField   *sql_field,*dup_field;
555
532
  KeyInfo               *key_info;
556
533
  KeyPartInfo *key_part_info;
557
534
  int           timestamps= 0, timestamps_with_niladic= 0;
558
 
  int           dup_no;
 
535
  int           field_no,dup_no;
559
536
  int           select_field_pos,auto_increment=0;
560
 
  List<CreateField>::iterator it(alter_info->create_list.begin());
561
 
  List<CreateField>::iterator it2(alter_info->create_list.begin());
 
537
  List_iterator<CreateField> it(alter_info->create_list);
 
538
  List_iterator<CreateField> it2(alter_info->create_list);
562
539
  uint32_t total_uneven_bit_length= 0;
563
540
 
564
541
  plugin::StorageEngine *engine= plugin::StorageEngine::findByName(create_proto.engine().name());
567
544
  null_fields=blob_columns=0;
568
545
  max_key_length= engine->max_key_length();
569
546
 
570
 
  for (int32_t field_no=0; (sql_field=it++) ; field_no++)
 
547
  for (field_no=0; (sql_field=it++) ; field_no++)
571
548
  {
572
549
    const CHARSET_INFO *save_cs;
573
550
 
577
554
      executing a prepared statement for the second time.
578
555
    */
579
556
    sql_field->length= sql_field->char_length;
580
 
 
581
557
    if (!sql_field->charset)
582
558
      sql_field->charset= create_info->default_table_charset;
583
 
 
584
559
    /*
585
560
      table_charset is set in ALTER Table if we want change character set
586
561
      for all varchar/char columns.
652
627
        interval= sql_field->interval= typelib(session->mem_root,
653
628
                                               sql_field->interval_list);
654
629
 
655
 
        List<String>::iterator int_it(sql_field->interval_list.begin());
 
630
        List_iterator<String> int_it(sql_field->interval_list);
656
631
        String conv, *tmp;
657
632
        char comma_buf[4];
658
633
        int comma_length= cs->cset->wc_mb(cs, ',', (unsigned char*) comma_buf,
678
653
          interval->type_lengths[i]= lengthsp;
679
654
          ((unsigned char *)interval->type_names[i])[lengthsp]= '\0';
680
655
        }
681
 
        sql_field->interval_list.clear(); // Don't need interval_list anymore
 
656
        sql_field->interval_list.empty(); // Don't need interval_list anymore
682
657
      }
683
658
 
684
659
      /* DRIZZLE_TYPE_ENUM */
701
676
          else /* not NULL */
702
677
          {
703
678
            def->length(cs->cset->lengthsp(cs, def->ptr(), def->length()));
704
 
            if (interval->find_type2(def->ptr(), def->length(), cs) == 0) /* not found */
 
679
            if (find_type2(interval, def->ptr(), def->length(), cs) == 0) /* not found */
705
680
            {
706
681
              my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
707
682
              return(true);
778
753
    if (not create_proto.engine().name().compare("MyISAM") &&
779
754
        ((sql_field->flags & BLOB_FLAG) ||
780
755
         (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR)))
781
 
    {
782
756
      (*db_options)|= HA_OPTION_PACK_RECORD;
783
 
    }
784
 
 
785
 
    it2= alter_info->create_list.begin();
 
757
    it2.rewind();
786
758
  }
787
759
 
788
760
  /* record_offset will be increased with 'length-of-null-bits' later */
789
761
  record_offset= 0;
790
762
  null_fields+= total_uneven_bit_length;
791
763
 
792
 
  it= alter_info->create_list.begin();
 
764
  it.rewind();
793
765
  while ((sql_field=it++))
794
766
  {
795
767
    assert(sql_field->charset != 0);
829
801
 
830
802
  /* Create keys */
831
803
 
832
 
  List<Key>::iterator key_iterator(alter_info->key_list.begin());
833
 
  List<Key>::iterator key_iterator2(alter_info->key_list.begin());
 
804
  List_iterator<Key> key_iterator(alter_info->key_list);
 
805
  List_iterator<Key> key_iterator2(alter_info->key_list);
834
806
  uint32_t key_parts=0, fk_key_count=0;
835
807
  bool primary_key=0,unique_key=0;
836
808
  Key *key, *key2;
880
852
    }
881
853
    if (check_identifier_name(&key->name, ER_TOO_LONG_IDENT))
882
854
      return(true);
883
 
    key_iterator2= alter_info->key_list.begin();
 
855
    key_iterator2.rewind ();
884
856
    if (key->type != Key::FOREIGN_KEY)
885
857
    {
886
858
      while ((key2 = key_iterator2++) != key)
933
905
  if (!*key_info_buffer || ! key_part_info)
934
906
    return(true);                               // Out of memory
935
907
 
936
 
  key_iterator= alter_info->key_list.begin();
 
908
  key_iterator.rewind();
937
909
  key_number=0;
938
910
  for (; (key=key_iterator++) ; key_number++)
939
911
  {
992
964
 
993
965
    message::Table::Field *protofield= NULL;
994
966
 
995
 
    List<Key_part_spec>::iterator cols(key->columns.begin());
996
 
    List<Key_part_spec>::iterator cols2(key->columns.begin());
 
967
    List_iterator<Key_part_spec> cols(key->columns), cols2(key->columns);
997
968
    for (uint32_t column_nr=0 ; (column=cols++) ; column_nr++)
998
969
    {
999
970
      uint32_t length;
1000
971
      Key_part_spec *dup_column;
1001
972
      int proto_field_nr= 0;
1002
973
 
1003
 
      it= alter_info->create_list.begin();
 
974
      it.rewind();
1004
975
      field=0;
1005
976
      while ((sql_field=it++) && ++proto_field_nr &&
1006
977
             my_strcasecmp(system_charset_info,
1007
978
                           column->field_name.str,
1008
979
                           sql_field->field_name))
1009
 
      {
1010
980
        field++;
1011
 
      }
1012
 
 
1013
981
      if (!sql_field)
1014
982
      {
1015
983
        my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name.str);
1016
984
        return(true);
1017
985
      }
1018
 
 
1019
986
      while ((dup_column= cols2++) != column)
1020
987
      {
1021
988
        if (!my_strcasecmp(system_charset_info,
1027
994
          return(true);
1028
995
        }
1029
996
      }
1030
 
      cols2= key->columns.begin();
 
997
      cols2.rewind();
1031
998
 
1032
999
      if (create_proto.field_size() > 0)
1033
1000
        protofield= create_proto.mutable_field(proto_field_nr - 1);
1048
1015
            return true;
1049
1016
          }
1050
1017
        }
1051
 
 
1052
1018
        if (! (sql_field->flags & NOT_NULL_FLAG))
1053
1019
        {
1054
1020
          if (key->type == Key::PRIMARY)
1061
1027
            {
1062
1028
              message::Table::Field::FieldConstraints *constraints;
1063
1029
              constraints= protofield->mutable_constraints();
1064
 
              constraints->set_is_notnull(true);
 
1030
              constraints->set_is_nullable(false);
1065
1031
            }
1066
1032
 
1067
1033
          }
1075
1041
            }
1076
1042
          }
1077
1043
        }
1078
 
 
1079
1044
        if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
1080
1045
        {
1081
1046
          if (column_nr == 0 || (engine->check_flag(HTON_BIT_AUTO_PART_KEY)))
1200
1165
        key_info->name=(char*) key_name;
1201
1166
      }
1202
1167
    }
1203
 
 
1204
1168
    if (!key_info->name || check_column_name(key_info->name))
1205
1169
    {
1206
1170
      my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key_info->name);
1207
1171
      return(true);
1208
1172
    }
1209
 
 
1210
1173
    if (!(key_info->flags & HA_NULL_PART_KEY))
1211
 
    {
1212
1174
      unique_key=1;
1213
 
    }
1214
 
 
1215
1175
    key_info->key_length=(uint16_t) key_length;
1216
 
 
1217
1176
    if (key_length > max_key_length)
1218
1177
    {
1219
1178
      my_error(ER_TOO_LONG_KEY,MYF(0),max_key_length);
1220
1179
      return(true);
1221
1180
    }
1222
 
 
1223
1181
    key_info++;
1224
1182
  }
1225
 
 
1226
1183
  if (!unique_key && !primary_key &&
1227
1184
      (engine->check_flag(HTON_BIT_REQUIRE_PRIMARY_KEY)))
1228
1185
  {
1229
1186
    my_message(ER_REQUIRES_PRIMARY_KEY, ER(ER_REQUIRES_PRIMARY_KEY), MYF(0));
1230
1187
    return(true);
1231
1188
  }
1232
 
 
1233
1189
  if (auto_increment > 0)
1234
1190
  {
1235
1191
    my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
1240
1196
                     (qsort_cmp) sort_keys);
1241
1197
 
1242
1198
  /* Check fields. */
1243
 
  it= alter_info->create_list.begin();
 
1199
  it.rewind();
1244
1200
  while ((sql_field=it++))
1245
1201
  {
1246
1202
    Field::utype type= (Field::utype) MTYP_TYPENR(sql_field->unireg_check);
1247
1203
 
1248
1204
    if (session->variables.sql_mode & MODE_NO_ZERO_DATE &&
1249
1205
        !sql_field->def &&
1250
 
        (sql_field->sql_type == DRIZZLE_TYPE_TIMESTAMP  or sql_field->sql_type == DRIZZLE_TYPE_MICROTIME) &&
 
1206
        sql_field->sql_type == DRIZZLE_TYPE_TIMESTAMP &&
1251
1207
        (sql_field->flags & NOT_NULL_FLAG) &&
1252
1208
        (type == Field::NONE || type == Field::TIMESTAMP_UN_FIELD))
1253
1209
    {
1311
1267
}
1312
1268
 
1313
1269
static bool locked_create_event(Session *session,
1314
 
                                const identifier::Table &identifier,
 
1270
                                const TableIdentifier &identifier,
1315
1271
                                HA_CREATE_INFO *create_info,
1316
1272
                                message::Table &table_proto,
1317
1273
                                AlterInfo *alter_info,
1346
1302
        return error;
1347
1303
      }
1348
1304
 
1349
 
      my_error(ER_TABLE_EXISTS_ERROR, identifier);
 
1305
      std::string path;
 
1306
      identifier.getSQLPath(path);
 
1307
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
1350
1308
 
1351
1309
      return error;
1352
1310
    }
1366
1324
      */
1367
1325
      if (definition::Cache::singleton().find(identifier.getKey()))
1368
1326
      {
1369
 
        my_error(ER_TABLE_EXISTS_ERROR, identifier);
 
1327
        std::string path;
 
1328
        identifier.getSQLPath(path);
 
1329
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
1370
1330
 
1371
1331
        return error;
1372
1332
      }
1405
1365
  if (table_proto.type() == message::Table::STANDARD && not internal_tmp_table)
1406
1366
  {
1407
1367
    TransactionServices &transaction_services= TransactionServices::singleton();
1408
 
    transaction_services.createTable(*session, table_proto);
 
1368
    transaction_services.createTable(session, table_proto);
1409
1369
  }
1410
1370
 
1411
1371
  return false;
1443
1403
*/
1444
1404
 
1445
1405
bool create_table_no_lock(Session *session,
1446
 
                                const identifier::Table &identifier,
 
1406
                                const TableIdentifier &identifier,
1447
1407
                                HA_CREATE_INFO *create_info,
1448
1408
                                message::Table &table_proto,
1449
1409
                                AlterInfo *alter_info,
1469
1429
 
1470
1430
  /* Build a Table object to pass down to the engine, and the do the actual create. */
1471
1431
  if (not prepare_create_table(session, create_info, table_proto, alter_info,
1472
 
                               internal_tmp_table,
1473
 
                               &db_options,
1474
 
                               &key_info_buffer, &key_count,
1475
 
                               select_field_count))
 
1432
                                     internal_tmp_table,
 
1433
                                     &db_options,
 
1434
                                     &key_info_buffer, &key_count,
 
1435
                                     select_field_count))
1476
1436
  {
1477
1437
    boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* CREATE TABLE (some confussion on naming, double check) */
1478
1438
    error= locked_create_event(session,
1495
1455
  @note the following two methods implement create [temporary] table.
1496
1456
*/
1497
1457
static bool drizzle_create_table(Session *session,
1498
 
                                 const identifier::Table &identifier,
 
1458
                                 const TableIdentifier &identifier,
1499
1459
                                 HA_CREATE_INFO *create_info,
1500
1460
                                 message::Table &table_proto,
1501
1461
                                 AlterInfo *alter_info,
1522
1482
    }
1523
1483
    else
1524
1484
    {
1525
 
      my_error(ER_TABLE_EXISTS_ERROR, identifier);
 
1485
      std::string path;
 
1486
      identifier.getSQLPath(path);
 
1487
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
1526
1488
      result= true;
1527
1489
    }
1528
1490
  }
1552
1514
  Database locking aware wrapper for create_table_no_lock(),
1553
1515
*/
1554
1516
bool create_table(Session *session,
1555
 
                        const identifier::Table &identifier,
 
1517
                        const TableIdentifier &identifier,
1556
1518
                        HA_CREATE_INFO *create_info,
1557
1519
                        message::Table &table_proto,
1558
1520
                        AlterInfo *alter_info,
1648
1610
bool
1649
1611
rename_table(Session &session,
1650
1612
                   plugin::StorageEngine *base,
1651
 
                   const identifier::Table &from,
1652
 
                   const identifier::Table &to)
 
1613
                   const TableIdentifier &from,
 
1614
                   const TableIdentifier &to)
1653
1615
{
1654
1616
  int error= 0;
1655
1617
 
1715
1677
  session->abortLock(table);    /* end threads waiting on lock */
1716
1678
 
1717
1679
  /* Wait until all there are no other threads that has this table open */
1718
 
  identifier::Table identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName());
 
1680
  TableIdentifier identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName());
1719
1681
  table::Cache::singleton().removeTable(session, identifier, RTFC_WAIT_OTHER_THREAD_FLAG);
1720
1682
}
1721
1683
 
1768
1730
                                                            HA_CHECK_OPT *))
1769
1731
{
1770
1732
  TableList *table;
1771
 
  Select_Lex *select= &session->getLex()->select_lex;
 
1733
  Select_Lex *select= &session->lex->select_lex;
1772
1734
  List<Item> field_list;
1773
1735
  Item *item;
 
1736
  LEX *lex= session->lex;
1774
1737
  int result_code= 0;
1775
1738
  TransactionServices &transaction_services= TransactionServices::singleton();
1776
1739
  const CHARSET_INFO * const cs= system_charset_info;
1777
1740
 
1778
1741
  if (! session->endActiveTransaction())
1779
1742
    return 1;
1780
 
 
1781
1743
  field_list.push_back(item = new Item_empty_string("Table",
1782
1744
                                                    NAME_CHAR_LEN * 2,
1783
1745
                                                    cs));
1793
1755
 
1794
1756
  for (table= tables; table; table= table->next_local)
1795
1757
  {
1796
 
    identifier::Table table_identifier(table->getSchemaName(), table->getTableName());
1797
 
    std::string table_name;
 
1758
    char table_name[NAME_LEN*2+2];
1798
1759
    bool fatal_error=0;
1799
1760
 
1800
 
    table_identifier.getSQLPath(table_name);
1801
 
 
 
1761
    snprintf(table_name, sizeof(table_name), "%s.%s", table->getSchemaName(), table->getTableName());
1802
1762
    table->lock_type= lock_type;
1803
1763
    /* open only one table from local list of command */
1804
1764
    {
1813
1773
        so it have to be prepared.
1814
1774
        @todo Investigate if we can put extra tables into argument instead of using lex->query_tables
1815
1775
      */
1816
 
      session->getLex()->query_tables= table;
1817
 
      session->getLex()->query_tables_last= &table->next_global;
1818
 
      session->getLex()->query_tables_own_last= 0;
 
1776
      lex->query_tables= table;
 
1777
      lex->query_tables_last= &table->next_global;
 
1778
      lex->query_tables_own_last= 0;
1819
1779
      session->no_warnings_for_error= 0;
1820
1780
 
1821
1781
      session->openTablesLock(table);
1845
1805
    {
1846
1806
      char buff[FN_REFLEN + DRIZZLE_ERRMSG_SIZE];
1847
1807
      uint32_t length;
1848
 
      session->getClient()->store(table_name.c_str());
 
1808
      session->getClient()->store(table_name);
1849
1809
      session->getClient()->store(operator_name);
1850
1810
      session->getClient()->store(STRING_WITH_LEN("error"));
1851
1811
      length= snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY),
1852
 
                       table_name.c_str());
 
1812
                       table_name);
1853
1813
      session->getClient()->store(buff, length);
1854
 
      transaction_services.autocommitOrRollback(*session, false);
 
1814
      transaction_services.autocommitOrRollback(session, false);
1855
1815
      session->endTransaction(COMMIT);
1856
1816
      session->close_thread_tables();
1857
 
      session->getLex()->reset_query_tables_list(false);
 
1817
      lex->reset_query_tables_list(false);
1858
1818
      table->table=0;                           // For query cache
1859
1819
      if (session->getClient()->flush())
1860
1820
        goto err;
1868
1828
      const char *old_message=session->enter_cond(COND_refresh, table::Cache::singleton().mutex(),
1869
1829
                                                  "Waiting to get writelock");
1870
1830
      session->abortLock(table->table);
1871
 
      identifier::Table identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
 
1831
      TableIdentifier identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
1872
1832
      table::Cache::singleton().removeTable(session, identifier, RTFC_WAIT_OTHER_THREAD_FLAG | RTFC_CHECK_KILLED_FLAG);
1873
1833
      session->exit_cond(old_message);
1874
1834
      if (session->getKilled())
1880
1840
 
1881
1841
send_result:
1882
1842
 
1883
 
    session->getLex()->cleanup_after_one_table_open();
 
1843
    lex->cleanup_after_one_table_open();
1884
1844
    session->clear_error();  // these errors shouldn't get client
1885
1845
    {
1886
 
      List<DRIZZLE_ERROR>::iterator it(session->warn_list.begin());
 
1846
      List_iterator_fast<DRIZZLE_ERROR> it(session->warn_list);
1887
1847
      DRIZZLE_ERROR *err;
1888
1848
      while ((err= it++))
1889
1849
      {
1890
 
        session->getClient()->store(table_name.c_str());
 
1850
        session->getClient()->store(table_name);
1891
1851
        session->getClient()->store(operator_name);
1892
1852
        session->getClient()->store(warning_level_names[err->level].str,
1893
1853
                               warning_level_names[err->level].length);
1897
1857
      }
1898
1858
      drizzle_reset_errors(session, true);
1899
1859
    }
1900
 
    session->getClient()->store(table_name.c_str());
 
1860
    session->getClient()->store(table_name);
1901
1861
    session->getClient()->store(operator_name);
1902
1862
 
1903
1863
    switch (result_code) {
1970
1930
        else
1971
1931
        {
1972
1932
          boost::unique_lock<boost::mutex> lock(table::Cache::singleton().mutex());
1973
 
          identifier::Table identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
 
1933
          TableIdentifier identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
1974
1934
          table::Cache::singleton().removeTable(session, identifier, RTFC_NO_FLAG);
1975
1935
        }
1976
1936
      }
1977
1937
    }
1978
 
    transaction_services.autocommitOrRollback(*session, false);
 
1938
    transaction_services.autocommitOrRollback(session, false);
1979
1939
    session->endTransaction(COMMIT);
1980
1940
    session->close_thread_tables();
1981
1941
    table->table=0;                             // For query cache
1987
1947
  return(false);
1988
1948
 
1989
1949
err:
1990
 
  transaction_services.autocommitOrRollback(*session, true);
 
1950
  transaction_services.autocommitOrRollback(session, true);
1991
1951
  session->endTransaction(ROLLBACK);
1992
1952
  session->close_thread_tables();                       // Shouldn't be needed
1993
1953
  if (table)
2010
1970
    during the call to plugin::StorageEngine::createTable().
2011
1971
    See bug #28614 for more info.
2012
1972
  */
2013
 
static bool create_table_wrapper(Session &session,
2014
 
                                 const message::Table& create_table_proto,
2015
 
                                 identifier::Table::const_reference destination_identifier,
2016
 
                                 identifier::Table::const_reference source_identifier,
 
1973
static bool create_table_wrapper(Session &session, const message::Table& create_table_proto,
 
1974
                                 const TableIdentifier &destination_identifier,
 
1975
                                 const TableIdentifier &src_table,
2017
1976
                                 bool is_engine_set)
2018
1977
{
2019
 
  // We require an additional table message because during parsing we used
2020
 
  // a "new" message and it will not have all of the information that the
2021
 
  // source table message would have.
2022
 
  message::Table new_table_message;
2023
 
 
2024
 
  message::table::shared_ptr source_table_message= plugin::StorageEngine::getTableMessage(session, source_identifier);
2025
 
 
2026
 
  if (not source_table_message)
2027
 
  {
2028
 
    my_error(ER_TABLE_UNKNOWN, source_identifier);
2029
 
    return false;
2030
 
  }
2031
 
 
2032
 
  new_table_message.CopyFrom(*source_table_message);
 
1978
  int protoerr= EEXIST;
 
1979
  message::Table new_proto;
 
1980
  message::table::shared_ptr src_proto;
 
1981
 
 
1982
  protoerr= plugin::StorageEngine::getTableDefinition(session,
 
1983
                                                      src_table,
 
1984
                                                      src_proto);
 
1985
  new_proto.CopyFrom(*src_proto);
2033
1986
 
2034
1987
  if (destination_identifier.isTmp())
2035
1988
  {
2036
 
    new_table_message.set_type(message::Table::TEMPORARY);
 
1989
    new_proto.set_type(message::Table::TEMPORARY);
2037
1990
  }
2038
1991
  else
2039
1992
  {
2040
 
    new_table_message.set_type(message::Table::STANDARD);
 
1993
    new_proto.set_type(message::Table::STANDARD);
2041
1994
  }
2042
1995
 
2043
1996
  if (is_engine_set)
2044
1997
  {
2045
 
    new_table_message.mutable_engine()->set_name(create_table_proto.engine().name());
 
1998
    new_proto.mutable_engine()->set_name(create_table_proto.engine().name());
2046
1999
  }
2047
2000
 
2048
2001
  { // We now do a selective copy of elements on to the new table.
2049
 
    new_table_message.set_name(create_table_proto.name());
2050
 
    new_table_message.set_schema(create_table_proto.schema());
2051
 
    new_table_message.set_catalog(create_table_proto.catalog());
 
2002
    new_proto.set_name(create_table_proto.name());
 
2003
    new_proto.set_schema(create_table_proto.schema());
 
2004
    new_proto.set_catalog(create_table_proto.catalog());
2052
2005
  }
2053
2006
 
2054
 
  /* Fix names of foreign keys being added */
2055
 
  for (int32_t j= 0; j < new_table_message.fk_constraint_size(); j++)
 
2007
  if (protoerr && protoerr != EEXIST)
2056
2008
  {
2057
 
    if (new_table_message.fk_constraint(j).has_name())
2058
 
    {
2059
 
      std::string name(new_table_message.name());
2060
 
      char number[20];
2061
 
 
2062
 
      name.append("_ibfk_");
2063
 
      snprintf(number, sizeof(number), "%d", j+1);
2064
 
      name.append(number);
2065
 
 
2066
 
      message::Table::ForeignKeyConstraint *pfkey= new_table_message.mutable_fk_constraint(j);
2067
 
      pfkey->set_name(name);
2068
 
    }
 
2009
    if (errno == ENOENT)
 
2010
      my_error(ER_BAD_DB_ERROR,MYF(0), destination_identifier.getSchemaName().c_str());
 
2011
    else
 
2012
      my_error(ER_CANT_CREATE_FILE, MYF(0), destination_identifier.getPath().c_str(), errno);
 
2013
 
 
2014
    return false;
2069
2015
  }
2070
2016
 
2071
2017
  /*
2072
2018
    As mysql_truncate don't work on a new table at this stage of
2073
 
    creation, instead create the table directly (for both normal and temporary tables).
 
2019
    creation, instead create the table directly (for both normal
 
2020
    and temporary tables).
2074
2021
  */
2075
 
  bool success= plugin::StorageEngine::createTable(session,
2076
 
                                                   destination_identifier,
2077
 
                                                   new_table_message);
 
2022
  int err= plugin::StorageEngine::createTable(session,
 
2023
                                              destination_identifier,
 
2024
                                              new_proto);
2078
2025
 
2079
 
  if (success && not destination_identifier.isTmp())
 
2026
  if (err == false && not destination_identifier.isTmp())
2080
2027
  {
2081
2028
    TransactionServices &transaction_services= TransactionServices::singleton();
2082
 
    transaction_services.createTable(session, new_table_message);
 
2029
    transaction_services.createTable(&session, new_proto);
2083
2030
  }
2084
2031
 
2085
 
  return success;
 
2032
  return err ? false : true;
2086
2033
}
2087
2034
 
2088
2035
/*
2101
2048
*/
2102
2049
 
2103
2050
bool create_like_table(Session* session,
2104
 
                       identifier::Table::const_reference destination_identifier,
2105
 
                       identifier::Table::const_reference source_identifier,
2106
 
                       message::Table &create_table_proto,
2107
 
                       bool is_if_not_exists,
2108
 
                       bool is_engine_set)
 
2051
                             const TableIdentifier &destination_identifier,
 
2052
                             TableList* table, TableList* src_table,
 
2053
                             message::Table &create_table_proto,
 
2054
                             bool is_if_not_exists,
 
2055
                             bool is_engine_set)
2109
2056
{
2110
2057
  bool res= true;
2111
 
  bool table_exists= false;
 
2058
  uint32_t not_used;
 
2059
 
 
2060
  /*
 
2061
    By opening source table we guarantee that it exists and no concurrent
 
2062
    DDL operation will mess with it. Later we also take an exclusive
 
2063
    name-lock on target table name, which makes copying of .frm cursor,
 
2064
    call to plugin::StorageEngine::createTable() and binlogging atomic
 
2065
    against concurrent DML and DDL operations on target table.
 
2066
    Thus by holding both these "locks" we ensure that our statement is
 
2067
    properly isolated from all concurrent operations which matter.
 
2068
  */
 
2069
  if (session->open_tables_from_list(&src_table, &not_used))
 
2070
    return true;
 
2071
 
 
2072
  TableIdentifier src_identifier(src_table->table->getShare()->getSchemaName(),
 
2073
                                 src_table->table->getShare()->getTableName(), src_table->table->getShare()->getType());
 
2074
 
 
2075
 
2112
2076
 
2113
2077
  /*
2114
2078
    Check that destination tables does not exist. Note that its name
2116
2080
 
2117
2081
    For temporary tables we don't aim to grab locks.
2118
2082
  */
 
2083
  bool table_exists= false;
2119
2084
  if (destination_identifier.isTmp())
2120
2085
  {
2121
2086
    if (session->find_temporary_table(destination_identifier))
2124
2089
    }
2125
2090
    else
2126
2091
    {
2127
 
      bool was_created= create_table_wrapper(*session,
2128
 
                                             create_table_proto,
2129
 
                                             destination_identifier,
2130
 
                                             source_identifier,
2131
 
                                             is_engine_set);
 
2092
      bool was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
 
2093
                                             src_identifier, is_engine_set);
2132
2094
      if (not was_created) // This is pretty paranoid, but we assume something might not clean up after itself
2133
2095
      {
2134
2096
        (void) session->rm_temporary_table(destination_identifier, true);
2173
2135
      {
2174
2136
        boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* We lock for CREATE TABLE LIKE to copy table definition */
2175
2137
        was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
2176
 
                                          source_identifier, is_engine_set);
 
2138
                                               src_identifier, is_engine_set);
2177
2139
      }
2178
2140
 
2179
2141
      // So we blew the creation of the table, and we scramble to clean up
2201
2163
    {
2202
2164
      char warn_buff[DRIZZLE_ERRMSG_SIZE];
2203
2165
      snprintf(warn_buff, sizeof(warn_buff),
2204
 
               ER(ER_TABLE_EXISTS_ERROR), destination_identifier.getTableName().c_str());
 
2166
               ER(ER_TABLE_EXISTS_ERROR), table->getTableName());
2205
2167
      push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
2206
 
                   ER_TABLE_EXISTS_ERROR, warn_buff);
2207
 
      return false;
2208
 
    }
2209
 
 
2210
 
    my_error(ER_TABLE_EXISTS_ERROR, destination_identifier);
2211
 
 
2212
 
    return true;
 
2168
                   ER_TABLE_EXISTS_ERROR,warn_buff);
 
2169
      res= false;
 
2170
    }
 
2171
    else
 
2172
    {
 
2173
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table->getTableName());
 
2174
    }
2213
2175
  }
2214
2176
 
2215
 
  return res;
 
2177
  return(res);
2216
2178
}
2217
2179
 
2218
2180