~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/statement/alter_table.cc

  • Committer: Paul McCullagh
  • Date: 2010-05-26 10:17:56 UTC
  • mto: (1567.1.3 new-staging)
  • mto: This revision was merged to the branch mainline in revision 1568.
  • Revision ID: paul.mccullagh@primebase.org-20100526101756-3qdwb9id3qhog0z1
Adjust for namespace changes

Show diffs side-by-side

added added

removed removed

Lines of Context:
44
44
 
45
45
#include "drizzled/transaction_services.h"
46
46
 
47
 
#include "drizzled/filesort.h"
48
 
 
49
 
#include "drizzled/message.h"
50
 
 
51
47
using namespace std;
52
48
 
53
49
namespace drizzled
55
51
 
56
52
extern pid_t current_pid;
57
53
 
58
 
static int copy_data_between_tables(Session *session,
59
 
                                    Table *from,Table *to,
 
54
static int copy_data_between_tables(Table *from,Table *to,
60
55
                                    List<CreateField> &create,
61
56
                                    bool ignore,
62
57
                                    uint32_t order_num,
63
 
                                    Order *order,
 
58
                                    order_st *order,
64
59
                                    ha_rows *copied,
65
60
                                    ha_rows *deleted,
66
61
                                    enum enum_enable_or_disable keys_onoff,
107
102
  assert(select_lex->db);
108
103
 
109
104
  /* 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;
 
105
  message::Table original_table_message;
111
106
  {
112
 
    TableIdentifier identifier(first_table->getSchemaName(), first_table->getTableName());
 
107
    TableIdentifier identifier(first_table->db, first_table->table_name);
113
108
    if (plugin::StorageEngine::getTableDefinition(*session, identifier, original_table_message) != EEXIST)
114
109
    {
115
 
      std::string path;
116
 
      identifier.getSQLPath(path);
117
 
      my_error(ER_BAD_TABLE_ERROR, MYF(0), path.c_str());
 
110
      my_error(ER_BAD_TABLE_ERROR, MYF(0), identifier.getSQLPath().c_str());
118
111
      return true;
119
112
    }
120
113
 
121
114
    if (not  create_info.db_type)
122
115
    {
123
116
      create_info.db_type= 
124
 
        plugin::StorageEngine::findByName(*session, original_table_message->engine().name());
 
117
        plugin::StorageEngine::findByName(*session, original_table_message.engine().name());
125
118
 
126
119
      if (not create_info.db_type)
127
120
      {
128
 
        std::string path;
129
 
        identifier.getSQLPath(path);
130
 
        my_error(ER_BAD_TABLE_ERROR, MYF(0), path.c_str());
 
121
        my_error(ER_BAD_TABLE_ERROR, MYF(0), identifier.getSQLPath().c_str());
131
122
        return true;
132
123
      }
133
124
    }
134
125
  }
135
126
 
136
127
  if (not validateCreateTableOption())
 
128
  {
137
129
    return true;
 
130
  }
138
131
 
139
132
  /* ALTER TABLE ends previous transaction */
140
133
  if (not session->endActiveTransaction())
 
134
  {
141
135
    return true;
 
136
  }
142
137
 
143
 
  if (not (need_start_waiting= not session->wait_if_global_read_lock(0, 1)))
 
138
  if (not (need_start_waiting= ! wait_if_global_read_lock(session, 0, 1)))
 
139
  {
144
140
    return true;
 
141
  }
145
142
 
146
143
  bool res;
147
 
  if (original_table_message->type() == message::Table::STANDARD )
 
144
  if (original_table_message.type() == message::Table::STANDARD )
148
145
  {
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());
 
146
    TableIdentifier identifier(first_table->db, first_table->table_name);
 
147
    TableIdentifier new_identifier(select_lex->db ? select_lex->db : first_table->db,
 
148
                                   session->lex->name.str ? session->lex->name.str : first_table->table_name);
152
149
 
153
150
    res= alter_table(session, 
154
151
                     identifier,
155
152
                     new_identifier,
156
153
                     &create_info,
157
 
                     *original_table_message,
 
154
                     original_table_message,
158
155
                     create_table_message,
159
156
                     first_table,
160
157
                     &alter_info,
161
158
                     select_lex->order_list.elements,
162
 
                     (Order *) select_lex->order_list.first,
 
159
                     (order_st *) select_lex->order_list.first,
163
160
                     session->lex->ignore);
164
161
  }
165
162
  else
166
163
  {
167
 
    TableIdentifier catch22(first_table->getSchemaName(), first_table->getTableName());
168
 
    Table *table= session->find_temporary_table(catch22);
 
164
    Table *table= session->find_temporary_table(first_table);
169
165
    assert(table);
170
166
    {
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());
 
167
      TableIdentifier identifier(first_table->db, first_table->table_name, table->s->getPath());
 
168
      TableIdentifier new_identifier(select_lex->db ? select_lex->db : first_table->db,
 
169
                                     session->lex->name.str ? session->lex->name.str : first_table->table_name,
 
170
                                     table->s->getPath());
175
171
 
176
172
      res= alter_table(session, 
177
173
                       identifier,
178
174
                       new_identifier,
179
175
                       &create_info,
180
 
                       *original_table_message,
 
176
                       original_table_message,
181
177
                       create_table_message,
182
178
                       first_table,
183
179
                       &alter_info,
184
180
                       select_lex->order_list.elements,
185
 
                       (Order *) select_lex->order_list.first,
 
181
                       (order_st *) select_lex->order_list.first,
186
182
                       session->lex->ignore);
187
183
    }
188
184
  }
191
187
     Release the protection against the global read lock and wake
192
188
     everyone, who might want to set a global read lock.
193
189
   */
194
 
  session->startWaitingGlobalReadLock();
195
 
 
 
190
  start_waiting_global_read_lock(session);
196
191
  return res;
197
192
}
198
193
 
264
259
  table_options= table_message.mutable_options();
265
260
 
266
261
  if (! (used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
267
 
    create_info->default_table_charset= table->getShare()->table_charset;
 
262
    create_info->default_table_charset= table->s->table_charset;
268
263
  if (! (used_fields & HA_CREATE_USED_AUTO) &&
269
264
      table->found_next_number_field)
270
265
  {
271
266
    /* Table has an autoincrement, copy value to new table */
272
267
    table->cursor->info(HA_STATUS_AUTO);
273
268
    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
269
  }
277
270
  table->restoreRecordAsDefault(); /* Empty record for DEFAULT */
278
271
  CreateField *def;
280
273
  /* First collect all fields from table which isn't in drop_list */
281
274
  Field **f_ptr;
282
275
  Field *field;
283
 
  for (f_ptr= table->getFields(); (field= *f_ptr); f_ptr++)
 
276
  for (f_ptr= table->field; (field= *f_ptr); f_ptr++)
284
277
  {
285
278
    /* Check if field should be dropped */
286
279
    AlterDrop *drop;
347
340
        if (def->sql_type == DRIZZLE_TYPE_BLOB)
348
341
        {
349
342
          my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), def->change);
350
 
          return true;
 
343
                goto err;
351
344
        }
352
345
        if ((def->def= alter->def))
353
346
        {
355
348
          def->flags&= ~NO_DEFAULT_VALUE_FLAG;
356
349
        }
357
350
        else
358
 
        {
359
351
          def->flags|= NO_DEFAULT_VALUE_FLAG;
360
 
        }
361
352
        alter_it.remove();
362
353
      }
363
354
    }
367
358
  {
368
359
    if (def->change && ! def->field)
369
360
    {
370
 
      my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table->getMutableShare()->getTableName());
371
 
      return true;
 
361
      my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table->s->getTableName());
 
362
      goto err;
372
363
    }
373
364
    /*
374
 
      If we have been given a field which has no default value, and is not null then we need to bail.
 
365
      Check that the DATE/DATETIME not null field we are going to add is
 
366
      either has a default value or the '0000-00-00' is allowed by the
 
367
      set sql mode.
 
368
      If the '0000-00-00' value isn't allowed then raise the error_if_not_empty
 
369
      flag to allow ALTER Table only if the table to be altered is empty.
375
370
    */
376
 
    if (not (~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) and not def->change)
 
371
    if ((def->sql_type == DRIZZLE_TYPE_DATE ||
 
372
         def->sql_type == DRIZZLE_TYPE_DATETIME) &&
 
373
        ! alter_info->datetime_field &&
 
374
        ! (~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) &&
 
375
        session->variables.sql_mode & MODE_NO_ZERO_DATE)
377
376
    {
 
377
      alter_info->datetime_field= def;
378
378
      alter_info->error_if_not_empty= true;
379
379
    }
380
380
    if (! def->after)
381
 
    {
382
381
      new_create_list.push_back(def);
383
 
    }
384
382
    else if (def->after == first_keyword)
385
 
    {
386
383
      new_create_list.push_front(def);
387
 
    }
388
384
    else
389
385
    {
390
386
      CreateField *find;
396
392
      }
397
393
      if (! find)
398
394
      {
399
 
        my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table->getMutableShare()->getTableName());
400
 
        return true;
 
395
        my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table->s->getTableName());
 
396
        goto err;
401
397
      }
402
398
      find_it.after(def); /* Put element after this */
403
399
      /*
412
408
      */
413
409
      if (alter_info->build_method == HA_BUILD_ONLINE)
414
410
      {
415
 
        my_error(ER_NOT_SUPPORTED_YET, MYF(0), session->getQueryString()->c_str());
416
 
        return true;
 
411
        my_error(ER_NOT_SUPPORTED_YET, MYF(0), session->query.c_str());
 
412
        goto err;
417
413
      }
418
414
      alter_info->build_method= HA_BUILD_OFFLINE;
419
415
    }
423
419
    my_error(ER_BAD_FIELD_ERROR,
424
420
             MYF(0),
425
421
             alter_info->alter_list.head()->name,
426
 
             table->getMutableShare()->getTableName());
427
 
    return true;
 
422
             table->s->getTableName());
 
423
    goto err;
428
424
  }
429
425
  if (! new_create_list.elements)
430
426
  {
431
427
    my_message(ER_CANT_REMOVE_ALL_FIELDS,
432
428
               ER(ER_CANT_REMOVE_ALL_FIELDS),
433
429
               MYF(0));
434
 
    return true;
 
430
    goto err;
435
431
  }
436
432
 
437
433
  /*
438
434
    Collect all keys which isn't in drop list. Add only those
439
435
    for which some fields exists.
440
436
  */
441
 
  for (uint32_t i= 0; i < table->getShare()->sizeKeys(); i++, key_info++)
 
437
  for (uint32_t i= 0; i < table->s->keys; i++, key_info++)
442
438
  {
443
439
    char *key_name= key_info->name;
444
440
    AlterDrop *drop;
537
533
      new_key_list.push_back(key);
538
534
    }
539
535
  }
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
536
  {
565
537
    Key *key;
566
538
    while ((key= key_it++)) /* Add new keys */
567
539
    {
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
 
 
 
540
      if (key->type == Key::FOREIGN_KEY &&
 
541
          ((Foreign_key *)key)->validate(new_create_list))
 
542
        goto err;
586
543
      if (key->type != Key::FOREIGN_KEY)
587
544
        new_key_list.push_back(key);
588
 
 
589
545
      if (key->name.str && is_primary_key_name(key->name.str))
590
546
      {
591
547
        my_error(ER_WRONG_NAME_FOR_INDEX,
592
548
                 MYF(0),
593
549
                 key->name.str);
594
 
        return true;
 
550
        goto err;
595
551
      }
596
552
    }
597
553
  }
598
554
 
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
555
  if (alter_info->drop_list.elements)
617
556
  {
618
557
    my_error(ER_CANT_DROP_FIELD_OR_KEY,
619
558
             MYF(0),
620
559
             alter_info->drop_list.head()->name);
621
 
    return true;
 
560
    goto err;
622
561
  }
623
562
  if (alter_info->alter_list.elements)
624
563
  {
625
564
    my_error(ER_CANT_DROP_FIELD_OR_KEY,
626
565
             MYF(0),
627
566
             alter_info->alter_list.head()->name);
628
 
    return true;
 
567
    goto err;
629
568
  }
630
569
 
631
570
  if (not table_message.options().has_comment()
632
 
      && table->getMutableShare()->hasComment())
633
 
    table_options->set_comment(table->getMutableShare()->getComment());
 
571
      && table->s->hasComment())
 
572
    table_options->set_comment(table->s->getComment());
634
573
 
635
 
  if (table->getShare()->getType())
 
574
  if (table->s->tmp_table)
636
575
  {
637
576
    table_message.set_type(message::Table::TEMPORARY);
638
577
  }
639
578
 
640
579
  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());
 
580
 
 
581
  table_message.set_update_timestamp(time(NULL));
643
582
 
644
583
  rc= false;
645
584
  alter_info->create_list.swap(new_create_list);
646
585
  alter_info->key_list.swap(new_key_list);
 
586
err:
647
587
 
648
588
  size_t num_engine_options= table_message.engine().options_size();
649
589
  size_t original_num_engine_options= original_proto.engine().options_size();
668
608
    }
669
609
  }
670
610
 
671
 
  drizzled::message::update(table_message);
672
 
 
673
 
  return false;
 
611
  return rc;
674
612
}
675
613
 
676
614
/* table_list should contain just one table */
712
650
 
713
651
  /* The ALTER Table is always in its own transaction */
714
652
  error= transaction_services.autocommitOrRollback(session, false);
715
 
  if (not session->endActiveTransaction())
 
653
  if (! session->endActiveTransaction())
716
654
    error=1;
717
 
 
718
655
  if (error)
719
656
    goto err;
720
 
 
721
 
  write_bin_log(session, *session->getQueryString());
 
657
  write_bin_log(session, session->query.c_str());
722
658
 
723
659
err:
724
660
  (void) transaction_services.autocommitOrRollback(session, error);
749
685
    false  OK
750
686
    true   Error
751
687
*/
752
 
static bool alter_table_manage_keys(Session *session,
753
 
                                    Table *table, int indexes_were_disabled,
 
688
static bool alter_table_manage_keys(Table *table, int indexes_were_disabled,
754
689
                                    enum enum_enable_or_disable keys_onoff)
755
690
{
756
691
  int error= 0;
768
703
 
769
704
  if (error == HA_ERR_WRONG_COMMAND)
770
705
  {
771
 
    push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
706
    push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
772
707
                        ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
773
 
                        table->getMutableShare()->getTableName());
 
708
                        table->s->getTableName());
774
709
    error= 0;
775
710
  } else if (error)
776
711
    table->print_error(error, MYF(0));
791
726
 
792
727
      if (session.find_temporary_table(new_table_identifier))
793
728
      {
794
 
        std::string path;
795
 
        new_table_identifier.getSQLPath(path);
796
 
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
 
729
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_table_identifier.getSQLPath().c_str());
797
730
        return false;
798
731
      }
799
732
    }
806
739
 
807
740
      if (not name_lock)
808
741
      {
809
 
        std::string path;
810
 
        new_table_identifier.getSQLPath(path);
811
 
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
 
742
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_table_identifier.getSQLPath().c_str());
812
743
        return false;
813
744
      }
814
745
 
815
746
      if (plugin::StorageEngine::doesTableExist(session, new_table_identifier))
816
747
      {
817
 
        std::string path;
818
 
        new_table_identifier.getSQLPath(path);
819
 
 
820
748
        /* Table will be closed by Session::executeCommand() */
821
 
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
 
749
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_table_identifier.getSQLPath().c_str());
822
750
 
823
 
        table::Cache::singleton().mutex().lock(); /* ALTER TABLe */
 
751
        pthread_mutex_lock(&LOCK_open); /* ALTER TABLe */
824
752
        session.unlink_open_table(name_lock);
825
 
        table::Cache::singleton().mutex().unlock();
 
753
        pthread_mutex_unlock(&LOCK_open);
826
754
 
827
755
        return false;
828
756
      }
884
812
                                 TableList *table_list,
885
813
                                 AlterInfo *alter_info,
886
814
                                 uint32_t order_num,
887
 
                                 Order *order,
 
815
                                 order_st *order,
888
816
                                 bool ignore)
889
817
{
 
818
  Table *new_table= NULL;
890
819
  int error= 0;
891
820
  char tmp_name[80];
892
821
  char old_name[32];
893
822
  ha_rows copied= 0;
894
823
  ha_rows deleted= 0;
895
824
 
896
 
  if (not original_table_identifier.isValid())
897
 
    return true;
898
 
 
899
 
  if (not new_table_identifier.isValid())
900
 
    return true;
 
825
  message::Table *original_table_definition= table->s->getTableProto();
901
826
 
902
827
  session->set_proc_info("init");
903
828
 
906
831
  plugin::StorageEngine *new_engine;
907
832
  plugin::StorageEngine *original_engine;
908
833
 
909
 
  original_engine= table->getMutableShare()->getEngine();
 
834
  original_engine= table->s->getEngine();
910
835
 
911
836
  if (not create_info->db_type)
912
837
  {
934
859
  if (original_engine->check_flag(HTON_BIT_ALTER_NOT_SUPPORTED) ||
935
860
      new_engine->check_flag(HTON_BIT_ALTER_NOT_SUPPORTED))
936
861
  {
937
 
    std::string path;
938
 
    new_table_identifier.getSQLPath(path);
939
 
    my_error(ER_ILLEGAL_HA, MYF(0), path.c_str());
 
862
    my_error(ER_ILLEGAL_HA, MYF(0), new_table_identifier.getSQLPath().c_str());
940
863
 
941
864
    return true;
942
865
  }
943
866
 
 
867
  if (create_info->row_type == ROW_TYPE_NOT_USED)
 
868
  {
 
869
    message::Table::TableOptions *table_options;
 
870
    table_options= create_proto.mutable_options();
 
871
 
 
872
    create_info->row_type= table->s->row_type;
 
873
    table_options->set_row_type(original_table_definition->options().row_type());
 
874
  }
 
875
 
944
876
  session->set_proc_info("setup");
945
877
 
946
878
  /*
954
886
    tmp.reset(ALTER_KEYS_ONOFF);
955
887
    tmp&= alter_info->flags;
956
888
 
957
 
    if (! (tmp.any()) && ! table->getShare()->getType()) // no need to touch frm
 
889
    if (! (tmp.any()) && ! table->s->tmp_table) // no need to touch frm
958
890
    {
959
891
      switch (alter_info->keys_onoff)
960
892
      {
970
902
          while the fact that the table is still open gives us protection
971
903
          from concurrent DDL statements.
972
904
        */
973
 
        table::Cache::singleton().mutex().lock(); /* DDL wait for/blocker */
 
905
        pthread_mutex_lock(&LOCK_open); /* DDL wait for/blocker */
974
906
        wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
975
 
        table::Cache::singleton().mutex().unlock();
 
907
        pthread_mutex_unlock(&LOCK_open);
976
908
        error= table->cursor->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
977
909
        /* COND_refresh will be signaled in close_thread_tables() */
978
910
        break;
979
911
      case DISABLE:
980
 
        table::Cache::singleton().mutex().lock(); /* DDL wait for/blocker */
 
912
        pthread_mutex_lock(&LOCK_open); /* DDL wait for/blocker */
981
913
        wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
982
 
        table::Cache::singleton().mutex().unlock();
 
914
        pthread_mutex_unlock(&LOCK_open);
983
915
        error=table->cursor->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
984
916
        /* COND_refresh will be signaled in close_thread_tables() */
985
917
        break;
994
926
        error= 0;
995
927
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
996
928
                            ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
997
 
                            table->getAlias());
 
929
                            table->alias);
998
930
      }
999
931
 
1000
 
      table::Cache::singleton().mutex().lock(); /* Lock to remove all instances of table from table cache before ALTER */
 
932
      pthread_mutex_lock(&LOCK_open); /* Lock to remove all instances of table from table cache before ALTER */
1001
933
      /*
1002
934
        Unlike to the above case close_cached_table() below will remove ALL
1003
935
        instances of Table from table cache (it will also remove table lock
1004
936
        held by this thread). So to make actual table renaming and writing
1005
937
        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
 
938
        protected by LOCK_open mutex. This also removes gap for races between
1007
939
        access() and mysql_rename_table() calls.
1008
940
      */
1009
941
 
1025
957
        */
1026
958
        if (plugin::StorageEngine::doesTableExist(*session, new_table_identifier))
1027
959
        {
1028
 
          std::string path;
1029
 
          new_table_identifier.getSQLPath(path);
1030
 
          my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
 
960
          my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_table_identifier.getSQLPath().c_str());
1031
961
          error= -1;
1032
962
        }
1033
963
        else
1034
964
        {
1035
 
          if (mysql_rename_table(*session, original_engine, original_table_identifier, new_table_identifier))
 
965
          if (mysql_rename_table(original_engine, original_table_identifier, new_table_identifier))
1036
966
          {
1037
967
            error= -1;
1038
968
          }
1044
974
        error= 0;
1045
975
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1046
976
                            ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
1047
 
                            table->getAlias());
 
977
                            table->alias);
1048
978
      }
1049
979
 
1050
980
      if (error == 0)
1051
981
      {
1052
 
        TransactionServices &transaction_services= TransactionServices::singleton();
1053
 
        transaction_services.allocateNewTransactionId();
1054
 
        write_bin_log(session, *session->getQueryString());
 
982
        write_bin_log(session, session->query.c_str());
1055
983
        session->my_ok();
1056
984
      }
1057
985
      else if (error > 0)
1060
988
        error= -1;
1061
989
      }
1062
990
 
1063
 
      table::Cache::singleton().mutex().unlock();
 
991
      pthread_mutex_unlock(&LOCK_open);
1064
992
      table_list->table= NULL;
1065
993
 
1066
994
      return error;
1100
1028
  }
1101
1029
 
1102
1030
  /* 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
 
 
 
1031
  new_table= open_alter_table(session, table, new_table_as_temporary);
1105
1032
 
1106
1033
  if (not new_table)
1107
1034
  {
1108
 
    plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
 
1035
    quick_rm_table(*session, new_table_as_temporary);
1109
1036
    return true;
1110
1037
  }
1111
1038
 
1112
1039
  /* Copy the data if necessary. */
1113
1040
  {
1114
 
    /* We must not ignore bad input! */
1115
 
    session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;    // calc cuted fields
 
1041
    session->count_cuted_fields= CHECK_FIELD_WARN;      // calc cuted fields
1116
1042
    session->cuted_fields= 0L;
1117
1043
    session->set_proc_info("copy to tmp table");
1118
1044
    copied= deleted= 0;
1120
1046
    /* We don't want update TIMESTAMP fields during ALTER Table. */
1121
1047
    new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
1122
1048
    new_table->next_number_field= new_table->found_next_number_field;
1123
 
    error= copy_data_between_tables(session,
1124
 
                                    table,
 
1049
    error= copy_data_between_tables(table,
1125
1050
                                    new_table,
1126
1051
                                    alter_info->create_list,
1127
1052
                                    ignore,
1133
1058
                                    alter_info->error_if_not_empty);
1134
1059
 
1135
1060
    /* We must not ignore bad input! */
1136
 
    assert(session->count_cuted_fields == CHECK_FIELD_ERROR_FOR_NULL);
 
1061
    session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
1137
1062
  }
1138
1063
 
1139
1064
  /* Now we need to resolve what just happened with the data copy. */
1149
1074
    */
1150
1075
    if (alter_info->error_if_not_empty && session->row_count)
1151
1076
    {
1152
 
      my_error(ER_INVALID_ALTER_TABLE_FOR_NOT_NULL, MYF(0));
 
1077
      const char *f_val= 0;
 
1078
      enum enum_drizzle_timestamp_type t_type= DRIZZLE_TIMESTAMP_DATE;
 
1079
 
 
1080
      switch (alter_info->datetime_field->sql_type)
 
1081
      {
 
1082
      case DRIZZLE_TYPE_DATE:
 
1083
        f_val= "0000-00-00";
 
1084
        t_type= DRIZZLE_TIMESTAMP_DATE;
 
1085
        break;
 
1086
      case DRIZZLE_TYPE_DATETIME:
 
1087
        f_val= "0000-00-00 00:00:00";
 
1088
        t_type= DRIZZLE_TIMESTAMP_DATETIME;
 
1089
        break;
 
1090
      default:
 
1091
        /* Shouldn't get here. */
 
1092
        assert(0);
 
1093
      }
 
1094
      bool save_abort_on_warning= session->abort_on_warning;
 
1095
      session->abort_on_warning= true;
 
1096
      make_truncated_value_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
1097
                                   f_val, internal::strlength(f_val), t_type,
 
1098
                                   alter_info->datetime_field->field_name);
 
1099
      session->abort_on_warning= save_abort_on_warning;
1153
1100
    }
1154
1101
 
1155
1102
    if (original_table_identifier.isTmp())
1161
1108
      }
1162
1109
      else
1163
1110
      {
1164
 
        plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
 
1111
        quick_rm_table(*session, new_table_as_temporary);
1165
1112
      }
1166
1113
 
1167
1114
      return true;
1175
1122
          Note that MERGE tables do not have their children attached here.
1176
1123
        */
1177
1124
        new_table->intern_close_table();
1178
 
        if (new_table->hasShare())
 
1125
        if (new_table->s)
1179
1126
        {
1180
 
          delete new_table->getMutableShare();
 
1127
          if (new_table->s->newed)
 
1128
          {
 
1129
            delete new_table->s;
 
1130
          }
 
1131
          else
 
1132
          {
 
1133
            free(new_table->s);
 
1134
          }
 
1135
 
 
1136
          new_table->s= NULL;
1181
1137
        }
1182
1138
 
1183
 
        delete new_table;
 
1139
        free(new_table);
1184
1140
      }
1185
1141
 
1186
 
      table::Cache::singleton().mutex().lock(); /* ALTER TABLE */
 
1142
      pthread_mutex_lock(&LOCK_open); /* ALTER TABLE */
1187
1143
 
1188
 
      plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
1189
 
      table::Cache::singleton().mutex().unlock();
 
1144
      quick_rm_table(*session, new_table_as_temporary);
 
1145
      pthread_mutex_unlock(&LOCK_open);
1190
1146
 
1191
1147
      return true;
1192
1148
    }
1197
1153
    /* Close lock if this is a transactional table */
1198
1154
    if (session->lock)
1199
1155
    {
1200
 
      session->unlockTables(session->lock);
 
1156
      mysql_unlock_tables(session, session->lock);
1201
1157
      session->lock= 0;
1202
1158
    }
1203
1159
 
1205
1161
    session->close_temporary_table(table);
1206
1162
 
1207
1163
    /* Should pass the 'new_name' as we store table name in the cache */
1208
 
    new_table->getMutableShare()->setIdentifier(new_table_identifier);
 
1164
    if (new_table->renameAlterTemporaryTable(new_table_identifier))
 
1165
    {
 
1166
      session->close_temporary_table(new_table);
 
1167
 
 
1168
      return true;
 
1169
    }
1209
1170
 
1210
1171
    new_table_identifier.setPath(new_table_as_temporary.getPath());
1211
1172
 
1212
 
    if (mysql_rename_table(*session, new_engine, new_table_as_temporary, new_table_identifier) != 0)
 
1173
    if (mysql_rename_table(new_engine, new_table_as_temporary, new_table_identifier) != 0)
1213
1174
    {
1214
1175
      return true;
1215
1176
    }
1225
1186
      */
1226
1187
      new_table->intern_close_table();
1227
1188
 
1228
 
      if (new_table->hasShare())
 
1189
      if (new_table->s)
1229
1190
      {
1230
 
        delete new_table->getMutableShare();
 
1191
        if (new_table->s->newed)
 
1192
        {
 
1193
          delete new_table->s;
 
1194
        }
 
1195
        else
 
1196
        {
 
1197
          free(new_table->s);
 
1198
        }
 
1199
 
 
1200
        new_table->s= NULL;
1231
1201
      }
1232
1202
 
1233
 
      delete new_table;
 
1203
      free(new_table);
1234
1204
    }
1235
1205
 
1236
 
    table::Cache::singleton().mutex().lock(); /* ALTER TABLE */
 
1206
    pthread_mutex_lock(&LOCK_open); /* ALTER TABLE */
1237
1207
 
1238
1208
    /*
1239
1209
      Data is copied. Now we:
1272
1242
      compare_table(). Then, we need one additional call to
1273
1243
    */
1274
1244
    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);
 
1245
                                           old_name, message::Table::TEMPORARY);
1277
1246
 
1278
 
    if (mysql_rename_table(*session, original_engine, original_table_identifier, original_table_to_drop))
 
1247
    if (mysql_rename_table(original_engine, original_table_identifier, original_table_to_drop))
1279
1248
    {
1280
1249
      error= 1;
1281
 
      plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
 
1250
      quick_rm_table(*session, new_table_as_temporary);
1282
1251
    }
1283
1252
    else
1284
1253
    {
1285
 
      if (mysql_rename_table(*session, new_engine, new_table_as_temporary, new_table_identifier) != 0)
 
1254
      if (mysql_rename_table(new_engine, new_table_as_temporary, new_table_identifier) != 0)
1286
1255
      {
1287
1256
        /* Try to get everything back. */
1288
1257
        error= 1;
1289
1258
 
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);
 
1259
        quick_rm_table(*session, new_table_identifier);
 
1260
 
 
1261
        quick_rm_table(*session, new_table_as_temporary);
 
1262
 
 
1263
        mysql_rename_table(original_engine, original_table_to_drop, original_table_identifier);
1295
1264
      }
1296
1265
      else
1297
1266
      {
1298
 
        plugin::StorageEngine::dropTable(*session, original_table_to_drop);
 
1267
        quick_rm_table(*session, original_table_to_drop);
1299
1268
      }
1300
1269
    }
1301
1270
 
1307
1276
        from list of open tables list and table cache.
1308
1277
      */
1309
1278
      session->unlink_open_table(table);
1310
 
      table::Cache::singleton().mutex().unlock();
 
1279
      pthread_mutex_unlock(&LOCK_open);
1311
1280
 
1312
1281
      return true;
1313
1282
    }
1314
1283
 
1315
 
    table::Cache::singleton().mutex().unlock();
 
1284
    pthread_mutex_unlock(&LOCK_open);
1316
1285
 
1317
1286
    session->set_proc_info("end");
1318
1287
 
1319
 
    write_bin_log(session, *session->getQueryString());
 
1288
    write_bin_log(session, session->query.c_str());
1320
1289
    table_list->table= NULL;
1321
1290
  }
1322
1291
 
1349
1318
                 TableList *table_list,
1350
1319
                 AlterInfo *alter_info,
1351
1320
                 uint32_t order_num,
1352
 
                 Order *order,
 
1321
                 order_st *order,
1353
1322
                 bool ignore)
1354
1323
{
1355
1324
  bool error;
1395
1364
 
1396
1365
    if (name_lock)
1397
1366
    {
1398
 
      table::Cache::singleton().mutex().lock(); /* ALTER TABLe */
 
1367
      pthread_mutex_lock(&LOCK_open); /* ALTER TABLe */
1399
1368
      session->unlink_open_table(name_lock);
1400
 
      table::Cache::singleton().mutex().unlock();
 
1369
      pthread_mutex_unlock(&LOCK_open);
1401
1370
    }
1402
1371
  }
1403
1372
 
1406
1375
/* alter_table */
1407
1376
 
1408
1377
static int
1409
 
copy_data_between_tables(Session *session,
1410
 
                         Table *from, Table *to,
 
1378
copy_data_between_tables(Table *from, Table *to,
1411
1379
                         List<CreateField> &create,
1412
1380
                         bool ignore,
1413
 
                         uint32_t order_num, Order *order,
 
1381
                         uint32_t order_num, order_st *order,
1414
1382
                         ha_rows *copied,
1415
1383
                         ha_rows *deleted,
1416
1384
                         enum enum_enable_or_disable keys_onoff,
1419
1387
  int error= 0;
1420
1388
  CopyField *copy,*copy_end;
1421
1389
  ulong found_count,delete_count;
 
1390
  Session *session= current_session;
1422
1391
  uint32_t length= 0;
1423
 
  SortField *sortorder;
 
1392
  SORT_FIELD *sortorder;
1424
1393
  ReadRecord info;
1425
1394
  TableList   tables;
1426
1395
  List<Item>   fields;
1437
1406
  */
1438
1407
  TransactionServices &transaction_services= TransactionServices::singleton();
1439
1408
 
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()]))
 
1409
  if (!(copy= new CopyField[to->s->fields]))
1450
1410
    return -1;
1451
1411
 
1452
1412
  if (to->cursor->ha_external_lock(session, F_WRLCK))
1453
1413
    return -1;
1454
1414
 
1455
1415
  /* We need external lock before we can disable/enable keys */
1456
 
  alter_table_manage_keys(session, to, from->cursor->indexes_are_disabled(), keys_onoff);
 
1416
  alter_table_manage_keys(to, from->cursor->indexes_are_disabled(), keys_onoff);
1457
1417
 
1458
1418
  /* We can abort alter table for any table type */
1459
1419
  session->abort_on_warning= !ignore;
1464
1424
  List_iterator<CreateField> it(create);
1465
1425
  CreateField *def;
1466
1426
  copy_end=copy;
1467
 
  for (Field **ptr= to->getFields(); *ptr ; ptr++)
 
1427
  for (Field **ptr=to->field ; *ptr ; ptr++)
1468
1428
  {
1469
1429
    def=it++;
1470
1430
    if (def->field)
1481
1441
 
1482
1442
  if (order)
1483
1443
  {
1484
 
    if (to->getShare()->hasPrimaryKey() && to->cursor->primary_key_is_clustered())
 
1444
    if (to->s->primary_key != MAX_KEY && to->cursor->primary_key_is_clustered())
1485
1445
    {
1486
1446
      char warn_buff[DRIZZLE_ERRMSG_SIZE];
1487
1447
      snprintf(warn_buff, sizeof(warn_buff),
1488
1448
               _("order_st BY ignored because there is a user-defined clustered "
1489
1449
                 "index in the table '%-.192s'"),
1490
 
               from->getMutableShare()->getTableName());
 
1450
               from->s->getTableName());
1491
1451
      push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
1492
1452
                   warn_buff);
1493
1453
    }
1494
1454
    else
1495
1455
    {
1496
 
      FileSort filesort(*session);
1497
1456
      from->sort.io_cache= new internal::IO_CACHE;
 
1457
      memset(from->sort.io_cache, 0, sizeof(internal::IO_CACHE));
1498
1458
 
1499
1459
      memset(&tables, 0, sizeof(tables));
1500
1460
      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()));
 
1461
      tables.alias= tables.table_name= const_cast<char *>(from->s->getTableName());
 
1462
      tables.db= const_cast<char *>(from->s->getSchemaName());
1504
1463
      error= 1;
1505
1464
 
1506
1465
      if (session->lex->select_lex.setup_ref_array(session, order_num) ||
1507
1466
          setup_order(session, session->lex->select_lex.ref_pointer_array,
1508
1467
                      &tables, fields, all_fields, order) ||
1509
1468
          !(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)
 
1469
          (from->sort.found_records= filesort(session, from, sortorder, length,
 
1470
                                              (optimizer::SqlSelect *) 0, HA_POS_ERROR,
 
1471
                                              1, &examined_rows)) ==
 
1472
          HA_POS_ERROR)
1513
1473
      {
1514
1474
        goto err;
1515
1475
      }
1525
1485
  to->restoreRecordAsDefault();        // Create empty record
1526
1486
  while (!(error=info.read_record(&info)))
1527
1487
  {
1528
 
    if (session->getKilled())
 
1488
    if (session->killed)
1529
1489
    {
1530
1490
      session->send_kill_message();
1531
1491
      error= 1;
1546
1506
        to->next_number_field->reset();
1547
1507
    }
1548
1508
 
1549
 
    for (CopyField *copy_ptr= copy; copy_ptr != copy_end ; copy_ptr++)
 
1509
    for (CopyField *copy_ptr=copy ; copy_ptr != copy_end ; copy_ptr++)
1550
1510
    {
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
1511
      copy_ptr->do_copy(copy_ptr);
1561
1512
    }
1562
 
 
1563
 
    if (error)
1564
 
    {
1565
 
      break;
1566
 
    }
1567
 
 
1568
1513
    prev_insert_id= to->cursor->next_insert_id;
1569
1514
    error= to->cursor->insertRecord(to->record[0]);
1570
1515
    to->auto_increment_field_not_null= false;
1571
1516
 
1572
1517
    if (error)
1573
1518
    { 
1574
 
      if (!ignore || to->cursor->is_fatal_error(error, HA_CHECK_DUP))
 
1519
      if (!ignore ||
 
1520
          to->cursor->is_fatal_error(error, HA_CHECK_DUP))
1575
1521
      { 
1576
1522
        to->print_error(error, MYF(0));
1577
1523
        break;
1646
1592
  Table *new_table;
1647
1593
 
1648
1594
  /* Open the table so we need to copy the data to it. */
1649
 
  if (table->getShare()->getType())
 
1595
  if (table->s->tmp_table)
1650
1596
  {
1651
1597
    TableList tbl;
1652
 
    tbl.setSchemaName(const_cast<char *>(identifier.getSchemaName().c_str()));
 
1598
    tbl.db= const_cast<char *>(identifier.getSchemaName().c_str());
1653
1599
    tbl.alias= const_cast<char *>(identifier.getTableName().c_str());
1654
 
    tbl.setTableName(const_cast<char *>(identifier.getTableName().c_str()));
 
1600
    tbl.table_name= const_cast<char *>(identifier.getTableName().c_str());
1655
1601
 
1656
1602
    /* Table is in session->temporary_tables */
1657
1603
    new_table= session->openTable(&tbl, (bool*) 0, DRIZZLE_LOCK_IGNORE_FLUSH);