~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/statement/alter_table.cc

  • Committer: Eric Day
  • Date: 2010-03-25 19:28:37 UTC
  • mfrom: (1405 staging)
  • mto: This revision was merged to the branch mainline in revision 1409.
  • Revision ID: eday@oddments.org-20100325192837-4exmacbrywjovsqp
Merged trunk, rsolved conflicts.

Show diffs side-by-side

added added

removed removed

Lines of Context:
73
73
                                  message::Table &create_message,
74
74
                                  AlterInfo *alter_info);
75
75
 
76
 
static Table *open_alter_table(Session *session, Table *table, char *db, char *table_name);
 
76
static Table *open_alter_table(Session *session, Table *table, TableIdentifier &identifier);
77
77
 
78
78
bool statement::AlterTable::execute()
79
79
{
97
97
    }
98
98
  }
99
99
 
 
100
 
100
101
  /* Must be set in the parser */
101
102
  assert(select_lex->db);
102
103
 
 
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 */
 
105
  message::Table original_table_message;
 
106
  {
 
107
    TableIdentifier identifier(first_table->db, first_table->table_name);
 
108
    if (plugin::StorageEngine::getTableDefinition(*session, identifier, original_table_message) != EEXIST)
 
109
    {
 
110
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), identifier.getSQLPath().c_str());
 
111
      return true;
 
112
    }
 
113
  }
 
114
 
103
115
  /* ALTER TABLE ends previous transaction */
104
 
  if (! session->endActiveTransaction())
105
 
  {
106
 
    return true;
107
 
  }
108
 
 
109
 
  if (! (need_start_waiting= ! wait_if_global_read_lock(session, 0, 1)))
110
 
  {
111
 
    return true;
112
 
  }
113
 
 
114
 
  bool res= alter_table(session, 
115
 
                        select_lex->db, 
116
 
                        session->lex->name.str,
117
 
                        &create_info,
118
 
                        create_table_message,
119
 
                        first_table,
120
 
                        &alter_info,
121
 
                        select_lex->order_list.elements,
122
 
                        (order_st *) select_lex->order_list.first,
123
 
                        session->lex->ignore);
 
116
  if (not session->endActiveTransaction())
 
117
  {
 
118
    return true;
 
119
  }
 
120
 
 
121
  if (not (need_start_waiting= ! wait_if_global_read_lock(session, 0, 1)))
 
122
  {
 
123
    return true;
 
124
  }
 
125
 
 
126
  bool res;
 
127
  if (original_table_message.type() == message::Table::STANDARD )
 
128
  {
 
129
    TableIdentifier identifier(first_table->db, first_table->table_name);
 
130
    TableIdentifier new_identifier(select_lex->db ? select_lex->db : first_table->db,
 
131
                                   session->lex->name.str ? session->lex->name.str : first_table->table_name);
 
132
 
 
133
    res= alter_table(session, 
 
134
                     identifier,
 
135
                     new_identifier,
 
136
                     &create_info,
 
137
                     create_table_message,
 
138
                     first_table,
 
139
                     &alter_info,
 
140
                     select_lex->order_list.elements,
 
141
                     (order_st *) select_lex->order_list.first,
 
142
                     session->lex->ignore);
 
143
  }
 
144
  else
 
145
  {
 
146
    Table *table= session->find_temporary_table(first_table);
 
147
    assert(table);
 
148
    {
 
149
      TableIdentifier identifier(first_table->db, first_table->table_name, table->s->path.str);
 
150
      TableIdentifier new_identifier(select_lex->db ? select_lex->db : first_table->db,
 
151
                                     session->lex->name.str ? session->lex->name.str : first_table->table_name,
 
152
                                     table->s->path.str);
 
153
 
 
154
      res= alter_table(session, 
 
155
                       identifier,
 
156
                       new_identifier,
 
157
                       &create_info,
 
158
                       create_table_message,
 
159
                       first_table,
 
160
                       &alter_info,
 
161
                       select_lex->order_list.elements,
 
162
                       (order_st *) select_lex->order_list.first,
 
163
                       session->lex->ignore);
 
164
    }
 
165
  }
 
166
 
124
167
  /*
125
168
     Release the protection against the global read lock and wake
126
169
     everyone, who might want to set a global read lock.
640
683
  return(error);
641
684
}
642
685
 
 
686
static bool lockTableIfDifferent(Session &session,
 
687
                                 TableIdentifier &original_table_identifier,
 
688
                                 TableIdentifier &new_table_identifier,
 
689
                                 Table *name_lock)
 
690
{
 
691
  /* Check that we are not trying to rename to an existing table */
 
692
  if (not (original_table_identifier == new_table_identifier))
 
693
  {
 
694
    if (original_table_identifier.isTmp())
 
695
    {
 
696
 
 
697
      if (session.find_temporary_table(new_table_identifier))
 
698
      {
 
699
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_table_identifier.getSQLPath().c_str());
 
700
        return false;
 
701
      }
 
702
    }
 
703
    else
 
704
    {
 
705
      if (session.lock_table_name_if_not_cached(new_table_identifier, &name_lock))
 
706
      {
 
707
        return false;
 
708
      }
 
709
 
 
710
      if (not name_lock)
 
711
      {
 
712
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_table_identifier.getSQLPath().c_str());
 
713
        return false;
 
714
      }
 
715
 
 
716
      if (plugin::StorageEngine::doesTableExist(session, new_table_identifier))
 
717
      {
 
718
        /* Table will be closed by Session::executeCommand() */
 
719
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_table_identifier.getSQLPath().c_str());
 
720
 
 
721
        pthread_mutex_lock(&LOCK_open); /* ALTER TABLe */
 
722
        session.unlink_open_table(name_lock);
 
723
        pthread_mutex_unlock(&LOCK_open);
 
724
 
 
725
        return false;
 
726
      }
 
727
    }
 
728
  }
 
729
 
 
730
  return true;
 
731
}
 
732
 
643
733
/**
644
734
  Alter table
645
735
 
681
771
    false  OK
682
772
    true   Error
683
773
*/
684
 
bool alter_table(Session *session,
685
 
                 char *new_db,
686
 
                 char *new_name,
687
 
                 HA_CREATE_INFO *create_info,
688
 
                 message::Table &create_proto,
689
 
                 TableList *table_list,
690
 
                 AlterInfo *alter_info,
691
 
                 uint32_t order_num,
692
 
                 order_st *order,
693
 
                 bool ignore)
 
774
 
 
775
static bool internal_alter_table(Session *session,
 
776
                                 Table *table,
 
777
                                 TableIdentifier &original_table_identifier,
 
778
                                 TableIdentifier &new_table_identifier,
 
779
                                 HA_CREATE_INFO *create_info,
 
780
                                 message::Table &create_proto,
 
781
                                 TableList *table_list,
 
782
                                 AlterInfo *alter_info,
 
783
                                 uint32_t order_num,
 
784
                                 order_st *order,
 
785
                                 bool ignore)
694
786
{
695
 
  Table *table;
696
787
  Table *new_table= NULL;
697
 
  Table *name_lock= NULL;
698
 
  string new_name_str;
699
788
  int error= 0;
700
789
  char tmp_name[80];
701
790
  char old_name[32];
702
 
  char *table_name;
703
 
  char *db;
704
 
  const char *new_alias;
705
791
  ha_rows copied= 0;
706
792
  ha_rows deleted= 0;
707
 
  plugin::StorageEngine *old_db_type;
708
 
  plugin::StorageEngine *new_db_type;
709
 
  plugin::StorageEngine *save_old_db_type;
710
 
  bitset<32> tmp;
 
793
 
 
794
  message::Table *original_table_definition= table->s->getTableProto();
711
795
 
712
796
  session->set_proc_info("init");
713
797
 
714
 
  /*
715
 
    Assign variables table_name, new_name, db, new_db, path
716
 
    to simplify further comparisons: we want to see if it's a RENAME
717
 
    later just by comparing the pointers, avoiding the need for strcmp.
718
 
  */
719
 
  table_name= table_list->table_name;
720
 
  db= table_list->db;
721
 
  if (! new_db || ! my_strcasecmp(table_alias_charset, new_db, db))
722
 
    new_db= db;
723
 
 
724
 
  if (alter_info->tablespace_op != NO_TABLESPACE_OP)
725
 
  {
726
 
    /* DISCARD/IMPORT TABLESPACE is always alone in an ALTER Table */
727
 
    return mysql_discard_or_import_tablespace(session, table_list, alter_info->tablespace_op);
728
 
  }
729
 
 
730
 
  /*
731
 
    If this is just a rename of a view, short cut to the
732
 
    following scenario: 1) lock LOCK_open 2) do a RENAME
733
 
    2) unlock LOCK_open.
734
 
    This is a copy-paste added to make sure
735
 
    ALTER (sic:) Table .. RENAME works for views. ALTER VIEW is handled
736
 
    as an independent branch in mysql_execute_command. The need
737
 
    for a copy-paste arose because the main code flow of ALTER Table
738
 
    ... RENAME tries to use openTableLock, which does not work for views
739
 
    (openTableLock was never modified to merge table lists of child tables
740
 
    into the main table list, like open_tables does).
741
 
    This code is wrong and will be removed, please do not copy.
742
 
  */
743
 
 
744
 
  if (not (table= session->openTableLock(table_list, TL_WRITE_ALLOW_READ)))
745
 
    return true;
746
 
  
747
798
  table->use_all_columns();
748
799
 
749
 
  /* Check that we are not trying to rename to an existing table */
750
 
  if (new_name)
751
 
  {
752
 
    char new_alias_buff[FN_REFLEN];
753
 
    char lower_case_table_name[FN_REFLEN];
754
 
 
755
 
    strcpy(lower_case_table_name, new_name);
756
 
    strcpy(new_alias_buff, new_name);
757
 
    new_alias= new_alias_buff;
758
 
 
759
 
    my_casedn_str(files_charset_info, lower_case_table_name);
760
 
    new_alias= new_name; // Create lower case table name
761
 
    my_casedn_str(files_charset_info, new_name);
762
 
 
763
 
    if (new_db == db &&
764
 
        not my_strcasecmp(table_alias_charset, lower_case_table_name, table_name))
765
 
    {
766
 
      /*
767
 
        Source and destination table names are equal: make later check
768
 
        easier.
769
 
      */
770
 
      new_alias= new_name= table_name;
771
 
    }
772
 
    else
773
 
    {
774
 
      if (table->s->tmp_table != STANDARD_TABLE)
775
 
      {
776
 
        if (session->find_temporary_table(new_db, lower_case_table_name))
777
 
        {
778
 
          my_error(ER_TABLE_EXISTS_ERROR, MYF(0), lower_case_table_name);
779
 
          return true;
780
 
        }
781
 
      }
782
 
      else
783
 
      {
784
 
        if (session->lock_table_name_if_not_cached(new_db, new_name, &name_lock))
785
 
          return true;
786
 
 
787
 
        if (not name_lock)
788
 
        {
789
 
          my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
790
 
          return true;
791
 
        }
792
 
 
793
 
        TableIdentifier identifier(new_db, lower_case_table_name);
794
 
 
795
 
        if (plugin::StorageEngine::doesTableExist(*session, identifier))
796
 
        {
797
 
          /* Table will be closed by Session::executeCommand() */
798
 
          my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
799
 
          goto err;
800
 
        }
801
 
      }
802
 
    }
803
 
  }
804
 
  else
805
 
  {
806
 
    new_alias= table_name;
807
 
    new_name= table_name;
808
 
  }
809
 
 
810
 
  old_db_type= table->s->db_type();
 
800
  plugin::StorageEngine *new_engine;
 
801
  plugin::StorageEngine *original_engine;
 
802
 
 
803
  original_engine= table->s->getEngine();
 
804
 
811
805
  if (not create_info->db_type)
812
806
  {
813
 
    create_info->db_type= old_db_type;
 
807
    create_info->db_type= original_engine;
814
808
  }
815
 
 
816
 
  create_proto.set_schema(new_db);
817
 
 
818
 
  if (table->s->tmp_table != STANDARD_TABLE)
 
809
  new_engine= create_info->db_type;
 
810
 
 
811
 
 
812
  create_proto.set_schema(new_table_identifier.getSchemaName().c_str());
 
813
 
 
814
  if (new_table_identifier.isTmp())
819
815
  {
820
816
    create_proto.set_type(message::Table::TEMPORARY);
821
817
  }
824
820
    create_proto.set_type(message::Table::STANDARD);
825
821
  }
826
822
 
827
 
  new_db_type= create_info->db_type;
828
 
 
829
823
  /**
830
824
    @todo Have a check on the table definition for FK in the future 
831
825
    to remove the need for the cursor. (aka can_switch_engines())
832
826
  */
833
 
  if (new_db_type != old_db_type &&
 
827
  if (new_engine != original_engine &&
834
828
      not table->cursor->can_switch_engines())
835
829
  {
836
830
    assert(0);
837
831
    my_error(ER_ROW_IS_REFERENCED, MYF(0));
838
 
    goto err;
 
832
 
 
833
    return true;
 
834
  }
 
835
 
 
836
  if (original_engine->check_flag(HTON_BIT_ALTER_NOT_SUPPORTED) ||
 
837
      new_engine->check_flag(HTON_BIT_ALTER_NOT_SUPPORTED))
 
838
  {
 
839
    my_error(ER_ILLEGAL_HA, MYF(0), new_table_identifier.getSQLPath().c_str());
 
840
 
 
841
    return true;
839
842
  }
840
843
 
841
844
  if (create_info->row_type == ROW_TYPE_NOT_USED)
844
847
    table_options= create_proto.mutable_options();
845
848
 
846
849
    create_info->row_type= table->s->row_type;
847
 
    table_options->set_row_type((message::Table_TableOptions_RowType)table->s->row_type);
848
 
  }
849
 
 
850
 
  if (old_db_type->check_flag(HTON_BIT_ALTER_NOT_SUPPORTED) ||
851
 
      new_db_type->check_flag(HTON_BIT_ALTER_NOT_SUPPORTED))
852
 
  {
853
 
    my_error(ER_ILLEGAL_HA, MYF(0), table_name);
854
 
    goto err;
 
850
    table_options->set_row_type(original_table_definition->options().row_type());
855
851
  }
856
852
 
857
853
  session->set_proc_info("setup");
858
 
  
 
854
 
859
855
  /*
860
856
   * test if no other bits except ALTER_RENAME and ALTER_KEYS_ONOFF are set
861
 
   */
862
 
  tmp.set();
863
 
  tmp.reset(ALTER_RENAME);
864
 
  tmp.reset(ALTER_KEYS_ONOFF);
865
 
  tmp&= alter_info->flags;
866
 
  if (! (tmp.any()) &&
867
 
      ! table->s->tmp_table) // no need to touch frm
 
857
 */
868
858
  {
869
 
    switch (alter_info->keys_onoff)
870
 
    {
871
 
    case LEAVE_AS_IS:
872
 
      break;
873
 
    case ENABLE:
874
 
      /*
875
 
        wait_while_table_is_used() ensures that table being altered is
876
 
        opened only by this thread and that Table::TableShare::version
877
 
        of Table object corresponding to this table is 0.
878
 
        The latter guarantees that no DML statement will open this table
879
 
        until ALTER Table finishes (i.e. until close_thread_tables())
880
 
        while the fact that the table is still open gives us protection
881
 
        from concurrent DDL statements.
882
 
      */
883
 
      pthread_mutex_lock(&LOCK_open); /* DDL wait for/blocker */
884
 
      wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
885
 
      pthread_mutex_unlock(&LOCK_open);
886
 
      error= table->cursor->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
887
 
      /* COND_refresh will be signaled in close_thread_tables() */
888
 
      break;
889
 
    case DISABLE:
890
 
      pthread_mutex_lock(&LOCK_open); /* DDL wait for/blocker */
891
 
      wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
892
 
      pthread_mutex_unlock(&LOCK_open);
893
 
      error=table->cursor->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
894
 
      /* COND_refresh will be signaled in close_thread_tables() */
895
 
      break;
896
 
    default:
897
 
      assert(false);
898
 
      error= 0;
899
 
      break;
900
 
    }
901
 
 
902
 
    if (error == HA_ERR_WRONG_COMMAND)
903
 
    {
904
 
      error= 0;
905
 
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
906
 
                          ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
907
 
                          table->alias);
908
 
    }
909
 
 
910
 
    pthread_mutex_lock(&LOCK_open); /* Lock to remove all instances of table from table cache before ALTER */
911
 
    /*
912
 
      Unlike to the above case close_cached_table() below will remove ALL
913
 
      instances of Table from table cache (it will also remove table lock
914
 
      held by this thread). So to make actual table renaming and writing
915
 
      to binlog atomic we have to put them into the same critical section
916
 
      protected by LOCK_open mutex. This also removes gap for races between
917
 
      access() and mysql_rename_table() calls.
918
 
    */
919
 
 
920
 
    if (error == 0 && 
921
 
        (new_name != table_name || new_db != db))
922
 
    {
923
 
      session->set_proc_info("rename");
924
 
      /*
925
 
        Then do a 'simple' rename of the table. First we need to close all
926
 
        instances of 'source' table.
927
 
      */
928
 
      session->close_cached_table(table);
929
 
      /*
930
 
        Then, we want check once again that target table does not exist.
931
 
        Actually the order of these two steps does not matter since
932
 
        earlier we took name-lock on the target table, so we do them
933
 
        in this particular order only to be consistent with 5.0, in which
934
 
        we don't take this name-lock and where this order really matters.
935
 
        TODO: Investigate if we need this access() check at all.
936
 
      */
937
 
      TableIdentifier identifier(db, table_name);
938
 
      if (not plugin::StorageEngine::doesTableExist(*session, identifier))
939
 
      {
940
 
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name);
 
859
    bitset<32> tmp;
 
860
 
 
861
    tmp.set();
 
862
    tmp.reset(ALTER_RENAME);
 
863
    tmp.reset(ALTER_KEYS_ONOFF);
 
864
    tmp&= alter_info->flags;
 
865
 
 
866
    if (! (tmp.any()) && ! table->s->tmp_table) // no need to touch frm
 
867
    {
 
868
      switch (alter_info->keys_onoff)
 
869
      {
 
870
      case LEAVE_AS_IS:
 
871
        break;
 
872
      case ENABLE:
 
873
        /*
 
874
          wait_while_table_is_used() ensures that table being altered is
 
875
          opened only by this thread and that Table::TableShare::version
 
876
          of Table object corresponding to this table is 0.
 
877
          The latter guarantees that no DML statement will open this table
 
878
          until ALTER Table finishes (i.e. until close_thread_tables())
 
879
          while the fact that the table is still open gives us protection
 
880
          from concurrent DDL statements.
 
881
        */
 
882
        pthread_mutex_lock(&LOCK_open); /* DDL wait for/blocker */
 
883
        wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
 
884
        pthread_mutex_unlock(&LOCK_open);
 
885
        error= table->cursor->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
 
886
        /* COND_refresh will be signaled in close_thread_tables() */
 
887
        break;
 
888
      case DISABLE:
 
889
        pthread_mutex_lock(&LOCK_open); /* DDL wait for/blocker */
 
890
        wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
 
891
        pthread_mutex_unlock(&LOCK_open);
 
892
        error=table->cursor->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
 
893
        /* COND_refresh will be signaled in close_thread_tables() */
 
894
        break;
 
895
      default:
 
896
        assert(false);
 
897
        error= 0;
 
898
        break;
 
899
      }
 
900
 
 
901
      if (error == HA_ERR_WRONG_COMMAND)
 
902
      {
 
903
        error= 0;
 
904
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
905
                            ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
 
906
                            table->alias);
 
907
      }
 
908
 
 
909
      pthread_mutex_lock(&LOCK_open); /* Lock to remove all instances of table from table cache before ALTER */
 
910
      /*
 
911
        Unlike to the above case close_cached_table() below will remove ALL
 
912
        instances of Table from table cache (it will also remove table lock
 
913
        held by this thread). So to make actual table renaming and writing
 
914
        to binlog atomic we have to put them into the same critical section
 
915
        protected by LOCK_open mutex. This also removes gap for races between
 
916
        access() and mysql_rename_table() calls.
 
917
      */
 
918
 
 
919
      if (error == 0 &&  not (original_table_identifier == new_table_identifier))
 
920
      {
 
921
        session->set_proc_info("rename");
 
922
        /*
 
923
          Then do a 'simple' rename of the table. First we need to close all
 
924
          instances of 'source' table.
 
925
        */
 
926
        session->close_cached_table(table);
 
927
        /*
 
928
          Then, we want check once again that target table does not exist.
 
929
          Actually the order of these two steps does not matter since
 
930
          earlier we took name-lock on the target table, so we do them
 
931
          in this particular order only to be consistent with 5.0, in which
 
932
          we don't take this name-lock and where this order really matters.
 
933
          @todo Investigate if we need this access() check at all.
 
934
        */
 
935
        if (plugin::StorageEngine::doesTableExist(*session, new_table_identifier))
 
936
        {
 
937
          my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_table_identifier.getSQLPath().c_str());
 
938
          error= -1;
 
939
        }
 
940
        else
 
941
        {
 
942
          if (mysql_rename_table(original_engine, original_table_identifier, new_table_identifier, 0))
 
943
          {
 
944
            error= -1;
 
945
          }
 
946
        }
 
947
      }
 
948
 
 
949
      if (error == HA_ERR_WRONG_COMMAND)
 
950
      {
 
951
        error= 0;
 
952
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
953
                            ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
 
954
                            table->alias);
 
955
      }
 
956
 
 
957
      if (error == 0)
 
958
      {
 
959
        write_bin_log(session, session->query.c_str());
 
960
        session->my_ok();
 
961
      }
 
962
      else if (error > 0)
 
963
      {
 
964
        table->print_error(error, MYF(0));
941
965
        error= -1;
942
966
      }
943
 
      else
944
 
      {
945
 
        *internal::fn_ext(new_name)= 0;
946
 
        if (mysql_rename_table(old_db_type, db, table_name, new_db, new_alias, 0))
947
 
          error= -1;
948
 
      }
949
 
    }
950
 
 
951
 
    if (error == HA_ERR_WRONG_COMMAND)
952
 
    {
953
 
      error= 0;
954
 
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
955
 
                          ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
956
 
                          table->alias);
957
 
    }
958
 
 
959
 
    if (error == 0)
960
 
    {
961
 
      write_bin_log(session, session->query.c_str());
962
 
      session->my_ok();
963
 
    }
964
 
    else if (error > 0)
965
 
    {
966
 
      table->print_error(error, MYF(0));
967
 
      error= -1;
968
 
    }
969
 
 
970
 
    if (name_lock)
971
 
      session->unlink_open_table(name_lock);
972
 
 
973
 
    pthread_mutex_unlock(&LOCK_open);
974
 
    table_list->table= NULL;
975
 
    return error;
 
967
 
 
968
      pthread_mutex_unlock(&LOCK_open);
 
969
      table_list->table= NULL;
 
970
 
 
971
      return error;
 
972
    }
976
973
  }
977
974
 
978
975
  /* We have to do full alter table. */
979
 
  new_db_type= create_info->db_type;
 
976
  new_engine= create_info->db_type;
980
977
 
981
978
  if (mysql_prepare_alter_table(session, table, create_info, create_proto, alter_info))
982
 
      goto err;
 
979
  {
 
980
    return true;
 
981
  }
983
982
 
984
 
  set_table_default_charset(create_info, db);
 
983
  set_table_default_charset(create_info, new_table_identifier.getSchemaName().c_str());
985
984
 
986
985
  alter_info->build_method= HA_BUILD_OFFLINE;
987
986
 
988
987
  snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%"PRIx64, TMP_FILE_PREFIX, (unsigned long) current_pid, session->thread_id);
989
988
 
990
 
  /* Safety fix for innodb */
991
 
  my_casedn_str(files_charset_info, tmp_name);
992
 
 
993
989
  /* Create a temporary table with the new format */
 
990
  /**
 
991
    @note we make an internal temporary table unless the table is a temporary table. In last
 
992
    case we just use it as is. Neither of these tables require locks in order to  be
 
993
    filled.
 
994
  */
 
995
  TableIdentifier new_table_as_temporary(original_table_identifier.getSchemaName(),
 
996
                                         tmp_name,
 
997
                                         create_proto.type() != message::Table::TEMPORARY ? INTERNAL_TMP_TABLE :
 
998
                                         TEMP_TABLE);
 
999
 
 
1000
  error= create_temporary_table(session, new_table_as_temporary, create_info, create_proto, alter_info);
 
1001
 
 
1002
  if (error != 0)
994
1003
  {
995
 
    /**
996
 
      @note we make an internal temporary table unless the table is a temporary table. In last
997
 
      case we just use it as is. Neither of these tables require locks in order to  be
998
 
      filled.
999
 
    */
1000
 
    TableIdentifier new_table_temp(new_db,
1001
 
                                   tmp_name,
1002
 
                                   create_proto.type() != message::Table::TEMPORARY ? INTERNAL_TMP_TABLE :
1003
 
                                   TEMP_TABLE);
1004
 
 
1005
 
    error= create_temporary_table(session, new_table_temp, create_info, create_proto, alter_info);
1006
 
 
1007
 
    if (error != 0)
1008
 
      goto err;
 
1004
    return true;
1009
1005
  }
1010
1006
 
1011
1007
  /* Open the table so we need to copy the data to it. */
1012
 
  new_table= open_alter_table(session, table, new_db, tmp_name);
 
1008
  new_table= open_alter_table(session, table, new_table_as_temporary);
1013
1009
 
1014
 
  if (new_table == NULL)
1015
 
    goto err1;
 
1010
  if (not new_table)
 
1011
  {
 
1012
    quick_rm_table(*session, new_table_as_temporary);
 
1013
    return true;
 
1014
  }
1016
1015
 
1017
1016
  /* Copy the data if necessary. */
1018
 
  session->count_cuted_fields= CHECK_FIELD_WARN;        // calc cuted fields
1019
 
  session->cuted_fields= 0L;
1020
 
  session->set_proc_info("copy to tmp table");
1021
 
  copied= deleted= 0;
1022
 
 
1023
 
  assert(new_table);
1024
 
 
1025
 
  /* We don't want update TIMESTAMP fields during ALTER Table. */
1026
 
  new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
1027
 
  new_table->next_number_field= new_table->found_next_number_field;
1028
 
  error= copy_data_between_tables(table,
1029
 
                                  new_table,
1030
 
                                  alter_info->create_list,
1031
 
                                  ignore,
1032
 
                                  order_num,
1033
 
                                  order,
1034
 
                                  &copied,
1035
 
                                  &deleted,
1036
 
                                  alter_info->keys_onoff,
1037
 
                                  alter_info->error_if_not_empty);
1038
 
 
1039
 
  /* We must not ignore bad input! */
1040
 
  session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
1041
 
 
1042
 
  if (table->s->tmp_table != STANDARD_TABLE)
1043
 
  {
1044
 
    /* We changed a temporary table */
1045
 
    if (error)
1046
 
      goto err1;
1047
 
 
 
1017
  {
 
1018
    session->count_cuted_fields= CHECK_FIELD_WARN;      // calc cuted fields
 
1019
    session->cuted_fields= 0L;
 
1020
    session->set_proc_info("copy to tmp table");
 
1021
    copied= deleted= 0;
 
1022
 
 
1023
    /* We don't want update TIMESTAMP fields during ALTER Table. */
 
1024
    new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
 
1025
    new_table->next_number_field= new_table->found_next_number_field;
 
1026
    error= copy_data_between_tables(table,
 
1027
                                    new_table,
 
1028
                                    alter_info->create_list,
 
1029
                                    ignore,
 
1030
                                    order_num,
 
1031
                                    order,
 
1032
                                    &copied,
 
1033
                                    &deleted,
 
1034
                                    alter_info->keys_onoff,
 
1035
                                    alter_info->error_if_not_empty);
 
1036
 
 
1037
    /* We must not ignore bad input! */
 
1038
    session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
 
1039
  }
 
1040
 
 
1041
  /* Now we need to resolve what just happened with the data copy. */
 
1042
 
 
1043
  if (error)
 
1044
  {
 
1045
 
 
1046
    /*
 
1047
      No default value was provided for a DATE/DATETIME field, the
 
1048
      current sql_mode doesn't allow the '0000-00-00' value and
 
1049
      the table to be altered isn't empty.
 
1050
      Report error here.
 
1051
    */
 
1052
    if (alter_info->error_if_not_empty && session->row_count)
 
1053
    {
 
1054
      const char *f_val= 0;
 
1055
      enum enum_drizzle_timestamp_type t_type= DRIZZLE_TIMESTAMP_DATE;
 
1056
 
 
1057
      switch (alter_info->datetime_field->sql_type)
 
1058
      {
 
1059
      case DRIZZLE_TYPE_DATE:
 
1060
        f_val= "0000-00-00";
 
1061
        t_type= DRIZZLE_TIMESTAMP_DATE;
 
1062
        break;
 
1063
      case DRIZZLE_TYPE_DATETIME:
 
1064
        f_val= "0000-00-00 00:00:00";
 
1065
        t_type= DRIZZLE_TIMESTAMP_DATETIME;
 
1066
        break;
 
1067
      default:
 
1068
        /* Shouldn't get here. */
 
1069
        assert(0);
 
1070
      }
 
1071
      bool save_abort_on_warning= session->abort_on_warning;
 
1072
      session->abort_on_warning= true;
 
1073
      make_truncated_value_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
 
1074
                                   f_val, internal::strlength(f_val), t_type,
 
1075
                                   alter_info->datetime_field->field_name);
 
1076
      session->abort_on_warning= save_abort_on_warning;
 
1077
    }
 
1078
 
 
1079
    if (original_table_identifier.isTmp())
 
1080
    {
 
1081
      if (new_table)
 
1082
      {
 
1083
        /* close_temporary_table() frees the new_table pointer. */
 
1084
        session->close_temporary_table(new_table);
 
1085
      }
 
1086
      else
 
1087
      {
 
1088
        quick_rm_table(*session, new_table_as_temporary);
 
1089
      }
 
1090
 
 
1091
      return true;
 
1092
    }
 
1093
    else
 
1094
    {
 
1095
      if (new_table)
 
1096
      {
 
1097
        /*
 
1098
          Close the intermediate table that will be the new table.
 
1099
          Note that MERGE tables do not have their children attached here.
 
1100
        */
 
1101
        new_table->intern_close_table();
 
1102
        free(new_table);
 
1103
      }
 
1104
 
 
1105
      pthread_mutex_lock(&LOCK_open); /* ALTER TABLE */
 
1106
 
 
1107
      quick_rm_table(*session, new_table_as_temporary);
 
1108
      pthread_mutex_unlock(&LOCK_open);
 
1109
 
 
1110
      return true;
 
1111
    }
 
1112
  }
 
1113
  // Temporary table and success
 
1114
  else if (original_table_identifier.isTmp())
 
1115
  {
1048
1116
    /* Close lock if this is a transactional table */
1049
1117
    if (session->lock)
1050
1118
    {
1056
1124
    session->close_temporary_table(table);
1057
1125
 
1058
1126
    /* Should pass the 'new_name' as we store table name in the cache */
1059
 
    if (new_table->rename_temporary_table(new_db, new_name))
1060
 
      goto err1;
1061
 
 
1062
 
    goto end_temporary;
1063
 
  }
1064
 
 
1065
 
  if (new_table)
1066
 
  {
1067
 
    /*
1068
 
      Close the intermediate table that will be the new table.
1069
 
      Note that MERGE tables do not have their children attached here.
1070
 
    */
1071
 
    new_table->intern_close_table();
1072
 
    free(new_table);
1073
 
  }
1074
 
 
1075
 
  pthread_mutex_lock(&LOCK_open); /* ALTER TABLE */
1076
 
 
1077
 
  if (error)
1078
 
  {
1079
 
    TableIdentifier identifier(new_db, tmp_name, INTERNAL_TMP_TABLE);
1080
 
    quick_rm_table(*session, identifier);
1081
 
    pthread_mutex_unlock(&LOCK_open);
1082
 
    goto err;
1083
 
  }
1084
 
 
1085
 
  /*
1086
 
    Data is copied. Now we:
1087
 
    1) Wait until all other threads close old version of table.
1088
 
    2) Close instances of table open by this thread and replace them
1089
 
       with exclusive name-locks.
1090
 
    3) Rename the old table to a temp name, rename the new one to the
1091
 
       old name.
1092
 
    4) If we are under LOCK TABLES and don't do ALTER Table ... RENAME
1093
 
       we reopen new version of table.
1094
 
    5) Write statement to the binary log.
1095
 
    6) If we are under LOCK TABLES and do ALTER Table ... RENAME we
1096
 
       remove name-locks from list of open tables and table cache.
1097
 
    7) If we are not not under LOCK TABLES we rely on close_thread_tables()
1098
 
       call to remove name-locks from table cache and list of open table.
1099
 
  */
1100
 
 
1101
 
  session->set_proc_info("rename result table");
1102
 
 
1103
 
  snprintf(old_name, sizeof(old_name), "%s2-%lx-%"PRIx64, TMP_FILE_PREFIX, (unsigned long) current_pid, session->thread_id);
1104
 
 
1105
 
  my_casedn_str(files_charset_info, old_name);
1106
 
 
1107
 
  wait_while_table_is_used(session, table, HA_EXTRA_PREPARE_FOR_RENAME);
1108
 
  session->close_data_files_and_morph_locks(db, table_name);
1109
 
 
1110
 
  error= 0;
1111
 
  save_old_db_type= old_db_type;
1112
 
 
1113
 
  /*
1114
 
    This leads to the storage engine (SE) not being notified for renames in
1115
 
    mysql_rename_table(), because we just juggle with the FRM and nothing
1116
 
    more. If we have an intermediate table, then we notify the SE that
1117
 
    it should become the actual table. Later, we will recycle the old table.
1118
 
    However, in case of ALTER Table RENAME there might be no intermediate
1119
 
    table. This is when the old and new tables are compatible, according to
1120
 
    compare_table(). Then, we need one additional call to
1121
 
  */
1122
 
  if (mysql_rename_table(old_db_type, db, table_name, db, old_name, FN_TO_IS_TMP))
1123
 
  {
1124
 
    error= 1;
1125
 
    TableIdentifier identifier(new_db, tmp_name, INTERNAL_TMP_TABLE);
1126
 
    quick_rm_table(*session, identifier);
1127
 
  }
 
1127
    if (new_table->renameAlterTemporaryTable(new_table_identifier))
 
1128
    {
 
1129
      if (new_table)
 
1130
      {
 
1131
        /* close_temporary_table() frees the new_table pointer. */
 
1132
        session->close_temporary_table(new_table);
 
1133
      }
 
1134
      else
 
1135
      {
 
1136
        quick_rm_table(*session, new_table_as_temporary);
 
1137
      }
 
1138
 
 
1139
      return true;
 
1140
    }
 
1141
  }
 
1142
  // Normal table success
1128
1143
  else
1129
1144
  {
1130
 
    if (mysql_rename_table(new_db_type, new_db, tmp_name, new_db, new_alias, FN_FROM_IS_TMP) != 0)
1131
 
    {
1132
 
      /* Try to get everything back. */
 
1145
    if (new_table)
 
1146
    {
 
1147
      /*
 
1148
        Close the intermediate table that will be the new table.
 
1149
        Note that MERGE tables do not have their children attached here.
 
1150
      */
 
1151
      new_table->intern_close_table();
 
1152
      free(new_table);
 
1153
    }
 
1154
 
 
1155
    pthread_mutex_lock(&LOCK_open); /* ALTER TABLE */
 
1156
 
 
1157
    /*
 
1158
      Data is copied. Now we:
 
1159
      1) Wait until all other threads close old version of table.
 
1160
      2) Close instances of table open by this thread and replace them
 
1161
      with exclusive name-locks.
 
1162
      3) Rename the old table to a temp name, rename the new one to the
 
1163
      old name.
 
1164
      4) If we are under LOCK TABLES and don't do ALTER Table ... RENAME
 
1165
      we reopen new version of table.
 
1166
      5) Write statement to the binary log.
 
1167
      6) If we are under LOCK TABLES and do ALTER Table ... RENAME we
 
1168
      remove name-locks from list of open tables and table cache.
 
1169
      7) If we are not not under LOCK TABLES we rely on close_thread_tables()
 
1170
      call to remove name-locks from table cache and list of open table.
 
1171
    */
 
1172
 
 
1173
    session->set_proc_info("rename result table");
 
1174
 
 
1175
    snprintf(old_name, sizeof(old_name), "%s2-%lx-%"PRIx64, TMP_FILE_PREFIX, (unsigned long) current_pid, session->thread_id);
 
1176
 
 
1177
    my_casedn_str(files_charset_info, old_name);
 
1178
 
 
1179
    wait_while_table_is_used(session, table, HA_EXTRA_PREPARE_FOR_RENAME);
 
1180
    session->close_data_files_and_morph_locks(original_table_identifier);
 
1181
 
 
1182
    error= 0;
 
1183
 
 
1184
    /*
 
1185
      This leads to the storage engine (SE) not being notified for renames in
 
1186
      mysql_rename_table(), because we just juggle with the FRM and nothing
 
1187
      more. If we have an intermediate table, then we notify the SE that
 
1188
      it should become the actual table. Later, we will recycle the old table.
 
1189
      However, in case of ALTER Table RENAME there might be no intermediate
 
1190
      table. This is when the old and new tables are compatible, according to
 
1191
      compare_table(). Then, we need one additional call to
 
1192
    */
 
1193
    TableIdentifier original_table_to_drop(original_table_identifier.getSchemaName(),
 
1194
                                           old_name, TEMP_TABLE);
 
1195
 
 
1196
    if (mysql_rename_table(original_engine, original_table_identifier, original_table_to_drop, FN_TO_IS_TMP))
 
1197
    {
1133
1198
      error= 1;
1134
 
 
1135
 
      TableIdentifier alias_identifier(new_db, new_alias, STANDARD_TABLE);
1136
 
      quick_rm_table(*session, alias_identifier);
1137
 
 
1138
 
      TableIdentifier tmp_identifier(new_db, tmp_name, INTERNAL_TMP_TABLE);
1139
 
      quick_rm_table(*session, tmp_identifier);
1140
 
 
1141
 
      mysql_rename_table(old_db_type, db, old_name, db, table_name, FN_FROM_IS_TMP);
1142
 
    }
1143
 
  }
1144
 
 
1145
 
  if (error)
1146
 
  {
1147
 
    /* This shouldn't happen. But let us play it safe. */
1148
 
    goto err_with_placeholders;
1149
 
  }
1150
 
 
1151
 
  {
1152
 
    TableIdentifier old_identifier(db, old_name, INTERNAL_TMP_TABLE);
1153
 
    quick_rm_table(*session, old_identifier);
1154
 
  }
1155
 
  
1156
 
 
1157
 
  pthread_mutex_unlock(&LOCK_open);
1158
 
 
1159
 
  session->set_proc_info("end");
1160
 
 
1161
 
  write_bin_log(session, session->query.c_str());
1162
 
  table_list->table= NULL;
1163
 
 
1164
 
end_temporary:
 
1199
      quick_rm_table(*session, new_table_as_temporary);
 
1200
    }
 
1201
    else
 
1202
    {
 
1203
      if (mysql_rename_table(new_engine, new_table_as_temporary, new_table_identifier, FN_FROM_IS_TMP) != 0)
 
1204
      {
 
1205
        /* Try to get everything back. */
 
1206
        error= 1;
 
1207
 
 
1208
        quick_rm_table(*session, new_table_identifier);
 
1209
 
 
1210
        quick_rm_table(*session, new_table_as_temporary);
 
1211
 
 
1212
        mysql_rename_table(original_engine, original_table_to_drop, original_table_identifier, FN_FROM_IS_TMP);
 
1213
      }
 
1214
      else
 
1215
      {
 
1216
        quick_rm_table(*session, original_table_to_drop);
 
1217
      }
 
1218
    }
 
1219
 
 
1220
    if (error)
 
1221
    {
 
1222
      /*
 
1223
        An error happened while we were holding exclusive name-lock on table
 
1224
        being altered. To be safe under LOCK TABLES we should remove placeholders
 
1225
        from list of open tables list and table cache.
 
1226
      */
 
1227
      session->unlink_open_table(table);
 
1228
      pthread_mutex_unlock(&LOCK_open);
 
1229
 
 
1230
      return true;
 
1231
    }
 
1232
 
 
1233
 
 
1234
    pthread_mutex_unlock(&LOCK_open);
 
1235
 
 
1236
    session->set_proc_info("end");
 
1237
 
 
1238
    write_bin_log(session, session->query.c_str());
 
1239
    table_list->table= NULL;
 
1240
  }
 
1241
 
1165
1242
  /*
1166
1243
   * Field::store() may have called my_error().  If this is 
1167
1244
   * the case, we must not send an ok packet, since 
1168
1245
   * Diagnostics_area::is_set() will fail an assert.
1169
 
   */
1170
 
  if (! session->is_error())
1171
 
  {
1172
 
    snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
1173
 
            (ulong) (copied + deleted), (ulong) deleted,
1174
 
            (ulong) session->cuted_fields);
1175
 
    session->my_ok(copied + deleted, 0, 0L, tmp_name);
1176
 
    session->some_tables_deleted=0;
1177
 
    return false;
1178
 
  }
1179
 
  else
 
1246
 */
 
1247
  if (session->is_error())
1180
1248
  {
1181
1249
    /* my_error() was called.  Return true (which means error...) */
1182
1250
    return true;
1183
1251
  }
1184
1252
 
1185
 
err1:
1186
 
  if (new_table)
1187
 
  {
1188
 
    /* close_temporary_table() frees the new_table pointer. */
1189
 
    session->close_temporary_table(new_table);
1190
 
  }
1191
 
  else
1192
 
  {
1193
 
    TableIdentifier tmp_identifier(new_db, tmp_name, INTERNAL_TMP_TABLE);
1194
 
    quick_rm_table(*session, tmp_identifier);
1195
 
  }
1196
 
 
1197
 
err:
1198
 
  /*
1199
 
    No default value was provided for a DATE/DATETIME field, the
1200
 
    current sql_mode doesn't allow the '0000-00-00' value and
1201
 
    the table to be altered isn't empty.
1202
 
    Report error here.
1203
 
  */
1204
 
  if (alter_info->error_if_not_empty && session->row_count)
1205
 
  {
1206
 
    const char *f_val= 0;
1207
 
    enum enum_drizzle_timestamp_type t_type= DRIZZLE_TIMESTAMP_DATE;
1208
 
    switch (alter_info->datetime_field->sql_type)
1209
 
    {
1210
 
      case DRIZZLE_TYPE_DATE:
1211
 
        f_val= "0000-00-00";
1212
 
        t_type= DRIZZLE_TIMESTAMP_DATE;
1213
 
        break;
1214
 
      case DRIZZLE_TYPE_DATETIME:
1215
 
        f_val= "0000-00-00 00:00:00";
1216
 
        t_type= DRIZZLE_TIMESTAMP_DATETIME;
1217
 
        break;
1218
 
      default:
1219
 
        /* Shouldn't get here. */
1220
 
        assert(0);
1221
 
    }
1222
 
    bool save_abort_on_warning= session->abort_on_warning;
1223
 
    session->abort_on_warning= true;
1224
 
    make_truncated_value_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1225
 
                                 f_val, internal::strlength(f_val), t_type,
1226
 
                                 alter_info->datetime_field->field_name);
1227
 
    session->abort_on_warning= save_abort_on_warning;
1228
 
  }
1229
 
  if (name_lock)
1230
 
  {
1231
 
    pthread_mutex_lock(&LOCK_open); /* ALTER TABLe */
1232
 
    session->unlink_open_table(name_lock);
1233
 
    pthread_mutex_unlock(&LOCK_open);
1234
 
  }
1235
 
  return true;
1236
 
 
1237
 
err_with_placeholders:
1238
 
  /*
1239
 
    An error happened while we were holding exclusive name-lock on table
1240
 
    being altered. To be safe under LOCK TABLES we should remove placeholders
1241
 
    from list of open tables list and table cache.
1242
 
  */
1243
 
  session->unlink_open_table(table);
1244
 
  if (name_lock)
1245
 
    session->unlink_open_table(name_lock);
1246
 
  pthread_mutex_unlock(&LOCK_open);
1247
 
  return true;
 
1253
  snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
 
1254
           (ulong) (copied + deleted), (ulong) deleted,
 
1255
           (ulong) session->cuted_fields);
 
1256
  session->my_ok(copied + deleted, 0, 0L, tmp_name);
 
1257
  session->some_tables_deleted= 0;
 
1258
 
 
1259
  return false;
 
1260
}
 
1261
 
 
1262
bool alter_table(Session *session,
 
1263
                 TableIdentifier &original_table_identifier,
 
1264
                 TableIdentifier &new_table_identifier,
 
1265
                 HA_CREATE_INFO *create_info,
 
1266
                 message::Table &create_proto,
 
1267
                 TableList *table_list,
 
1268
                 AlterInfo *alter_info,
 
1269
                 uint32_t order_num,
 
1270
                 order_st *order,
 
1271
                 bool ignore)
 
1272
{
 
1273
  bool error;
 
1274
  Table *table;
 
1275
 
 
1276
  if (alter_info->tablespace_op != NO_TABLESPACE_OP)
 
1277
  {
 
1278
    /* DISCARD/IMPORT TABLESPACE is always alone in an ALTER Table */
 
1279
    return mysql_discard_or_import_tablespace(session, table_list, alter_info->tablespace_op);
 
1280
  }
 
1281
 
 
1282
  session->set_proc_info("init");
 
1283
 
 
1284
  if (not (table= session->openTableLock(table_list, TL_WRITE_ALLOW_READ)))
 
1285
    return true;
 
1286
 
 
1287
  session->set_proc_info("gained write lock on table");
 
1288
 
 
1289
  /* 
 
1290
    Check that we are not trying to rename to an existing table,
 
1291
    if one existed we get a lock, if we can't we error.
 
1292
  */
 
1293
  {
 
1294
    Table *name_lock= NULL;
 
1295
 
 
1296
    if (not lockTableIfDifferent(*session, original_table_identifier, new_table_identifier, name_lock))
 
1297
    {
 
1298
      return true;
 
1299
    }
 
1300
 
 
1301
    error= internal_alter_table(session,
 
1302
                                table,
 
1303
                                original_table_identifier,
 
1304
                                new_table_identifier,
 
1305
                                create_info,
 
1306
                                create_proto,
 
1307
                                table_list,
 
1308
                                alter_info,
 
1309
                                order_num,
 
1310
                                order,
 
1311
                                ignore);
 
1312
 
 
1313
    if (name_lock)
 
1314
    {
 
1315
      pthread_mutex_lock(&LOCK_open); /* ALTER TABLe */
 
1316
      session->unlink_open_table(name_lock);
 
1317
      pthread_mutex_unlock(&LOCK_open);
 
1318
    }
 
1319
  }
 
1320
 
 
1321
  return error;
1248
1322
}
1249
1323
/* alter_table */
1250
1324
 
1344
1418
                                              (optimizer::SqlSelect *) 0, HA_POS_ERROR,
1345
1419
                                              1, &examined_rows)) ==
1346
1420
          HA_POS_ERROR)
 
1421
      {
1347
1422
        goto err;
 
1423
      }
1348
1424
    }
1349
 
  };
 
1425
  }
1350
1426
 
1351
1427
  /* Tell handler that we have values for all columns in the to table */
1352
1428
  to->use_all_columns();
1456
1532
  return error;
1457
1533
}
1458
1534
 
1459
 
static Table *open_alter_table(Session *session, Table *table, char *db, char *table_name)
 
1535
static Table *open_alter_table(Session *session, Table *table, TableIdentifier &identifier)
1460
1536
{
1461
1537
  Table *new_table;
1462
1538
 
1464
1540
  if (table->s->tmp_table)
1465
1541
  {
1466
1542
    TableList tbl;
1467
 
    tbl.db= db;
1468
 
    tbl.alias= table_name;
1469
 
    tbl.table_name= table_name;
 
1543
    tbl.db= const_cast<char *>(identifier.getSchemaName().c_str());
 
1544
    tbl.alias= const_cast<char *>(identifier.getTableName().c_str());
 
1545
    tbl.table_name= const_cast<char *>(identifier.getTableName().c_str());
1470
1546
 
1471
1547
    /* Table is in session->temporary_tables */
1472
1548
    new_table= session->openTable(&tbl, (bool*) 0, DRIZZLE_LOCK_IGNORE_FLUSH);
1473
1549
  }
1474
1550
  else
1475
1551
  {
1476
 
    TableIdentifier new_identifier(db, table_name, INTERNAL_TMP_TABLE);
1477
 
 
1478
1552
    /* Open our intermediate table */
1479
 
    new_table= session->open_temporary_table(new_identifier, false);
 
1553
    new_table= session->open_temporary_table(identifier, false);
1480
1554
  }
1481
1555
 
1482
1556
  return new_table;