~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/statement/alter_table.cc

  • Committer: Andrew Hutchings
  • Date: 2011-01-04 20:16:55 UTC
  • mto: This revision was merged to the branch mainline in revision 2057.
  • Revision ID: andrew@linuxjedi.co.uk-20110104201655-fm6splh5wqpv8wnb
Revert join_cache buffer cleanup, causes valgrind problems and as much as I don't like it I think the current implementation seems to work

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
 
  is_engine_set= not createTableMessage().engine().name().empty();
101
 
 
102
92
  if (is_engine_set)
103
93
  {
104
 
    create_info().db_type= 
105
 
      plugin::StorageEngine::findByName(*getSession(), createTableMessage().engine().name());
 
94
    create_info.db_type= 
 
95
      plugin::StorageEngine::findByName(*session, create_table_message.engine().name());
106
96
 
107
 
    if (create_info().db_type == NULL)
 
97
    if (create_info.db_type == NULL)
108
98
    {
109
 
      my_error(createTableMessage().engine().name(), ER_UNKNOWN_STORAGE_ENGINE, MYF(0));
 
99
      my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), 
 
100
               create_table_message.engine().name().c_str());
110
101
 
111
102
      return true;
112
103
    }
118
109
  /* 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
110
  message::table::shared_ptr original_table_message;
120
111
  {
121
 
    identifier::Table identifier(first_table->getSchemaName(), first_table->getTableName());
122
 
    if (not (original_table_message= plugin::StorageEngine::getTableMessage(*getSession(), identifier)))
 
112
    TableIdentifier identifier(first_table->getSchemaName(), first_table->getTableName());
 
113
    if (plugin::StorageEngine::getTableDefinition(*session, identifier, original_table_message) != EEXIST)
123
114
    {
124
 
      my_error(ER_BAD_TABLE_ERROR, identifier);
 
115
      std::string path;
 
116
      identifier.getSQLPath(path);
 
117
      my_error(ER_BAD_TABLE_ERROR, MYF(0), path.c_str());
125
118
      return true;
126
119
    }
127
120
 
128
 
    if (not  create_info().db_type)
 
121
    if (not  create_info.db_type)
129
122
    {
130
 
      create_info().db_type= 
131
 
        plugin::StorageEngine::findByName(*getSession(), original_table_message->engine().name());
 
123
      create_info.db_type= 
 
124
        plugin::StorageEngine::findByName(*session, original_table_message->engine().name());
132
125
 
133
 
      if (not create_info().db_type)
 
126
      if (not create_info.db_type)
134
127
      {
135
 
        my_error(ER_BAD_TABLE_ERROR, identifier);
 
128
        std::string path;
 
129
        identifier.getSQLPath(path);
 
130
        my_error(ER_BAD_TABLE_ERROR, MYF(0), path.c_str());
136
131
        return true;
137
132
      }
138
133
    }
141
136
  if (not validateCreateTableOption())
142
137
    return true;
143
138
 
144
 
  if (getSession()->inTransaction())
145
 
  {
146
 
    my_error(ER_TRANSACTIONAL_DDL_NOT_SUPPORTED, MYF(0));
 
139
  /* ALTER TABLE ends previous transaction */
 
140
  if (not session->endActiveTransaction())
147
141
    return true;
148
 
  }
149
142
 
150
 
  if (not (need_start_waiting= not getSession()->wait_if_global_read_lock(0, 1)))
 
143
  if (not (need_start_waiting= not session->wait_if_global_read_lock(0, 1)))
151
144
    return true;
152
145
 
153
146
  bool res;
154
147
  if (original_table_message->type() == message::Table::STANDARD )
155
148
  {
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());
 
149
    TableIdentifier identifier(first_table->getSchemaName(), first_table->getTableName());
 
150
    TableIdentifier new_identifier(select_lex->db ? select_lex->db : first_table->getSchemaName(),
 
151
                                   session->lex->name.str ? session->lex->name.str : first_table->getTableName());
159
152
 
160
 
    res= alter_table(getSession(), 
 
153
    res= alter_table(session, 
161
154
                     identifier,
162
155
                     new_identifier,
163
 
                     &create_info(),
 
156
                     &create_info,
164
157
                     *original_table_message,
165
 
                     createTableMessage(),
 
158
                     create_table_message,
166
159
                     first_table,
167
160
                     &alter_info,
168
161
                     select_lex->order_list.elements,
169
162
                     (Order *) select_lex->order_list.first,
170
 
                     getSession()->getLex()->ignore);
 
163
                     session->lex->ignore);
171
164
  }
172
165
  else
173
166
  {
174
 
    identifier::Table catch22(first_table->getSchemaName(), first_table->getTableName());
175
 
    Table *table= getSession()->find_temporary_table(catch22);
 
167
    TableIdentifier catch22(first_table->getSchemaName(), first_table->getTableName());
 
168
    Table *table= session->find_temporary_table(catch22);
176
169
    assert(table);
177
170
    {
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());
 
171
      TableIdentifier identifier(first_table->getSchemaName(), first_table->getTableName(), table->getMutableShare()->getPath());
 
172
      TableIdentifier new_identifier(select_lex->db ? select_lex->db : first_table->getSchemaName(),
 
173
                                     session->lex->name.str ? session->lex->name.str : first_table->getTableName(),
 
174
                                     table->getMutableShare()->getPath());
182
175
 
183
 
      res= alter_table(getSession(), 
 
176
      res= alter_table(session, 
184
177
                       identifier,
185
178
                       new_identifier,
186
 
                       &create_info(),
 
179
                       &create_info,
187
180
                       *original_table_message,
188
 
                       createTableMessage(),
 
181
                       create_table_message,
189
182
                       first_table,
190
183
                       &alter_info,
191
184
                       select_lex->order_list.elements,
192
185
                       (Order *) select_lex->order_list.first,
193
 
                       getSession()->getLex()->ignore);
 
186
                       session->lex->ignore);
194
187
    }
195
188
  }
196
189
 
198
191
     Release the protection against the global read lock and wake
199
192
     everyone, who might want to set a global read lock.
200
193
   */
201
 
  getSession()->startWaitingGlobalReadLock();
 
194
  session->startWaitingGlobalReadLock();
202
195
 
203
196
  return res;
204
197
}
245
238
  @retval false  success
246
239
*/
247
240
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)
 
241
                                      Table *table,
 
242
                                      HA_CREATE_INFO *create_info,
 
243
                                      const message::Table &original_proto,
 
244
                                      message::Table &table_message,
 
245
                                      AlterInfo *alter_info)
253
246
{
254
247
  /* New column definitions are added here */
255
248
  List<CreateField> new_create_list;
256
249
  /* New key definitions are added here */
257
250
  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());
 
251
  List_iterator<AlterDrop> drop_it(alter_info->drop_list);
 
252
  List_iterator<CreateField> def_it(alter_info->create_list);
 
253
  List_iterator<AlterColumn> alter_it(alter_info->alter_list);
 
254
  List_iterator<Key> key_it(alter_info->key_list);
 
255
  List_iterator<CreateField> find_it(new_create_list);
 
256
  List_iterator<CreateField> field_it(new_create_list);
264
257
  List<Key_part_spec> key_parts;
265
258
  uint32_t used_fields= create_info->used_fields;
266
259
  KeyInfo *key_info= table->key_info;
270
263
  message::Table::TableOptions *table_options;
271
264
  table_options= table_message.mutable_options();
272
265
 
273
 
  if (not (used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
 
266
  if (! (used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
274
267
    create_info->default_table_charset= table->getShare()->table_charset;
275
 
 
276
 
  if (not (used_fields & HA_CREATE_USED_AUTO) && table->found_next_number_field)
 
268
  if (! (used_fields & HA_CREATE_USED_AUTO) &&
 
269
      table->found_next_number_field)
277
270
  {
278
271
    /* Table has an autoincrement, copy value to new table */
279
272
    table->cursor->info(HA_STATUS_AUTO);
281
274
    if (create_info->auto_increment_value != original_proto.options().auto_increment_value())
282
275
      table_options->set_has_user_set_auto_increment_value(false);
283
276
  }
284
 
 
285
277
  table->restoreRecordAsDefault(); /* Empty record for DEFAULT */
286
278
  CreateField *def;
287
279
 
288
280
  /* First collect all fields from table which isn't in drop_list */
 
281
  Field **f_ptr;
289
282
  Field *field;
290
 
  for (Field **f_ptr= table->getFields(); (field= *f_ptr); f_ptr++)
 
283
  for (f_ptr= table->getFields(); (field= *f_ptr); f_ptr++)
291
284
  {
292
285
    /* Check if field should be dropped */
293
286
    AlterDrop *drop;
294
 
    drop_it= alter_info->drop_list.begin();
 
287
    drop_it.rewind();
295
288
    while ((drop= drop_it++))
296
289
    {
297
290
      if (drop->type == AlterDrop::COLUMN &&
307
300
        break;
308
301
      }
309
302
    }
310
 
 
311
303
    if (drop)
312
304
    {
313
305
      drop_it.remove();
318
310
    field->setReadSet();
319
311
 
320
312
    /* Check if field is changed */
321
 
    def_it= alter_info->create_list.begin();
 
313
    def_it.rewind();
322
314
    while ((def= def_it++))
323
315
    {
324
316
      if (def->change &&
325
317
          ! my_strcasecmp(system_charset_info, field->field_name, def->change))
326
318
              break;
327
319
    }
328
 
 
329
320
    if (def)
330
321
    {
331
322
      /* Field is changed */
344
335
      */
345
336
      def= new CreateField(field, field);
346
337
      new_create_list.push_back(def);
347
 
      alter_it= alter_info->alter_list.begin(); /* Change default if ALTER */
 
338
      alter_it.rewind(); /* Change default if ALTER */
348
339
      AlterColumn *alter;
349
340
 
350
341
      while ((alter= alter_it++))
374
365
      }
375
366
    }
376
367
  }
377
 
 
378
 
  def_it= alter_info->create_list.begin();
 
368
  def_it.rewind();
379
369
  while ((def= def_it++)) /* Add new columns */
380
370
  {
381
371
    if (def->change && ! def->field)
401
391
    else
402
392
    {
403
393
      CreateField *find;
404
 
      find_it= new_create_list.begin();
405
 
 
 
394
      find_it.rewind();
406
395
      while ((find= find_it++)) /* Add new columns */
407
396
      {
408
 
        if (not my_strcasecmp(system_charset_info,def->after, find->field_name))
 
397
        if (! my_strcasecmp(system_charset_info,def->after, find->field_name))
409
398
          break;
410
399
      }
411
 
 
412
 
      if (not find)
 
400
      if (! find)
413
401
      {
414
402
        my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table->getMutableShare()->getTableName());
415
403
        return true;
416
404
      }
417
 
 
418
405
      find_it.after(def); /* Put element after this */
419
 
 
420
406
      /*
421
407
        XXX: hack for Bug#28427.
422
408
        If column order has changed, force OFFLINE ALTER Table
429
415
      */
430
416
      if (alter_info->build_method == HA_BUILD_ONLINE)
431
417
      {
432
 
        my_error(*session->getQueryString(), ER_NOT_SUPPORTED_YET);
 
418
        my_error(ER_NOT_SUPPORTED_YET, MYF(0), session->getQueryString()->c_str());
433
419
        return true;
434
420
      }
435
 
 
436
421
      alter_info->build_method= HA_BUILD_OFFLINE;
437
422
    }
438
423
  }
439
 
 
440
424
  if (alter_info->alter_list.elements)
441
425
  {
442
426
    my_error(ER_BAD_FIELD_ERROR,
445
429
             table->getMutableShare()->getTableName());
446
430
    return true;
447
431
  }
448
 
 
449
 
  if (not new_create_list.elements)
 
432
  if (! new_create_list.elements)
450
433
  {
451
434
    my_message(ER_CANT_REMOVE_ALL_FIELDS,
452
435
               ER(ER_CANT_REMOVE_ALL_FIELDS),
462
445
  {
463
446
    char *key_name= key_info->name;
464
447
    AlterDrop *drop;
465
 
 
466
 
    drop_it= alter_info->drop_list.begin();
 
448
    drop_it.rewind();
467
449
    while ((drop= drop_it++))
468
450
    {
469
451
      if (drop->type == AlterDrop::KEY &&
470
452
          ! my_strcasecmp(system_charset_info, key_name, drop->name))
471
453
        break;
472
454
    }
473
 
 
474
455
    if (drop)
475
456
    {
476
457
      drop_it.remove();
478
459
    }
479
460
 
480
461
    KeyPartInfo *key_part= key_info->key_part;
481
 
    key_parts.clear();
 
462
    key_parts.empty();
482
463
    for (uint32_t j= 0; j < key_info->key_parts; j++, key_part++)
483
464
    {
484
465
      if (! key_part->field)
486
467
 
487
468
      const char *key_part_name= key_part->field->field_name;
488
469
      CreateField *cfield;
489
 
      field_it= new_create_list.begin();
 
470
      field_it.rewind();
490
471
      while ((cfield= field_it++))
491
472
      {
492
473
        if (cfield->change)
493
474
        {
494
 
          if (not my_strcasecmp(system_charset_info, key_part_name, cfield->change))
 
475
          if (! my_strcasecmp(system_charset_info, key_part_name, cfield->change))
495
476
            break;
496
477
        }
497
 
        else if (not my_strcasecmp(system_charset_info, key_part_name, cfield->field_name))
 
478
        else if (! my_strcasecmp(system_charset_info, key_part_name, cfield->field_name))
498
479
          break;
499
480
      }
500
 
 
501
 
      if (not cfield)
 
481
      if (! cfield)
502
482
              continue; /* Field is removed */
503
483
      
504
484
      uint32_t key_part_length= key_part->length;
530
510
    }
531
511
    if (key_parts.elements)
532
512
    {
533
 
      key_create_information_st key_create_info= default_key_create_info;
 
513
      KEY_CREATE_INFO key_create_info;
534
514
      Key *key;
535
 
      Key::Keytype key_type;
 
515
      enum Key::Keytype key_type;
 
516
      memset(&key_create_info, 0, sizeof(key_create_info));
536
517
 
537
518
      key_create_info.algorithm= key_info->algorithm;
538
 
 
539
519
      if (key_info->flags & HA_USES_BLOCK_SIZE)
540
520
        key_create_info.block_size= key_info->block_size;
541
 
 
542
521
      if (key_info->flags & HA_USES_COMMENT)
543
522
        key_create_info.comment= key_info->comment;
544
523
 
550
529
          key_type= Key::UNIQUE;
551
530
      }
552
531
      else
553
 
      {
554
532
        key_type= Key::MULTIPLE;
555
 
      }
556
533
 
557
534
      key= new Key(key_type,
558
535
                   key_name,
565
542
  }
566
543
 
567
544
  /* Copy over existing foreign keys */
568
 
  for (int32_t j= 0; j < original_proto.fk_constraint_size(); j++)
 
545
  for (int j= 0; j < original_proto.fk_constraint_size(); j++)
569
546
  {
570
547
    AlterDrop *drop;
571
 
    drop_it= alter_info->drop_list.begin();
 
548
    drop_it.rewind();
572
549
    while ((drop= drop_it++))
573
550
    {
574
551
      if (drop->type == AlterDrop::FOREIGN_KEY &&
657
634
 
658
635
  if (not table_message.options().has_comment()
659
636
      && table->getMutableShare()->hasComment())
660
 
  {
661
637
    table_options->set_comment(table->getMutableShare()->getComment());
662
 
  }
663
638
 
664
639
  if (table->getShare()->getType())
665
640
  {
666
641
    table_message.set_type(message::Table::TEMPORARY);
667
642
  }
668
643
 
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());
 
644
  table_message.set_creation_timestamp(table->getShare()->getTableProto()->creation_timestamp());
 
645
  table_message.set_version(table->getShare()->getTableProto()->version());
 
646
  table_message.set_uuid(table->getShare()->getTableProto()->uuid());
672
647
 
673
648
  rc= false;
674
649
  alter_info->create_list.swap(new_create_list);
709
684
{
710
685
  Table *table;
711
686
  bool discard;
 
687
  int error;
712
688
 
713
689
  /*
714
690
    Note that DISCARD/IMPORT TABLESPACE always is the only operation in an
715
691
    ALTER Table
716
692
  */
 
693
 
717
694
  TransactionServices &transaction_services= TransactionServices::singleton();
718
695
  session->set_proc_info("discard_or_import_tablespace");
719
696
 
723
700
   We set this flag so that ha_innobase::open and ::external_lock() do
724
701
   not complain when we lock the table
725
702
 */
726
 
  session->setDoingTablespaceOperation(true);
727
 
  if (not (table= session->openTableLock(table_list, TL_WRITE)))
 
703
  session->tablespace_op= true;
 
704
  if (!(table= session->openTableLock(table_list, TL_WRITE)))
728
705
  {
729
 
    session->setDoingTablespaceOperation(false);
 
706
    session->tablespace_op= false;
730
707
    return -1;
731
708
  }
732
709
 
733
 
  int error;
734
 
  do {
735
 
    error= table->cursor->ha_discard_or_import_tablespace(discard);
736
 
 
737
 
    session->set_proc_info("end");
738
 
 
739
 
    if (error)
740
 
      break;
741
 
 
742
 
    /* The ALTER Table is always in its own transaction */
743
 
    error= transaction_services.autocommitOrRollback(*session, false);
744
 
    if (not session->endActiveTransaction())
745
 
      error= 1;
746
 
 
747
 
    if (error)
748
 
      break;
749
 
 
750
 
    write_bin_log(session, *session->getQueryString());
751
 
 
752
 
  } while(0);
753
 
 
754
 
  (void) transaction_services.autocommitOrRollback(*session, error);
755
 
  session->setDoingTablespaceOperation(false);
 
710
  error= table->cursor->ha_discard_or_import_tablespace(discard);
 
711
 
 
712
  session->set_proc_info("end");
 
713
 
 
714
  if (error)
 
715
    goto err;
 
716
 
 
717
  /* The ALTER Table is always in its own transaction */
 
718
  error= transaction_services.autocommitOrRollback(session, false);
 
719
  if (not session->endActiveTransaction())
 
720
    error=1;
 
721
 
 
722
  if (error)
 
723
    goto err;
 
724
 
 
725
  write_bin_log(session, *session->getQueryString());
 
726
 
 
727
err:
 
728
  (void) transaction_services.autocommitOrRollback(session, error);
 
729
  session->tablespace_op=false;
756
730
 
757
731
  if (error == 0)
758
732
  {
802
776
                        ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
803
777
                        table->getMutableShare()->getTableName());
804
778
    error= 0;
805
 
  }
806
 
  else if (error)
807
 
  {
 
779
  } else if (error)
808
780
    table->print_error(error, MYF(0));
809
 
  }
810
781
 
811
782
  return(error);
812
783
}
813
784
 
814
785
static bool lockTableIfDifferent(Session &session,
815
 
                                 identifier::Table &original_table_identifier,
816
 
                                 identifier::Table &new_table_identifier,
 
786
                                 TableIdentifier &original_table_identifier,
 
787
                                 TableIdentifier &new_table_identifier,
817
788
                                 Table *name_lock)
818
789
{
819
790
  /* Check that we are not trying to rename to an existing table */
824
795
 
825
796
      if (session.find_temporary_table(new_table_identifier))
826
797
      {
827
 
        my_error(ER_TABLE_EXISTS_ERROR, new_table_identifier);
 
798
        std::string path;
 
799
        new_table_identifier.getSQLPath(path);
 
800
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
828
801
        return false;
829
802
      }
830
803
    }
837
810
 
838
811
      if (not name_lock)
839
812
      {
840
 
        my_error(ER_TABLE_EXISTS_ERROR, new_table_identifier);
 
813
        std::string path;
 
814
        new_table_identifier.getSQLPath(path);
 
815
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
841
816
        return false;
842
817
      }
843
818
 
844
819
      if (plugin::StorageEngine::doesTableExist(session, new_table_identifier))
845
820
      {
 
821
        std::string path;
 
822
        new_table_identifier.getSQLPath(path);
 
823
 
846
824
        /* Table will be closed by Session::executeCommand() */
847
 
        my_error(ER_TABLE_EXISTS_ERROR, new_table_identifier);
 
825
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
848
826
 
849
 
        {
850
 
          boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex());
851
 
          session.unlink_open_table(name_lock);
852
 
        }
 
827
        table::Cache::singleton().mutex().lock(); /* ALTER TABLe */
 
828
        session.unlink_open_table(name_lock);
 
829
        table::Cache::singleton().mutex().unlock();
853
830
 
854
831
        return false;
855
832
      }
903
880
 
904
881
static bool internal_alter_table(Session *session,
905
882
                                 Table *table,
906
 
                                 identifier::Table &original_table_identifier,
907
 
                                 identifier::Table &new_table_identifier,
 
883
                                 TableIdentifier &original_table_identifier,
 
884
                                 TableIdentifier &new_table_identifier,
908
885
                                 HA_CREATE_INFO *create_info,
909
886
                                 const message::Table &original_proto,
910
887
                                 message::Table &create_proto,
961
938
  if (original_engine->check_flag(HTON_BIT_ALTER_NOT_SUPPORTED) ||
962
939
      new_engine->check_flag(HTON_BIT_ALTER_NOT_SUPPORTED))
963
940
  {
964
 
    my_error(ER_ILLEGAL_HA, new_table_identifier);
 
941
    std::string path;
 
942
    new_table_identifier.getSQLPath(path);
 
943
    my_error(ER_ILLEGAL_HA, MYF(0), path.c_str());
965
944
 
966
945
    return true;
967
946
  }
979
958
    tmp.reset(ALTER_KEYS_ONOFF);
980
959
    tmp&= alter_info->flags;
981
960
 
982
 
    if (not (tmp.any()) && not table->getShare()->getType()) // no need to touch frm
 
961
    if (! (tmp.any()) && ! table->getShare()->getType()) // no need to touch frm
983
962
    {
984
963
      switch (alter_info->keys_onoff)
985
964
      {
986
965
      case LEAVE_AS_IS:
987
966
        break;
988
 
 
989
967
      case ENABLE:
990
968
        /*
991
969
          wait_while_table_is_used() ensures that table being altered is
996
974
          while the fact that the table is still open gives us protection
997
975
          from concurrent DDL statements.
998
976
        */
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
 
        }
 
977
        table::Cache::singleton().mutex().lock(); /* DDL wait for/blocker */
 
978
        wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
 
979
        table::Cache::singleton().mutex().unlock();
1003
980
        error= table->cursor->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
1004
 
 
1005
981
        /* COND_refresh will be signaled in close_thread_tables() */
1006
982
        break;
1007
 
 
1008
983
      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
 
 
 
984
        table::Cache::singleton().mutex().lock(); /* DDL wait for/blocker */
 
985
        wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
 
986
        table::Cache::singleton().mutex().unlock();
 
987
        error=table->cursor->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
1015
988
        /* COND_refresh will be signaled in close_thread_tables() */
1016
989
        break;
 
990
      default:
 
991
        assert(false);
 
992
        error= 0;
 
993
        break;
1017
994
      }
1018
995
 
1019
996
      if (error == HA_ERR_WRONG_COMMAND)
1020
997
      {
1021
 
        error= EE_OK;
 
998
        error= 0;
1022
999
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1023
1000
                            ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
1024
1001
                            table->getAlias());
1025
1002
      }
1026
1003
 
1027
 
      boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex()); /* Lock to remove all instances of table from table cache before ALTER */
 
1004
      table::Cache::singleton().mutex().lock(); /* Lock to remove all instances of table from table cache before ALTER */
1028
1005
      /*
1029
1006
        Unlike to the above case close_cached_table() below will remove ALL
1030
1007
        instances of Table from table cache (it will also remove table lock
1034
1011
        access() and rename_table() calls.
1035
1012
      */
1036
1013
 
1037
 
      if (not error &&  not (original_table_identifier == new_table_identifier))
 
1014
      if (error == 0 &&  not (original_table_identifier == new_table_identifier))
1038
1015
      {
1039
1016
        session->set_proc_info("rename");
1040
1017
        /*
1052
1029
        */
1053
1030
        if (plugin::StorageEngine::doesTableExist(*session, new_table_identifier))
1054
1031
        {
1055
 
          my_error(ER_TABLE_EXISTS_ERROR, new_table_identifier);
 
1032
          std::string path;
 
1033
          new_table_identifier.getSQLPath(path);
 
1034
          my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
1056
1035
          error= -1;
1057
1036
        }
1058
1037
        else
1066
1045
 
1067
1046
      if (error == HA_ERR_WRONG_COMMAND)
1068
1047
      {
1069
 
        error= EE_OK;
 
1048
        error= 0;
1070
1049
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1071
1050
                            ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
1072
1051
                            table->getAlias());
1073
1052
      }
1074
1053
 
1075
 
      if (not error)
 
1054
      if (error == 0)
1076
1055
      {
1077
1056
        TransactionServices &transaction_services= TransactionServices::singleton();
1078
1057
        transaction_services.allocateNewTransactionId();
1079
1058
        write_bin_log(session, *session->getQueryString());
1080
1059
        session->my_ok();
1081
1060
      }
1082
 
      else if (error > EE_OK) // If we have already set the error, we pass along -1
 
1061
      else if (error > 0)
1083
1062
      {
1084
1063
        table->print_error(error, MYF(0));
 
1064
        error= -1;
1085
1065
      }
1086
1066
 
 
1067
      table::Cache::singleton().mutex().unlock();
1087
1068
      table_list->table= NULL;
1088
1069
 
1089
1070
      return error;
1110
1091
    case we just use it as is. Neither of these tables require locks in order to  be
1111
1092
    filled.
1112
1093
  */
1113
 
  identifier::Table new_table_as_temporary(original_table_identifier.getSchemaName(),
 
1094
  TableIdentifier new_table_as_temporary(original_table_identifier.getSchemaName(),
1114
1095
                                         tmp_name,
1115
1096
                                         create_proto.type() != message::Table::TEMPORARY ? message::Table::INTERNAL :
1116
1097
                                         message::Table::TEMPORARY);
1117
1098
 
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);
 
1099
  error= create_temporary_table(session, new_table_as_temporary, create_info, create_proto, alter_info);
1128
1100
 
1129
1101
  if (error != 0)
1130
1102
  {
1174
1146
  {
1175
1147
 
1176
1148
    /*
1177
 
      No default value was provided for new fields.
 
1149
      No default value was provided for a DATE/DATETIME field, the
 
1150
      current sql_mode doesn't allow the '0000-00-00' value and
 
1151
      the table to be altered isn't empty.
 
1152
      Report error here.
1178
1153
    */
1179
1154
    if (alter_info->error_if_not_empty && session->row_count)
1180
1155
    {
1212
1187
        delete new_table;
1213
1188
      }
1214
1189
 
1215
 
      boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex());
 
1190
      table::Cache::singleton().mutex().lock(); /* ALTER TABLE */
1216
1191
 
1217
1192
      plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
 
1193
      table::Cache::singleton().mutex().unlock();
1218
1194
 
1219
1195
      return true;
1220
1196
    }
1261
1237
      delete new_table;
1262
1238
    }
1263
1239
 
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))
 
1240
    table::Cache::singleton().mutex().lock(); /* ALTER TABLE */
 
1241
 
 
1242
    /*
 
1243
      Data is copied. Now we:
 
1244
      1) Wait until all other threads close old version of table.
 
1245
      2) Close instances of table open by this thread and replace them
 
1246
      with exclusive name-locks.
 
1247
      3) Rename the old table to a temp name, rename the new one to the
 
1248
      old name.
 
1249
      4) If we are under LOCK TABLES and don't do ALTER Table ... RENAME
 
1250
      we reopen new version of table.
 
1251
      5) Write statement to the binary log.
 
1252
      6) If we are under LOCK TABLES and do ALTER Table ... RENAME we
 
1253
      remove name-locks from list of open tables and table cache.
 
1254
      7) If we are not not under LOCK TABLES we rely on close_thread_tables()
 
1255
      call to remove name-locks from table cache and list of open table.
 
1256
    */
 
1257
 
 
1258
    session->set_proc_info("rename result table");
 
1259
 
 
1260
    snprintf(old_name, sizeof(old_name), "%s2-%lx-%"PRIx64, TMP_FILE_PREFIX, (unsigned long) current_pid, session->thread_id);
 
1261
 
 
1262
    my_casedn_str(files_charset_info, old_name);
 
1263
 
 
1264
    wait_while_table_is_used(session, table, HA_EXTRA_PREPARE_FOR_RENAME);
 
1265
    session->close_data_files_and_morph_locks(original_table_identifier);
 
1266
 
 
1267
    error= 0;
 
1268
 
 
1269
    /*
 
1270
      This leads to the storage engine (SE) not being notified for renames in
 
1271
      rename_table(), because we just juggle with the FRM and nothing
 
1272
      more. If we have an intermediate table, then we notify the SE that
 
1273
      it should become the actual table. Later, we will recycle the old table.
 
1274
      However, in case of ALTER Table RENAME there might be no intermediate
 
1275
      table. This is when the old and new tables are compatible, according to
 
1276
      compare_table(). Then, we need one additional call to
 
1277
    */
 
1278
    TableIdentifier original_table_to_drop(original_table_identifier.getSchemaName(),
 
1279
                                           old_name, create_proto.type() != message::Table::TEMPORARY ? message::Table::INTERNAL :
 
1280
                                         message::Table::TEMPORARY);
 
1281
 
 
1282
    if (rename_table(*session, original_engine, original_table_identifier, original_table_to_drop))
 
1283
    {
 
1284
      error= 1;
 
1285
      plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
 
1286
    }
 
1287
    else
 
1288
    {
 
1289
      if (rename_table(*session, new_engine, new_table_as_temporary, new_table_identifier) != 0)
1308
1290
      {
1309
 
        error= ER_ERROR_ON_RENAME;
 
1291
        /* Try to get everything back. */
 
1292
        error= 1;
 
1293
 
 
1294
        plugin::StorageEngine::dropTable(*session, new_table_identifier);
 
1295
 
1310
1296
        plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
 
1297
 
 
1298
        rename_table(*session, original_engine, original_table_to_drop, original_table_identifier);
1311
1299
      }
1312
1300
      else
1313
1301
      {
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
 
    }
 
1302
        plugin::StorageEngine::dropTable(*session, original_table_to_drop);
 
1303
      }
 
1304
    }
 
1305
 
 
1306
    if (error)
 
1307
    {
 
1308
      /*
 
1309
        An error happened while we were holding exclusive name-lock on table
 
1310
        being altered. To be safe under LOCK TABLES we should remove placeholders
 
1311
        from list of open tables list and table cache.
 
1312
      */
 
1313
      session->unlink_open_table(table);
 
1314
      table::Cache::singleton().mutex().unlock();
 
1315
 
 
1316
      return true;
 
1317
    }
 
1318
 
 
1319
    table::Cache::singleton().mutex().unlock();
1343
1320
 
1344
1321
    session->set_proc_info("end");
1345
1322
 
1362
1339
           (ulong) (copied + deleted), (ulong) deleted,
1363
1340
           (ulong) session->cuted_fields);
1364
1341
  session->my_ok(copied + deleted, 0, 0L, tmp_name);
1365
 
  session->some_tables_deleted= false;
 
1342
  session->some_tables_deleted= 0;
1366
1343
 
1367
1344
  return false;
1368
1345
}
1369
1346
 
1370
1347
bool alter_table(Session *session,
1371
 
                 identifier::Table &original_table_identifier,
1372
 
                 identifier::Table &new_table_identifier,
 
1348
                 TableIdentifier &original_table_identifier,
 
1349
                 TableIdentifier &new_table_identifier,
1373
1350
                 HA_CREATE_INFO *create_info,
1374
1351
                 const message::Table &original_proto,
1375
1352
                 message::Table &create_proto,
1422
1399
 
1423
1400
    if (name_lock)
1424
1401
    {
1425
 
      boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex());
 
1402
      table::Cache::singleton().mutex().lock(); /* ALTER TABLe */
1426
1403
      session->unlink_open_table(name_lock);
 
1404
      table::Cache::singleton().mutex().unlock();
1427
1405
    }
1428
1406
  }
1429
1407
 
1482
1460
  alter_table_manage_keys(session, to, from->cursor->indexes_are_disabled(), keys_onoff);
1483
1461
 
1484
1462
  /* We can abort alter table for any table type */
1485
 
  session->setAbortOnWarning(not ignore);
 
1463
  session->abort_on_warning= !ignore;
1486
1464
 
1487
1465
  from->cursor->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
1488
1466
  to->cursor->ha_start_bulk_insert(from->cursor->stats.records);
1489
1467
 
1490
 
  List<CreateField>::iterator it(create.begin());
 
1468
  List_iterator<CreateField> it(create);
1491
1469
  CreateField *def;
1492
 
  copy_end= copy;
 
1470
  copy_end=copy;
1493
1471
  for (Field **ptr= to->getFields(); *ptr ; ptr++)
1494
1472
  {
1495
1473
    def=it++;
1505
1483
 
1506
1484
  found_count=delete_count=0;
1507
1485
 
1508
 
  do
 
1486
  if (order)
1509
1487
  {
1510
 
    if (order)
1511
 
    {
1512
 
      if (to->getShare()->hasPrimaryKey() && to->cursor->primary_key_is_clustered())
 
1488
    if (to->getShare()->hasPrimaryKey() && to->cursor->primary_key_is_clustered())
 
1489
    {
 
1490
      char warn_buff[DRIZZLE_ERRMSG_SIZE];
 
1491
      snprintf(warn_buff, sizeof(warn_buff),
 
1492
               _("order_st BY ignored because there is a user-defined clustered "
 
1493
                 "index in the table '%-.192s'"),
 
1494
               from->getMutableShare()->getTableName());
 
1495
      push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
 
1496
                   warn_buff);
 
1497
    }
 
1498
    else
 
1499
    {
 
1500
      FileSort filesort(*session);
 
1501
      from->sort.io_cache= new internal::IO_CACHE;
 
1502
 
 
1503
      memset(&tables, 0, sizeof(tables));
 
1504
      tables.table= from;
 
1505
      tables.setTableName(const_cast<char *>(from->getMutableShare()->getTableName()));
 
1506
      tables.alias= const_cast<char *>(tables.getTableName());
 
1507
      tables.setSchemaName(const_cast<char *>(from->getMutableShare()->getSchemaName()));
 
1508
      error= 1;
 
1509
 
 
1510
      if (session->lex->select_lex.setup_ref_array(session, order_num) ||
 
1511
          setup_order(session, session->lex->select_lex.ref_pointer_array,
 
1512
                      &tables, fields, all_fields, order) ||
 
1513
          !(sortorder= make_unireg_sortorder(order, &length, NULL)) ||
 
1514
          (from->sort.found_records= filesort.run(from, sortorder, length,
 
1515
                                                  (optimizer::SqlSelect *) 0, HA_POS_ERROR,
 
1516
                                                  1, examined_rows)) == HA_POS_ERROR)
1513
1517
      {
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);
 
1518
        goto err;
1521
1519
      }
 
1520
    }
 
1521
  }
 
1522
 
 
1523
  /* Tell handler that we have values for all columns in the to table */
 
1524
  to->use_all_columns();
 
1525
  info.init_read_record(session, from, (optimizer::SqlSelect *) 0, 1, true);
 
1526
  if (ignore)
 
1527
    to->cursor->extra(HA_EXTRA_IGNORE_DUP_KEY);
 
1528
  session->row_count= 0;
 
1529
  to->restoreRecordAsDefault();        // Create empty record
 
1530
  while (!(error=info.read_record(&info)))
 
1531
  {
 
1532
    if (session->getKilled())
 
1533
    {
 
1534
      session->send_kill_message();
 
1535
      error= 1;
 
1536
      break;
 
1537
    }
 
1538
    session->row_count++;
 
1539
    /* Return error if source table isn't empty. */
 
1540
    if (error_if_not_empty)
 
1541
    {
 
1542
      error= 1;
 
1543
      break;
 
1544
    }
 
1545
    if (to->next_number_field)
 
1546
    {
 
1547
      if (auto_increment_field_copied)
 
1548
        to->auto_increment_field_not_null= true;
1522
1549
      else
 
1550
        to->next_number_field->reset();
 
1551
    }
 
1552
 
 
1553
    for (CopyField *copy_ptr= copy; copy_ptr != copy_end ; copy_ptr++)
 
1554
    {
 
1555
      if (not copy->to_field->hasDefault() and copy->from_null_ptr and  *copy->from_null_ptr & copy->from_bit)
1523
1556
      {
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()));
 
1557
        copy->to_field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
1558
                                    ER_WARN_DATA_TRUNCATED, 1);
 
1559
        copy->to_field->reset();
1531
1560
        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
 
        }
 
1561
        break;
1543
1562
      }
 
1563
 
 
1564
      copy_ptr->do_copy(copy_ptr);
1544
1565
    }
1545
1566
 
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
1567
    if (error)
1551
1568
    {
1552
 
      to->print_error(errno, MYF(0));
1553
 
 
1554
1569
      break;
1555
1570
    }
1556
1571
 
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)
 
1572
    prev_insert_id= to->cursor->next_insert_id;
 
1573
    error= to->cursor->insertRecord(to->record[0]);
 
1574
    to->auto_increment_field_not_null= false;
 
1575
 
 
1576
    if (error)
 
1577
    { 
 
1578
      if (!ignore || to->cursor->is_fatal_error(error, HA_CHECK_DUP))
1611
1579
      { 
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
 
      }
 
1580
        to->print_error(error, MYF(0));
 
1581
        break;
 
1582
      }
 
1583
      to->cursor->restore_auto_increment(prev_insert_id);
 
1584
      delete_count++;
1624
1585
    }
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)
 
1586
    else
1631
1587
    {
1632
 
      to->print_error(errno, MYF(0));
1633
 
      error= 1;
 
1588
      found_count++;
1634
1589
    }
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);
 
1590
  }
 
1591
 
 
1592
  info.end_read_record();
 
1593
  from->free_io_cache();
 
1594
  delete [] copy;                               // This is never 0
 
1595
 
 
1596
  if (to->cursor->ha_end_bulk_insert() && error <= 0)
 
1597
  {
 
1598
    to->print_error(errno, MYF(0));
 
1599
    error=1;
 
1600
  }
 
1601
  to->cursor->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
 
1602
 
 
1603
  /*
 
1604
    Ensure that the new table is saved properly to disk so that we
 
1605
    can do a rename
 
1606
  */
 
1607
  if (transaction_services.autocommitOrRollback(session, false))
 
1608
    error=1;
 
1609
  if (! session->endActiveTransaction())
 
1610
    error=1;
 
1611
 
 
1612
 err:
 
1613
  session->abort_on_warning= 0;
1650
1614
  from->free_io_cache();
1651
1615
  *copied= found_count;
1652
1616
  *deleted=delete_count;
1653
1617
  to->cursor->ha_release_auto_increment();
1654
 
 
1655
 
  if (to->cursor->ha_external_lock(session, F_UNLCK))
1656
 
  {
 
1618
  if (to->cursor->ha_external_lock(session,F_UNLCK))
1657
1619
    error=1;
1658
 
  }
1659
1620
 
1660
1621
  return(error > 0 ? -1 : 0);
1661
1622
}
1662
1623
 
1663
 
static Table *open_alter_table(Session *session, Table *table, identifier::Table &identifier)
 
1624
static int
 
1625
create_temporary_table(Session *session,
 
1626
                       TableIdentifier &identifier,
 
1627
                       HA_CREATE_INFO *create_info,
 
1628
                       message::Table &create_proto,
 
1629
                       AlterInfo *alter_info)
 
1630
{
 
1631
  int error;
 
1632
 
 
1633
  /*
 
1634
    Create a table with a temporary name.
 
1635
    We don't log the statement, it will be logged later.
 
1636
  */
 
1637
  create_proto.set_name(identifier.getTableName());
 
1638
 
 
1639
  create_proto.mutable_engine()->set_name(create_info->db_type->getName());
 
1640
 
 
1641
  error= create_table(session,
 
1642
                            identifier,
 
1643
                            create_info, create_proto, alter_info, true, 0, false);
 
1644
 
 
1645
  return error;
 
1646
}
 
1647
 
 
1648
static Table *open_alter_table(Session *session, Table *table, TableIdentifier &identifier)
1664
1649
{
1665
1650
  Table *new_table;
1666
1651