~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/statement/alter_table.cc

  • Committer: Padraig O'Sullivan
  • Date: 2010-02-10 16:26:01 UTC
  • mto: This revision was merged to the branch mainline in revision 1294.
  • Revision ID: osullivan.padraig@gmail.com-20100210162601-itx2ndl397pc1wr6
Corrected an order of initialization in a few optimizer classes

Show diffs side-by-side

added added

removed removed

Lines of Context:
35
35
#include "drizzled/data_home.h"
36
36
#include "drizzled/sql_table.h"
37
37
#include "drizzled/table_proto.h"
 
38
#include "drizzled/plugin/info_schema_table.h"
38
39
#include "drizzled/optimizer/range.h"
39
40
#include "drizzled/time_functions.h"
40
41
#include "drizzled/records.h"
44
45
 
45
46
#include "drizzled/transaction_services.h"
46
47
 
47
 
#include "drizzled/filesort.h"
48
 
 
49
 
#include "drizzled/message.h"
50
 
 
51
48
using namespace std;
52
49
 
53
50
namespace drizzled
55
52
 
56
53
extern pid_t current_pid;
57
54
 
58
 
static int copy_data_between_tables(Session *session,
59
 
                                    Table *from,Table *to,
 
55
static int copy_data_between_tables(Table *from,Table *to,
60
56
                                    List<CreateField> &create,
61
57
                                    bool ignore,
62
58
                                    uint32_t order_num,
63
 
                                    Order *order,
 
59
                                    order_st *order,
64
60
                                    ha_rows *copied,
65
61
                                    ha_rows *deleted,
66
62
                                    enum enum_enable_or_disable keys_onoff,
69
65
static bool mysql_prepare_alter_table(Session *session,
70
66
                                      Table *table,
71
67
                                      HA_CREATE_INFO *create_info,
72
 
                                      const message::Table &original_proto,
73
 
                                      message::Table &table_message,
 
68
                                      message::Table *table_proto,
74
69
                                      AlterInfo *alter_info);
75
70
 
76
71
static int create_temporary_table(Session *session,
 
72
                                  Table *table,
77
73
                                  TableIdentifier &identifier,
78
74
                                  HA_CREATE_INFO *create_info,
79
 
                                  message::Table &create_message,
 
75
                                  message::Table *create_proto,
80
76
                                  AlterInfo *alter_info);
81
77
 
82
 
static Table *open_alter_table(Session *session, Table *table, TableIdentifier &identifier);
 
78
static Table *open_alter_table(Session *session, Table *table, char *db, char *table_name);
83
79
 
84
80
bool statement::AlterTable::execute()
85
81
{
92
88
  if (is_engine_set)
93
89
  {
94
90
    create_info.db_type= 
95
 
      plugin::StorageEngine::findByName(*session, create_table_message.engine().name());
 
91
      plugin::StorageEngine::findByName(*session, create_table_proto.engine().name());
96
92
 
97
93
    if (create_info.db_type == NULL)
98
94
    {
99
95
      my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), 
100
 
               create_table_message.engine().name().c_str());
 
96
               create_table_proto.name().c_str());
101
97
 
102
98
      return true;
103
99
    }
106
102
  /* Must be set in the parser */
107
103
  assert(select_lex->db);
108
104
 
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 */
110
 
  message::table::shared_ptr original_table_message;
111
 
  {
112
 
    TableIdentifier identifier(first_table->getSchemaName(), first_table->getTableName());
113
 
    if (plugin::StorageEngine::getTableDefinition(*session, identifier, original_table_message) != EEXIST)
114
 
    {
115
 
      std::string path;
116
 
      identifier.getSQLPath(path);
117
 
      my_error(ER_BAD_TABLE_ERROR, MYF(0), path.c_str());
118
 
      return true;
119
 
    }
120
 
 
121
 
    if (not  create_info.db_type)
122
 
    {
123
 
      create_info.db_type= 
124
 
        plugin::StorageEngine::findByName(*session, original_table_message->engine().name());
125
 
 
126
 
      if (not create_info.db_type)
127
 
      {
128
 
        std::string path;
129
 
        identifier.getSQLPath(path);
130
 
        my_error(ER_BAD_TABLE_ERROR, MYF(0), path.c_str());
131
 
        return true;
132
 
      }
133
 
    }
134
 
  }
135
 
 
136
 
  if (not validateCreateTableOption())
137
 
    return true;
138
 
 
139
105
  /* ALTER TABLE ends previous transaction */
140
 
  if (not session->endActiveTransaction())
141
 
    return true;
142
 
 
143
 
  if (not (need_start_waiting= not session->wait_if_global_read_lock(0, 1)))
144
 
    return true;
145
 
 
146
 
  bool res;
147
 
  if (original_table_message->type() == message::Table::STANDARD )
148
 
  {
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());
152
 
 
153
 
    res= alter_table(session, 
154
 
                     identifier,
155
 
                     new_identifier,
156
 
                     &create_info,
157
 
                     *original_table_message,
158
 
                     create_table_message,
159
 
                     first_table,
160
 
                     &alter_info,
161
 
                     select_lex->order_list.elements,
162
 
                     (Order *) select_lex->order_list.first,
163
 
                     session->lex->ignore);
164
 
  }
165
 
  else
166
 
  {
167
 
    TableIdentifier catch22(first_table->getSchemaName(), first_table->getTableName());
168
 
    Table *table= session->find_temporary_table(catch22);
169
 
    assert(table);
170
 
    {
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());
175
 
 
176
 
      res= alter_table(session, 
177
 
                       identifier,
178
 
                       new_identifier,
179
 
                       &create_info,
180
 
                       *original_table_message,
181
 
                       create_table_message,
182
 
                       first_table,
183
 
                       &alter_info,
184
 
                       select_lex->order_list.elements,
185
 
                       (Order *) select_lex->order_list.first,
186
 
                       session->lex->ignore);
187
 
    }
188
 
  }
189
 
 
 
106
  if (! session->endActiveTransaction())
 
107
  {
 
108
    return true;
 
109
  }
 
110
 
 
111
  if (! (need_start_waiting= ! wait_if_global_read_lock(session, 0, 1)))
 
112
  {
 
113
    return true;
 
114
  }
 
115
 
 
116
  bool res= alter_table(session, 
 
117
                        select_lex->db, 
 
118
                        session->lex->name.str,
 
119
                        &create_info,
 
120
                        &create_table_proto,
 
121
                        first_table,
 
122
                        &alter_info,
 
123
                        select_lex->order_list.elements,
 
124
                        (order_st *) select_lex->order_list.first,
 
125
                        session->lex->ignore);
190
126
  /*
191
127
     Release the protection against the global read lock and wake
192
128
     everyone, who might want to set a global read lock.
193
129
   */
194
 
  session->startWaitingGlobalReadLock();
195
 
 
 
130
  start_waiting_global_read_lock(session);
196
131
  return res;
197
132
}
198
133
 
240
175
static bool mysql_prepare_alter_table(Session *session,
241
176
                                      Table *table,
242
177
                                      HA_CREATE_INFO *create_info,
243
 
                                      const message::Table &original_proto,
244
 
                                      message::Table &table_message,
 
178
                                      message::Table *table_proto,
245
179
                                      AlterInfo *alter_info)
246
180
{
247
181
  /* New column definitions are added here */
256
190
  List_iterator<CreateField> field_it(new_create_list);
257
191
  List<Key_part_spec> key_parts;
258
192
  uint32_t used_fields= create_info->used_fields;
259
 
  KeyInfo *key_info= table->key_info;
 
193
  KEY *key_info= table->key_info;
260
194
  bool rc= true;
261
195
 
262
196
  /* Let new create options override the old ones */
263
197
  message::Table::TableOptions *table_options;
264
 
  table_options= table_message.mutable_options();
 
198
  table_options= table_proto->mutable_options();
265
199
 
 
200
  if (! (used_fields & HA_CREATE_USED_BLOCK_SIZE))
 
201
    table_options->set_block_size(table->s->block_size);
266
202
  if (! (used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
267
 
    create_info->default_table_charset= table->getShare()->table_charset;
 
203
    create_info->default_table_charset= table->s->table_charset;
268
204
  if (! (used_fields & HA_CREATE_USED_AUTO) &&
269
205
      table->found_next_number_field)
270
206
  {
271
207
    /* Table has an autoincrement, copy value to new table */
272
208
    table->cursor->info(HA_STATUS_AUTO);
273
209
    create_info->auto_increment_value= table->cursor->stats.auto_increment_value;
274
 
    if (create_info->auto_increment_value != original_proto.options().auto_increment_value())
275
 
      table_options->set_has_user_set_auto_increment_value(false);
276
210
  }
 
211
  if (! (used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE)
 
212
      && table->s->hasKeyBlockSize())
 
213
    table_options->set_key_block_size(table->s->getKeyBlockSize());
 
214
 
 
215
  if ((used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE)
 
216
      && table_options->key_block_size() == 0)
 
217
    table_options->clear_key_block_size();
 
218
 
277
219
  table->restoreRecordAsDefault(); /* Empty record for DEFAULT */
278
220
  CreateField *def;
279
221
 
280
222
  /* First collect all fields from table which isn't in drop_list */
281
223
  Field **f_ptr;
282
224
  Field *field;
283
 
  for (f_ptr= table->getFields(); (field= *f_ptr); f_ptr++)
 
225
  for (f_ptr= table->field; (field= *f_ptr); f_ptr++)
284
226
  {
285
227
    /* Check if field should be dropped */
286
228
    AlterDrop *drop;
347
289
        if (def->sql_type == DRIZZLE_TYPE_BLOB)
348
290
        {
349
291
          my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), def->change);
350
 
          return true;
 
292
                goto err;
351
293
        }
352
294
        if ((def->def= alter->def))
353
295
        {
355
297
          def->flags&= ~NO_DEFAULT_VALUE_FLAG;
356
298
        }
357
299
        else
358
 
        {
359
300
          def->flags|= NO_DEFAULT_VALUE_FLAG;
360
 
        }
361
301
        alter_it.remove();
362
302
      }
363
303
    }
367
307
  {
368
308
    if (def->change && ! def->field)
369
309
    {
370
 
      my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table->getMutableShare()->getTableName());
371
 
      return true;
 
310
      my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table->s->table_name.str);
 
311
      goto err;
372
312
    }
373
313
    /*
374
 
      If we have been given a field which has no default value, and is not null then we need to bail.
 
314
      Check that the DATE/DATETIME not null field we are going to add is
 
315
      either has a default value or the '0000-00-00' is allowed by the
 
316
      set sql mode.
 
317
      If the '0000-00-00' value isn't allowed then raise the error_if_not_empty
 
318
      flag to allow ALTER Table only if the table to be altered is empty.
375
319
    */
376
 
    if (not (~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) and not def->change)
 
320
    if ((def->sql_type == DRIZZLE_TYPE_DATE ||
 
321
         def->sql_type == DRIZZLE_TYPE_DATETIME) &&
 
322
        ! alter_info->datetime_field &&
 
323
        ! (~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) &&
 
324
        session->variables.sql_mode & MODE_NO_ZERO_DATE)
377
325
    {
 
326
      alter_info->datetime_field= def;
378
327
      alter_info->error_if_not_empty= true;
379
328
    }
380
329
    if (! def->after)
381
 
    {
382
330
      new_create_list.push_back(def);
383
 
    }
384
331
    else if (def->after == first_keyword)
385
 
    {
386
332
      new_create_list.push_front(def);
387
 
    }
388
333
    else
389
334
    {
390
335
      CreateField *find;
396
341
      }
397
342
      if (! find)
398
343
      {
399
 
        my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table->getMutableShare()->getTableName());
400
 
        return true;
 
344
        my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table->s->table_name.str);
 
345
        goto err;
401
346
      }
402
347
      find_it.after(def); /* Put element after this */
403
348
      /*
412
357
      */
413
358
      if (alter_info->build_method == HA_BUILD_ONLINE)
414
359
      {
415
 
        my_error(ER_NOT_SUPPORTED_YET, MYF(0), session->getQueryString()->c_str());
416
 
        return true;
 
360
        my_error(ER_NOT_SUPPORTED_YET, MYF(0), session->query);
 
361
        goto err;
417
362
      }
418
363
      alter_info->build_method= HA_BUILD_OFFLINE;
419
364
    }
423
368
    my_error(ER_BAD_FIELD_ERROR,
424
369
             MYF(0),
425
370
             alter_info->alter_list.head()->name,
426
 
             table->getMutableShare()->getTableName());
427
 
    return true;
 
371
             table->s->table_name.str);
 
372
    goto err;
428
373
  }
429
374
  if (! new_create_list.elements)
430
375
  {
431
376
    my_message(ER_CANT_REMOVE_ALL_FIELDS,
432
377
               ER(ER_CANT_REMOVE_ALL_FIELDS),
433
378
               MYF(0));
434
 
    return true;
 
379
    goto err;
435
380
  }
436
381
 
437
382
  /*
438
383
    Collect all keys which isn't in drop list. Add only those
439
384
    for which some fields exists.
440
385
  */
441
 
  for (uint32_t i= 0; i < table->getShare()->sizeKeys(); i++, key_info++)
 
386
  for (uint32_t i= 0; i < table->s->keys; i++, key_info++)
442
387
  {
443
388
    char *key_name= key_info->name;
444
389
    AlterDrop *drop;
455
400
      continue;
456
401
    }
457
402
 
458
 
    KeyPartInfo *key_part= key_info->key_part;
 
403
    KEY_PART_INFO *key_part= key_info->key_part;
459
404
    key_parts.empty();
460
405
    for (uint32_t j= 0; j < key_info->key_parts; j++, key_part++)
461
406
    {
537
482
      new_key_list.push_back(key);
538
483
    }
539
484
  }
540
 
 
541
 
  /* Copy over existing foreign keys */
542
 
  for (int j= 0; j < original_proto.fk_constraint_size(); j++)
543
 
  {
544
 
    AlterDrop *drop;
545
 
    drop_it.rewind();
546
 
    while ((drop= drop_it++))
547
 
    {
548
 
      if (drop->type == AlterDrop::FOREIGN_KEY &&
549
 
          ! my_strcasecmp(system_charset_info, original_proto.fk_constraint(j).name().c_str(), drop->name))
550
 
      {
551
 
        break;
552
 
      }
553
 
    }
554
 
    if (drop)
555
 
    {
556
 
      drop_it.remove();
557
 
      continue;
558
 
    }
559
 
 
560
 
    message::Table::ForeignKeyConstraint *pfkey= table_message.add_fk_constraint();
561
 
    *pfkey= original_proto.fk_constraint(j);
562
 
  }
563
 
 
564
485
  {
565
486
    Key *key;
566
487
    while ((key= key_it++)) /* Add new keys */
567
488
    {
568
 
      if (key->type == Key::FOREIGN_KEY)
569
 
      {
570
 
        if (((Foreign_key *)key)->validate(new_create_list))
571
 
        {
572
 
          return true;
573
 
        }
574
 
 
575
 
        Foreign_key *fkey= (Foreign_key*)key;
576
 
        add_foreign_key_to_table_message(&table_message,
577
 
                                         fkey->name.str,
578
 
                                         fkey->columns,
579
 
                                         fkey->ref_table,
580
 
                                         fkey->ref_columns,
581
 
                                         fkey->delete_opt,
582
 
                                         fkey->update_opt,
583
 
                                         fkey->match_opt);
584
 
      }
585
 
 
 
489
      if (key->type == Key::FOREIGN_KEY &&
 
490
          ((Foreign_key *)key)->validate(new_create_list))
 
491
        goto err;
586
492
      if (key->type != Key::FOREIGN_KEY)
587
493
        new_key_list.push_back(key);
588
 
 
589
494
      if (key->name.str && is_primary_key_name(key->name.str))
590
495
      {
591
496
        my_error(ER_WRONG_NAME_FOR_INDEX,
592
497
                 MYF(0),
593
498
                 key->name.str);
594
 
        return true;
 
499
        goto err;
595
500
      }
596
501
    }
597
502
  }
598
503
 
599
 
  /* Fix names of foreign keys being added */
600
 
  for (int j= 0; j < table_message.fk_constraint_size(); j++)
601
 
  {
602
 
    if (! table_message.fk_constraint(j).has_name())
603
 
    {
604
 
      std::string name(table->getMutableShare()->getTableName());
605
 
      char number[20];
606
 
 
607
 
      name.append("_ibfk_");
608
 
      snprintf(number, sizeof(number), "%d", j+1);
609
 
      name.append(number);
610
 
 
611
 
      message::Table::ForeignKeyConstraint *pfkey= table_message.mutable_fk_constraint(j);
612
 
      pfkey->set_name(name);
613
 
    }
614
 
  }
615
 
 
616
504
  if (alter_info->drop_list.elements)
617
505
  {
618
506
    my_error(ER_CANT_DROP_FIELD_OR_KEY,
619
507
             MYF(0),
620
508
             alter_info->drop_list.head()->name);
621
 
    return true;
 
509
    goto err;
622
510
  }
623
511
  if (alter_info->alter_list.elements)
624
512
  {
625
513
    my_error(ER_CANT_DROP_FIELD_OR_KEY,
626
514
             MYF(0),
627
515
             alter_info->alter_list.head()->name);
628
 
    return true;
 
516
    goto err;
629
517
  }
630
518
 
631
 
  if (not table_message.options().has_comment()
632
 
      && table->getMutableShare()->hasComment())
633
 
    table_options->set_comment(table->getMutableShare()->getComment());
 
519
  if (! table_proto->options().has_comment()
 
520
      && table->s->hasComment())
 
521
    table_options->set_comment(table->s->getComment());
634
522
 
635
 
  if (table->getShare()->getType())
 
523
  if (table->s->tmp_table)
636
524
  {
637
 
    table_message.set_type(message::Table::TEMPORARY);
 
525
    table_proto->set_type(message::Table::TEMPORARY);
638
526
  }
639
527
 
640
 
  table_message.set_creation_timestamp(table->getShare()->getTableProto()->creation_timestamp());
641
 
  table_message.set_version(table->getShare()->getTableProto()->version());
642
 
  table_message.set_uuid(table->getShare()->getTableProto()->uuid());
643
 
 
644
528
  rc= false;
645
529
  alter_info->create_list.swap(new_create_list);
646
530
  alter_info->key_list.swap(new_key_list);
647
 
 
648
 
  size_t num_engine_options= table_message.engine().options_size();
649
 
  size_t original_num_engine_options= original_proto.engine().options_size();
650
 
  for (size_t x= 0; x < original_num_engine_options; ++x)
651
 
  {
652
 
    bool found= false;
653
 
 
654
 
    for (size_t y= 0; y < num_engine_options; ++y)
655
 
    {
656
 
      found= not table_message.engine().options(y).name().compare(original_proto.engine().options(x).name());
657
 
      
658
 
      if (found)
659
 
        break;
660
 
    }
661
 
 
662
 
    if (not found)
663
 
    {
664
 
      message::Engine::Option *opt= table_message.mutable_engine()->add_options();
665
 
 
666
 
      opt->set_name(original_proto.engine().options(x).name());
667
 
      opt->set_state(original_proto.engine().options(x).state());
668
 
    }
669
 
  }
670
 
 
671
 
  drizzled::message::update(table_message);
672
 
 
673
 
  return false;
 
531
err:
 
532
  return rc;
674
533
}
675
534
 
676
535
/* table_list should contain just one table */
711
570
    goto err;
712
571
 
713
572
  /* The ALTER Table is always in its own transaction */
714
 
  error= transaction_services.autocommitOrRollback(session, false);
715
 
  if (not session->endActiveTransaction())
 
573
  error= transaction_services.ha_autocommit_or_rollback(session, false);
 
574
  if (! session->endActiveTransaction())
716
575
    error=1;
717
 
 
718
576
  if (error)
719
577
    goto err;
720
 
 
721
 
  write_bin_log(session, *session->getQueryString());
 
578
  write_bin_log(session, session->query, session->query_length);
722
579
 
723
580
err:
724
 
  (void) transaction_services.autocommitOrRollback(session, error);
 
581
  (void) transaction_services.ha_autocommit_or_rollback(session, error);
725
582
  session->tablespace_op=false;
726
583
 
727
584
  if (error == 0)
749
606
    false  OK
750
607
    true   Error
751
608
*/
752
 
static bool alter_table_manage_keys(Session *session,
753
 
                                    Table *table, int indexes_were_disabled,
754
 
                                    enum enum_enable_or_disable keys_onoff)
 
609
static bool alter_table_manage_keys(Table *table, int indexes_were_disabled,
 
610
                             enum enum_enable_or_disable keys_onoff)
755
611
{
756
612
  int error= 0;
757
613
  switch (keys_onoff) {
759
615
    error= table->cursor->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
760
616
    break;
761
617
  case LEAVE_AS_IS:
762
 
    if (not indexes_were_disabled)
 
618
    if (!indexes_were_disabled)
763
619
      break;
764
620
    /* fall-through: disabled indexes */
765
621
  case DISABLE:
768
624
 
769
625
  if (error == HA_ERR_WRONG_COMMAND)
770
626
  {
771
 
    push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
627
    push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
772
628
                        ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
773
 
                        table->getMutableShare()->getTableName());
 
629
                        table->s->table_name.str);
774
630
    error= 0;
775
631
  } else if (error)
776
632
    table->print_error(error, MYF(0));
778
634
  return(error);
779
635
}
780
636
 
781
 
static bool lockTableIfDifferent(Session &session,
782
 
                                 TableIdentifier &original_table_identifier,
783
 
                                 TableIdentifier &new_table_identifier,
784
 
                                 Table *name_lock)
785
 
{
786
 
  /* Check that we are not trying to rename to an existing table */
787
 
  if (not (original_table_identifier == new_table_identifier))
788
 
  {
789
 
    if (original_table_identifier.isTmp())
790
 
    {
791
 
 
792
 
      if (session.find_temporary_table(new_table_identifier))
793
 
      {
794
 
        std::string path;
795
 
        new_table_identifier.getSQLPath(path);
796
 
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
797
 
        return false;
798
 
      }
799
 
    }
800
 
    else
801
 
    {
802
 
      if (session.lock_table_name_if_not_cached(new_table_identifier, &name_lock))
803
 
      {
804
 
        return false;
805
 
      }
806
 
 
807
 
      if (not name_lock)
808
 
      {
809
 
        std::string path;
810
 
        new_table_identifier.getSQLPath(path);
811
 
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
812
 
        return false;
813
 
      }
814
 
 
815
 
      if (plugin::StorageEngine::doesTableExist(session, new_table_identifier))
816
 
      {
817
 
        std::string path;
818
 
        new_table_identifier.getSQLPath(path);
819
 
 
820
 
        /* Table will be closed by Session::executeCommand() */
821
 
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
822
 
 
823
 
        table::Cache::singleton().mutex().lock(); /* ALTER TABLe */
824
 
        session.unlink_open_table(name_lock);
825
 
        table::Cache::singleton().mutex().unlock();
826
 
 
827
 
        return false;
828
 
      }
829
 
    }
830
 
  }
831
 
 
832
 
  return true;
833
 
}
834
 
 
835
637
/**
836
638
  Alter table
837
639
 
845
647
      table_list       The table to change.
846
648
      alter_info       Lists of fields, keys to be changed, added
847
649
                       or dropped.
848
 
      order_num        How many ORDER BY fields has been specified.
 
650
      order_num        How many order_st BY fields has been specified.
849
651
      order            List of fields to order_st BY.
850
652
      ignore           Whether we have ALTER IGNORE Table
851
653
 
873
675
    false  OK
874
676
    true   Error
875
677
*/
876
 
 
877
 
static bool internal_alter_table(Session *session,
878
 
                                 Table *table,
879
 
                                 TableIdentifier &original_table_identifier,
880
 
                                 TableIdentifier &new_table_identifier,
881
 
                                 HA_CREATE_INFO *create_info,
882
 
                                 const message::Table &original_proto,
883
 
                                 message::Table &create_proto,
884
 
                                 TableList *table_list,
885
 
                                 AlterInfo *alter_info,
886
 
                                 uint32_t order_num,
887
 
                                 Order *order,
888
 
                                 bool ignore)
 
678
bool alter_table(Session *session,
 
679
                 char *new_db,
 
680
                 char *new_name,
 
681
                 HA_CREATE_INFO *create_info,
 
682
                 message::Table *create_proto,
 
683
                 TableList *table_list,
 
684
                 AlterInfo *alter_info,
 
685
                 uint32_t order_num,
 
686
                 order_st *order,
 
687
                 bool ignore)
889
688
{
 
689
  Table *table;
 
690
  Table *new_table= NULL;
 
691
  Table *name_lock= NULL;
 
692
  string new_name_str;
890
693
  int error= 0;
891
694
  char tmp_name[80];
892
695
  char old_name[32];
 
696
  char new_name_buff[FN_REFLEN];
 
697
  char new_alias_buff[FN_REFLEN];
 
698
  char *table_name;
 
699
  char *db;
 
700
  const char *new_alias;
893
701
  ha_rows copied= 0;
894
702
  ha_rows deleted= 0;
895
 
 
896
 
  if (not original_table_identifier.isValid())
897
 
    return true;
898
 
 
899
 
  if (not new_table_identifier.isValid())
900
 
    return true;
 
703
  plugin::StorageEngine *old_db_type;
 
704
  plugin::StorageEngine *new_db_type;
 
705
  plugin::StorageEngine *save_old_db_type;
 
706
  bitset<32> tmp;
 
707
 
 
708
  new_name_buff[0]= '\0';
 
709
 
 
710
  /**
 
711
   * @todo this is a result of retaining the behavior that was here before. This should be removed
 
712
   * and the correct error handling should be done in doDropTable for the I_S engine.
 
713
   */
 
714
  plugin::InfoSchemaTable *sch_table= plugin::InfoSchemaTable::getTable(table_list->table_name);
 
715
  if (sch_table)
 
716
  {
 
717
    my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.c_str());
 
718
    return true;
 
719
  }
901
720
 
902
721
  session->set_proc_info("init");
903
722
 
 
723
  /*
 
724
    Assign variables table_name, new_name, db, new_db, path
 
725
    to simplify further comparisons: we want to see if it's a RENAME
 
726
    later just by comparing the pointers, avoiding the need for strcmp.
 
727
  */
 
728
  table_name= table_list->table_name;
 
729
  db= table_list->db;
 
730
  if (! new_db || ! my_strcasecmp(table_alias_charset, new_db, db))
 
731
    new_db= db;
 
732
 
 
733
  if (alter_info->tablespace_op != NO_TABLESPACE_OP)
 
734
  {
 
735
    /* DISCARD/IMPORT TABLESPACE is always alone in an ALTER Table */
 
736
    return mysql_discard_or_import_tablespace(session, table_list, alter_info->tablespace_op);
 
737
  }
 
738
 
 
739
  ostringstream oss;
 
740
  oss << drizzle_data_home << "/" << db << "/" << table_name;
 
741
 
 
742
  (void) internal::unpack_filename(new_name_buff, oss.str().c_str());
 
743
 
 
744
  /*
 
745
    If this is just a rename of a view, short cut to the
 
746
    following scenario: 1) lock LOCK_open 2) do a RENAME
 
747
    2) unlock LOCK_open.
 
748
    This is a copy-paste added to make sure
 
749
    ALTER (sic:) Table .. RENAME works for views. ALTER VIEW is handled
 
750
    as an independent branch in mysql_execute_command. The need
 
751
    for a copy-paste arose because the main code flow of ALTER Table
 
752
    ... RENAME tries to use openTableLock, which does not work for views
 
753
    (openTableLock was never modified to merge table lists of child tables
 
754
    into the main table list, like open_tables does).
 
755
    This code is wrong and will be removed, please do not copy.
 
756
  */
 
757
 
 
758
  if (!(table= session->openTableLock(table_list, TL_WRITE_ALLOW_READ)))
 
759
    return true;
 
760
  
904
761
  table->use_all_columns();
905
762
 
906
 
  plugin::StorageEngine *new_engine;
907
 
  plugin::StorageEngine *original_engine;
908
 
 
909
 
  original_engine= table->getMutableShare()->getEngine();
910
 
 
911
 
  if (not create_info->db_type)
912
 
  {
913
 
    create_info->db_type= original_engine;
914
 
  }
915
 
  new_engine= create_info->db_type;
916
 
 
917
 
 
918
 
  create_proto.set_schema(new_table_identifier.getSchemaName());
919
 
  create_proto.set_type(new_table_identifier.getType());
920
 
 
921
 
  /**
922
 
    @todo Have a check on the table definition for FK in the future 
923
 
    to remove the need for the cursor. (aka can_switch_engines())
924
 
  */
925
 
  if (new_engine != original_engine &&
926
 
      not table->cursor->can_switch_engines())
 
763
  /* Check that we are not trying to rename to an existing table */
 
764
  if (new_name)
 
765
  {
 
766
    strcpy(new_name_buff, new_name);
 
767
    strcpy(new_alias_buff, new_name);
 
768
    new_alias= new_alias_buff;
 
769
 
 
770
    my_casedn_str(files_charset_info, new_name_buff);
 
771
    new_alias= new_name; // Create lower case table name
 
772
    my_casedn_str(files_charset_info, new_name);
 
773
 
 
774
    if (new_db == db &&
 
775
        ! my_strcasecmp(table_alias_charset, new_name_buff, table_name))
 
776
    {
 
777
      /*
 
778
        Source and destination table names are equal: make later check
 
779
        easier.
 
780
      */
 
781
      new_alias= new_name= table_name;
 
782
    }
 
783
    else
 
784
    {
 
785
      if (table->s->tmp_table != NO_TMP_TABLE)
 
786
      {
 
787
        if (session->find_temporary_table(new_db, new_name_buff))
 
788
        {
 
789
          my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name_buff);
 
790
          return true;
 
791
        }
 
792
      }
 
793
      else
 
794
      {
 
795
        if (session->lock_table_name_if_not_cached(new_db, new_name, &name_lock))
 
796
          return true;
 
797
 
 
798
        if (! name_lock)
 
799
        {
 
800
          my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
 
801
          return true;
 
802
        }
 
803
 
 
804
        build_table_filename(new_name_buff, sizeof(new_name_buff), new_db, new_name_buff, false);
 
805
 
 
806
        if (plugin::StorageEngine::getTableDefinition(*session, new_name_buff, new_db, new_name_buff, false) == EEXIST)
 
807
        {
 
808
          /* Table will be closed by Session::executeCommand() */
 
809
          my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
 
810
          goto err;
 
811
        }
 
812
      }
 
813
    }
 
814
  }
 
815
  else
 
816
  {
 
817
    new_alias= table_name;
 
818
    new_name= table_name;
 
819
  }
 
820
 
 
821
  old_db_type= table->s->db_type();
 
822
  if (! create_info->db_type)
 
823
  {
 
824
    create_info->db_type= old_db_type;
 
825
  }
 
826
 
 
827
  if (table->s->tmp_table != NO_TMP_TABLE)
 
828
  {
 
829
    create_proto->set_type(message::Table::TEMPORARY);
 
830
  }
 
831
  else
 
832
  {
 
833
    create_proto->set_type(message::Table::STANDARD);
 
834
  }
 
835
 
 
836
  new_db_type= create_info->db_type;
 
837
 
 
838
  if (new_db_type != old_db_type &&
 
839
      !table->cursor->can_switch_engines())
927
840
  {
928
841
    assert(0);
929
842
    my_error(ER_ROW_IS_REFERENCED, MYF(0));
930
 
 
931
 
    return true;
932
 
  }
933
 
 
934
 
  if (original_engine->check_flag(HTON_BIT_ALTER_NOT_SUPPORTED) ||
935
 
      new_engine->check_flag(HTON_BIT_ALTER_NOT_SUPPORTED))
936
 
  {
937
 
    std::string path;
938
 
    new_table_identifier.getSQLPath(path);
939
 
    my_error(ER_ILLEGAL_HA, MYF(0), path.c_str());
940
 
 
941
 
    return true;
 
843
    goto err;
 
844
  }
 
845
 
 
846
  if (create_info->row_type == ROW_TYPE_NOT_USED)
 
847
  {
 
848
    message::Table::TableOptions *table_options;
 
849
    table_options= create_proto->mutable_options();
 
850
 
 
851
    create_info->row_type= table->s->row_type;
 
852
    table_options->set_row_type((message::Table_TableOptions_RowType)table->s->row_type);
 
853
  }
 
854
 
 
855
  if (old_db_type->check_flag(HTON_BIT_ALTER_NOT_SUPPORTED) ||
 
856
      new_db_type->check_flag(HTON_BIT_ALTER_NOT_SUPPORTED))
 
857
  {
 
858
    my_error(ER_ILLEGAL_HA, MYF(0), table_name);
 
859
    goto err;
942
860
  }
943
861
 
944
862
  session->set_proc_info("setup");
945
 
 
 
863
  
946
864
  /*
947
865
   * test if no other bits except ALTER_RENAME and ALTER_KEYS_ONOFF are set
948
 
 */
 
866
   */
 
867
  tmp.set();
 
868
  tmp.reset(ALTER_RENAME);
 
869
  tmp.reset(ALTER_KEYS_ONOFF);
 
870
  tmp&= alter_info->flags;
 
871
  if (! (tmp.any()) &&
 
872
      ! table->s->tmp_table) // no need to touch frm
949
873
  {
950
 
    bitset<32> tmp;
951
 
 
952
 
    tmp.set();
953
 
    tmp.reset(ALTER_RENAME);
954
 
    tmp.reset(ALTER_KEYS_ONOFF);
955
 
    tmp&= alter_info->flags;
956
 
 
957
 
    if (! (tmp.any()) && ! table->getShare()->getType()) // no need to touch frm
958
 
    {
959
 
      switch (alter_info->keys_onoff)
960
 
      {
961
 
      case LEAVE_AS_IS:
962
 
        break;
963
 
      case ENABLE:
964
 
        /*
965
 
          wait_while_table_is_used() ensures that table being altered is
966
 
          opened only by this thread and that Table::TableShare::version
967
 
          of Table object corresponding to this table is 0.
968
 
          The latter guarantees that no DML statement will open this table
969
 
          until ALTER Table finishes (i.e. until close_thread_tables())
970
 
          while the fact that the table is still open gives us protection
971
 
          from concurrent DDL statements.
972
 
        */
973
 
        table::Cache::singleton().mutex().lock(); /* DDL wait for/blocker */
974
 
        wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
975
 
        table::Cache::singleton().mutex().unlock();
976
 
        error= table->cursor->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
977
 
        /* COND_refresh will be signaled in close_thread_tables() */
978
 
        break;
979
 
      case DISABLE:
980
 
        table::Cache::singleton().mutex().lock(); /* DDL wait for/blocker */
981
 
        wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
982
 
        table::Cache::singleton().mutex().unlock();
983
 
        error=table->cursor->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
984
 
        /* COND_refresh will be signaled in close_thread_tables() */
985
 
        break;
986
 
      default:
987
 
        assert(false);
988
 
        error= 0;
989
 
        break;
990
 
      }
991
 
 
992
 
      if (error == HA_ERR_WRONG_COMMAND)
993
 
      {
994
 
        error= 0;
995
 
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
996
 
                            ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
997
 
                            table->getAlias());
998
 
      }
999
 
 
1000
 
      table::Cache::singleton().mutex().lock(); /* Lock to remove all instances of table from table cache before ALTER */
1001
 
      /*
1002
 
        Unlike to the above case close_cached_table() below will remove ALL
1003
 
        instances of Table from table cache (it will also remove table lock
1004
 
        held by this thread). So to make actual table renaming and writing
1005
 
        to binlog atomic we have to put them into the same critical section
1006
 
        protected by table::Cache::singleton().mutex() mutex. This also removes gap for races between
1007
 
        access() and mysql_rename_table() calls.
1008
 
      */
1009
 
 
1010
 
      if (error == 0 &&  not (original_table_identifier == new_table_identifier))
1011
 
      {
1012
 
        session->set_proc_info("rename");
1013
 
        /*
1014
 
          Then do a 'simple' rename of the table. First we need to close all
1015
 
          instances of 'source' table.
1016
 
        */
1017
 
        session->close_cached_table(table);
1018
 
        /*
1019
 
          Then, we want check once again that target table does not exist.
1020
 
          Actually the order of these two steps does not matter since
1021
 
          earlier we took name-lock on the target table, so we do them
1022
 
          in this particular order only to be consistent with 5.0, in which
1023
 
          we don't take this name-lock and where this order really matters.
1024
 
          @todo Investigate if we need this access() check at all.
1025
 
        */
1026
 
        if (plugin::StorageEngine::doesTableExist(*session, new_table_identifier))
1027
 
        {
1028
 
          std::string path;
1029
 
          new_table_identifier.getSQLPath(path);
1030
 
          my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
 
874
    switch (alter_info->keys_onoff)
 
875
    {
 
876
    case LEAVE_AS_IS:
 
877
      break;
 
878
    case ENABLE:
 
879
      /*
 
880
        wait_while_table_is_used() ensures that table being altered is
 
881
        opened only by this thread and that Table::TableShare::version
 
882
        of Table object corresponding to this table is 0.
 
883
        The latter guarantees that no DML statement will open this table
 
884
        until ALTER Table finishes (i.e. until close_thread_tables())
 
885
        while the fact that the table is still open gives us protection
 
886
        from concurrent DDL statements.
 
887
      */
 
888
      pthread_mutex_lock(&LOCK_open); /* DDL wait for/blocker */
 
889
      wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
 
890
      pthread_mutex_unlock(&LOCK_open);
 
891
      error= table->cursor->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
 
892
      /* COND_refresh will be signaled in close_thread_tables() */
 
893
      break;
 
894
    case DISABLE:
 
895
      pthread_mutex_lock(&LOCK_open); /* DDL wait for/blocker */
 
896
      wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
 
897
      pthread_mutex_unlock(&LOCK_open);
 
898
      error=table->cursor->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
 
899
      /* COND_refresh will be signaled in close_thread_tables() */
 
900
      break;
 
901
    default:
 
902
      assert(false);
 
903
      error= 0;
 
904
      break;
 
905
    }
 
906
 
 
907
    if (error == HA_ERR_WRONG_COMMAND)
 
908
    {
 
909
      error= 0;
 
910
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
911
                          ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
 
912
                          table->alias);
 
913
    }
 
914
 
 
915
    pthread_mutex_lock(&LOCK_open); /* Lock to remove all instances of table from table cache before ALTER */
 
916
    /*
 
917
      Unlike to the above case close_cached_table() below will remove ALL
 
918
      instances of Table from table cache (it will also remove table lock
 
919
      held by this thread). So to make actual table renaming and writing
 
920
      to binlog atomic we have to put them into the same critical section
 
921
      protected by LOCK_open mutex. This also removes gap for races between
 
922
      access() and mysql_rename_table() calls.
 
923
    */
 
924
 
 
925
    if (error == 0 && 
 
926
        (new_name != table_name || new_db != db))
 
927
    {
 
928
      session->set_proc_info("rename");
 
929
      /*
 
930
        Then do a 'simple' rename of the table. First we need to close all
 
931
        instances of 'source' table.
 
932
      */
 
933
      session->close_cached_table(table);
 
934
      /*
 
935
        Then, we want check once again that target table does not exist.
 
936
        Actually the order of these two steps does not matter since
 
937
        earlier we took name-lock on the target table, so we do them
 
938
        in this particular order only to be consistent with 5.0, in which
 
939
        we don't take this name-lock and where this order really matters.
 
940
        TODO: Investigate if we need this access() check at all.
 
941
      */
 
942
      if (plugin::StorageEngine::getTableDefinition(*session, new_name, db, table_name, false) == EEXIST)
 
943
      {
 
944
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name);
 
945
        error= -1;
 
946
      }
 
947
      else
 
948
      {
 
949
        *internal::fn_ext(new_name)= 0;
 
950
        if (mysql_rename_table(old_db_type, db, table_name, new_db, new_alias, 0))
1031
951
          error= -1;
1032
 
        }
1033
 
        else
1034
 
        {
1035
 
          if (mysql_rename_table(*session, original_engine, original_table_identifier, new_table_identifier))
1036
 
          {
1037
 
            error= -1;
1038
 
          }
1039
 
        }
1040
 
      }
1041
 
 
1042
 
      if (error == HA_ERR_WRONG_COMMAND)
1043
 
      {
1044
 
        error= 0;
1045
 
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1046
 
                            ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
1047
 
                            table->getAlias());
1048
 
      }
1049
 
 
1050
 
      if (error == 0)
1051
 
      {
1052
 
        TransactionServices &transaction_services= TransactionServices::singleton();
1053
 
        transaction_services.allocateNewTransactionId();
1054
 
        write_bin_log(session, *session->getQueryString());
1055
 
        session->my_ok();
1056
 
      }
1057
 
      else if (error > 0)
1058
 
      {
1059
 
        table->print_error(error, MYF(0));
1060
 
        error= -1;
1061
 
      }
1062
 
 
1063
 
      table::Cache::singleton().mutex().unlock();
1064
 
      table_list->table= NULL;
1065
 
 
1066
 
      return error;
1067
 
    }
 
952
      }
 
953
    }
 
954
 
 
955
    if (error == HA_ERR_WRONG_COMMAND)
 
956
    {
 
957
      error= 0;
 
958
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
959
                          ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
 
960
                          table->alias);
 
961
    }
 
962
 
 
963
    if (error == 0)
 
964
    {
 
965
      write_bin_log(session, session->query, session->query_length);
 
966
      session->my_ok();
 
967
    }
 
968
    else if (error > 0)
 
969
    {
 
970
      table->print_error(error, MYF(0));
 
971
      error= -1;
 
972
    }
 
973
 
 
974
    if (name_lock)
 
975
      session->unlink_open_table(name_lock);
 
976
 
 
977
    pthread_mutex_unlock(&LOCK_open);
 
978
    table_list->table= NULL;
 
979
    return error;
1068
980
  }
1069
981
 
1070
982
  /* We have to do full alter table. */
1071
 
  new_engine= create_info->db_type;
1072
 
 
1073
 
  if (mysql_prepare_alter_table(session, table, create_info, original_proto, create_proto, alter_info))
1074
 
  {
1075
 
    return true;
1076
 
  }
1077
 
 
1078
 
  set_table_default_charset(create_info, new_table_identifier.getSchemaName().c_str());
 
983
  new_db_type= create_info->db_type;
 
984
 
 
985
  if (mysql_prepare_alter_table(session, table, create_info, create_proto,
 
986
                                alter_info))
 
987
      goto err;
 
988
 
 
989
  set_table_default_charset(create_info, db);
1079
990
 
1080
991
  alter_info->build_method= HA_BUILD_OFFLINE;
1081
992
 
1082
993
  snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%"PRIx64, TMP_FILE_PREFIX, (unsigned long) current_pid, session->thread_id);
1083
994
 
 
995
  /* Safety fix for innodb */
 
996
  my_casedn_str(files_charset_info, tmp_name);
 
997
 
1084
998
  /* Create a temporary table with the new format */
1085
 
  /**
1086
 
    @note we make an internal temporary table unless the table is a temporary table. In last
1087
 
    case we just use it as is. Neither of these tables require locks in order to  be
1088
 
    filled.
1089
 
  */
1090
 
  TableIdentifier new_table_as_temporary(original_table_identifier.getSchemaName(),
1091
 
                                         tmp_name,
1092
 
                                         create_proto.type() != message::Table::TEMPORARY ? message::Table::INTERNAL :
1093
 
                                         message::Table::TEMPORARY);
1094
 
 
1095
 
  error= create_temporary_table(session, new_table_as_temporary, create_info, create_proto, alter_info);
1096
 
 
1097
 
  if (error != 0)
1098
999
  {
1099
 
    return true;
 
1000
    /**
 
1001
      @note we make an internal temporary table unless the table is a temporary table. In last
 
1002
      case we just use it as is. Neither of these tables require locks in order to  be
 
1003
      filled.
 
1004
    */
 
1005
    TableIdentifier new_table_temp(new_db,
 
1006
                                   tmp_name,
 
1007
                                   create_proto->type() != message::Table::TEMPORARY ? INTERNAL_TMP_TABLE :
 
1008
                                   TEMP_TABLE);
 
1009
 
 
1010
    error= create_temporary_table(session, table, new_table_temp, create_info, create_proto, alter_info);
 
1011
 
 
1012
    if (error != 0)
 
1013
      goto err;
1100
1014
  }
1101
1015
 
1102
1016
  /* Open the table so we need to copy the data to it. */
1103
 
  Table *new_table= open_alter_table(session, table, new_table_as_temporary);
1104
 
 
1105
 
 
1106
 
  if (not new_table)
1107
 
  {
1108
 
    plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
1109
 
    return true;
1110
 
  }
 
1017
  new_table= open_alter_table(session, table, new_db, tmp_name);
 
1018
 
 
1019
  if (new_table == NULL)
 
1020
    goto err1;
1111
1021
 
1112
1022
  /* Copy the data if necessary. */
1113
 
  {
1114
 
    /* We must not ignore bad input! */
1115
 
    session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;    // calc cuted fields
1116
 
    session->cuted_fields= 0L;
1117
 
    session->set_proc_info("copy to tmp table");
1118
 
    copied= deleted= 0;
1119
 
 
1120
 
    /* We don't want update TIMESTAMP fields during ALTER Table. */
1121
 
    new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
1122
 
    new_table->next_number_field= new_table->found_next_number_field;
1123
 
    error= copy_data_between_tables(session,
1124
 
                                    table,
1125
 
                                    new_table,
1126
 
                                    alter_info->create_list,
1127
 
                                    ignore,
1128
 
                                    order_num,
1129
 
                                    order,
1130
 
                                    &copied,
1131
 
                                    &deleted,
1132
 
                                    alter_info->keys_onoff,
1133
 
                                    alter_info->error_if_not_empty);
1134
 
 
1135
 
    /* We must not ignore bad input! */
1136
 
    assert(session->count_cuted_fields == CHECK_FIELD_ERROR_FOR_NULL);
1137
 
  }
1138
 
 
1139
 
  /* Now we need to resolve what just happened with the data copy. */
1140
 
 
1141
 
  if (error)
1142
 
  {
1143
 
 
1144
 
    /*
1145
 
      No default value was provided for a DATE/DATETIME field, the
1146
 
      current sql_mode doesn't allow the '0000-00-00' value and
1147
 
      the table to be altered isn't empty.
1148
 
      Report error here.
1149
 
    */
1150
 
    if (alter_info->error_if_not_empty && session->row_count)
1151
 
    {
1152
 
      my_error(ER_INVALID_ALTER_TABLE_FOR_NOT_NULL, MYF(0));
1153
 
    }
1154
 
 
1155
 
    if (original_table_identifier.isTmp())
1156
 
    {
1157
 
      if (new_table)
1158
 
      {
1159
 
        /* close_temporary_table() frees the new_table pointer. */
1160
 
        session->close_temporary_table(new_table);
1161
 
      }
1162
 
      else
1163
 
      {
1164
 
        plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
1165
 
      }
1166
 
 
1167
 
      return true;
1168
 
    }
1169
 
    else
1170
 
    {
1171
 
      if (new_table)
1172
 
      {
1173
 
        /*
1174
 
          Close the intermediate table that will be the new table.
1175
 
          Note that MERGE tables do not have their children attached here.
1176
 
        */
1177
 
        new_table->intern_close_table();
1178
 
        if (new_table->hasShare())
1179
 
        {
1180
 
          delete new_table->getMutableShare();
1181
 
        }
1182
 
 
1183
 
        delete new_table;
1184
 
      }
1185
 
 
1186
 
      table::Cache::singleton().mutex().lock(); /* ALTER TABLE */
1187
 
 
1188
 
      plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
1189
 
      table::Cache::singleton().mutex().unlock();
1190
 
 
1191
 
      return true;
1192
 
    }
1193
 
  }
1194
 
  // Temporary table and success
1195
 
  else if (original_table_identifier.isTmp())
1196
 
  {
 
1023
  session->count_cuted_fields= CHECK_FIELD_WARN;        // calc cuted fields
 
1024
  session->cuted_fields= 0L;
 
1025
  session->set_proc_info("copy to tmp table");
 
1026
  copied= deleted= 0;
 
1027
 
 
1028
  assert(new_table);
 
1029
 
 
1030
  /* We don't want update TIMESTAMP fields during ALTER Table. */
 
1031
  new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
 
1032
  new_table->next_number_field= new_table->found_next_number_field;
 
1033
  error= copy_data_between_tables(table,
 
1034
                                  new_table,
 
1035
                                  alter_info->create_list,
 
1036
                                  ignore,
 
1037
                                  order_num,
 
1038
                                  order,
 
1039
                                  &copied,
 
1040
                                  &deleted,
 
1041
                                  alter_info->keys_onoff,
 
1042
                                  alter_info->error_if_not_empty);
 
1043
 
 
1044
  /* We must not ignore bad input! */
 
1045
  session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
 
1046
 
 
1047
  if (table->s->tmp_table != NO_TMP_TABLE)
 
1048
  {
 
1049
    /* We changed a temporary table */
 
1050
    if (error)
 
1051
      goto err1;
 
1052
 
1197
1053
    /* Close lock if this is a transactional table */
1198
1054
    if (session->lock)
1199
1055
    {
1200
 
      session->unlockTables(session->lock);
 
1056
      mysql_unlock_tables(session, session->lock);
1201
1057
      session->lock= 0;
1202
1058
    }
1203
1059
 
1205
1061
    session->close_temporary_table(table);
1206
1062
 
1207
1063
    /* Should pass the 'new_name' as we store table name in the cache */
1208
 
    new_table->getMutableShare()->setIdentifier(new_table_identifier);
1209
 
 
1210
 
    new_table_identifier.setPath(new_table_as_temporary.getPath());
1211
 
 
1212
 
    if (mysql_rename_table(*session, new_engine, new_table_as_temporary, new_table_identifier) != 0)
1213
 
    {
1214
 
      return true;
1215
 
    }
1216
 
  }
1217
 
  // Normal table success
 
1064
    if (new_table->rename_temporary_table(new_db, new_name))
 
1065
      goto err1;
 
1066
 
 
1067
    goto end_temporary;
 
1068
  }
 
1069
 
 
1070
  if (new_table)
 
1071
  {
 
1072
    /*
 
1073
      Close the intermediate table that will be the new table.
 
1074
      Note that MERGE tables do not have their children attached here.
 
1075
    */
 
1076
    new_table->intern_close_table();
 
1077
    free(new_table);
 
1078
  }
 
1079
 
 
1080
  pthread_mutex_lock(&LOCK_open); /* ALTER TABLE */
 
1081
 
 
1082
  if (error)
 
1083
  {
 
1084
    TableIdentifier identifier(new_db, tmp_name, INTERNAL_TMP_TABLE);
 
1085
    quick_rm_table(*session, identifier);
 
1086
    pthread_mutex_unlock(&LOCK_open);
 
1087
    goto err;
 
1088
  }
 
1089
 
 
1090
  /*
 
1091
    Data is copied. Now we:
 
1092
    1) Wait until all other threads close old version of table.
 
1093
    2) Close instances of table open by this thread and replace them
 
1094
       with exclusive name-locks.
 
1095
    3) Rename the old table to a temp name, rename the new one to the
 
1096
       old name.
 
1097
    4) If we are under LOCK TABLES and don't do ALTER Table ... RENAME
 
1098
       we reopen new version of table.
 
1099
    5) Write statement to the binary log.
 
1100
    6) If we are under LOCK TABLES and do ALTER Table ... RENAME we
 
1101
       remove name-locks from list of open tables and table cache.
 
1102
    7) If we are not not under LOCK TABLES we rely on close_thread_tables()
 
1103
       call to remove name-locks from table cache and list of open table.
 
1104
  */
 
1105
 
 
1106
  session->set_proc_info("rename result table");
 
1107
 
 
1108
  snprintf(old_name, sizeof(old_name), "%s2-%lx-%"PRIx64, TMP_FILE_PREFIX, (unsigned long) current_pid, session->thread_id);
 
1109
 
 
1110
  my_casedn_str(files_charset_info, old_name);
 
1111
 
 
1112
  wait_while_table_is_used(session, table, HA_EXTRA_PREPARE_FOR_RENAME);
 
1113
  session->close_data_files_and_morph_locks(db, table_name);
 
1114
 
 
1115
  error= 0;
 
1116
  save_old_db_type= old_db_type;
 
1117
 
 
1118
  /*
 
1119
    This leads to the storage engine (SE) not being notified for renames in
 
1120
    mysql_rename_table(), because we just juggle with the FRM and nothing
 
1121
    more. If we have an intermediate table, then we notify the SE that
 
1122
    it should become the actual table. Later, we will recycle the old table.
 
1123
    However, in case of ALTER Table RENAME there might be no intermediate
 
1124
    table. This is when the old and new tables are compatible, according to
 
1125
    compare_table(). Then, we need one additional call to
 
1126
  */
 
1127
  if (mysql_rename_table(old_db_type, db, table_name, db, old_name, FN_TO_IS_TMP))
 
1128
  {
 
1129
    error= 1;
 
1130
    TableIdentifier identifier(new_db, tmp_name, INTERNAL_TMP_TABLE);
 
1131
    quick_rm_table(*session, identifier);
 
1132
  }
1218
1133
  else
1219
1134
  {
1220
 
    if (new_table)
1221
 
    {
1222
 
      /*
1223
 
        Close the intermediate table that will be the new table.
1224
 
        Note that MERGE tables do not have their children attached here.
1225
 
      */
1226
 
      new_table->intern_close_table();
1227
 
 
1228
 
      if (new_table->hasShare())
1229
 
      {
1230
 
        delete new_table->getMutableShare();
1231
 
      }
1232
 
 
1233
 
      delete new_table;
1234
 
    }
1235
 
 
1236
 
    table::Cache::singleton().mutex().lock(); /* ALTER TABLE */
1237
 
 
1238
 
    /*
1239
 
      Data is copied. Now we:
1240
 
      1) Wait until all other threads close old version of table.
1241
 
      2) Close instances of table open by this thread and replace them
1242
 
      with exclusive name-locks.
1243
 
      3) Rename the old table to a temp name, rename the new one to the
1244
 
      old name.
1245
 
      4) If we are under LOCK TABLES and don't do ALTER Table ... RENAME
1246
 
      we reopen new version of table.
1247
 
      5) Write statement to the binary log.
1248
 
      6) If we are under LOCK TABLES and do ALTER Table ... RENAME we
1249
 
      remove name-locks from list of open tables and table cache.
1250
 
      7) If we are not not under LOCK TABLES we rely on close_thread_tables()
1251
 
      call to remove name-locks from table cache and list of open table.
1252
 
    */
1253
 
 
1254
 
    session->set_proc_info("rename result table");
1255
 
 
1256
 
    snprintf(old_name, sizeof(old_name), "%s2-%lx-%"PRIx64, TMP_FILE_PREFIX, (unsigned long) current_pid, session->thread_id);
1257
 
 
1258
 
    my_casedn_str(files_charset_info, old_name);
1259
 
 
1260
 
    wait_while_table_is_used(session, table, HA_EXTRA_PREPARE_FOR_RENAME);
1261
 
    session->close_data_files_and_morph_locks(original_table_identifier);
1262
 
 
1263
 
    error= 0;
1264
 
 
1265
 
    /*
1266
 
      This leads to the storage engine (SE) not being notified for renames in
1267
 
      mysql_rename_table(), because we just juggle with the FRM and nothing
1268
 
      more. If we have an intermediate table, then we notify the SE that
1269
 
      it should become the actual table. Later, we will recycle the old table.
1270
 
      However, in case of ALTER Table RENAME there might be no intermediate
1271
 
      table. This is when the old and new tables are compatible, according to
1272
 
      compare_table(). Then, we need one additional call to
1273
 
    */
1274
 
    TableIdentifier original_table_to_drop(original_table_identifier.getSchemaName(),
1275
 
                                           old_name, create_proto.type() != message::Table::TEMPORARY ? message::Table::INTERNAL :
1276
 
                                         message::Table::TEMPORARY);
1277
 
 
1278
 
    if (mysql_rename_table(*session, original_engine, original_table_identifier, original_table_to_drop))
1279
 
    {
 
1135
    if (mysql_rename_table(new_db_type, new_db, tmp_name, new_db, new_alias, FN_FROM_IS_TMP) != 0)
 
1136
    {
 
1137
      /* Try to get everything back. */
1280
1138
      error= 1;
1281
 
      plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
1282
 
    }
1283
 
    else
1284
 
    {
1285
 
      if (mysql_rename_table(*session, new_engine, new_table_as_temporary, new_table_identifier) != 0)
1286
 
      {
1287
 
        /* Try to get everything back. */
1288
 
        error= 1;
1289
 
 
1290
 
        plugin::StorageEngine::dropTable(*session, new_table_identifier);
1291
 
 
1292
 
        plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
1293
 
 
1294
 
        mysql_rename_table(*session, original_engine, original_table_to_drop, original_table_identifier);
1295
 
      }
1296
 
      else
1297
 
      {
1298
 
        plugin::StorageEngine::dropTable(*session, original_table_to_drop);
1299
 
      }
1300
 
    }
1301
 
 
1302
 
    if (error)
1303
 
    {
1304
 
      /*
1305
 
        An error happened while we were holding exclusive name-lock on table
1306
 
        being altered. To be safe under LOCK TABLES we should remove placeholders
1307
 
        from list of open tables list and table cache.
1308
 
      */
1309
 
      session->unlink_open_table(table);
1310
 
      table::Cache::singleton().mutex().unlock();
1311
 
 
1312
 
      return true;
1313
 
    }
1314
 
 
1315
 
    table::Cache::singleton().mutex().unlock();
1316
 
 
1317
 
    session->set_proc_info("end");
1318
 
 
1319
 
    write_bin_log(session, *session->getQueryString());
1320
 
    table_list->table= NULL;
1321
 
  }
1322
 
 
 
1139
 
 
1140
      TableIdentifier alias_identifier(new_db, new_alias, NO_TMP_TABLE);
 
1141
      quick_rm_table(*session, alias_identifier);
 
1142
 
 
1143
      TableIdentifier tmp_identifier(new_db, tmp_name, INTERNAL_TMP_TABLE);
 
1144
      quick_rm_table(*session, tmp_identifier);
 
1145
 
 
1146
      mysql_rename_table(old_db_type, db, old_name, db, table_name, FN_FROM_IS_TMP);
 
1147
    }
 
1148
  }
 
1149
 
 
1150
  if (error)
 
1151
  {
 
1152
    /* This shouldn't happen. But let us play it safe. */
 
1153
    goto err_with_placeholders;
 
1154
  }
 
1155
 
 
1156
  {
 
1157
    TableIdentifier old_identifier(db, old_name, INTERNAL_TMP_TABLE);
 
1158
    quick_rm_table(*session, old_identifier);
 
1159
  }
 
1160
  
 
1161
 
 
1162
  pthread_mutex_unlock(&LOCK_open);
 
1163
 
 
1164
  session->set_proc_info("end");
 
1165
 
 
1166
  write_bin_log(session, session->query, session->query_length);
 
1167
  table_list->table= NULL;
 
1168
 
 
1169
end_temporary:
1323
1170
  /*
1324
1171
   * Field::store() may have called my_error().  If this is 
1325
1172
   * the case, we must not send an ok packet, since 
1326
1173
   * Diagnostics_area::is_set() will fail an assert.
1327
 
 */
1328
 
  if (session->is_error())
 
1174
   */
 
1175
  if (! session->is_error())
 
1176
  {
 
1177
    snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
 
1178
            (ulong) (copied + deleted), (ulong) deleted,
 
1179
            (ulong) session->cuted_fields);
 
1180
    session->my_ok(copied + deleted, 0, 0L, tmp_name);
 
1181
    session->some_tables_deleted=0;
 
1182
    return false;
 
1183
  }
 
1184
  else
1329
1185
  {
1330
1186
    /* my_error() was called.  Return true (which means error...) */
1331
1187
    return true;
1332
1188
  }
1333
1189
 
1334
 
  snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
1335
 
           (ulong) (copied + deleted), (ulong) deleted,
1336
 
           (ulong) session->cuted_fields);
1337
 
  session->my_ok(copied + deleted, 0, 0L, tmp_name);
1338
 
  session->some_tables_deleted= 0;
1339
 
 
1340
 
  return false;
1341
 
}
1342
 
 
1343
 
bool alter_table(Session *session,
1344
 
                 TableIdentifier &original_table_identifier,
1345
 
                 TableIdentifier &new_table_identifier,
1346
 
                 HA_CREATE_INFO *create_info,
1347
 
                 const message::Table &original_proto,
1348
 
                 message::Table &create_proto,
1349
 
                 TableList *table_list,
1350
 
                 AlterInfo *alter_info,
1351
 
                 uint32_t order_num,
1352
 
                 Order *order,
1353
 
                 bool ignore)
1354
 
{
1355
 
  bool error;
1356
 
  Table *table;
1357
 
 
1358
 
  if (alter_info->tablespace_op != NO_TABLESPACE_OP)
1359
 
  {
1360
 
    /* DISCARD/IMPORT TABLESPACE is always alone in an ALTER Table */
1361
 
    return mysql_discard_or_import_tablespace(session, table_list, alter_info->tablespace_op);
1362
 
  }
1363
 
 
1364
 
  session->set_proc_info("init");
1365
 
 
1366
 
  if (not (table= session->openTableLock(table_list, TL_WRITE_ALLOW_READ)))
1367
 
    return true;
1368
 
 
1369
 
  session->set_proc_info("gained write lock on table");
1370
 
 
1371
 
  /* 
1372
 
    Check that we are not trying to rename to an existing table,
1373
 
    if one existed we get a lock, if we can't we error.
1374
 
  */
1375
 
  {
1376
 
    Table *name_lock= NULL;
1377
 
 
1378
 
    if (not lockTableIfDifferent(*session, original_table_identifier, new_table_identifier, name_lock))
1379
 
    {
1380
 
      return true;
1381
 
    }
1382
 
 
1383
 
    error= internal_alter_table(session,
1384
 
                                table,
1385
 
                                original_table_identifier,
1386
 
                                new_table_identifier,
1387
 
                                create_info,
1388
 
                                original_proto,
1389
 
                                create_proto,
1390
 
                                table_list,
1391
 
                                alter_info,
1392
 
                                order_num,
1393
 
                                order,
1394
 
                                ignore);
1395
 
 
1396
 
    if (name_lock)
1397
 
    {
1398
 
      table::Cache::singleton().mutex().lock(); /* ALTER TABLe */
1399
 
      session->unlink_open_table(name_lock);
1400
 
      table::Cache::singleton().mutex().unlock();
1401
 
    }
1402
 
  }
1403
 
 
1404
 
  return error;
 
1190
err1:
 
1191
  if (new_table)
 
1192
  {
 
1193
    /* close_temporary_table() frees the new_table pointer. */
 
1194
    session->close_temporary_table(new_table);
 
1195
  }
 
1196
  else
 
1197
  {
 
1198
    TableIdentifier tmp_identifier(new_db, tmp_name, INTERNAL_TMP_TABLE);
 
1199
    quick_rm_table(*session, tmp_identifier);
 
1200
  }
 
1201
 
 
1202
err:
 
1203
  /*
 
1204
    No default value was provided for a DATE/DATETIME field, the
 
1205
    current sql_mode doesn't allow the '0000-00-00' value and
 
1206
    the table to be altered isn't empty.
 
1207
    Report error here.
 
1208
  */
 
1209
  if (alter_info->error_if_not_empty && session->row_count)
 
1210
  {
 
1211
    const char *f_val= 0;
 
1212
    enum enum_drizzle_timestamp_type t_type= DRIZZLE_TIMESTAMP_DATE;
 
1213
    switch (alter_info->datetime_field->sql_type)
 
1214
    {
 
1215
      case DRIZZLE_TYPE_DATE:
 
1216
        f_val= "0000-00-00";
 
1217
        t_type= DRIZZLE_TIMESTAMP_DATE;
 
1218
        break;
 
1219
      case DRIZZLE_TYPE_DATETIME:
 
1220
        f_val= "0000-00-00 00:00:00";
 
1221
        t_type= DRIZZLE_TIMESTAMP_DATETIME;
 
1222
        break;
 
1223
      default:
 
1224
        /* Shouldn't get here. */
 
1225
        assert(0);
 
1226
    }
 
1227
    bool save_abort_on_warning= session->abort_on_warning;
 
1228
    session->abort_on_warning= true;
 
1229
    make_truncated_value_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
1230
                                 f_val, internal::strlength(f_val), t_type,
 
1231
                                 alter_info->datetime_field->field_name);
 
1232
    session->abort_on_warning= save_abort_on_warning;
 
1233
  }
 
1234
  if (name_lock)
 
1235
  {
 
1236
    pthread_mutex_lock(&LOCK_open); /* ALTER TABLe */
 
1237
    session->unlink_open_table(name_lock);
 
1238
    pthread_mutex_unlock(&LOCK_open);
 
1239
  }
 
1240
  return true;
 
1241
 
 
1242
err_with_placeholders:
 
1243
  /*
 
1244
    An error happened while we were holding exclusive name-lock on table
 
1245
    being altered. To be safe under LOCK TABLES we should remove placeholders
 
1246
    from list of open tables list and table cache.
 
1247
  */
 
1248
  session->unlink_open_table(table);
 
1249
  if (name_lock)
 
1250
    session->unlink_open_table(name_lock);
 
1251
  pthread_mutex_unlock(&LOCK_open);
 
1252
  return true;
1405
1253
}
1406
1254
/* alter_table */
1407
1255
 
1408
1256
static int
1409
 
copy_data_between_tables(Session *session,
1410
 
                         Table *from, Table *to,
 
1257
copy_data_between_tables(Table *from, Table *to,
1411
1258
                         List<CreateField> &create,
1412
1259
                         bool ignore,
1413
 
                         uint32_t order_num, Order *order,
 
1260
                         uint32_t order_num, order_st *order,
1414
1261
                         ha_rows *copied,
1415
1262
                         ha_rows *deleted,
1416
1263
                         enum enum_enable_or_disable keys_onoff,
1419
1266
  int error= 0;
1420
1267
  CopyField *copy,*copy_end;
1421
1268
  ulong found_count,delete_count;
 
1269
  Session *session= current_session;
1422
1270
  uint32_t length= 0;
1423
 
  SortField *sortorder;
1424
 
  ReadRecord info;
 
1271
  SORT_FIELD *sortorder;
 
1272
  READ_RECORD info;
1425
1273
  TableList   tables;
1426
1274
  List<Item>   fields;
1427
1275
  List<Item>   all_fields;
1437
1285
  */
1438
1286
  TransactionServices &transaction_services= TransactionServices::singleton();
1439
1287
 
1440
 
  /* 
1441
 
   * LP Bug #552420 
1442
 
   *
1443
 
   * Since open_temporary_table() doesn't invoke lockTables(), we
1444
 
   * don't get the usual automatic call to StorageEngine::startStatement(), so
1445
 
   * we manually call it here...
1446
 
   */
1447
 
  to->getMutableShare()->getEngine()->startStatement(session);
1448
 
 
1449
 
  if (!(copy= new CopyField[to->getShare()->sizeFields()]))
 
1288
  if (!(copy= new CopyField[to->s->fields]))
1450
1289
    return -1;
1451
1290
 
1452
1291
  if (to->cursor->ha_external_lock(session, F_WRLCK))
1453
1292
    return -1;
1454
1293
 
1455
1294
  /* We need external lock before we can disable/enable keys */
1456
 
  alter_table_manage_keys(session, to, from->cursor->indexes_are_disabled(), keys_onoff);
 
1295
  alter_table_manage_keys(to, from->cursor->indexes_are_disabled(), keys_onoff);
1457
1296
 
1458
1297
  /* We can abort alter table for any table type */
1459
1298
  session->abort_on_warning= !ignore;
1464
1303
  List_iterator<CreateField> it(create);
1465
1304
  CreateField *def;
1466
1305
  copy_end=copy;
1467
 
  for (Field **ptr= to->getFields(); *ptr ; ptr++)
 
1306
  for (Field **ptr=to->field ; *ptr ; ptr++)
1468
1307
  {
1469
1308
    def=it++;
1470
1309
    if (def->field)
1481
1320
 
1482
1321
  if (order)
1483
1322
  {
1484
 
    if (to->getShare()->hasPrimaryKey() && to->cursor->primary_key_is_clustered())
 
1323
    if (to->s->primary_key != MAX_KEY && to->cursor->primary_key_is_clustered())
1485
1324
    {
1486
1325
      char warn_buff[DRIZZLE_ERRMSG_SIZE];
1487
1326
      snprintf(warn_buff, sizeof(warn_buff),
1488
1327
               _("order_st BY ignored because there is a user-defined clustered "
1489
1328
                 "index in the table '%-.192s'"),
1490
 
               from->getMutableShare()->getTableName());
 
1329
               from->s->table_name.str);
1491
1330
      push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
1492
1331
                   warn_buff);
1493
1332
    }
1494
1333
    else
1495
1334
    {
1496
 
      FileSort filesort(*session);
1497
1335
      from->sort.io_cache= new internal::IO_CACHE;
 
1336
      memset(from->sort.io_cache, 0, sizeof(internal::IO_CACHE));
1498
1337
 
1499
1338
      memset(&tables, 0, sizeof(tables));
1500
1339
      tables.table= from;
1501
 
      tables.setTableName(const_cast<char *>(from->getMutableShare()->getTableName()));
1502
 
      tables.alias= const_cast<char *>(tables.getTableName());
1503
 
      tables.setSchemaName(const_cast<char *>(from->getMutableShare()->getSchemaName()));
 
1340
      tables.alias= tables.table_name= from->s->table_name.str;
 
1341
      tables.db= from->s->db.str;
1504
1342
      error= 1;
1505
1343
 
1506
1344
      if (session->lex->select_lex.setup_ref_array(session, order_num) ||
1507
1345
          setup_order(session, session->lex->select_lex.ref_pointer_array,
1508
1346
                      &tables, fields, all_fields, order) ||
1509
1347
          !(sortorder= make_unireg_sortorder(order, &length, NULL)) ||
1510
 
          (from->sort.found_records= filesort.run(from, sortorder, length,
1511
 
                                                  (optimizer::SqlSelect *) 0, HA_POS_ERROR,
1512
 
                                                  1, examined_rows)) == HA_POS_ERROR)
1513
 
      {
 
1348
          (from->sort.found_records= filesort(session, from, sortorder, length,
 
1349
                                              (optimizer::SqlSelect *) 0, HA_POS_ERROR,
 
1350
                                              1, &examined_rows)) ==
 
1351
          HA_POS_ERROR)
1514
1352
        goto err;
1515
 
      }
1516
1353
    }
1517
 
  }
 
1354
  };
1518
1355
 
1519
1356
  /* Tell handler that we have values for all columns in the to table */
1520
1357
  to->use_all_columns();
1521
 
  info.init_read_record(session, from, (optimizer::SqlSelect *) 0, 1, true);
 
1358
  init_read_record(&info, session, from, (optimizer::SqlSelect *) 0, 1,1);
1522
1359
  if (ignore)
1523
1360
    to->cursor->extra(HA_EXTRA_IGNORE_DUP_KEY);
1524
1361
  session->row_count= 0;
1525
1362
  to->restoreRecordAsDefault();        // Create empty record
1526
1363
  while (!(error=info.read_record(&info)))
1527
1364
  {
1528
 
    if (session->getKilled())
 
1365
    if (session->killed)
1529
1366
    {
1530
1367
      session->send_kill_message();
1531
1368
      error= 1;
1546
1383
        to->next_number_field->reset();
1547
1384
    }
1548
1385
 
1549
 
    for (CopyField *copy_ptr= copy; copy_ptr != copy_end ; copy_ptr++)
 
1386
    for (CopyField *copy_ptr=copy ; copy_ptr != copy_end ; copy_ptr++)
1550
1387
    {
1551
 
      if (not copy->to_field->hasDefault() and copy->from_null_ptr and  *copy->from_null_ptr & copy->from_bit)
1552
 
      {
1553
 
        copy->to_field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
1554
 
                                    ER_WARN_DATA_TRUNCATED, 1);
1555
 
        copy->to_field->reset();
1556
 
        error= 1;
1557
 
        break;
1558
 
      }
1559
 
 
1560
1388
      copy_ptr->do_copy(copy_ptr);
1561
1389
    }
1562
 
 
1563
 
    if (error)
1564
 
    {
1565
 
      break;
1566
 
    }
1567
 
 
1568
1390
    prev_insert_id= to->cursor->next_insert_id;
1569
 
    error= to->cursor->insertRecord(to->record[0]);
 
1391
    error= to->cursor->ha_write_row(to->record[0]);
1570
1392
    to->auto_increment_field_not_null= false;
1571
 
 
1572
1393
    if (error)
1573
1394
    { 
1574
 
      if (!ignore || to->cursor->is_fatal_error(error, HA_CHECK_DUP))
 
1395
      if (!ignore ||
 
1396
          to->cursor->is_fatal_error(error, HA_CHECK_DUP))
1575
1397
      { 
1576
1398
        to->print_error(error, MYF(0));
1577
1399
        break;
1580
1402
      delete_count++;
1581
1403
    }
1582
1404
    else
1583
 
    {
1584
1405
      found_count++;
1585
 
    }
1586
1406
  }
1587
 
 
1588
 
  info.end_read_record();
 
1407
  end_read_record(&info);
1589
1408
  from->free_io_cache();
1590
1409
  delete [] copy;                               // This is never 0
1591
1410
 
1600
1419
    Ensure that the new table is saved properly to disk so that we
1601
1420
    can do a rename
1602
1421
  */
1603
 
  if (transaction_services.autocommitOrRollback(session, false))
 
1422
  if (transaction_services.ha_autocommit_or_rollback(session, false))
1604
1423
    error=1;
1605
1424
  if (! session->endActiveTransaction())
1606
1425
    error=1;
1613
1432
  to->cursor->ha_release_auto_increment();
1614
1433
  if (to->cursor->ha_external_lock(session,F_UNLCK))
1615
1434
    error=1;
1616
 
 
1617
1435
  return(error > 0 ? -1 : 0);
1618
1436
}
1619
1437
 
1620
1438
static int
1621
1439
create_temporary_table(Session *session,
 
1440
                       Table *table,
1622
1441
                       TableIdentifier &identifier,
1623
1442
                       HA_CREATE_INFO *create_info,
1624
 
                       message::Table &create_proto,
 
1443
                       message::Table *create_proto,
1625
1444
                       AlterInfo *alter_info)
1626
1445
{
1627
1446
  int error;
 
1447
  plugin::StorageEngine *old_db_type, *new_db_type;
 
1448
 
 
1449
  old_db_type= table->s->db_type();
 
1450
  new_db_type= create_info->db_type;
1628
1451
 
1629
1452
  /*
1630
1453
    Create a table with a temporary name.
1631
1454
    We don't log the statement, it will be logged later.
1632
1455
  */
1633
 
  create_proto.set_name(identifier.getTableName());
 
1456
  create_proto->set_name(identifier.getTableName());
1634
1457
 
1635
 
  create_proto.mutable_engine()->set_name(create_info->db_type->getName());
 
1458
  message::Table::StorageEngine *protoengine;
 
1459
  protoengine= create_proto->mutable_engine();
 
1460
  protoengine->set_name(new_db_type->getName());
1636
1461
 
1637
1462
  error= mysql_create_table(session,
1638
1463
                            identifier,
1641
1466
  return error;
1642
1467
}
1643
1468
 
1644
 
static Table *open_alter_table(Session *session, Table *table, TableIdentifier &identifier)
 
1469
static Table *open_alter_table(Session *session, Table *table, char *db, char *table_name)
1645
1470
{
1646
1471
  Table *new_table;
1647
1472
 
1648
1473
  /* Open the table so we need to copy the data to it. */
1649
 
  if (table->getShare()->getType())
 
1474
  if (table->s->tmp_table)
1650
1475
  {
1651
1476
    TableList tbl;
1652
 
    tbl.setSchemaName(const_cast<char *>(identifier.getSchemaName().c_str()));
1653
 
    tbl.alias= const_cast<char *>(identifier.getTableName().c_str());
1654
 
    tbl.setTableName(const_cast<char *>(identifier.getTableName().c_str()));
 
1477
    tbl.db= db;
 
1478
    tbl.alias= table_name;
 
1479
    tbl.table_name= table_name;
1655
1480
 
1656
1481
    /* Table is in session->temporary_tables */
1657
1482
    new_table= session->openTable(&tbl, (bool*) 0, DRIZZLE_LOCK_IGNORE_FLUSH);
1658
1483
  }
1659
1484
  else
1660
1485
  {
 
1486
    TableIdentifier new_identifier(db, table_name, INTERNAL_TMP_TABLE);
 
1487
 
1661
1488
    /* Open our intermediate table */
1662
 
    new_table= session->open_temporary_table(identifier, false);
 
1489
    new_table= session->open_temporary_table(new_identifier, false);
1663
1490
  }
1664
1491
 
1665
1492
  return new_table;