~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_table.cc

  • Committer: Monty Taylor
  • Date: 2011-03-08 23:35:47 UTC
  • mfrom: (2224.2.9 statement2)
  • mto: This revision was merged to the branch mainline in revision 2227.
  • Revision ID: mordred@inaugust.com-20110308233547-w2s3tm5svzv339dp
Merged Olaf - Statement refactor.

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
 
16
16
/* drop and alter of tables */
17
17
 
18
 
#include "config.h"
 
18
#include <config.h>
19
19
#include <plugin/myisam/myisam.h>
20
20
#include <drizzled/show.h>
21
21
#include <drizzled/error.h>
22
22
#include <drizzled/gettext.h>
23
23
#include <drizzled/data_home.h>
24
24
#include <drizzled/sql_parse.h>
25
 
#include <drizzled/my_hash.h>
26
25
#include <drizzled/sql_lex.h>
27
26
#include <drizzled/session.h>
28
27
#include <drizzled/sql_base.h>
29
 
#include "drizzled/strfunc.h"
30
 
#include <drizzled/db.h>
31
28
#include <drizzled/lock.h>
32
29
#include <drizzled/unireg.h>
33
30
#include <drizzled/item/int.h>
34
31
#include <drizzled/item/empty_string.h>
35
32
#include <drizzled/transaction_services.h>
36
 
#include "drizzled/transaction_services.h"
 
33
#include <drizzled/transaction_services.h>
37
34
#include <drizzled/table_proto.h>
38
35
#include <drizzled/plugin/client.h>
39
36
#include <drizzled/identifier.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"
 
37
#include <drizzled/internal/m_string.h>
 
38
#include <drizzled/global_charset_info.h>
 
39
#include <drizzled/charset.h>
 
40
 
 
41
#include <drizzled/definition/cache.h>
 
42
 
 
43
#include <drizzled/statement/alter_table.h>
 
44
#include <drizzled/sql_table.h>
 
45
#include <drizzled/pthread_globals.h>
 
46
#include <drizzled/typelib.h>
 
47
#include <drizzled/plugin/storage_engine.h>
50
48
 
51
49
#include <algorithm>
52
50
#include <sstream>
58
56
namespace drizzled
59
57
{
60
58
 
61
 
extern pid_t current_pid;
62
 
 
63
59
bool is_primary_key(KeyInfo *key_info)
64
60
{
65
61
  static const char * primary_key_name="PRIMARY";
87
83
    let's fetch the database default character set and
88
84
    apply it to the table.
89
85
  */
90
 
  SchemaIdentifier identifier(db);
 
86
  identifier::Schema identifier(db);
91
87
  if (create_info->default_table_charset == NULL)
92
88
    create_info->default_table_charset= plugin::StorageEngine::getSchemaCollation(identifier);
93
89
}
94
90
 
95
91
/*
96
 
  SYNOPSIS
97
 
    write_bin_log()
98
 
    session                           Thread object
99
 
    query                         Query to log
100
 
    query_length                  Length of query
101
 
 
102
 
  RETURN VALUES
103
 
    NONE
104
 
 
105
 
  DESCRIPTION
106
 
    Write the binlog if open, routine used in multiple places in this
107
 
    cursor
108
 
*/
109
 
 
110
 
void write_bin_log(Session *session, const std::string &query)
111
 
{
112
 
  TransactionServices &transaction_services= TransactionServices::singleton();
113
 
  transaction_services.rawStatement(session, query);
114
 
}
115
 
 
116
 
/*
117
92
  Execute the drop of a normal or temporary table
118
93
 
119
94
  SYNOPSIS
120
 
    mysql_rm_table_part2()
 
95
    rm_table_part2()
121
96
    session                     Thread Cursor
122
97
    tables              Tables to drop
123
98
    if_exists           If set, don't give an error if table doesn't exists.
140
115
   -1   Thread was killed
141
116
*/
142
117
 
143
 
int mysql_rm_table_part2(Session *session, TableList *tables, bool if_exists,
144
 
                         bool drop_temporary)
 
118
int rm_table_part2(Session *session, TableList *tables, bool if_exists,
 
119
                   bool drop_temporary)
145
120
{
146
121
  TableList *table;
147
 
  String wrong_tables;
 
122
  util::string::vector wrong_tables;
148
123
  int error= 0;
149
124
  bool foreign_key_error= false;
150
125
 
 
126
  do
151
127
  {
152
 
    table::Cache::singleton().mutex().lock(); /* Part 2 of rm a table */
 
128
    boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex());
153
129
 
154
130
    if (not drop_temporary && session->lock_table_names_exclusively(tables))
155
131
    {
156
 
      table::Cache::singleton().mutex().unlock();
157
132
      return 1;
158
133
    }
159
134
 
162
137
 
163
138
    for (table= tables; table; table= table->next_local)
164
139
    {
165
 
      TableIdentifier tmp_identifier(table->getSchemaName(), table->getTableName());
 
140
      identifier::Table tmp_identifier(table->getSchemaName(), table->getTableName());
166
141
 
167
142
      error= session->drop_temporary_table(tmp_identifier);
168
143
 
172
147
        continue;
173
148
      case -1:
174
149
        error= 1;
175
 
        goto err_with_placeholders;
 
150
        break;
176
151
      default:
177
152
        // temporary table not found
178
153
        error= 0;
195
170
        if (session->getKilled())
196
171
        {
197
172
          error= -1;
198
 
          goto err_with_placeholders;
 
173
          break;
199
174
        }
200
175
      }
201
 
      TableIdentifier identifier(table->getSchemaName(), table->getTableName(), table->getInternalTmpTable() ? message::Table::INTERNAL : message::Table::STANDARD);
 
176
      identifier::Table identifier(table->getSchemaName(), table->getTableName(), table->getInternalTmpTable() ? message::Table::INTERNAL : message::Table::STANDARD);
 
177
 
 
178
      message::table::shared_ptr message= plugin::StorageEngine::getTableMessage(*session, identifier, true);
202
179
 
203
180
      if (drop_temporary || not plugin::StorageEngine::doesTableExist(*session, identifier))
204
181
      {
205
182
        // Table was not found on disk and table can't be created from engine
206
183
        if (if_exists)
 
184
        {
207
185
          push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
208
186
                              ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
209
187
                              table->getTableName());
 
188
        }
210
189
        else
 
190
        {
211
191
          error= 1;
 
192
        }
212
193
      }
213
194
      else
214
195
      {
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);
 
196
        drizzled::error_t local_error;
 
197
 
 
198
        /* Generate transaction event ONLY when we successfully drop */ 
 
199
        if (plugin::StorageEngine::dropTable(*session, identifier, local_error))
 
200
        {
 
201
          if (message) // If we have no definition, we don't know if the table should have been replicated
 
202
          {
 
203
            TransactionServices &transaction_services= TransactionServices::singleton();
 
204
            transaction_services.dropTable(*session, identifier, *message, if_exists);
 
205
          }
 
206
        }
 
207
        else
 
208
        {
 
209
          if (local_error == HA_ERR_NO_SUCH_TABLE and if_exists)
 
210
          {
 
211
            error= 0;
 
212
            session->clear_error();
 
213
          }
 
214
 
 
215
          if (local_error == HA_ERR_ROW_IS_REFERENCED)
 
216
          {
 
217
            /* the table is referenced by a foreign key constraint */
 
218
            foreign_key_error= true;
 
219
          }
 
220
          error= local_error;
 
221
        }
234
222
      }
235
223
 
236
224
      if (error)
237
225
      {
238
 
        if (wrong_tables.length())
239
 
          wrong_tables.append(',');
240
 
        wrong_tables.append(String(table->getTableName(), system_charset_info));
 
226
        wrong_tables.push_back(table->getTableName());
241
227
      }
242
228
    }
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;
250
 
 
251
 
  if (wrong_tables.length())
 
229
 
 
230
    tables->unlock_table_names();
 
231
 
 
232
  } while (0);
 
233
 
 
234
  if (wrong_tables.size())
252
235
  {
253
236
    if (not foreign_key_error)
254
237
    {
 
238
      std::string table_error;
 
239
 
 
240
      for (util::string::vector::iterator iter= wrong_tables.begin();
 
241
           iter != wrong_tables.end();
 
242
           iter++)
 
243
      {
 
244
        table_error+= *iter;
 
245
        table_error+= ',';
 
246
      }
 
247
      table_error.resize(table_error.size() -1);
 
248
 
255
249
      my_printf_error(ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), MYF(0),
256
 
                      wrong_tables.c_ptr());
 
250
                      table_error.c_str());
257
251
    }
258
252
    else
259
253
    {
262
256
    error= 1;
263
257
  }
264
258
 
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();
270
259
  session->no_warnings_for_error= 0;
271
260
 
272
261
  return error;
388
377
    tmp.type_names++;
389
378
    tmp.type_lengths++;
390
379
    tmp.count--;
391
 
    if (interval_set.find(typelib_set_member(*cur_value, *cur_length, cs)) != interval_set.end())
 
380
    if (interval_set.count(typelib_set_member(*cur_value, *cur_length, cs)))
392
381
    {
393
382
      my_error(ER_DUPLICATED_VALUE_IN_TYPE, MYF(0),
394
383
               name,*cur_value,set_or_name);
471
460
    sql_field->length= 8; // Unireg field length
472
461
    (*blob_columns)++;
473
462
    break;
474
 
  case DRIZZLE_TYPE_VARCHAR:
475
 
    break;
 
463
 
476
464
  case DRIZZLE_TYPE_ENUM:
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;
 
465
    {
 
466
      if (check_duplicates_in_interval("ENUM",
 
467
                                       sql_field->field_name,
 
468
                                       sql_field->interval,
 
469
                                       sql_field->charset,
 
470
                                       &dup_val_count))
 
471
      {
 
472
        return 1;
 
473
      }
 
474
    }
 
475
    break;
 
476
 
 
477
  case DRIZZLE_TYPE_MICROTIME:
490
478
  case DRIZZLE_TYPE_TIMESTAMP:
491
479
    /* We should replace old TIMESTAMP fields with their newer analogs */
492
480
    if (sql_field->unireg_check == Field::TIMESTAMP_OLD_FIELD)
502
490
      }
503
491
    }
504
492
    else if (sql_field->unireg_check != Field::NONE)
 
493
    {
505
494
      (*timestamps_with_niladic)++;
 
495
    }
506
496
 
507
497
    (*timestamps)++;
508
 
    /* fall-through */
509
 
  default:
 
498
 
 
499
    break;
 
500
 
 
501
  case DRIZZLE_TYPE_BOOLEAN:
 
502
  case DRIZZLE_TYPE_DATE:  // Rest of string types
 
503
  case DRIZZLE_TYPE_DATETIME:
 
504
  case DRIZZLE_TYPE_DECIMAL:
 
505
  case DRIZZLE_TYPE_DOUBLE:
 
506
  case DRIZZLE_TYPE_LONG:
 
507
  case DRIZZLE_TYPE_LONGLONG:
 
508
  case DRIZZLE_TYPE_NULL:
 
509
  case DRIZZLE_TYPE_TIME:
 
510
  case DRIZZLE_TYPE_UUID:
 
511
  case DRIZZLE_TYPE_VARCHAR:
510
512
    break;
511
513
  }
512
514
 
513
515
  return 0;
514
516
}
515
517
 
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)
 
518
static int prepare_create_table(Session *session,
 
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)
525
527
{
526
528
  const char    *key_name;
527
529
  CreateField   *sql_field,*dup_field;
530
532
  KeyInfo               *key_info;
531
533
  KeyPartInfo *key_part_info;
532
534
  int           timestamps= 0, timestamps_with_niladic= 0;
533
 
  int           field_no,dup_no;
 
535
  int           dup_no;
534
536
  int           select_field_pos,auto_increment=0;
535
 
  List_iterator<CreateField> it(alter_info->create_list);
536
 
  List_iterator<CreateField> it2(alter_info->create_list);
 
537
  List<CreateField>::iterator it(alter_info->create_list.begin());
 
538
  List<CreateField>::iterator it2(alter_info->create_list.begin());
537
539
  uint32_t total_uneven_bit_length= 0;
538
540
 
539
541
  plugin::StorageEngine *engine= plugin::StorageEngine::findByName(create_proto.engine().name());
540
542
 
541
 
  select_field_pos= alter_info->create_list.elements - select_field_count;
 
543
  select_field_pos= alter_info->create_list.size() - select_field_count;
542
544
  null_fields=blob_columns=0;
543
545
  max_key_length= engine->max_key_length();
544
546
 
545
 
  for (field_no=0; (sql_field=it++) ; field_no++)
 
547
  for (int32_t field_no=0; (sql_field=it++) ; field_no++)
546
548
  {
547
549
    const CHARSET_INFO *save_cs;
548
550
 
552
554
      executing a prepared statement for the second time.
553
555
    */
554
556
    sql_field->length= sql_field->char_length;
 
557
 
555
558
    if (!sql_field->charset)
556
559
      sql_field->charset= create_info->default_table_charset;
 
560
 
557
561
    /*
558
562
      table_charset is set in ALTER Table if we want change character set
559
563
      for all varchar/char columns.
625
629
        interval= sql_field->interval= typelib(session->mem_root,
626
630
                                               sql_field->interval_list);
627
631
 
628
 
        List_iterator<String> int_it(sql_field->interval_list);
 
632
        List<String>::iterator int_it(sql_field->interval_list.begin());
629
633
        String conv, *tmp;
630
634
        char comma_buf[4];
631
635
        int comma_length= cs->cset->wc_mb(cs, ',', (unsigned char*) comma_buf,
651
655
          interval->type_lengths[i]= lengthsp;
652
656
          ((unsigned char *)interval->type_names[i])[lengthsp]= '\0';
653
657
        }
654
 
        sql_field->interval_list.empty(); // Don't need interval_list anymore
 
658
        sql_field->interval_list.clear(); // Don't need interval_list anymore
655
659
      }
656
660
 
657
661
      /* DRIZZLE_TYPE_ENUM */
674
678
          else /* not NULL */
675
679
          {
676
680
            def->length(cs->cset->lengthsp(cs, def->ptr(), def->length()));
677
 
            if (find_type2(interval, def->ptr(), def->length(), cs) == 0) /* not found */
 
681
            if (interval->find_type2(def->ptr(), def->length(), cs) == 0) /* not found */
678
682
            {
679
683
              my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
680
684
              return(true);
751
755
    if (not create_proto.engine().name().compare("MyISAM") &&
752
756
        ((sql_field->flags & BLOB_FLAG) ||
753
757
         (sql_field->sql_type == DRIZZLE_TYPE_VARCHAR)))
 
758
    {
754
759
      (*db_options)|= HA_OPTION_PACK_RECORD;
755
 
    it2.rewind();
 
760
    }
 
761
 
 
762
    it2= alter_info->create_list.begin();
756
763
  }
757
764
 
758
765
  /* record_offset will be increased with 'length-of-null-bits' later */
759
766
  record_offset= 0;
760
767
  null_fields+= total_uneven_bit_length;
761
768
 
762
 
  it.rewind();
 
769
  it= alter_info->create_list.begin();
763
770
  while ((sql_field=it++))
764
771
  {
765
772
    assert(sql_field->charset != 0);
799
806
 
800
807
  /* Create keys */
801
808
 
802
 
  List_iterator<Key> key_iterator(alter_info->key_list);
803
 
  List_iterator<Key> key_iterator2(alter_info->key_list);
 
809
  List<Key>::iterator key_iterator(alter_info->key_list.begin());
 
810
  List<Key>::iterator key_iterator2(alter_info->key_list.begin());
804
811
  uint32_t key_parts=0, fk_key_count=0;
805
812
  bool primary_key=0,unique_key=0;
806
813
  Key *key, *key2;
830
837
                                       fk_key->update_opt,
831
838
                                       fk_key->match_opt);
832
839
 
833
 
      if (fk_key->ref_columns.elements &&
834
 
          fk_key->ref_columns.elements != fk_key->columns.elements)
 
840
      if (fk_key->ref_columns.size() &&
 
841
          fk_key->ref_columns.size() != fk_key->columns.size())
835
842
      {
836
843
        my_error(ER_WRONG_FK_DEF, MYF(0),
837
844
                 (fk_key->name.str ? fk_key->name.str :
843
850
    }
844
851
    (*key_count)++;
845
852
    tmp= engine->max_key_parts();
846
 
    if (key->columns.elements > tmp)
 
853
    if (key->columns.size() > tmp)
847
854
    {
848
855
      my_error(ER_TOO_MANY_KEY_PARTS,MYF(0),tmp);
849
856
      return(true);
850
857
    }
851
858
    if (check_identifier_name(&key->name, ER_TOO_LONG_IDENT))
852
859
      return(true);
853
 
    key_iterator2.rewind ();
 
860
    key_iterator2= alter_info->key_list.begin();
854
861
    if (key->type != Key::FOREIGN_KEY)
855
862
    {
856
863
      while ((key2 = key_iterator2++) != key)
867
874
          /* @todo issue warning message */
868
875
          /* mark that the generated key should be ignored */
869
876
          if (!key2->generated ||
870
 
              (key->generated && key->columns.elements <
871
 
               key2->columns.elements))
 
877
              (key->generated && key->columns.size() <
 
878
               key2->columns.size()))
872
879
            key->name.str= ignore_key;
873
880
          else
874
881
          {
875
882
            key2->name.str= ignore_key;
876
 
            key_parts-= key2->columns.elements;
 
883
            key_parts-= key2->columns.size();
877
884
            (*key_count)--;
878
885
          }
879
886
          break;
881
888
      }
882
889
    }
883
890
    if (key->name.str != ignore_key)
884
 
      key_parts+=key->columns.elements;
 
891
      key_parts+=key->columns.size();
885
892
    else
886
893
      (*key_count)--;
887
894
    if (key->name.str && !tmp_table && (key->type != Key::PRIMARY) &&
903
910
  if (!*key_info_buffer || ! key_part_info)
904
911
    return(true);                               // Out of memory
905
912
 
906
 
  key_iterator.rewind();
 
913
  key_iterator= alter_info->key_list.begin();
907
914
  key_number=0;
908
915
  for (; (key=key_iterator++) ; key_number++)
909
916
  {
934
941
    if (key->generated)
935
942
      key_info->flags|= HA_GENERATED_KEY;
936
943
 
937
 
    key_info->key_parts=(uint8_t) key->columns.elements;
 
944
    key_info->key_parts=(uint8_t) key->columns.size();
938
945
    key_info->key_part=key_part_info;
939
946
    key_info->usable_key_parts= key_number;
940
947
    key_info->algorithm= key->key_create_info.algorithm;
962
969
 
963
970
    message::Table::Field *protofield= NULL;
964
971
 
965
 
    List_iterator<Key_part_spec> cols(key->columns), cols2(key->columns);
 
972
    List<Key_part_spec>::iterator cols(key->columns.begin());
 
973
    List<Key_part_spec>::iterator cols2(key->columns.begin());
966
974
    for (uint32_t column_nr=0 ; (column=cols++) ; column_nr++)
967
975
    {
968
976
      uint32_t length;
969
977
      Key_part_spec *dup_column;
970
978
      int proto_field_nr= 0;
971
979
 
972
 
      it.rewind();
 
980
      it= alter_info->create_list.begin();
973
981
      field=0;
974
982
      while ((sql_field=it++) && ++proto_field_nr &&
975
983
             my_strcasecmp(system_charset_info,
976
984
                           column->field_name.str,
977
985
                           sql_field->field_name))
 
986
      {
978
987
        field++;
 
988
      }
 
989
 
979
990
      if (!sql_field)
980
991
      {
981
992
        my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name.str);
982
993
        return(true);
983
994
      }
 
995
 
984
996
      while ((dup_column= cols2++) != column)
985
997
      {
986
998
        if (!my_strcasecmp(system_charset_info,
992
1004
          return(true);
993
1005
        }
994
1006
      }
995
 
      cols2.rewind();
 
1007
      cols2= key->columns.begin();
996
1008
 
997
1009
      if (create_proto.field_size() > 0)
998
1010
        protofield= create_proto.mutable_field(proto_field_nr - 1);
1013
1025
            return true;
1014
1026
          }
1015
1027
        }
 
1028
 
1016
1029
        if (! (sql_field->flags & NOT_NULL_FLAG))
1017
1030
        {
1018
1031
          if (key->type == Key::PRIMARY)
1025
1038
            {
1026
1039
              message::Table::Field::FieldConstraints *constraints;
1027
1040
              constraints= protofield->mutable_constraints();
1028
 
              constraints->set_is_nullable(false);
 
1041
              constraints->set_is_notnull(true);
1029
1042
            }
1030
1043
 
1031
1044
          }
1039
1052
            }
1040
1053
          }
1041
1054
        }
 
1055
 
1042
1056
        if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
1043
1057
        {
1044
1058
          if (column_nr == 0 || (engine->check_flag(HTON_BIT_AUTO_PART_KEY)))
1163
1177
        key_info->name=(char*) key_name;
1164
1178
      }
1165
1179
    }
 
1180
 
1166
1181
    if (!key_info->name || check_column_name(key_info->name))
1167
1182
    {
1168
1183
      my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key_info->name);
1169
1184
      return(true);
1170
1185
    }
 
1186
 
1171
1187
    if (!(key_info->flags & HA_NULL_PART_KEY))
 
1188
    {
1172
1189
      unique_key=1;
 
1190
    }
 
1191
 
1173
1192
    key_info->key_length=(uint16_t) key_length;
 
1193
 
1174
1194
    if (key_length > max_key_length)
1175
1195
    {
1176
1196
      my_error(ER_TOO_LONG_KEY,MYF(0),max_key_length);
1177
1197
      return(true);
1178
1198
    }
 
1199
 
1179
1200
    key_info++;
1180
1201
  }
 
1202
 
1181
1203
  if (!unique_key && !primary_key &&
1182
1204
      (engine->check_flag(HTON_BIT_REQUIRE_PRIMARY_KEY)))
1183
1205
  {
1184
1206
    my_message(ER_REQUIRES_PRIMARY_KEY, ER(ER_REQUIRES_PRIMARY_KEY), MYF(0));
1185
1207
    return(true);
1186
1208
  }
 
1209
 
1187
1210
  if (auto_increment > 0)
1188
1211
  {
1189
1212
    my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
1194
1217
                     (qsort_cmp) sort_keys);
1195
1218
 
1196
1219
  /* Check fields. */
1197
 
  it.rewind();
 
1220
  it= alter_info->create_list.begin();
1198
1221
  while ((sql_field=it++))
1199
1222
  {
1200
1223
    Field::utype type= (Field::utype) MTYP_TYPENR(sql_field->unireg_check);
1201
1224
 
1202
1225
    if (session->variables.sql_mode & MODE_NO_ZERO_DATE &&
1203
1226
        !sql_field->def &&
1204
 
        sql_field->sql_type == DRIZZLE_TYPE_TIMESTAMP &&
 
1227
        (sql_field->sql_type == DRIZZLE_TYPE_TIMESTAMP  or sql_field->sql_type == DRIZZLE_TYPE_MICROTIME) &&
1205
1228
        (sql_field->flags & NOT_NULL_FLAG) &&
1206
1229
        (type == Field::NONE || type == Field::TIMESTAMP_UN_FIELD))
1207
1230
    {
1265
1288
}
1266
1289
 
1267
1290
static bool locked_create_event(Session *session,
1268
 
                                const TableIdentifier &identifier,
 
1291
                                const identifier::Table &identifier,
1269
1292
                                HA_CREATE_INFO *create_info,
1270
1293
                                message::Table &table_proto,
1271
1294
                                AlterInfo *alter_info,
1300
1323
        return error;
1301
1324
      }
1302
1325
 
1303
 
      std::string path;
1304
 
      identifier.getSQLPath(path);
1305
 
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
 
1326
      my_error(ER_TABLE_EXISTS_ERROR, identifier);
1306
1327
 
1307
1328
      return error;
1308
1329
    }
1322
1343
      */
1323
1344
      if (definition::Cache::singleton().find(identifier.getKey()))
1324
1345
      {
1325
 
        std::string path;
1326
 
        identifier.getSQLPath(path);
1327
 
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
 
1346
        my_error(ER_TABLE_EXISTS_ERROR, identifier);
1328
1347
 
1329
1348
        return error;
1330
1349
      }
1363
1382
  if (table_proto.type() == message::Table::STANDARD && not internal_tmp_table)
1364
1383
  {
1365
1384
    TransactionServices &transaction_services= TransactionServices::singleton();
1366
 
    transaction_services.createTable(session, table_proto);
 
1385
    transaction_services.createTable(*session, table_proto);
1367
1386
  }
1368
1387
 
1369
1388
  return false;
1376
1395
  Create a table
1377
1396
 
1378
1397
  SYNOPSIS
1379
 
    mysql_create_table_no_lock()
 
1398
    create_table_no_lock()
1380
1399
    session                     Thread object
1381
1400
    db                  Database
1382
1401
    table_name          Table name
1392
1411
 
1393
1412
    Note that this function assumes that caller already have taken
1394
1413
    name-lock on table being created or used some other way to ensure
1395
 
    that concurrent operations won't intervene. mysql_create_table()
 
1414
    that concurrent operations won't intervene. create_table()
1396
1415
    is a wrapper that can be used for this.
1397
1416
 
1398
1417
  RETURN VALUES
1400
1419
    true  error
1401
1420
*/
1402
1421
 
1403
 
bool mysql_create_table_no_lock(Session *session,
1404
 
                                const TableIdentifier &identifier,
 
1422
bool create_table_no_lock(Session *session,
 
1423
                                const identifier::Table &identifier,
1405
1424
                                HA_CREATE_INFO *create_info,
1406
1425
                                message::Table &table_proto,
1407
1426
                                AlterInfo *alter_info,
1414
1433
  bool          error= true;
1415
1434
 
1416
1435
  /* Check for duplicate fields and check type of table to create */
1417
 
  if (not alter_info->create_list.elements)
 
1436
  if (not alter_info->create_list.size())
1418
1437
  {
1419
1438
    my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
1420
1439
               MYF(0));
1426
1445
  set_table_default_charset(create_info, identifier.getSchemaName().c_str());
1427
1446
 
1428
1447
  /* Build a Table object to pass down to the engine, and the do the actual create. */
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))
 
1448
  if (not prepare_create_table(session, create_info, table_proto, alter_info,
 
1449
                               internal_tmp_table,
 
1450
                               &db_options,
 
1451
                               &key_info_buffer, &key_count,
 
1452
                               select_field_count))
1434
1453
  {
1435
1454
    boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* CREATE TABLE (some confussion on naming, double check) */
1436
1455
    error= locked_create_event(session,
1453
1472
  @note the following two methods implement create [temporary] table.
1454
1473
*/
1455
1474
static bool drizzle_create_table(Session *session,
1456
 
                                 const TableIdentifier &identifier,
 
1475
                                 const identifier::Table &identifier,
1457
1476
                                 HA_CREATE_INFO *create_info,
1458
1477
                                 message::Table &table_proto,
1459
1478
                                 AlterInfo *alter_info,
1480
1499
    }
1481
1500
    else
1482
1501
    {
1483
 
      std::string path;
1484
 
      identifier.getSQLPath(path);
1485
 
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
 
1502
      my_error(ER_TABLE_EXISTS_ERROR, identifier);
1486
1503
      result= true;
1487
1504
    }
1488
1505
  }
1489
1506
  else
1490
1507
  {
1491
 
    result= mysql_create_table_no_lock(session,
 
1508
    result= create_table_no_lock(session,
1492
1509
                                       identifier,
1493
1510
                                       create_info,
1494
1511
                                       table_proto,
1509
1526
 
1510
1527
 
1511
1528
/*
1512
 
  Database locking aware wrapper for mysql_create_table_no_lock(),
 
1529
  Database locking aware wrapper for create_table_no_lock(),
1513
1530
*/
1514
 
bool mysql_create_table(Session *session,
1515
 
                        const TableIdentifier &identifier,
 
1531
bool create_table(Session *session,
 
1532
                        const identifier::Table &identifier,
1516
1533
                        HA_CREATE_INFO *create_info,
1517
1534
                        message::Table &table_proto,
1518
1535
                        AlterInfo *alter_info,
1522
1539
{
1523
1540
  if (identifier.isTmp())
1524
1541
  {
1525
 
    return mysql_create_table_no_lock(session,
 
1542
    return create_table_no_lock(session,
1526
1543
                                      identifier,
1527
1544
                                      create_info,
1528
1545
                                      table_proto,
1592
1609
  Rename a table.
1593
1610
 
1594
1611
  SYNOPSIS
1595
 
    mysql_rename_table()
 
1612
    rename_table()
1596
1613
      session
1597
1614
      base                      The plugin::StorageEngine handle.
1598
1615
      old_db                    The old database name.
1606
1623
*/
1607
1624
 
1608
1625
bool
1609
 
mysql_rename_table(Session &session,
 
1626
rename_table(Session &session,
1610
1627
                   plugin::StorageEngine *base,
1611
 
                   const TableIdentifier &from,
1612
 
                   const TableIdentifier &to)
 
1628
                   const identifier::Table &from,
 
1629
                   const identifier::Table &to)
1613
1630
{
1614
1631
  int error= 0;
1615
1632
 
1675
1692
  session->abortLock(table);    /* end threads waiting on lock */
1676
1693
 
1677
1694
  /* Wait until all there are no other threads that has this table open */
1678
 
  TableIdentifier identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName());
 
1695
  identifier::Table identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName());
1679
1696
  table::Cache::singleton().removeTable(session, identifier, RTFC_WAIT_OTHER_THREAD_FLAG);
1680
1697
}
1681
1698
 
1719
1736
    true  Message should be sent by caller
1720
1737
          (admin operation or network communication failed)
1721
1738
*/
1722
 
static bool mysql_admin_table(Session* session, TableList* tables,
 
1739
static bool admin_table(Session* session, TableList* tables,
1723
1740
                              HA_CHECK_OPT* check_opt,
1724
1741
                              const char *operator_name,
1725
1742
                              thr_lock_type lock_type,
1728
1745
                                                            HA_CHECK_OPT *))
1729
1746
{
1730
1747
  TableList *table;
1731
 
  Select_Lex *select= &session->lex->select_lex;
 
1748
  Select_Lex *select= &session->getLex()->select_lex;
1732
1749
  List<Item> field_list;
1733
1750
  Item *item;
1734
 
  LEX *lex= session->lex;
1735
1751
  int result_code= 0;
1736
1752
  TransactionServices &transaction_services= TransactionServices::singleton();
1737
1753
  const CHARSET_INFO * const cs= system_charset_info;
1738
1754
 
1739
1755
  if (! session->endActiveTransaction())
1740
1756
    return 1;
 
1757
 
1741
1758
  field_list.push_back(item = new Item_empty_string("Table",
1742
1759
                                                    NAME_CHAR_LEN * 2,
1743
1760
                                                    cs));
1748
1765
  item->maybe_null = 1;
1749
1766
  field_list.push_back(item = new Item_empty_string("Msg_text", 255, cs));
1750
1767
  item->maybe_null = 1;
1751
 
  if (session->client->sendFields(&field_list))
 
1768
  if (session->getClient()->sendFields(&field_list))
1752
1769
    return true;
1753
1770
 
1754
1771
  for (table= tables; table; table= table->next_local)
1755
1772
  {
1756
 
    char table_name[NAME_LEN*2+2];
 
1773
    identifier::Table table_identifier(table->getSchemaName(), table->getTableName());
 
1774
    std::string table_name;
1757
1775
    bool fatal_error=0;
1758
1776
 
1759
 
    snprintf(table_name, sizeof(table_name), "%s.%s", table->getSchemaName(), table->getTableName());
 
1777
    table_identifier.getSQLPath(table_name);
 
1778
 
1760
1779
    table->lock_type= lock_type;
1761
1780
    /* open only one table from local list of command */
1762
1781
    {
1771
1790
        so it have to be prepared.
1772
1791
        @todo Investigate if we can put extra tables into argument instead of using lex->query_tables
1773
1792
      */
1774
 
      lex->query_tables= table;
1775
 
      lex->query_tables_last= &table->next_global;
1776
 
      lex->query_tables_own_last= 0;
 
1793
      session->getLex()->query_tables= table;
 
1794
      session->getLex()->query_tables_last= &table->next_global;
 
1795
      session->getLex()->query_tables_own_last= 0;
1777
1796
      session->no_warnings_for_error= 0;
1778
1797
 
1779
1798
      session->openTablesLock(table);
1792
1811
    */
1793
1812
    if (!table->table)
1794
1813
    {
1795
 
      if (!session->warn_list.elements)
 
1814
      if (!session->warn_list.size())
1796
1815
        push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1797
1816
                     ER_CHECK_NO_SUCH_TABLE, ER(ER_CHECK_NO_SUCH_TABLE));
1798
1817
      result_code= HA_ADMIN_CORRUPT;
1803
1822
    {
1804
1823
      char buff[FN_REFLEN + DRIZZLE_ERRMSG_SIZE];
1805
1824
      uint32_t length;
1806
 
      session->client->store(table_name);
1807
 
      session->client->store(operator_name);
1808
 
      session->client->store(STRING_WITH_LEN("error"));
 
1825
      session->getClient()->store(table_name.c_str());
 
1826
      session->getClient()->store(operator_name);
 
1827
      session->getClient()->store(STRING_WITH_LEN("error"));
1809
1828
      length= snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY),
1810
 
                       table_name);
1811
 
      session->client->store(buff, length);
1812
 
      transaction_services.autocommitOrRollback(session, false);
 
1829
                       table_name.c_str());
 
1830
      session->getClient()->store(buff, length);
 
1831
      transaction_services.autocommitOrRollback(*session, false);
1813
1832
      session->endTransaction(COMMIT);
1814
1833
      session->close_thread_tables();
1815
 
      lex->reset_query_tables_list(false);
 
1834
      session->getLex()->reset_query_tables_list(false);
1816
1835
      table->table=0;                           // For query cache
1817
 
      if (session->client->flush())
 
1836
      if (session->getClient()->flush())
1818
1837
        goto err;
1819
1838
      continue;
1820
1839
    }
1826
1845
      const char *old_message=session->enter_cond(COND_refresh, table::Cache::singleton().mutex(),
1827
1846
                                                  "Waiting to get writelock");
1828
1847
      session->abortLock(table->table);
1829
 
      TableIdentifier identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
 
1848
      identifier::Table identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
1830
1849
      table::Cache::singleton().removeTable(session, identifier, RTFC_WAIT_OTHER_THREAD_FLAG | RTFC_CHECK_KILLED_FLAG);
1831
1850
      session->exit_cond(old_message);
1832
1851
      if (session->getKilled())
1838
1857
 
1839
1858
send_result:
1840
1859
 
1841
 
    lex->cleanup_after_one_table_open();
 
1860
    session->getLex()->cleanup_after_one_table_open();
1842
1861
    session->clear_error();  // these errors shouldn't get client
1843
1862
    {
1844
 
      List_iterator_fast<DRIZZLE_ERROR> it(session->warn_list);
 
1863
      List<DRIZZLE_ERROR>::iterator it(session->warn_list.begin());
1845
1864
      DRIZZLE_ERROR *err;
1846
1865
      while ((err= it++))
1847
1866
      {
1848
 
        session->client->store(table_name);
1849
 
        session->client->store(operator_name);
1850
 
        session->client->store(warning_level_names[err->level].str,
 
1867
        session->getClient()->store(table_name.c_str());
 
1868
        session->getClient()->store(operator_name);
 
1869
        session->getClient()->store(warning_level_names[err->level].str,
1851
1870
                               warning_level_names[err->level].length);
1852
 
        session->client->store(err->msg);
1853
 
        if (session->client->flush())
 
1871
        session->getClient()->store(err->msg);
 
1872
        if (session->getClient()->flush())
1854
1873
          goto err;
1855
1874
      }
1856
1875
      drizzle_reset_errors(session, true);
1857
1876
    }
1858
 
    session->client->store(table_name);
1859
 
    session->client->store(operator_name);
 
1877
    session->getClient()->store(table_name.c_str());
 
1878
    session->getClient()->store(operator_name);
1860
1879
 
1861
1880
    switch (result_code) {
1862
1881
    case HA_ADMIN_NOT_IMPLEMENTED:
1864
1883
        char buf[ERRMSGSIZE+20];
1865
1884
        uint32_t length=snprintf(buf, ERRMSGSIZE,
1866
1885
                             ER(ER_CHECK_NOT_IMPLEMENTED), operator_name);
1867
 
        session->client->store(STRING_WITH_LEN("note"));
1868
 
        session->client->store(buf, length);
 
1886
        session->getClient()->store(STRING_WITH_LEN("note"));
 
1887
        session->getClient()->store(buf, length);
1869
1888
      }
1870
1889
      break;
1871
1890
 
1872
1891
    case HA_ADMIN_OK:
1873
 
      session->client->store(STRING_WITH_LEN("status"));
1874
 
      session->client->store(STRING_WITH_LEN("OK"));
 
1892
      session->getClient()->store(STRING_WITH_LEN("status"));
 
1893
      session->getClient()->store(STRING_WITH_LEN("OK"));
1875
1894
      break;
1876
1895
 
1877
1896
    case HA_ADMIN_FAILED:
1878
 
      session->client->store(STRING_WITH_LEN("status"));
1879
 
      session->client->store(STRING_WITH_LEN("Operation failed"));
 
1897
      session->getClient()->store(STRING_WITH_LEN("status"));
 
1898
      session->getClient()->store(STRING_WITH_LEN("Operation failed"));
1880
1899
      break;
1881
1900
 
1882
1901
    case HA_ADMIN_REJECT:
1883
 
      session->client->store(STRING_WITH_LEN("status"));
1884
 
      session->client->store(STRING_WITH_LEN("Operation need committed state"));
 
1902
      session->getClient()->store(STRING_WITH_LEN("status"));
 
1903
      session->getClient()->store(STRING_WITH_LEN("Operation need committed state"));
1885
1904
      open_for_modify= false;
1886
1905
      break;
1887
1906
 
1888
1907
    case HA_ADMIN_ALREADY_DONE:
1889
 
      session->client->store(STRING_WITH_LEN("status"));
1890
 
      session->client->store(STRING_WITH_LEN("Table is already up to date"));
 
1908
      session->getClient()->store(STRING_WITH_LEN("status"));
 
1909
      session->getClient()->store(STRING_WITH_LEN("Table is already up to date"));
1891
1910
      break;
1892
1911
 
1893
1912
    case HA_ADMIN_CORRUPT:
1894
 
      session->client->store(STRING_WITH_LEN("error"));
1895
 
      session->client->store(STRING_WITH_LEN("Corrupt"));
 
1913
      session->getClient()->store(STRING_WITH_LEN("error"));
 
1914
      session->getClient()->store(STRING_WITH_LEN("Corrupt"));
1896
1915
      fatal_error=1;
1897
1916
      break;
1898
1917
 
1899
1918
    case HA_ADMIN_INVALID:
1900
 
      session->client->store(STRING_WITH_LEN("error"));
1901
 
      session->client->store(STRING_WITH_LEN("Invalid argument"));
 
1919
      session->getClient()->store(STRING_WITH_LEN("error"));
 
1920
      session->getClient()->store(STRING_WITH_LEN("Invalid argument"));
1902
1921
      break;
1903
1922
 
1904
1923
    default:                            // Probably HA_ADMIN_INTERNAL_ERROR
1907
1926
        uint32_t length=snprintf(buf, ERRMSGSIZE,
1908
1927
                             _("Unknown - internal error %d during operation"),
1909
1928
                             result_code);
1910
 
        session->client->store(STRING_WITH_LEN("error"));
1911
 
        session->client->store(buf, length);
 
1929
        session->getClient()->store(STRING_WITH_LEN("error"));
 
1930
        session->getClient()->store(buf, length);
1912
1931
        fatal_error=1;
1913
1932
        break;
1914
1933
      }
1928
1947
        else
1929
1948
        {
1930
1949
          boost::unique_lock<boost::mutex> lock(table::Cache::singleton().mutex());
1931
 
          TableIdentifier identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
 
1950
          identifier::Table identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
1932
1951
          table::Cache::singleton().removeTable(session, identifier, RTFC_NO_FLAG);
1933
1952
        }
1934
1953
      }
1935
1954
    }
1936
 
    transaction_services.autocommitOrRollback(session, false);
 
1955
    transaction_services.autocommitOrRollback(*session, false);
1937
1956
    session->endTransaction(COMMIT);
1938
1957
    session->close_thread_tables();
1939
1958
    table->table=0;                             // For query cache
1940
 
    if (session->client->flush())
 
1959
    if (session->getClient()->flush())
1941
1960
      goto err;
1942
1961
  }
1943
1962
 
1945
1964
  return(false);
1946
1965
 
1947
1966
err:
1948
 
  transaction_services.autocommitOrRollback(session, true);
 
1967
  transaction_services.autocommitOrRollback(*session, true);
1949
1968
  session->endTransaction(ROLLBACK);
1950
1969
  session->close_thread_tables();                       // Shouldn't be needed
1951
1970
  if (table)
1968
1987
    during the call to plugin::StorageEngine::createTable().
1969
1988
    See bug #28614 for more info.
1970
1989
  */
1971
 
static bool create_table_wrapper(Session &session, const message::Table& create_table_proto,
1972
 
                                 const TableIdentifier &destination_identifier,
1973
 
                                 const TableIdentifier &src_table,
 
1990
static bool create_table_wrapper(Session &session,
 
1991
                                 const message::Table& create_table_proto,
 
1992
                                 identifier::Table::const_reference destination_identifier,
 
1993
                                 identifier::Table::const_reference source_identifier,
1974
1994
                                 bool is_engine_set)
1975
1995
{
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);
 
1996
  // We require an additional table message because during parsing we used
 
1997
  // a "new" message and it will not have all of the information that the
 
1998
  // source table message would have.
 
1999
  message::Table new_table_message;
 
2000
 
 
2001
  message::table::shared_ptr source_table_message= plugin::StorageEngine::getTableMessage(session, source_identifier);
 
2002
 
 
2003
  if (not source_table_message)
 
2004
  {
 
2005
    my_error(ER_TABLE_UNKNOWN, source_identifier);
 
2006
    return false;
 
2007
  }
 
2008
 
 
2009
  new_table_message.CopyFrom(*source_table_message);
1984
2010
 
1985
2011
  if (destination_identifier.isTmp())
1986
2012
  {
1987
 
    new_proto.set_type(message::Table::TEMPORARY);
 
2013
    new_table_message.set_type(message::Table::TEMPORARY);
1988
2014
  }
1989
2015
  else
1990
2016
  {
1991
 
    new_proto.set_type(message::Table::STANDARD);
 
2017
    new_table_message.set_type(message::Table::STANDARD);
1992
2018
  }
1993
2019
 
1994
2020
  if (is_engine_set)
1995
2021
  {
1996
 
    new_proto.mutable_engine()->set_name(create_table_proto.engine().name());
 
2022
    new_table_message.mutable_engine()->set_name(create_table_proto.engine().name());
1997
2023
  }
1998
2024
 
1999
2025
  { // We now do a selective copy of elements on to the new table.
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());
 
2026
    new_table_message.set_name(create_table_proto.name());
 
2027
    new_table_message.set_schema(create_table_proto.schema());
 
2028
    new_table_message.set_catalog(create_table_proto.catalog());
2003
2029
  }
2004
2030
 
2005
 
  if (protoerr && protoerr != EEXIST)
 
2031
  /* Fix names of foreign keys being added */
 
2032
  for (int32_t j= 0; j < new_table_message.fk_constraint_size(); j++)
2006
2033
  {
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;
 
2034
    if (new_table_message.fk_constraint(j).has_name())
 
2035
    {
 
2036
      std::string name(new_table_message.name());
 
2037
      char number[20];
 
2038
 
 
2039
      name.append("_ibfk_");
 
2040
      snprintf(number, sizeof(number), "%d", j+1);
 
2041
      name.append(number);
 
2042
 
 
2043
      message::Table::ForeignKeyConstraint *pfkey= new_table_message.mutable_fk_constraint(j);
 
2044
      pfkey->set_name(name);
 
2045
    }
2013
2046
  }
2014
2047
 
2015
2048
  /*
2016
2049
    As mysql_truncate don't work on a new table at this stage of
2017
 
    creation, instead create the table directly (for both normal
2018
 
    and temporary tables).
 
2050
    creation, instead create the table directly (for both normal and temporary tables).
2019
2051
  */
2020
 
  int err= plugin::StorageEngine::createTable(session,
2021
 
                                              destination_identifier,
2022
 
                                              new_proto);
 
2052
  bool success= plugin::StorageEngine::createTable(session,
 
2053
                                                   destination_identifier,
 
2054
                                                   new_table_message);
2023
2055
 
2024
 
  if (err == false && not destination_identifier.isTmp())
 
2056
  if (success && not destination_identifier.isTmp())
2025
2057
  {
2026
2058
    TransactionServices &transaction_services= TransactionServices::singleton();
2027
 
    transaction_services.createTable(&session, new_proto);
 
2059
    transaction_services.createTable(session, new_table_message);
2028
2060
  }
2029
2061
 
2030
 
  return err ? false : true;
 
2062
  return success;
2031
2063
}
2032
2064
 
2033
2065
/*
2034
2066
  Create a table identical to the specified table
2035
2067
 
2036
2068
  SYNOPSIS
2037
 
    mysql_create_like_table()
 
2069
    create_like_table()
2038
2070
    session             Thread object
2039
2071
    table       Table list element for target table
2040
2072
    src_table   Table list element for source table
2045
2077
    true  error
2046
2078
*/
2047
2079
 
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)
 
2080
bool create_like_table(Session* session,
 
2081
                       identifier::Table::const_reference destination_identifier,
 
2082
                       identifier::Table::const_reference source_identifier,
 
2083
                       message::Table &create_table_proto,
 
2084
                       bool is_if_not_exists,
 
2085
                       bool is_engine_set)
2054
2086
{
2055
2087
  bool res= true;
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
 
 
 
2088
  bool table_exists= false;
2074
2089
 
2075
2090
  /*
2076
2091
    Check that destination tables does not exist. Note that its name
2078
2093
 
2079
2094
    For temporary tables we don't aim to grab locks.
2080
2095
  */
2081
 
  bool table_exists= false;
2082
2096
  if (destination_identifier.isTmp())
2083
2097
  {
2084
2098
    if (session->find_temporary_table(destination_identifier))
2087
2101
    }
2088
2102
    else
2089
2103
    {
2090
 
      bool was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
2091
 
                                             src_identifier, is_engine_set);
 
2104
      bool was_created= create_table_wrapper(*session,
 
2105
                                             create_table_proto,
 
2106
                                             destination_identifier,
 
2107
                                             source_identifier,
 
2108
                                             is_engine_set);
2092
2109
      if (not was_created) // This is pretty paranoid, but we assume something might not clean up after itself
2093
2110
      {
2094
2111
        (void) session->rm_temporary_table(destination_identifier, true);
2133
2150
      {
2134
2151
        boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* We lock for CREATE TABLE LIKE to copy table definition */
2135
2152
        was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
2136
 
                                               src_identifier, is_engine_set);
 
2153
                                          source_identifier, is_engine_set);
2137
2154
      }
2138
2155
 
2139
2156
      // So we blew the creation of the table, and we scramble to clean up
2161
2178
    {
2162
2179
      char warn_buff[DRIZZLE_ERRMSG_SIZE];
2163
2180
      snprintf(warn_buff, sizeof(warn_buff),
2164
 
               ER(ER_TABLE_EXISTS_ERROR), table->getTableName());
 
2181
               ER(ER_TABLE_EXISTS_ERROR), destination_identifier.getTableName().c_str());
2165
2182
      push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
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
 
    }
 
2183
                   ER_TABLE_EXISTS_ERROR, warn_buff);
 
2184
      return false;
 
2185
    }
 
2186
 
 
2187
    my_error(ER_TABLE_EXISTS_ERROR, destination_identifier);
 
2188
 
 
2189
    return true;
2173
2190
  }
2174
2191
 
2175
 
  return(res);
 
2192
  return res;
2176
2193
}
2177
2194
 
2178
2195
 
2179
 
bool mysql_analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
 
2196
bool analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
2180
2197
{
2181
2198
  thr_lock_type lock_type = TL_READ_NO_INSERT;
2182
2199
 
2183
 
  return(mysql_admin_table(session, tables, check_opt,
 
2200
  return(admin_table(session, tables, check_opt,
2184
2201
                                "analyze", lock_type, true,
2185
2202
                                &Cursor::ha_analyze));
2186
2203
}
2187
2204
 
2188
2205
 
2189
 
bool mysql_check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
 
2206
bool check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
2190
2207
{
2191
2208
  thr_lock_type lock_type = TL_READ_NO_INSERT;
2192
2209
 
2193
 
  return(mysql_admin_table(session, tables, check_opt,
 
2210
  return(admin_table(session, tables, check_opt,
2194
2211
                                "check", lock_type,
2195
2212
                                false,
2196
2213
                                &Cursor::ha_check));