~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/statement/alter_table.cc

  • Committer: Stewart Smith
  • Date: 2011-01-14 05:16:49 UTC
  • mto: (2086.1.3 build)
  • mto: This revision was merged to the branch mainline in revision 2087.
  • Revision ID: stewart@flamingspork.com-20110114051649-4kg0mdrgdtako8vp
add a FIXME to flesh out insert docs

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19
19
 */
20
20
 
21
 
#include <config.h>
 
21
#include "config.h"
22
22
 
23
23
#include <fcntl.h>
24
24
 
25
25
#include <sstream>
26
26
 
27
 
#include <drizzled/show.h>
28
 
#include <drizzled/lock.h>
29
 
#include <drizzled/session.h>
30
 
#include <drizzled/statement/alter_table.h>
31
 
#include <drizzled/global_charset_info.h>
32
 
 
33
 
 
34
 
#include <drizzled/gettext.h>
35
 
#include <drizzled/data_home.h>
36
 
#include <drizzled/sql_table.h>
37
 
#include <drizzled/table_proto.h>
38
 
#include <drizzled/optimizer/range.h>
39
 
#include <drizzled/time_functions.h>
40
 
#include <drizzled/records.h>
41
 
#include <drizzled/pthread_globals.h>
42
 
#include <drizzled/internal/my_sys.h>
43
 
#include <drizzled/internal/iocache.h>
44
 
#include <drizzled/plugin/storage_engine.h>
45
 
#include <drizzled/copy_field.h>
46
 
 
47
 
#include <drizzled/transaction_services.h>
48
 
 
49
 
#include <drizzled/filesort.h>
50
 
 
51
 
#include <drizzled/message.h>
 
27
#include "drizzled/show.h"
 
28
#include "drizzled/lock.h"
 
29
#include "drizzled/session.h"
 
30
#include "drizzled/statement/alter_table.h"
 
31
#include "drizzled/global_charset_info.h"
 
32
 
 
33
 
 
34
#include "drizzled/gettext.h"
 
35
#include "drizzled/data_home.h"
 
36
#include "drizzled/sql_table.h"
 
37
#include "drizzled/table_proto.h"
 
38
#include "drizzled/optimizer/range.h"
 
39
#include "drizzled/time_functions.h"
 
40
#include "drizzled/records.h"
 
41
#include "drizzled/pthread_globals.h"
 
42
#include "drizzled/internal/my_sys.h"
 
43
#include "drizzled/internal/iocache.h"
 
44
 
 
45
#include "drizzled/transaction_services.h"
 
46
 
 
47
#include "drizzled/filesort.h"
 
48
 
 
49
#include "drizzled/message.h"
52
50
 
53
51
using namespace std;
54
52
 
75
73
                                      message::Table &table_message,
76
74
                                      AlterInfo *alter_info);
77
75
 
78
 
static Table *open_alter_table(Session *session, Table *table, identifier::Table &identifier);
79
 
 
80
 
namespace statement {
81
 
 
82
 
AlterTable::AlterTable(Session *in_session, Table_ident *ident, drizzled::ha_build_method build_arg) :
83
 
  CreateTable(in_session)
84
 
85
 
  in_session->getLex()->sql_command= SQLCOM_ALTER_TABLE;
86
 
  (void)ident;
87
 
  alter_info.build_method= build_arg;
88
 
}
89
 
 
90
 
} // namespace statement
 
76
static int create_temporary_table(Session *session,
 
77
                                  TableIdentifier &identifier,
 
78
                                  HA_CREATE_INFO *create_info,
 
79
                                  message::Table &create_message,
 
80
                                  AlterInfo *alter_info);
 
81
 
 
82
static Table *open_alter_table(Session *session, Table *table, TableIdentifier &identifier);
91
83
 
92
84
bool statement::AlterTable::execute()
93
85
{
94
 
  TableList *first_table= (TableList *) getSession()->getLex()->select_lex.table_list.first;
95
 
  TableList *all_tables= getSession()->getLex()->query_tables;
 
86
  TableList *first_table= (TableList *) session->lex->select_lex.table_list.first;
 
87
  TableList *all_tables= session->lex->query_tables;
96
88
  assert(first_table == all_tables && first_table != 0);
97
 
  Select_Lex *select_lex= &getSession()->getLex()->select_lex;
 
89
  Select_Lex *select_lex= &session->lex->select_lex;
98
90
  bool need_start_waiting= false;
99
91
 
100
92
  is_engine_set= not createTableMessage().engine().name().empty();
102
94
  if (is_engine_set)
103
95
  {
104
96
    create_info().db_type= 
105
 
      plugin::StorageEngine::findByName(*getSession(), createTableMessage().engine().name());
 
97
      plugin::StorageEngine::findByName(*session, createTableMessage().engine().name());
106
98
 
107
99
    if (create_info().db_type == NULL)
108
100
    {
109
 
      my_error(createTableMessage().engine().name(), ER_UNKNOWN_STORAGE_ENGINE, MYF(0));
 
101
      my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), 
 
102
               createTableMessage().engine().name().c_str());
110
103
 
111
104
      return true;
112
105
    }
118
111
  /* Chicken/Egg... we need to search for the table, to know if the table exists, so we can build a full identifier from it */
119
112
  message::table::shared_ptr original_table_message;
120
113
  {
121
 
    identifier::Table identifier(first_table->getSchemaName(), first_table->getTableName());
122
 
    if (not (original_table_message= plugin::StorageEngine::getTableMessage(*getSession(), identifier)))
 
114
    TableIdentifier identifier(first_table->getSchemaName(), first_table->getTableName());
 
115
    if (plugin::StorageEngine::getTableDefinition(*session, identifier, original_table_message) != EEXIST)
123
116
    {
124
 
      my_error(ER_BAD_TABLE_ERROR, identifier);
 
117
      std::string path;
 
118
      identifier.getSQLPath(path);
 
119
      my_error(ER_BAD_TABLE_ERROR, MYF(0), path.c_str());
125
120
      return true;
126
121
    }
127
122
 
128
123
    if (not  create_info().db_type)
129
124
    {
130
125
      create_info().db_type= 
131
 
        plugin::StorageEngine::findByName(*getSession(), original_table_message->engine().name());
 
126
        plugin::StorageEngine::findByName(*session, original_table_message->engine().name());
132
127
 
133
128
      if (not create_info().db_type)
134
129
      {
135
 
        my_error(ER_BAD_TABLE_ERROR, identifier);
 
130
        std::string path;
 
131
        identifier.getSQLPath(path);
 
132
        my_error(ER_BAD_TABLE_ERROR, MYF(0), path.c_str());
136
133
        return true;
137
134
      }
138
135
    }
141
138
  if (not validateCreateTableOption())
142
139
    return true;
143
140
 
144
 
  if (getSession()->inTransaction())
145
 
  {
146
 
    my_error(ER_TRANSACTIONAL_DDL_NOT_SUPPORTED, MYF(0));
 
141
  /* ALTER TABLE ends previous transaction */
 
142
  if (not session->endActiveTransaction())
147
143
    return true;
148
 
  }
149
144
 
150
 
  if (not (need_start_waiting= not getSession()->wait_if_global_read_lock(0, 1)))
 
145
  if (not (need_start_waiting= not session->wait_if_global_read_lock(0, 1)))
151
146
    return true;
152
147
 
153
148
  bool res;
154
149
  if (original_table_message->type() == message::Table::STANDARD )
155
150
  {
156
 
    identifier::Table identifier(first_table->getSchemaName(), first_table->getTableName());
157
 
    identifier::Table new_identifier(select_lex->db ? select_lex->db : first_table->getSchemaName(),
158
 
                                   getSession()->getLex()->name.str ? getSession()->getLex()->name.str : first_table->getTableName());
 
151
    TableIdentifier identifier(first_table->getSchemaName(), first_table->getTableName());
 
152
    TableIdentifier new_identifier(select_lex->db ? select_lex->db : first_table->getSchemaName(),
 
153
                                   session->lex->name.str ? session->lex->name.str : first_table->getTableName());
159
154
 
160
 
    res= alter_table(getSession(), 
 
155
    res= alter_table(session, 
161
156
                     identifier,
162
157
                     new_identifier,
163
158
                     &create_info(),
167
162
                     &alter_info,
168
163
                     select_lex->order_list.elements,
169
164
                     (Order *) select_lex->order_list.first,
170
 
                     getSession()->getLex()->ignore);
 
165
                     session->lex->ignore);
171
166
  }
172
167
  else
173
168
  {
174
 
    identifier::Table catch22(first_table->getSchemaName(), first_table->getTableName());
175
 
    Table *table= getSession()->find_temporary_table(catch22);
 
169
    TableIdentifier catch22(first_table->getSchemaName(), first_table->getTableName());
 
170
    Table *table= session->find_temporary_table(catch22);
176
171
    assert(table);
177
172
    {
178
 
      identifier::Table identifier(first_table->getSchemaName(), first_table->getTableName(), table->getMutableShare()->getPath());
179
 
      identifier::Table new_identifier(select_lex->db ? select_lex->db : first_table->getSchemaName(),
180
 
                                       getSession()->getLex()->name.str ? getSession()->getLex()->name.str : first_table->getTableName(),
181
 
                                       table->getMutableShare()->getPath());
 
173
      TableIdentifier identifier(first_table->getSchemaName(), first_table->getTableName(), table->getMutableShare()->getPath());
 
174
      TableIdentifier new_identifier(select_lex->db ? select_lex->db : first_table->getSchemaName(),
 
175
                                     session->lex->name.str ? session->lex->name.str : first_table->getTableName(),
 
176
                                     table->getMutableShare()->getPath());
182
177
 
183
 
      res= alter_table(getSession(), 
 
178
      res= alter_table(session, 
184
179
                       identifier,
185
180
                       new_identifier,
186
181
                       &create_info(),
190
185
                       &alter_info,
191
186
                       select_lex->order_list.elements,
192
187
                       (Order *) select_lex->order_list.first,
193
 
                       getSession()->getLex()->ignore);
 
188
                       session->lex->ignore);
194
189
    }
195
190
  }
196
191
 
198
193
     Release the protection against the global read lock and wake
199
194
     everyone, who might want to set a global read lock.
200
195
   */
201
 
  getSession()->startWaitingGlobalReadLock();
 
196
  session->startWaitingGlobalReadLock();
202
197
 
203
198
  return res;
204
199
}
245
240
  @retval false  success
246
241
*/
247
242
static bool prepare_alter_table(Session *session,
248
 
                                Table *table,
249
 
                                HA_CREATE_INFO *create_info,
250
 
                                const message::Table &original_proto,
251
 
                                message::Table &table_message,
252
 
                                AlterInfo *alter_info)
 
243
                                      Table *table,
 
244
                                      HA_CREATE_INFO *create_info,
 
245
                                      const message::Table &original_proto,
 
246
                                      message::Table &table_message,
 
247
                                      AlterInfo *alter_info)
253
248
{
254
249
  /* New column definitions are added here */
255
250
  List<CreateField> new_create_list;
256
251
  /* New key definitions are added here */
257
252
  List<Key> new_key_list;
258
 
  List<AlterDrop>::iterator drop_it(alter_info->drop_list.begin());
259
 
  List<CreateField>::iterator def_it(alter_info->create_list.begin());
260
 
  List<AlterColumn>::iterator alter_it(alter_info->alter_list.begin());
261
 
  List<Key>::iterator key_it(alter_info->key_list.begin());
262
 
  List<CreateField>::iterator find_it(new_create_list.begin());
263
 
  List<CreateField>::iterator field_it(new_create_list.begin());
 
253
  List_iterator<AlterDrop> drop_it(alter_info->drop_list);
 
254
  List_iterator<CreateField> def_it(alter_info->create_list);
 
255
  List_iterator<AlterColumn> alter_it(alter_info->alter_list);
 
256
  List_iterator<Key> key_it(alter_info->key_list);
 
257
  List_iterator<CreateField> find_it(new_create_list);
 
258
  List_iterator<CreateField> field_it(new_create_list);
264
259
  List<Key_part_spec> key_parts;
265
260
  uint32_t used_fields= create_info->used_fields;
266
261
  KeyInfo *key_info= table->key_info;
270
265
  message::Table::TableOptions *table_options;
271
266
  table_options= table_message.mutable_options();
272
267
 
273
 
  if (not (used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
 
268
  if (! (used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
274
269
    create_info->default_table_charset= table->getShare()->table_charset;
275
 
 
276
 
  if (not (used_fields & HA_CREATE_USED_AUTO) && table->found_next_number_field)
 
270
  if (! (used_fields & HA_CREATE_USED_AUTO) &&
 
271
      table->found_next_number_field)
277
272
  {
278
273
    /* Table has an autoincrement, copy value to new table */
279
274
    table->cursor->info(HA_STATUS_AUTO);
281
276
    if (create_info->auto_increment_value != original_proto.options().auto_increment_value())
282
277
      table_options->set_has_user_set_auto_increment_value(false);
283
278
  }
284
 
 
285
279
  table->restoreRecordAsDefault(); /* Empty record for DEFAULT */
286
280
  CreateField *def;
287
281
 
291
285
  {
292
286
    /* Check if field should be dropped */
293
287
    AlterDrop *drop;
294
 
    drop_it= alter_info->drop_list.begin();
 
288
    drop_it.rewind();
295
289
    while ((drop= drop_it++))
296
290
    {
297
291
      if (drop->type == AlterDrop::COLUMN &&
318
312
    field->setReadSet();
319
313
 
320
314
    /* Check if field is changed */
321
 
    def_it= alter_info->create_list.begin();
 
315
    def_it.rewind();
322
316
    while ((def= def_it++))
323
317
    {
324
318
      if (def->change &&
344
338
      */
345
339
      def= new CreateField(field, field);
346
340
      new_create_list.push_back(def);
347
 
      alter_it= alter_info->alter_list.begin(); /* Change default if ALTER */
 
341
      alter_it.rewind(); /* Change default if ALTER */
348
342
      AlterColumn *alter;
349
343
 
350
344
      while ((alter= alter_it++))
375
369
    }
376
370
  }
377
371
 
378
 
  def_it= alter_info->create_list.begin();
 
372
  def_it.rewind();
379
373
  while ((def= def_it++)) /* Add new columns */
380
374
  {
381
375
    if (def->change && ! def->field)
401
395
    else
402
396
    {
403
397
      CreateField *find;
404
 
      find_it= new_create_list.begin();
405
 
 
 
398
      find_it.rewind();
406
399
      while ((find= find_it++)) /* Add new columns */
407
400
      {
408
 
        if (not my_strcasecmp(system_charset_info,def->after, find->field_name))
 
401
        if (! my_strcasecmp(system_charset_info,def->after, find->field_name))
409
402
          break;
410
403
      }
411
 
 
412
 
      if (not find)
 
404
      if (! find)
413
405
      {
414
406
        my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table->getMutableShare()->getTableName());
415
407
        return true;
416
408
      }
417
 
 
418
409
      find_it.after(def); /* Put element after this */
419
 
 
420
410
      /*
421
411
        XXX: hack for Bug#28427.
422
412
        If column order has changed, force OFFLINE ALTER Table
429
419
      */
430
420
      if (alter_info->build_method == HA_BUILD_ONLINE)
431
421
      {
432
 
        my_error(*session->getQueryString(), ER_NOT_SUPPORTED_YET);
 
422
        my_error(ER_NOT_SUPPORTED_YET, MYF(0), session->getQueryString()->c_str());
433
423
        return true;
434
424
      }
435
 
 
436
425
      alter_info->build_method= HA_BUILD_OFFLINE;
437
426
    }
438
427
  }
446
435
    return true;
447
436
  }
448
437
 
449
 
  if (not new_create_list.elements)
 
438
  if (! new_create_list.elements)
450
439
  {
451
440
    my_message(ER_CANT_REMOVE_ALL_FIELDS,
452
441
               ER(ER_CANT_REMOVE_ALL_FIELDS),
462
451
  {
463
452
    char *key_name= key_info->name;
464
453
    AlterDrop *drop;
465
 
 
466
 
    drop_it= alter_info->drop_list.begin();
 
454
    drop_it.rewind();
467
455
    while ((drop= drop_it++))
468
456
    {
469
457
      if (drop->type == AlterDrop::KEY &&
470
458
          ! my_strcasecmp(system_charset_info, key_name, drop->name))
471
459
        break;
472
460
    }
473
 
 
474
461
    if (drop)
475
462
    {
476
463
      drop_it.remove();
478
465
    }
479
466
 
480
467
    KeyPartInfo *key_part= key_info->key_part;
481
 
    key_parts.clear();
 
468
    key_parts.empty();
482
469
    for (uint32_t j= 0; j < key_info->key_parts; j++, key_part++)
483
470
    {
484
471
      if (! key_part->field)
486
473
 
487
474
      const char *key_part_name= key_part->field->field_name;
488
475
      CreateField *cfield;
489
 
      field_it= new_create_list.begin();
 
476
      field_it.rewind();
490
477
      while ((cfield= field_it++))
491
478
      {
492
479
        if (cfield->change)
493
480
        {
494
 
          if (not my_strcasecmp(system_charset_info, key_part_name, cfield->change))
 
481
          if (! my_strcasecmp(system_charset_info, key_part_name, cfield->change))
495
482
            break;
496
483
        }
497
 
        else if (not my_strcasecmp(system_charset_info, key_part_name, cfield->field_name))
 
484
        else if (! my_strcasecmp(system_charset_info, key_part_name, cfield->field_name))
498
485
          break;
499
486
      }
500
 
 
501
 
      if (not cfield)
 
487
      if (! cfield)
502
488
              continue; /* Field is removed */
503
489
      
504
490
      uint32_t key_part_length= key_part->length;
530
516
    }
531
517
    if (key_parts.elements)
532
518
    {
533
 
      key_create_information_st key_create_info= default_key_create_info;
 
519
      KEY_CREATE_INFO key_create_info;
534
520
      Key *key;
535
 
      Key::Keytype key_type;
 
521
      enum Key::Keytype key_type;
 
522
      memset(&key_create_info, 0, sizeof(key_create_info));
536
523
 
537
524
      key_create_info.algorithm= key_info->algorithm;
538
 
 
539
525
      if (key_info->flags & HA_USES_BLOCK_SIZE)
540
526
        key_create_info.block_size= key_info->block_size;
541
 
 
542
527
      if (key_info->flags & HA_USES_COMMENT)
543
528
        key_create_info.comment= key_info->comment;
544
529
 
550
535
          key_type= Key::UNIQUE;
551
536
      }
552
537
      else
553
 
      {
554
538
        key_type= Key::MULTIPLE;
555
 
      }
556
539
 
557
540
      key= new Key(key_type,
558
541
                   key_name,
565
548
  }
566
549
 
567
550
  /* Copy over existing foreign keys */
568
 
  for (int32_t j= 0; j < original_proto.fk_constraint_size(); j++)
 
551
  for (int j= 0; j < original_proto.fk_constraint_size(); j++)
569
552
  {
570
553
    AlterDrop *drop;
571
 
    drop_it= alter_info->drop_list.begin();
 
554
    drop_it.rewind();
572
555
    while ((drop= drop_it++))
573
556
    {
574
557
      if (drop->type == AlterDrop::FOREIGN_KEY &&
657
640
 
658
641
  if (not table_message.options().has_comment()
659
642
      && table->getMutableShare()->hasComment())
660
 
  {
661
643
    table_options->set_comment(table->getMutableShare()->getComment());
662
 
  }
663
644
 
664
645
  if (table->getShare()->getType())
665
646
  {
666
647
    table_message.set_type(message::Table::TEMPORARY);
667
648
  }
668
649
 
669
 
  table_message.set_creation_timestamp(table->getShare()->getTableMessage()->creation_timestamp());
670
 
  table_message.set_version(table->getShare()->getTableMessage()->version());
671
 
  table_message.set_uuid(table->getShare()->getTableMessage()->uuid());
 
650
  table_message.set_creation_timestamp(table->getShare()->getTableProto()->creation_timestamp());
 
651
  table_message.set_version(table->getShare()->getTableProto()->version());
 
652
  table_message.set_uuid(table->getShare()->getTableProto()->uuid());
672
653
 
673
654
  rc= false;
674
655
  alter_info->create_list.swap(new_create_list);
709
690
{
710
691
  Table *table;
711
692
  bool discard;
 
693
  int error;
712
694
 
713
695
  /*
714
696
    Note that DISCARD/IMPORT TABLESPACE always is the only operation in an
715
697
    ALTER Table
716
698
  */
 
699
 
717
700
  TransactionServices &transaction_services= TransactionServices::singleton();
718
701
  session->set_proc_info("discard_or_import_tablespace");
719
702
 
723
706
   We set this flag so that ha_innobase::open and ::external_lock() do
724
707
   not complain when we lock the table
725
708
 */
726
 
  session->setDoingTablespaceOperation(true);
727
 
  if (not (table= session->openTableLock(table_list, TL_WRITE)))
 
709
  session->tablespace_op= true;
 
710
  if (!(table= session->openTableLock(table_list, TL_WRITE)))
728
711
  {
729
 
    session->setDoingTablespaceOperation(false);
 
712
    session->tablespace_op= false;
730
713
    return -1;
731
714
  }
732
715
 
733
 
  int error;
734
716
  do {
735
717
    error= table->cursor->ha_discard_or_import_tablespace(discard);
736
718
 
740
722
      break;
741
723
 
742
724
    /* The ALTER Table is always in its own transaction */
743
 
    error= transaction_services.autocommitOrRollback(*session, false);
 
725
    error= transaction_services.autocommitOrRollback(session, false);
744
726
    if (not session->endActiveTransaction())
745
727
      error= 1;
746
728
 
751
733
 
752
734
  } while(0);
753
735
 
754
 
  (void) transaction_services.autocommitOrRollback(*session, error);
755
 
  session->setDoingTablespaceOperation(false);
 
736
  (void) transaction_services.autocommitOrRollback(session, error);
 
737
  session->tablespace_op=false;
756
738
 
757
739
  if (error == 0)
758
740
  {
812
794
}
813
795
 
814
796
static bool lockTableIfDifferent(Session &session,
815
 
                                 identifier::Table &original_table_identifier,
816
 
                                 identifier::Table &new_table_identifier,
 
797
                                 TableIdentifier &original_table_identifier,
 
798
                                 TableIdentifier &new_table_identifier,
817
799
                                 Table *name_lock)
818
800
{
819
801
  /* Check that we are not trying to rename to an existing table */
824
806
 
825
807
      if (session.find_temporary_table(new_table_identifier))
826
808
      {
827
 
        my_error(ER_TABLE_EXISTS_ERROR, new_table_identifier);
 
809
        std::string path;
 
810
        new_table_identifier.getSQLPath(path);
 
811
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
828
812
        return false;
829
813
      }
830
814
    }
837
821
 
838
822
      if (not name_lock)
839
823
      {
840
 
        my_error(ER_TABLE_EXISTS_ERROR, new_table_identifier);
 
824
        std::string path;
 
825
        new_table_identifier.getSQLPath(path);
 
826
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
841
827
        return false;
842
828
      }
843
829
 
844
830
      if (plugin::StorageEngine::doesTableExist(session, new_table_identifier))
845
831
      {
 
832
        std::string path;
 
833
        new_table_identifier.getSQLPath(path);
 
834
 
846
835
        /* Table will be closed by Session::executeCommand() */
847
 
        my_error(ER_TABLE_EXISTS_ERROR, new_table_identifier);
 
836
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
848
837
 
849
 
        {
850
 
          boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex());
851
 
          session.unlink_open_table(name_lock);
852
 
        }
 
838
        table::Cache::singleton().mutex().lock(); /* ALTER TABLe */
 
839
        session.unlink_open_table(name_lock);
 
840
        table::Cache::singleton().mutex().unlock();
853
841
 
854
842
        return false;
855
843
      }
903
891
 
904
892
static bool internal_alter_table(Session *session,
905
893
                                 Table *table,
906
 
                                 identifier::Table &original_table_identifier,
907
 
                                 identifier::Table &new_table_identifier,
 
894
                                 TableIdentifier &original_table_identifier,
 
895
                                 TableIdentifier &new_table_identifier,
908
896
                                 HA_CREATE_INFO *create_info,
909
897
                                 const message::Table &original_proto,
910
898
                                 message::Table &create_proto,
961
949
  if (original_engine->check_flag(HTON_BIT_ALTER_NOT_SUPPORTED) ||
962
950
      new_engine->check_flag(HTON_BIT_ALTER_NOT_SUPPORTED))
963
951
  {
964
 
    my_error(ER_ILLEGAL_HA, new_table_identifier);
 
952
    std::string path;
 
953
    new_table_identifier.getSQLPath(path);
 
954
    my_error(ER_ILLEGAL_HA, MYF(0), path.c_str());
965
955
 
966
956
    return true;
967
957
  }
979
969
    tmp.reset(ALTER_KEYS_ONOFF);
980
970
    tmp&= alter_info->flags;
981
971
 
982
 
    if (not (tmp.any()) && not table->getShare()->getType()) // no need to touch frm
 
972
    if (! (tmp.any()) && ! table->getShare()->getType()) // no need to touch frm
983
973
    {
984
974
      switch (alter_info->keys_onoff)
985
975
      {
986
976
      case LEAVE_AS_IS:
987
977
        break;
988
 
 
989
978
      case ENABLE:
990
979
        /*
991
980
          wait_while_table_is_used() ensures that table being altered is
996
985
          while the fact that the table is still open gives us protection
997
986
          from concurrent DDL statements.
998
987
        */
999
 
        {
1000
 
          boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex()); /* DDL wait for/blocker */
1001
 
          wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
1002
 
        }
 
988
        table::Cache::singleton().mutex().lock(); /* DDL wait for/blocker */
 
989
        wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
 
990
        table::Cache::singleton().mutex().unlock();
1003
991
        error= table->cursor->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
1004
 
 
1005
992
        /* COND_refresh will be signaled in close_thread_tables() */
1006
993
        break;
1007
 
 
1008
994
      case DISABLE:
1009
 
        {
1010
 
          boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex()); /* DDL wait for/blocker */
1011
 
          wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
1012
 
        }
1013
 
        error= table->cursor->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
1014
 
 
 
995
        table::Cache::singleton().mutex().lock(); /* DDL wait for/blocker */
 
996
        wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
 
997
        table::Cache::singleton().mutex().unlock();
 
998
        error=table->cursor->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
1015
999
        /* COND_refresh will be signaled in close_thread_tables() */
1016
1000
        break;
 
1001
      default:
 
1002
        assert(false);
 
1003
        error= 0;
 
1004
        break;
1017
1005
      }
1018
1006
 
1019
1007
      if (error == HA_ERR_WRONG_COMMAND)
1020
1008
      {
1021
 
        error= EE_OK;
 
1009
        error= 0;
1022
1010
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1023
1011
                            ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
1024
1012
                            table->getAlias());
1025
1013
      }
1026
1014
 
1027
 
      boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex()); /* Lock to remove all instances of table from table cache before ALTER */
 
1015
      table::Cache::singleton().mutex().lock(); /* Lock to remove all instances of table from table cache before ALTER */
1028
1016
      /*
1029
1017
        Unlike to the above case close_cached_table() below will remove ALL
1030
1018
        instances of Table from table cache (it will also remove table lock
1034
1022
        access() and rename_table() calls.
1035
1023
      */
1036
1024
 
1037
 
      if (not error &&  not (original_table_identifier == new_table_identifier))
 
1025
      if (error == 0 &&  not (original_table_identifier == new_table_identifier))
1038
1026
      {
1039
1027
        session->set_proc_info("rename");
1040
1028
        /*
1052
1040
        */
1053
1041
        if (plugin::StorageEngine::doesTableExist(*session, new_table_identifier))
1054
1042
        {
1055
 
          my_error(ER_TABLE_EXISTS_ERROR, new_table_identifier);
 
1043
          std::string path;
 
1044
          new_table_identifier.getSQLPath(path);
 
1045
          my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
1056
1046
          error= -1;
1057
1047
        }
1058
1048
        else
1066
1056
 
1067
1057
      if (error == HA_ERR_WRONG_COMMAND)
1068
1058
      {
1069
 
        error= EE_OK;
 
1059
        error= 0;
1070
1060
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1071
1061
                            ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
1072
1062
                            table->getAlias());
1073
1063
      }
1074
1064
 
1075
 
      if (not error)
 
1065
      if (error == 0)
1076
1066
      {
1077
1067
        TransactionServices &transaction_services= TransactionServices::singleton();
1078
1068
        transaction_services.allocateNewTransactionId();
1079
1069
        write_bin_log(session, *session->getQueryString());
1080
1070
        session->my_ok();
1081
1071
      }
1082
 
      else if (error > EE_OK) // If we have already set the error, we pass along -1
 
1072
      else if (error > 0)
1083
1073
      {
1084
1074
        table->print_error(error, MYF(0));
 
1075
        error= -1;
1085
1076
      }
1086
1077
 
 
1078
      table::Cache::singleton().mutex().unlock();
1087
1079
      table_list->table= NULL;
1088
1080
 
1089
1081
      return error;
1110
1102
    case we just use it as is. Neither of these tables require locks in order to  be
1111
1103
    filled.
1112
1104
  */
1113
 
  identifier::Table new_table_as_temporary(original_table_identifier.getSchemaName(),
 
1105
  TableIdentifier new_table_as_temporary(original_table_identifier.getSchemaName(),
1114
1106
                                         tmp_name,
1115
1107
                                         create_proto.type() != message::Table::TEMPORARY ? message::Table::INTERNAL :
1116
1108
                                         message::Table::TEMPORARY);
1117
1109
 
1118
 
  /*
1119
 
    Create a table with a temporary name.
1120
 
    We don't log the statement, it will be logged later.
1121
 
  */
1122
 
  create_proto.set_name(new_table_as_temporary.getTableName());
1123
 
  create_proto.mutable_engine()->set_name(create_info->db_type->getName());
1124
 
 
1125
 
  error= create_table(session,
1126
 
                      new_table_as_temporary,
1127
 
                      create_info, create_proto, alter_info, true, 0, false);
 
1110
  error= create_temporary_table(session, new_table_as_temporary, create_info, create_proto, alter_info);
1128
1111
 
1129
1112
  if (error != 0)
1130
1113
  {
1174
1157
  {
1175
1158
 
1176
1159
    /*
1177
 
      No default value was provided for new fields.
 
1160
      No default value was provided for a DATE/DATETIME field, the
 
1161
      current sql_mode doesn't allow the '0000-00-00' value and
 
1162
      the table to be altered isn't empty.
 
1163
      Report error here.
1178
1164
    */
1179
1165
    if (alter_info->error_if_not_empty && session->row_count)
1180
1166
    {
1212
1198
        delete new_table;
1213
1199
      }
1214
1200
 
1215
 
      boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex());
 
1201
      table::Cache::singleton().mutex().lock(); /* ALTER TABLE */
1216
1202
 
1217
1203
      plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
 
1204
      table::Cache::singleton().mutex().unlock();
1218
1205
 
1219
1206
      return true;
1220
1207
    }
1261
1248
      delete new_table;
1262
1249
    }
1263
1250
 
1264
 
    {
1265
 
      boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex()); /* ALTER TABLE */
1266
 
      /*
1267
 
        Data is copied. Now we:
1268
 
        1) Wait until all other threads close old version of table.
1269
 
        2) Close instances of table open by this thread and replace them
1270
 
        with exclusive name-locks.
1271
 
        3) Rename the old table to a temp name, rename the new one to the
1272
 
        old name.
1273
 
        4) If we are under LOCK TABLES and don't do ALTER Table ... RENAME
1274
 
        we reopen new version of table.
1275
 
        5) Write statement to the binary log.
1276
 
        6) If we are under LOCK TABLES and do ALTER Table ... RENAME we
1277
 
        remove name-locks from list of open tables and table cache.
1278
 
        7) If we are not not under LOCK TABLES we rely on close_thread_tables()
1279
 
        call to remove name-locks from table cache and list of open table.
1280
 
      */
1281
 
 
1282
 
      session->set_proc_info("rename result table");
1283
 
 
1284
 
      snprintf(old_name, sizeof(old_name), "%s2-%lx-%"PRIx64, TMP_FILE_PREFIX, (unsigned long) current_pid, session->thread_id);
1285
 
 
1286
 
      my_casedn_str(files_charset_info, old_name);
1287
 
 
1288
 
      wait_while_table_is_used(session, table, HA_EXTRA_PREPARE_FOR_RENAME);
1289
 
      session->close_data_files_and_morph_locks(original_table_identifier);
1290
 
 
1291
 
      assert(not error);
1292
 
 
1293
 
      /*
1294
 
        This leads to the storage engine (SE) not being notified for renames in
1295
 
        rename_table(), because we just juggle with the FRM and nothing
1296
 
        more. If we have an intermediate table, then we notify the SE that
1297
 
        it should become the actual table. Later, we will recycle the old table.
1298
 
        However, in case of ALTER Table RENAME there might be no intermediate
1299
 
        table. This is when the old and new tables are compatible, according to
1300
 
        compare_table(). Then, we need one additional call to
1301
 
      */
1302
 
      identifier::Table original_table_to_drop(original_table_identifier.getSchemaName(),
1303
 
                                             old_name, create_proto.type() != message::Table::TEMPORARY ? message::Table::INTERNAL :
1304
 
                                             message::Table::TEMPORARY);
1305
 
 
1306
 
      drizzled::error_t rename_error= EE_OK;
1307
 
      if (rename_table(*session, original_engine, original_table_identifier, original_table_to_drop))
 
1251
    table::Cache::singleton().mutex().lock(); /* ALTER TABLE */
 
1252
 
 
1253
    /*
 
1254
      Data is copied. Now we:
 
1255
      1) Wait until all other threads close old version of table.
 
1256
      2) Close instances of table open by this thread and replace them
 
1257
      with exclusive name-locks.
 
1258
      3) Rename the old table to a temp name, rename the new one to the
 
1259
      old name.
 
1260
      4) If we are under LOCK TABLES and don't do ALTER Table ... RENAME
 
1261
      we reopen new version of table.
 
1262
      5) Write statement to the binary log.
 
1263
      6) If we are under LOCK TABLES and do ALTER Table ... RENAME we
 
1264
      remove name-locks from list of open tables and table cache.
 
1265
      7) If we are not not under LOCK TABLES we rely on close_thread_tables()
 
1266
      call to remove name-locks from table cache and list of open table.
 
1267
    */
 
1268
 
 
1269
    session->set_proc_info("rename result table");
 
1270
 
 
1271
    snprintf(old_name, sizeof(old_name), "%s2-%lx-%"PRIx64, TMP_FILE_PREFIX, (unsigned long) current_pid, session->thread_id);
 
1272
 
 
1273
    my_casedn_str(files_charset_info, old_name);
 
1274
 
 
1275
    wait_while_table_is_used(session, table, HA_EXTRA_PREPARE_FOR_RENAME);
 
1276
    session->close_data_files_and_morph_locks(original_table_identifier);
 
1277
 
 
1278
    error= 0;
 
1279
 
 
1280
    /*
 
1281
      This leads to the storage engine (SE) not being notified for renames in
 
1282
      rename_table(), because we just juggle with the FRM and nothing
 
1283
      more. If we have an intermediate table, then we notify the SE that
 
1284
      it should become the actual table. Later, we will recycle the old table.
 
1285
      However, in case of ALTER Table RENAME there might be no intermediate
 
1286
      table. This is when the old and new tables are compatible, according to
 
1287
      compare_table(). Then, we need one additional call to
 
1288
    */
 
1289
    TableIdentifier original_table_to_drop(original_table_identifier.getSchemaName(),
 
1290
                                           old_name, create_proto.type() != message::Table::TEMPORARY ? message::Table::INTERNAL :
 
1291
                                         message::Table::TEMPORARY);
 
1292
 
 
1293
    if (rename_table(*session, original_engine, original_table_identifier, original_table_to_drop))
 
1294
    {
 
1295
      error= 1;
 
1296
      plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
 
1297
    }
 
1298
    else
 
1299
    {
 
1300
      if (rename_table(*session, new_engine, new_table_as_temporary, new_table_identifier) != 0)
1308
1301
      {
1309
 
        error= ER_ERROR_ON_RENAME;
 
1302
        /* Try to get everything back. */
 
1303
        error= 1;
 
1304
 
 
1305
        plugin::StorageEngine::dropTable(*session, new_table_identifier);
 
1306
 
1310
1307
        plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
 
1308
 
 
1309
        rename_table(*session, original_engine, original_table_to_drop, original_table_identifier);
1311
1310
      }
1312
1311
      else
1313
1312
      {
1314
 
        if (rename_table(*session, new_engine, new_table_as_temporary, new_table_identifier) != 0)
1315
 
        {
1316
 
          /* Try to get everything back. */
1317
 
          rename_error= ER_ERROR_ON_RENAME;
1318
 
 
1319
 
          plugin::StorageEngine::dropTable(*session, new_table_identifier);
1320
 
 
1321
 
          plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
1322
 
 
1323
 
          rename_table(*session, original_engine, original_table_to_drop, original_table_identifier);
1324
 
        }
1325
 
        else
1326
 
        {
1327
 
          plugin::StorageEngine::dropTable(*session, original_table_to_drop);
1328
 
        }
1329
 
      }
1330
 
 
1331
 
      if (rename_error)
1332
 
      {
1333
 
        /*
1334
 
          An error happened while we were holding exclusive name-lock on table
1335
 
          being altered. To be safe under LOCK TABLES we should remove placeholders
1336
 
          from list of open tables list and table cache.
1337
 
        */
1338
 
        session->unlink_open_table(table);
1339
 
 
1340
 
        return true;
1341
 
      }
1342
 
    }
 
1313
        plugin::StorageEngine::dropTable(*session, original_table_to_drop);
 
1314
      }
 
1315
    }
 
1316
 
 
1317
    if (error)
 
1318
    {
 
1319
      /*
 
1320
        An error happened while we were holding exclusive name-lock on table
 
1321
        being altered. To be safe under LOCK TABLES we should remove placeholders
 
1322
        from list of open tables list and table cache.
 
1323
      */
 
1324
      session->unlink_open_table(table);
 
1325
      table::Cache::singleton().mutex().unlock();
 
1326
 
 
1327
      return true;
 
1328
    }
 
1329
 
 
1330
    table::Cache::singleton().mutex().unlock();
1343
1331
 
1344
1332
    session->set_proc_info("end");
1345
1333
 
1368
1356
}
1369
1357
 
1370
1358
bool alter_table(Session *session,
1371
 
                 identifier::Table &original_table_identifier,
1372
 
                 identifier::Table &new_table_identifier,
 
1359
                 TableIdentifier &original_table_identifier,
 
1360
                 TableIdentifier &new_table_identifier,
1373
1361
                 HA_CREATE_INFO *create_info,
1374
1362
                 const message::Table &original_proto,
1375
1363
                 message::Table &create_proto,
1422
1410
 
1423
1411
    if (name_lock)
1424
1412
    {
1425
 
      boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex());
 
1413
      table::Cache::singleton().mutex().lock(); /* ALTER TABLe */
1426
1414
      session->unlink_open_table(name_lock);
 
1415
      table::Cache::singleton().mutex().unlock();
1427
1416
    }
1428
1417
  }
1429
1418
 
1482
1471
  alter_table_manage_keys(session, to, from->cursor->indexes_are_disabled(), keys_onoff);
1483
1472
 
1484
1473
  /* We can abort alter table for any table type */
1485
 
  session->setAbortOnWarning(not ignore);
 
1474
  session->abort_on_warning= !ignore;
1486
1475
 
1487
1476
  from->cursor->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
1488
1477
  to->cursor->ha_start_bulk_insert(from->cursor->stats.records);
1489
1478
 
1490
 
  List<CreateField>::iterator it(create.begin());
 
1479
  List_iterator<CreateField> it(create);
1491
1480
  CreateField *def;
1492
1481
  copy_end= copy;
1493
1482
  for (Field **ptr= to->getFields(); *ptr ; ptr++)
1505
1494
 
1506
1495
  found_count=delete_count=0;
1507
1496
 
1508
 
  do
 
1497
  if (order)
1509
1498
  {
1510
 
    if (order)
1511
 
    {
1512
 
      if (to->getShare()->hasPrimaryKey() && to->cursor->primary_key_is_clustered())
 
1499
    if (to->getShare()->hasPrimaryKey() && to->cursor->primary_key_is_clustered())
 
1500
    {
 
1501
      char warn_buff[DRIZZLE_ERRMSG_SIZE];
 
1502
      snprintf(warn_buff, sizeof(warn_buff),
 
1503
               _("order_st BY ignored because there is a user-defined clustered "
 
1504
                 "index in the table '%-.192s'"),
 
1505
               from->getMutableShare()->getTableName());
 
1506
      push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
 
1507
                   warn_buff);
 
1508
    }
 
1509
    else
 
1510
    {
 
1511
      FileSort filesort(*session);
 
1512
      from->sort.io_cache= new internal::IO_CACHE;
 
1513
 
 
1514
      memset(&tables, 0, sizeof(tables));
 
1515
      tables.table= from;
 
1516
      tables.setTableName(const_cast<char *>(from->getMutableShare()->getTableName()));
 
1517
      tables.alias= const_cast<char *>(tables.getTableName());
 
1518
      tables.setSchemaName(const_cast<char *>(from->getMutableShare()->getSchemaName()));
 
1519
      error= 1;
 
1520
 
 
1521
      if (session->lex->select_lex.setup_ref_array(session, order_num) ||
 
1522
          setup_order(session, session->lex->select_lex.ref_pointer_array,
 
1523
                      &tables, fields, all_fields, order) ||
 
1524
          !(sortorder= make_unireg_sortorder(order, &length, NULL)) ||
 
1525
          (from->sort.found_records= filesort.run(from, sortorder, length,
 
1526
                                                  (optimizer::SqlSelect *) 0, HA_POS_ERROR,
 
1527
                                                  1, examined_rows)) == HA_POS_ERROR)
1513
1528
      {
1514
 
        char warn_buff[DRIZZLE_ERRMSG_SIZE];
1515
 
        snprintf(warn_buff, sizeof(warn_buff),
1516
 
                 _("order_st BY ignored because there is a user-defined clustered "
1517
 
                   "index in the table '%-.192s'"),
1518
 
                 from->getMutableShare()->getTableName());
1519
 
        push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
1520
 
                     warn_buff);
 
1529
        goto err;
1521
1530
      }
 
1531
    }
 
1532
  }
 
1533
 
 
1534
  /* Tell handler that we have values for all columns in the to table */
 
1535
  to->use_all_columns();
 
1536
  error= info.init_read_record(session, from, (optimizer::SqlSelect *) 0, 1, true);
 
1537
  if (error)
 
1538
  {
 
1539
    to->print_error(errno, MYF(0));
 
1540
    goto err;
 
1541
  }
 
1542
 
 
1543
  if (ignore)
 
1544
    to->cursor->extra(HA_EXTRA_IGNORE_DUP_KEY);
 
1545
 
 
1546
  session->row_count= 0;
 
1547
  to->restoreRecordAsDefault();        // Create empty record
 
1548
  while (!(error=info.read_record(&info)))
 
1549
  {
 
1550
    if (session->getKilled())
 
1551
    {
 
1552
      session->send_kill_message();
 
1553
      error= 1;
 
1554
      break;
 
1555
    }
 
1556
    session->row_count++;
 
1557
    /* Return error if source table isn't empty. */
 
1558
    if (error_if_not_empty)
 
1559
    {
 
1560
      error= 1;
 
1561
      break;
 
1562
    }
 
1563
    if (to->next_number_field)
 
1564
    {
 
1565
      if (auto_increment_field_copied)
 
1566
        to->auto_increment_field_not_null= true;
1522
1567
      else
 
1568
        to->next_number_field->reset();
 
1569
    }
 
1570
 
 
1571
    for (CopyField *copy_ptr= copy; copy_ptr != copy_end ; copy_ptr++)
 
1572
    {
 
1573
      if (not copy->to_field->hasDefault() and copy->from_null_ptr and  *copy->from_null_ptr & copy->from_bit)
1523
1574
      {
1524
 
        FileSort filesort(*session);
1525
 
        from->sort.io_cache= new internal::IO_CACHE;
1526
 
 
1527
 
        tables.table= from;
1528
 
        tables.setTableName(from->getMutableShare()->getTableName());
1529
 
        tables.alias= tables.getTableName();
1530
 
        tables.setSchemaName(const_cast<char *>(from->getMutableShare()->getSchemaName()));
 
1575
        copy->to_field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
1576
                                    ER_WARN_DATA_TRUNCATED, 1);
 
1577
        copy->to_field->reset();
1531
1578
        error= 1;
1532
 
 
1533
 
        if (session->getLex()->select_lex.setup_ref_array(session, order_num) ||
1534
 
            setup_order(session, session->getLex()->select_lex.ref_pointer_array,
1535
 
                        &tables, fields, all_fields, order) ||
1536
 
            !(sortorder= make_unireg_sortorder(order, &length, NULL)) ||
1537
 
            (from->sort.found_records= filesort.run(from, sortorder, length,
1538
 
                                                    (optimizer::SqlSelect *) 0, HA_POS_ERROR,
1539
 
                                                    1, examined_rows)) == HA_POS_ERROR)
1540
 
        {
1541
 
          break;
1542
 
        }
 
1579
        break;
1543
1580
      }
 
1581
 
 
1582
      copy_ptr->do_copy(copy_ptr);
1544
1583
    }
1545
1584
 
1546
 
    /* Tell handler that we have values for all columns in the to table */
1547
 
    to->use_all_columns();
1548
 
 
1549
 
    error= info.init_read_record(session, from, (optimizer::SqlSelect *) 0, 1, true);
1550
1585
    if (error)
1551
1586
    {
1552
 
      to->print_error(errno, MYF(0));
1553
 
 
1554
1587
      break;
1555
1588
    }
1556
1589
 
1557
 
    if (ignore)
1558
 
    {
1559
 
      to->cursor->extra(HA_EXTRA_IGNORE_DUP_KEY);
1560
 
    }
1561
 
 
1562
 
    session->row_count= 0;
1563
 
    to->restoreRecordAsDefault();        // Create empty record
1564
 
    while (not (error=info.read_record(&info)))
1565
 
    {
1566
 
      if (session->getKilled())
1567
 
      {
1568
 
        session->send_kill_message();
1569
 
        error= 1;
1570
 
        break;
1571
 
      }
1572
 
      session->row_count++;
1573
 
      /* Return error if source table isn't empty. */
1574
 
      if (error_if_not_empty)
1575
 
      {
1576
 
        error= 1;
1577
 
        break;
1578
 
      }
1579
 
      if (to->next_number_field)
1580
 
      {
1581
 
        if (auto_increment_field_copied)
1582
 
          to->auto_increment_field_not_null= true;
1583
 
        else
1584
 
          to->next_number_field->reset();
1585
 
      }
1586
 
 
1587
 
      for (CopyField *copy_ptr= copy; copy_ptr != copy_end ; copy_ptr++)
1588
 
      {
1589
 
        if (not copy->to_field->hasDefault() and copy->from_null_ptr and  *copy->from_null_ptr & copy->from_bit)
1590
 
        {
1591
 
          copy->to_field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
1592
 
                                      ER_WARN_DATA_TRUNCATED, 1);
1593
 
          copy->to_field->reset();
1594
 
          error= 1;
1595
 
          break;
1596
 
        }
1597
 
 
1598
 
        copy_ptr->do_copy(copy_ptr);
1599
 
      }
1600
 
 
1601
 
      if (error)
1602
 
      {
1603
 
        break;
1604
 
      }
1605
 
 
1606
 
      prev_insert_id= to->cursor->next_insert_id;
1607
 
      error= to->cursor->insertRecord(to->record[0]);
1608
 
      to->auto_increment_field_not_null= false;
1609
 
 
1610
 
      if (error)
 
1590
    prev_insert_id= to->cursor->next_insert_id;
 
1591
    error= to->cursor->insertRecord(to->record[0]);
 
1592
    to->auto_increment_field_not_null= false;
 
1593
 
 
1594
    if (error)
 
1595
    { 
 
1596
      if (!ignore || to->cursor->is_fatal_error(error, HA_CHECK_DUP))
1611
1597
      { 
1612
 
        if (!ignore || to->cursor->is_fatal_error(error, HA_CHECK_DUP))
1613
 
        { 
1614
 
          to->print_error(error, MYF(0));
1615
 
          break;
1616
 
        }
1617
 
        to->cursor->restore_auto_increment(prev_insert_id);
1618
 
        delete_count++;
1619
 
      }
1620
 
      else
1621
 
      {
1622
 
        found_count++;
1623
 
      }
 
1598
        to->print_error(error, MYF(0));
 
1599
        break;
 
1600
      }
 
1601
      to->cursor->restore_auto_increment(prev_insert_id);
 
1602
      delete_count++;
1624
1603
    }
1625
 
 
1626
 
    info.end_read_record();
1627
 
    from->free_io_cache();
1628
 
    delete [] copy;                             // This is never 0
1629
 
 
1630
 
    if (to->cursor->ha_end_bulk_insert() && error <= 0)
 
1604
    else
1631
1605
    {
1632
 
      to->print_error(errno, MYF(0));
1633
 
      error= 1;
 
1606
      found_count++;
1634
1607
    }
1635
 
    to->cursor->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
1636
 
 
1637
 
    /*
1638
 
      Ensure that the new table is saved properly to disk so that we
1639
 
      can do a rename
1640
 
    */
1641
 
    if (transaction_services.autocommitOrRollback(*session, false))
1642
 
      error= 1;
1643
 
 
1644
 
    if (not session->endActiveTransaction())
1645
 
      error= 1;
1646
 
 
1647
 
  } while (0);
1648
 
 
1649
 
  session->setAbortOnWarning(false);
 
1608
  }
 
1609
 
 
1610
  info.end_read_record();
 
1611
  from->free_io_cache();
 
1612
  delete [] copy;                               // This is never 0
 
1613
 
 
1614
  if (to->cursor->ha_end_bulk_insert() && error <= 0)
 
1615
  {
 
1616
    to->print_error(errno, MYF(0));
 
1617
    error=1;
 
1618
  }
 
1619
  to->cursor->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
 
1620
 
 
1621
  /*
 
1622
    Ensure that the new table is saved properly to disk so that we
 
1623
    can do a rename
 
1624
  */
 
1625
  if (transaction_services.autocommitOrRollback(session, false))
 
1626
    error=1;
 
1627
  if (! session->endActiveTransaction())
 
1628
    error=1;
 
1629
 
 
1630
 err:
 
1631
  session->abort_on_warning= 0;
1650
1632
  from->free_io_cache();
1651
1633
  *copied= found_count;
1652
1634
  *deleted=delete_count;
1653
1635
  to->cursor->ha_release_auto_increment();
1654
 
 
1655
 
  if (to->cursor->ha_external_lock(session, F_UNLCK))
1656
 
  {
 
1636
  if (to->cursor->ha_external_lock(session,F_UNLCK))
1657
1637
    error=1;
1658
 
  }
1659
1638
 
1660
1639
  return(error > 0 ? -1 : 0);
1661
1640
}
1662
1641
 
1663
 
static Table *open_alter_table(Session *session, Table *table, identifier::Table &identifier)
 
1642
static int
 
1643
create_temporary_table(Session *session,
 
1644
                       TableIdentifier &identifier,
 
1645
                       HA_CREATE_INFO *create_info,
 
1646
                       message::Table &create_proto,
 
1647
                       AlterInfo *alter_info)
 
1648
{
 
1649
  int error;
 
1650
 
 
1651
  /*
 
1652
    Create a table with a temporary name.
 
1653
    We don't log the statement, it will be logged later.
 
1654
  */
 
1655
  create_proto.set_name(identifier.getTableName());
 
1656
 
 
1657
  create_proto.mutable_engine()->set_name(create_info->db_type->getName());
 
1658
 
 
1659
  error= create_table(session,
 
1660
                      identifier,
 
1661
                      create_info, create_proto, alter_info, true, 0, false);
 
1662
 
 
1663
  return error;
 
1664
}
 
1665
 
 
1666
static Table *open_alter_table(Session *session, Table *table, TableIdentifier &identifier)
1664
1667
{
1665
1668
  Table *new_table;
1666
1669