18
18
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27
#include "drizzled/show.h"
28
#include "drizzled/lock.h"
29
#include "drizzled/session.h"
30
#include "drizzled/statement/alter_table.h"
31
#include "drizzled/global_charset_info.h"
21
#include <drizzled/server_includes.h>
22
#include <drizzled/show.h>
23
#include <drizzled/lock.h>
24
#include <drizzled/session.h>
25
#include <drizzled/statement/alter_table.h>
34
27
#include "drizzled/gettext.h"
35
28
#include "drizzled/data_home.h"
36
29
#include "drizzled/sql_table.h"
37
30
#include "drizzled/table_proto.h"
38
#include "drizzled/optimizer/range.h"
39
#include "drizzled/time_functions.h"
40
#include "drizzled/records.h"
41
#include "drizzled/pthread_globals.h"
42
#include "drizzled/internal/my_sys.h"
43
#include "drizzled/internal/iocache.h"
44
#include "drizzled/plugin/storage_engine.h"
45
#include <drizzled/copy_field.h>
47
#include "drizzled/transaction_services.h"
49
#include "drizzled/filesort.h"
51
#include "drizzled/message.h"
58
extern pid_t current_pid;
60
static int copy_data_between_tables(Session *session,
61
Table *from,Table *to,
32
using namespace drizzled;
34
static int copy_data_between_tables(Table *from,Table *to,
62
35
List<CreateField> &create,
64
37
uint32_t order_num,
68
41
enum enum_enable_or_disable keys_onoff,
69
42
bool error_if_not_empty);
71
static bool prepare_alter_table(Session *session,
43
static bool mysql_prepare_alter_table(Session *session,
73
45
HA_CREATE_INFO *create_info,
74
const message::Table &original_proto,
75
message::Table &table_message,
46
message::Table *table_proto,
76
47
AlterInfo *alter_info);
78
static Table *open_alter_table(Session *session, Table *table, identifier::Table &identifier);
82
AlterTable::AlterTable(Session *in_session, Table_ident *ident, drizzled::ha_build_method build_arg) :
83
CreateTable(in_session)
85
in_session->lex->sql_command= SQLCOM_ALTER_TABLE;
87
alter_info.build_method= build_arg;
90
} // namespace statement
48
static int create_temporary_table(Session *session,
52
HA_CREATE_INFO *create_info,
53
message::Table *create_proto,
54
AlterInfo *alter_info);
92
56
bool statement::AlterTable::execute()
94
TableList *first_table= (TableList *) getSession()->lex->select_lex.table_list.first;
95
TableList *all_tables= getSession()->lex->query_tables;
58
TableList *first_table= (TableList *) session->lex->select_lex.table_list.first;
59
TableList *all_tables= session->lex->query_tables;
96
60
assert(first_table == all_tables && first_table != 0);
97
Select_Lex *select_lex= &getSession()->lex->select_lex;
61
Select_Lex *select_lex= &session->lex->select_lex;
98
62
bool need_start_waiting= false;
100
is_engine_set= not createTableMessage().engine().name().empty();
65
Code in mysql_alter_table() may modify its HA_CREATE_INFO argument,
66
so we have to use a copy of this structure to make execution
67
prepared statement- safe. A shallow copy is enough as no memory
68
referenced from this structure will be modified.
70
HA_CREATE_INFO create_info(session->lex->create_info);
71
AlterInfo alter_info(session->lex->alter_info, session->mem_root);
73
if (session->is_fatal_error) /* out of memory creating a copy of alter_info */
104
create_info().db_type=
105
plugin::StorageEngine::findByName(*getSession(), createTableMessage().engine().name());
107
if (create_info().db_type == NULL)
109
my_error(createTableMessage().engine().name(), ER_UNKNOWN_STORAGE_ENGINE, MYF(0));
115
78
/* Must be set in the parser */
116
79
assert(select_lex->db);
118
/* Chicken/Egg... we need to search for the table, to know if the table exists, so we can build a full identifier from it */
119
message::table::shared_ptr original_table_message;
121
identifier::Table identifier(first_table->getSchemaName(), first_table->getTableName());
122
if (plugin::StorageEngine::getTableDefinition(*getSession(), identifier, original_table_message) != EEXIST)
124
my_error(ER_BAD_TABLE_ERROR, identifier);
128
if (not create_info().db_type)
130
create_info().db_type=
131
plugin::StorageEngine::findByName(*getSession(), original_table_message->engine().name());
133
if (not create_info().db_type)
135
my_error(ER_BAD_TABLE_ERROR, identifier);
141
if (not validateCreateTableOption())
144
if (getSession()->inTransaction())
146
my_error(ER_TRANSACTIONAL_DDL_NOT_SUPPORTED, MYF(0));
150
if (not (need_start_waiting= not getSession()->wait_if_global_read_lock(0, 1)))
154
if (original_table_message->type() == message::Table::STANDARD )
156
identifier::Table identifier(first_table->getSchemaName(), first_table->getTableName());
157
identifier::Table new_identifier(select_lex->db ? select_lex->db : first_table->getSchemaName(),
158
getSession()->lex->name.str ? getSession()->lex->name.str : first_table->getTableName());
160
res= alter_table(getSession(),
164
*original_table_message,
165
createTableMessage(),
168
select_lex->order_list.elements,
169
(Order *) select_lex->order_list.first,
170
getSession()->lex->ignore);
174
identifier::Table catch22(first_table->getSchemaName(), first_table->getTableName());
175
Table *table= getSession()->find_temporary_table(catch22);
178
identifier::Table identifier(first_table->getSchemaName(), first_table->getTableName(), table->getMutableShare()->getPath());
179
identifier::Table new_identifier(select_lex->db ? select_lex->db : first_table->getSchemaName(),
180
getSession()->lex->name.str ? getSession()->lex->name.str : first_table->getTableName(),
181
table->getMutableShare()->getPath());
183
res= alter_table(getSession(),
187
*original_table_message,
188
createTableMessage(),
191
select_lex->order_list.elements,
192
(Order *) select_lex->order_list.first,
193
getSession()->lex->ignore);
81
/* ALTER TABLE ends previous transaction */
82
if (! session->endActiveTransaction())
87
if (! (need_start_waiting= ! wait_if_global_read_lock(session, 0, 1)))
92
bool res= mysql_alter_table(session,
94
session->lex->name.str,
96
session->lex->create_table_proto,
99
select_lex->order_list.elements,
100
(order_st *) select_lex->order_list.first,
101
session->lex->ignore);
198
103
Release the protection against the global read lock and wake
199
104
everyone, who might want to set a global read lock.
201
getSession()->startWaitingGlobalReadLock();
106
start_waiting_global_read_lock(session);
208
111
Prepare column and key definitions for CREATE TABLE in ALTER Table.
904
static bool internal_alter_table(Session *session,
906
identifier::Table &original_table_identifier,
907
identifier::Table &new_table_identifier,
908
HA_CREATE_INFO *create_info,
909
const message::Table &original_proto,
910
message::Table &create_proto,
911
TableList *table_list,
912
AlterInfo *alter_info,
635
bool mysql_alter_table(Session *session,
638
HA_CREATE_INFO *create_info,
639
message::Table *create_proto,
640
TableList *table_list,
641
AlterInfo *alter_info,
647
Table *new_table= NULL;
648
Table *name_lock= NULL;
918
651
char tmp_name[80];
919
652
char old_name[32];
653
char new_name_buff[FN_REFLEN];
654
char new_alias_buff[FN_REFLEN];
657
const char *new_alias;
658
char path[FN_REFLEN];
920
659
ha_rows copied= 0;
921
660
ha_rows deleted= 0;
923
if (not original_table_identifier.isValid())
926
if (not new_table_identifier.isValid())
661
StorageEngine *old_db_type;
662
StorageEngine *new_db_type;
663
StorageEngine *save_old_db_type;
666
new_name_buff[0]= '\0';
668
if (table_list && table_list->schema_table)
670
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.c_str());
929
674
session->set_proc_info("init");
677
Assign variables table_name, new_name, db, new_db, path
678
to simplify further comparisons: we want to see if it's a RENAME
679
later just by comparing the pointers, avoiding the need for strcmp.
681
table_name= table_list->table_name;
683
if (! new_db || ! my_strcasecmp(table_alias_charset, new_db, db))
686
if (alter_info->tablespace_op != NO_TABLESPACE_OP)
688
/* DISCARD/IMPORT TABLESPACE is always alone in an ALTER Table */
689
return mysql_discard_or_import_tablespace(session, table_list, alter_info->tablespace_op);
692
build_table_filename(path, sizeof(path), db, table_name, false);
695
oss << drizzle_data_home << "/" << db << "/" << table_name;
697
(void) unpack_filename(new_name_buff, oss.str().c_str());
700
If this is just a rename of a view, short cut to the
701
following scenario: 1) lock LOCK_open 2) do a RENAME
703
This is a copy-paste added to make sure
704
ALTER (sic:) Table .. RENAME works for views. ALTER VIEW is handled
705
as an independent branch in mysql_execute_command. The need
706
for a copy-paste arose because the main code flow of ALTER Table
707
... RENAME tries to use openTableLock, which does not work for views
708
(openTableLock was never modified to merge table lists of child tables
709
into the main table list, like open_tables does).
710
This code is wrong and will be removed, please do not copy.
713
if (!(table= session->openTableLock(table_list, TL_WRITE_ALLOW_READ)))
931
716
table->use_all_columns();
933
plugin::StorageEngine *new_engine;
934
plugin::StorageEngine *original_engine;
936
original_engine= table->getMutableShare()->getEngine();
938
if (not create_info->db_type)
940
create_info->db_type= original_engine;
942
new_engine= create_info->db_type;
945
create_proto.set_schema(new_table_identifier.getSchemaName());
946
create_proto.set_type(new_table_identifier.getType());
949
@todo Have a check on the table definition for FK in the future
950
to remove the need for the cursor. (aka can_switch_engines())
952
if (new_engine != original_engine &&
953
not table->cursor->can_switch_engines())
718
/* Check that we are not trying to rename to an existing table */
721
strcpy(new_name_buff, new_name);
722
strcpy(new_alias_buff, new_name);
723
new_alias= new_alias_buff;
725
my_casedn_str(files_charset_info, new_name_buff);
726
new_alias= new_name; // Create lower case table name
727
my_casedn_str(files_charset_info, new_name);
730
! my_strcasecmp(table_alias_charset, new_name_buff, table_name))
733
Source and destination table names are equal: make later check
736
new_alias= new_name= table_name;
740
if (table->s->tmp_table != NO_TMP_TABLE)
742
if (session->find_temporary_table(new_db, new_name_buff))
744
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name_buff);
750
if (session->lock_table_name_if_not_cached(new_db, new_name, &name_lock))
755
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
759
build_table_filename(new_name_buff, sizeof(new_name_buff), new_db, new_name_buff, false);
761
if (StorageEngine::getTableProto(new_name_buff, NULL) == EEXIST)
763
/* Table will be closed by Session::executeCommand() */
764
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
772
new_alias= table_name;
773
new_name= table_name;
776
old_db_type= table->s->db_type();
777
if (! create_info->db_type)
779
create_info->db_type= old_db_type;
782
if (table->s->tmp_table != NO_TMP_TABLE)
783
create_info->options|= HA_LEX_CREATE_TMP_TABLE;
785
if (check_engine(session, new_name, create_info))
788
new_db_type= create_info->db_type;
790
if (new_db_type != old_db_type &&
791
!table->file->can_switch_engines())
956
794
my_error(ER_ROW_IS_REFERENCED, MYF(0));
961
if (original_engine->check_flag(HTON_BIT_ALTER_NOT_SUPPORTED) ||
962
new_engine->check_flag(HTON_BIT_ALTER_NOT_SUPPORTED))
798
if (create_info->row_type == ROW_TYPE_NOT_USED)
799
create_info->row_type= table->s->row_type;
801
if (old_db_type->check_flag(HTON_BIT_ALTER_NOT_SUPPORTED) ||
802
new_db_type->check_flag(HTON_BIT_ALTER_NOT_SUPPORTED))
964
my_error(ER_ILLEGAL_HA, new_table_identifier);
804
my_error(ER_ILLEGAL_HA, MYF(0), table_name);
969
808
session->set_proc_info("setup");
972
811
* test if no other bits except ALTER_RENAME and ALTER_KEYS_ONOFF are set
814
tmp.reset(ALTER_RENAME);
815
tmp.reset(ALTER_KEYS_ONOFF);
816
tmp&= alter_info->flags;
818
! table->s->tmp_table) // no need to touch frm
978
tmp.reset(ALTER_RENAME);
979
tmp.reset(ALTER_KEYS_ONOFF);
980
tmp&= alter_info->flags;
982
if (not (tmp.any()) && not table->getShare()->getType()) // no need to touch frm
984
switch (alter_info->keys_onoff)
991
wait_while_table_is_used() ensures that table being altered is
992
opened only by this thread and that Table::TableShare::version
993
of Table object corresponding to this table is 0.
994
The latter guarantees that no DML statement will open this table
995
until ALTER Table finishes (i.e. until close_thread_tables())
996
while the fact that the table is still open gives us protection
997
from concurrent DDL statements.
1000
boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex()); /* DDL wait for/blocker */
1001
wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
1003
error= table->cursor->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
1005
/* COND_refresh will be signaled in close_thread_tables() */
1010
boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex()); /* DDL wait for/blocker */
1011
wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
1013
error= table->cursor->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
1015
/* COND_refresh will be signaled in close_thread_tables() */
1019
if (error == HA_ERR_WRONG_COMMAND)
1022
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1023
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
1027
boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex()); /* Lock to remove all instances of table from table cache before ALTER */
1029
Unlike to the above case close_cached_table() below will remove ALL
1030
instances of Table from table cache (it will also remove table lock
1031
held by this thread). So to make actual table renaming and writing
1032
to binlog atomic we have to put them into the same critical section
1033
protected by table::Cache::singleton().mutex() mutex. This also removes gap for races between
1034
access() and rename_table() calls.
1037
if (not error && not (original_table_identifier == new_table_identifier))
1039
session->set_proc_info("rename");
1041
Then do a 'simple' rename of the table. First we need to close all
1042
instances of 'source' table.
1044
session->close_cached_table(table);
1046
Then, we want check once again that target table does not exist.
1047
Actually the order of these two steps does not matter since
1048
earlier we took name-lock on the target table, so we do them
1049
in this particular order only to be consistent with 5.0, in which
1050
we don't take this name-lock and where this order really matters.
1051
@todo Investigate if we need this access() check at all.
1053
if (plugin::StorageEngine::doesTableExist(*session, new_table_identifier))
1055
my_error(ER_TABLE_EXISTS_ERROR, new_table_identifier);
820
switch (alter_info->keys_onoff)
826
wait_while_table_is_used() ensures that table being altered is
827
opened only by this thread and that Table::TableShare::version
828
of Table object corresponding to this table is 0.
829
The latter guarantees that no DML statement will open this table
830
until ALTER Table finishes (i.e. until close_thread_tables())
831
while the fact that the table is still open gives us protection
832
from concurrent DDL statements.
834
pthread_mutex_lock(&LOCK_open); /* DDL wait for/blocker */
835
wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
836
pthread_mutex_unlock(&LOCK_open);
837
error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
838
/* COND_refresh will be signaled in close_thread_tables() */
841
pthread_mutex_lock(&LOCK_open); /* DDL wait for/blocker */
842
wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
843
pthread_mutex_unlock(&LOCK_open);
844
error=table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
845
/* COND_refresh will be signaled in close_thread_tables() */
853
if (error == HA_ERR_WRONG_COMMAND)
856
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
857
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
861
pthread_mutex_lock(&LOCK_open); /* Lock to remove all instances of table from table cache before ALTER */
863
Unlike to the above case close_cached_table() below will remove ALL
864
instances of Table from table cache (it will also remove table lock
865
held by this thread). So to make actual table renaming and writing
866
to binlog atomic we have to put them into the same critical section
867
protected by LOCK_open mutex. This also removes gap for races between
868
access() and mysql_rename_table() calls.
872
(new_name != table_name || new_db != db))
874
session->set_proc_info("rename");
876
Then do a 'simple' rename of the table. First we need to close all
877
instances of 'source' table.
879
session->close_cached_table(table);
881
Then, we want check once again that target table does not exist.
882
Actually the order of these two steps does not matter since
883
earlier we took name-lock on the target table, so we do them
884
in this particular order only to be consistent with 5.0, in which
885
we don't take this name-lock and where this order really matters.
886
TODO: Investigate if we need this access() check at all.
888
if (StorageEngine::getTableProto(new_name, NULL) == EEXIST)
890
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name);
895
*fn_ext(new_name)= 0;
896
if (mysql_rename_table(old_db_type, db, table_name, new_db, new_alias, 0))
1060
if (rename_table(*session, original_engine, original_table_identifier, new_table_identifier))
1067
if (error == HA_ERR_WRONG_COMMAND)
1070
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1071
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
1077
TransactionServices &transaction_services= TransactionServices::singleton();
1078
transaction_services.allocateNewTransactionId();
1079
write_bin_log(session, *session->getQueryString());
1082
else if (error > EE_OK) // If we have already set the error, we pass along -1
1084
table->print_error(error, MYF(0));
1087
table_list->table= NULL;
901
if (error == HA_ERR_WRONG_COMMAND)
904
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
905
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
911
write_bin_log(session, true, session->query, session->query_length);
916
table->file->print_error(error, MYF(0));
921
session->unlink_open_table(name_lock);
923
pthread_mutex_unlock(&LOCK_open);
924
table_list->table= NULL;
1093
928
/* We have to do full alter table. */
1094
new_engine= create_info->db_type;
1096
if (prepare_alter_table(session, table, create_info, original_proto, create_proto, alter_info))
1101
set_table_default_charset(create_info, new_table_identifier.getSchemaName().c_str());
931
If the old table had partitions and we are doing ALTER Table ...
932
engine= <new_engine>, the new table must preserve the original
933
partitioning. That means that the new engine is still the
934
partitioning engine, not the engine specified in the parser.
935
This is discovered in prep_alter_part_table, which in such case
936
updates create_info->db_type.
937
Now we need to update the stack copy of create_info->db_type,
938
as otherwise we won't be able to correctly move the files of the
939
temporary table to the result table files.
941
new_db_type= create_info->db_type;
943
if (mysql_prepare_alter_table(session, table, create_info, create_proto,
947
set_table_default_charset(create_info, db);
1103
949
alter_info->build_method= HA_BUILD_OFFLINE;
1105
951
snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%"PRIx64, TMP_FILE_PREFIX, (unsigned long) current_pid, session->thread_id);
953
/* Safety fix for innodb */
954
my_casedn_str(files_charset_info, tmp_name);
1107
956
/* Create a temporary table with the new format */
1109
@note we make an internal temporary table unless the table is a temporary table. In last
1110
case we just use it as is. Neither of these tables require locks in order to be
1113
identifier::Table new_table_as_temporary(original_table_identifier.getSchemaName(),
1115
create_proto.type() != message::Table::TEMPORARY ? message::Table::INTERNAL :
1116
message::Table::TEMPORARY);
1119
Create a table with a temporary name.
1120
We don't log the statement, it will be logged later.
1122
create_proto.set_name(new_table_as_temporary.getTableName());
1123
create_proto.mutable_engine()->set_name(create_info->db_type->getName());
1125
error= create_table(session,
1126
new_table_as_temporary,
1127
create_info, create_proto, alter_info, true, 0, false);
957
error= create_temporary_table(session, table, new_db, tmp_name, create_info, create_proto, alter_info);
1134
961
/* Open the table so we need to copy the data to it. */
1135
Table *new_table= open_alter_table(session, table, new_table_as_temporary);
1140
plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
962
if (table->s->tmp_table)
967
tbl.table_name= tmp_name;
969
/* Table is in session->temporary_tables */
970
new_table= session->openTable(&tbl, (bool*) 0, DRIZZLE_LOCK_IGNORE_FLUSH);
974
char tmp_path[FN_REFLEN];
975
/* table is a normal table: Create temporary table in same directory */
976
build_table_filename(tmp_path, sizeof(tmp_path), new_db, tmp_name, true);
977
/* Open our intermediate table */
978
new_table= session->open_temporary_table(tmp_path, new_db, tmp_name, 0, OTM_OPEN);
981
if (new_table == NULL)
1144
984
/* Copy the data if necessary. */
1146
/* We must not ignore bad input! */
1147
session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL; // calc cuted fields
1148
session->cuted_fields= 0L;
1149
session->set_proc_info("copy to tmp table");
1152
/* We don't want update TIMESTAMP fields during ALTER Table. */
1153
new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
1154
new_table->next_number_field= new_table->found_next_number_field;
1155
error= copy_data_between_tables(session,
1158
alter_info->create_list,
1164
alter_info->keys_onoff,
1165
alter_info->error_if_not_empty);
1167
/* We must not ignore bad input! */
1168
assert(session->count_cuted_fields == CHECK_FIELD_ERROR_FOR_NULL);
1171
/* Now we need to resolve what just happened with the data copy. */
1177
No default value was provided for new fields.
1179
if (alter_info->error_if_not_empty && session->row_count)
1181
my_error(ER_INVALID_ALTER_TABLE_FOR_NOT_NULL, MYF(0));
1184
if (original_table_identifier.isTmp())
1188
/* close_temporary_table() frees the new_table pointer. */
1189
session->close_temporary_table(new_table);
1193
plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
1203
Close the intermediate table that will be the new table.
1204
Note that MERGE tables do not have their children attached here.
1206
new_table->intern_close_table();
1207
if (new_table->hasShare())
1209
delete new_table->getMutableShare();
1215
boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex());
1217
plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
1222
// Temporary table and success
1223
else if (original_table_identifier.isTmp())
985
session->count_cuted_fields= CHECK_FIELD_WARN; // calc cuted fields
986
session->cuted_fields= 0L;
987
session->set_proc_info("copy to tmp table");
992
/* We don't want update TIMESTAMP fields during ALTER Table. */
993
new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
994
new_table->next_number_field= new_table->found_next_number_field;
995
error= copy_data_between_tables(table,
997
alter_info->create_list,
1003
alter_info->keys_onoff,
1004
alter_info->error_if_not_empty);
1006
/* We must not ignore bad input! */
1007
session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
1009
if (table->s->tmp_table != NO_TMP_TABLE)
1011
/* We changed a temporary table */
1225
1015
/* Close lock if this is a transactional table */
1226
1016
if (session->lock)
1228
session->unlockTables(session->lock);
1018
mysql_unlock_tables(session, session->lock);
1229
1019
session->lock= 0;
1232
1022
/* Remove link to old table and rename the new one */
1233
session->close_temporary_table(table);
1023
session->close_temporary_table(table, true, true);
1235
1025
/* Should pass the 'new_name' as we store table name in the cache */
1236
new_table->getMutableShare()->setIdentifier(new_table_identifier);
1238
new_table_identifier.setPath(new_table_as_temporary.getPath());
1240
if (rename_table(*session, new_engine, new_table_as_temporary, new_table_identifier) != 0)
1245
// Normal table success
1026
if (new_table->rename_temporary_table(new_db, new_name))
1035
Close the intermediate table that will be the new table.
1036
Note that MERGE tables do not have their children attached here.
1038
new_table->intern_close_table();
1042
pthread_mutex_lock(&LOCK_open); /* ALTER TABLE */
1046
quick_rm_table(new_db_type, new_db, tmp_name, true);
1047
pthread_mutex_unlock(&LOCK_open);
1052
Data is copied. Now we:
1053
1) Wait until all other threads close old version of table.
1054
2) Close instances of table open by this thread and replace them
1055
with exclusive name-locks.
1056
3) Rename the old table to a temp name, rename the new one to the
1058
4) If we are under LOCK TABLES and don't do ALTER Table ... RENAME
1059
we reopen new version of table.
1060
5) Write statement to the binary log.
1061
6) If we are under LOCK TABLES and do ALTER Table ... RENAME we
1062
remove name-locks from list of open tables and table cache.
1063
7) If we are not not under LOCK TABLES we rely on close_thread_tables()
1064
call to remove name-locks from table cache and list of open table.
1067
session->set_proc_info("rename result table");
1069
snprintf(old_name, sizeof(old_name), "%s2-%lx-%"PRIx64, TMP_FILE_PREFIX, (unsigned long) current_pid, session->thread_id);
1071
my_casedn_str(files_charset_info, old_name);
1073
wait_while_table_is_used(session, table, HA_EXTRA_PREPARE_FOR_RENAME);
1074
session->close_data_files_and_morph_locks(db, table_name);
1077
save_old_db_type= old_db_type;
1080
This leads to the storage engine (SE) not being notified for renames in
1081
mysql_rename_table(), because we just juggle with the FRM and nothing
1082
more. If we have an intermediate table, then we notify the SE that
1083
it should become the actual table. Later, we will recycle the old table.
1084
However, in case of ALTER Table RENAME there might be no intermediate
1085
table. This is when the old and new tables are compatible, according to
1086
compare_table(). Then, we need one additional call to
1087
mysql_rename_table() with flag NO_FRM_RENAME, which does nothing else but
1088
actual rename in the SE and the FRM is not touched. Note that, if the
1089
table is renamed and the SE is also changed, then an intermediate table
1090
is created and the additional call will not take place.
1092
if (mysql_rename_table(old_db_type, db, table_name, db, old_name, FN_TO_IS_TMP))
1095
quick_rm_table(new_db_type, new_db, tmp_name, true);
1251
Close the intermediate table that will be the new table.
1252
Note that MERGE tables do not have their children attached here.
1254
new_table->intern_close_table();
1256
if (new_table->hasShare())
1258
delete new_table->getMutableShare();
1265
boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex()); /* ALTER TABLE */
1267
Data is copied. Now we:
1268
1) Wait until all other threads close old version of table.
1269
2) Close instances of table open by this thread and replace them
1270
with exclusive name-locks.
1271
3) Rename the old table to a temp name, rename the new one to the
1273
4) If we are under LOCK TABLES and don't do ALTER Table ... RENAME
1274
we reopen new version of table.
1275
5) Write statement to the binary log.
1276
6) If we are under LOCK TABLES and do ALTER Table ... RENAME we
1277
remove name-locks from list of open tables and table cache.
1278
7) If we are not not under LOCK TABLES we rely on close_thread_tables()
1279
call to remove name-locks from table cache and list of open table.
1282
session->set_proc_info("rename result table");
1284
snprintf(old_name, sizeof(old_name), "%s2-%lx-%"PRIx64, TMP_FILE_PREFIX, (unsigned long) current_pid, session->thread_id);
1286
my_casedn_str(files_charset_info, old_name);
1288
wait_while_table_is_used(session, table, HA_EXTRA_PREPARE_FOR_RENAME);
1289
session->close_data_files_and_morph_locks(original_table_identifier);
1294
This leads to the storage engine (SE) not being notified for renames in
1295
rename_table(), because we just juggle with the FRM and nothing
1296
more. If we have an intermediate table, then we notify the SE that
1297
it should become the actual table. Later, we will recycle the old table.
1298
However, in case of ALTER Table RENAME there might be no intermediate
1299
table. This is when the old and new tables are compatible, according to
1300
compare_table(). Then, we need one additional call to
1302
identifier::Table original_table_to_drop(original_table_identifier.getSchemaName(),
1303
old_name, create_proto.type() != message::Table::TEMPORARY ? message::Table::INTERNAL :
1304
message::Table::TEMPORARY);
1306
drizzled::error_t rename_error= EE_OK;
1307
if (rename_table(*session, original_engine, original_table_identifier, original_table_to_drop))
1309
error= ER_ERROR_ON_RENAME;
1310
plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
1314
if (rename_table(*session, new_engine, new_table_as_temporary, new_table_identifier) != 0)
1316
/* Try to get everything back. */
1317
rename_error= ER_ERROR_ON_RENAME;
1319
plugin::StorageEngine::dropTable(*session, new_table_identifier);
1321
plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
1323
rename_table(*session, original_engine, original_table_to_drop, original_table_identifier);
1327
plugin::StorageEngine::dropTable(*session, original_table_to_drop);
1334
An error happened while we were holding exclusive name-lock on table
1335
being altered. To be safe under LOCK TABLES we should remove placeholders
1336
from list of open tables list and table cache.
1338
session->unlink_open_table(table);
1344
session->set_proc_info("end");
1346
write_bin_log(session, *session->getQueryString());
1347
table_list->table= NULL;
1099
if (mysql_rename_table(new_db_type, new_db, tmp_name, new_db, new_alias, FN_FROM_IS_TMP) != 0)
1101
/* Try to get everything back. */
1103
quick_rm_table(new_db_type, new_db, new_alias, false);
1104
quick_rm_table(new_db_type, new_db, tmp_name, true);
1105
mysql_rename_table(old_db_type, db, old_name, db, table_name, FN_FROM_IS_TMP);
1111
/* This shouldn't happen. But let us play it safe. */
1112
goto err_with_placeholders;
1115
quick_rm_table(old_db_type, db, old_name, true);
1117
pthread_mutex_unlock(&LOCK_open);
1119
session->set_proc_info("end");
1121
write_bin_log(session, true, session->query, session->query_length);
1123
if (old_db_type->check_flag(HTON_BIT_FLUSH_AFTER_RENAME))
1126
For the alter table to be properly flushed to the logs, we
1127
have to open the new table. If not, we get a problem on server
1128
shutdown. But we do not need to attach MERGE children.
1130
char table_path[FN_REFLEN];
1132
build_table_filename(table_path, sizeof(table_path), new_db, table_name, false);
1133
t_table= session->open_temporary_table(table_path, new_db, tmp_name, false, OTM_OPEN);
1136
t_table->intern_close_table();
1140
errmsg_printf(ERRMSG_LVL_WARN, _("Could not open table %s.%s after rename\n"), new_db, table_name);
1142
ha_flush_logs(old_db_type);
1144
table_list->table= NULL;
1351
1148
* Field::store() may have called my_error(). If this is
1352
1149
* the case, we must not send an ok packet, since
1353
1150
* Diagnostics_area::is_set() will fail an assert.
1355
if (session->is_error())
1152
if (! session->is_error())
1154
snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
1155
(ulong) (copied + deleted), (ulong) deleted,
1156
(ulong) session->cuted_fields);
1157
session->my_ok(copied + deleted, 0, 0L, tmp_name);
1158
session->some_tables_deleted=0;
1357
1163
/* my_error() was called. Return true (which means error...) */
1361
snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
1362
(ulong) (copied + deleted), (ulong) deleted,
1363
(ulong) session->cuted_fields);
1364
session->my_ok(copied + deleted, 0, 0L, tmp_name);
1365
session->some_tables_deleted= false;
1370
bool alter_table(Session *session,
1371
identifier::Table &original_table_identifier,
1372
identifier::Table &new_table_identifier,
1373
HA_CREATE_INFO *create_info,
1374
const message::Table &original_proto,
1375
message::Table &create_proto,
1376
TableList *table_list,
1377
AlterInfo *alter_info,
1385
if (alter_info->tablespace_op != NO_TABLESPACE_OP)
1387
/* DISCARD/IMPORT TABLESPACE is always alone in an ALTER Table */
1388
return discard_or_import_tablespace(session, table_list, alter_info->tablespace_op);
1391
session->set_proc_info("init");
1393
if (not (table= session->openTableLock(table_list, TL_WRITE_ALLOW_READ)))
1396
session->set_proc_info("gained write lock on table");
1399
Check that we are not trying to rename to an existing table,
1400
if one existed we get a lock, if we can't we error.
1403
Table *name_lock= NULL;
1405
if (not lockTableIfDifferent(*session, original_table_identifier, new_table_identifier, name_lock))
1410
error= internal_alter_table(session,
1412
original_table_identifier,
1413
new_table_identifier,
1425
boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex());
1426
session->unlink_open_table(name_lock);
1170
/* close_temporary_table() frees the new_table pointer. */
1171
session->close_temporary_table(new_table, true, true);
1174
quick_rm_table(new_db_type, new_db, tmp_name, true);
1178
No default value was provided for a DATE/DATETIME field, the
1179
current sql_mode doesn't allow the '0000-00-00' value and
1180
the table to be altered isn't empty.
1183
if (alter_info->error_if_not_empty && session->row_count)
1185
const char *f_val= 0;
1186
enum enum_drizzle_timestamp_type t_type= DRIZZLE_TIMESTAMP_DATE;
1187
switch (alter_info->datetime_field->sql_type)
1189
case DRIZZLE_TYPE_DATE:
1190
f_val= "0000-00-00";
1191
t_type= DRIZZLE_TIMESTAMP_DATE;
1193
case DRIZZLE_TYPE_DATETIME:
1194
f_val= "0000-00-00 00:00:00";
1195
t_type= DRIZZLE_TIMESTAMP_DATETIME;
1198
/* Shouldn't get here. */
1201
bool save_abort_on_warning= session->abort_on_warning;
1202
session->abort_on_warning= true;
1203
make_truncated_value_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1204
f_val, strlength(f_val), t_type,
1205
alter_info->datetime_field->field_name);
1206
session->abort_on_warning= save_abort_on_warning;
1210
pthread_mutex_lock(&LOCK_open); /* ALTER TABLe */
1211
session->unlink_open_table(name_lock);
1212
pthread_mutex_unlock(&LOCK_open);
1216
err_with_placeholders:
1218
An error happened while we were holding exclusive name-lock on table
1219
being altered. To be safe under LOCK TABLES we should remove placeholders
1220
from list of open tables list and table cache.
1222
session->unlink_open_table(table);
1224
session->unlink_open_table(name_lock);
1225
pthread_mutex_unlock(&LOCK_open);
1228
/* mysql_alter_table */
1435
copy_data_between_tables(Session *session,
1436
Table *from, Table *to,
1437
List<CreateField> &create,
1231
copy_data_between_tables(Table *from,Table *to,
1232
List<CreateField> &create,
1439
uint32_t order_num, Order *order,
1234
uint32_t order_num, order_st *order,
1442
1237
enum enum_enable_or_disable keys_onoff,
1443
1238
bool error_if_not_empty)
1446
1241
CopyField *copy,*copy_end;
1447
1242
ulong found_count,delete_count;
1243
Session *session= current_session;
1448
1244
uint32_t length= 0;
1449
SortField *sortorder;
1245
SORT_FIELD *sortorder;
1451
1247
TableList tables;
1452
1248
List<Item> fields;
1453
1249
List<Item> all_fields;
1506
1295
found_count=delete_count=0;
1512
if (to->getShare()->hasPrimaryKey() && to->cursor->primary_key_is_clustered())
1514
char warn_buff[DRIZZLE_ERRMSG_SIZE];
1515
snprintf(warn_buff, sizeof(warn_buff),
1516
_("order_st BY ignored because there is a user-defined clustered "
1517
"index in the table '%-.192s'"),
1518
from->getMutableShare()->getTableName());
1519
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
1299
if (to->s->primary_key != MAX_KEY && to->file->primary_key_is_clustered())
1301
char warn_buff[DRIZZLE_ERRMSG_SIZE];
1302
snprintf(warn_buff, sizeof(warn_buff),
1303
_("order_st BY ignored because there is a user-defined clustered "
1304
"index in the table '%-.192s'"),
1305
from->s->table_name.str);
1306
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
1311
from->sort.io_cache= new IO_CACHE;
1312
memset(from->sort.io_cache, 0, sizeof(IO_CACHE));
1314
memset(&tables, 0, sizeof(tables));
1316
tables.alias= tables.table_name= from->s->table_name.str;
1317
tables.db= from->s->db.str;
1320
if (session->lex->select_lex.setup_ref_array(session, order_num) ||
1321
setup_order(session, session->lex->select_lex.ref_pointer_array,
1322
&tables, fields, all_fields, order) ||
1323
!(sortorder= make_unireg_sortorder(order, &length, NULL)) ||
1324
(from->sort.found_records= filesort(session, from, sortorder, length,
1325
(SQL_SELECT *) 0, HA_POS_ERROR,
1326
1, &examined_rows)) ==
1332
/* Tell handler that we have values for all columns in the to table */
1333
to->use_all_columns();
1334
init_read_record(&info, session, from, (SQL_SELECT *) 0, 1,1);
1336
to->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
1337
session->row_count= 0;
1338
to->restoreRecordAsDefault(); // Create empty record
1339
while (!(error=info.read_record(&info)))
1341
if (session->killed)
1343
session->send_kill_message();
1347
session->row_count++;
1348
/* Return error if source table isn't empty. */
1349
if (error_if_not_empty)
1354
if (to->next_number_field)
1356
if (auto_increment_field_copied)
1357
to->auto_increment_field_not_null= true;
1524
FileSort filesort(*session);
1525
from->sort.io_cache= new internal::IO_CACHE;
1528
tables.setTableName(const_cast<char *>(from->getMutableShare()->getTableName()));
1529
tables.alias= const_cast<char *>(tables.getTableName());
1530
tables.setSchemaName(const_cast<char *>(from->getMutableShare()->getSchemaName()));
1533
if (session->lex->select_lex.setup_ref_array(session, order_num) ||
1534
setup_order(session, session->lex->select_lex.ref_pointer_array,
1535
&tables, fields, all_fields, order) ||
1536
!(sortorder= make_unireg_sortorder(order, &length, NULL)) ||
1537
(from->sort.found_records= filesort.run(from, sortorder, length,
1538
(optimizer::SqlSelect *) 0, HA_POS_ERROR,
1539
1, examined_rows)) == HA_POS_ERROR)
1546
/* Tell handler that we have values for all columns in the to table */
1547
to->use_all_columns();
1549
error= info.init_read_record(session, from, (optimizer::SqlSelect *) 0, 1, true);
1359
to->next_number_field->reset();
1362
for (CopyField *copy_ptr=copy ; copy_ptr != copy_end ; copy_ptr++)
1364
copy_ptr->do_copy(copy_ptr);
1366
prev_insert_id= to->file->next_insert_id;
1367
error=to->file->ha_write_row(to->record[0]);
1368
to->auto_increment_field_not_null= false;
1552
to->print_error(errno, MYF(0));
1559
to->cursor->extra(HA_EXTRA_IGNORE_DUP_KEY);
1562
session->row_count= 0;
1563
to->restoreRecordAsDefault(); // Create empty record
1564
while (not (error=info.read_record(&info)))
1566
if (session->getKilled())
1568
session->send_kill_message();
1572
session->row_count++;
1573
/* Return error if source table isn't empty. */
1574
if (error_if_not_empty)
1579
if (to->next_number_field)
1581
if (auto_increment_field_copied)
1582
to->auto_increment_field_not_null= true;
1584
to->next_number_field->reset();
1587
for (CopyField *copy_ptr= copy; copy_ptr != copy_end ; copy_ptr++)
1589
if (not copy->to_field->hasDefault() and copy->from_null_ptr and *copy->from_null_ptr & copy->from_bit)
1591
copy->to_field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
1592
ER_WARN_DATA_TRUNCATED, 1);
1593
copy->to_field->reset();
1598
copy_ptr->do_copy(copy_ptr);
1606
prev_insert_id= to->cursor->next_insert_id;
1607
error= to->cursor->insertRecord(to->record[0]);
1608
to->auto_increment_field_not_null= false;
1612
if (!ignore || to->cursor->is_fatal_error(error, HA_CHECK_DUP))
1614
to->print_error(error, MYF(0));
1617
to->cursor->restore_auto_increment(prev_insert_id);
1626
info.end_read_record();
1627
from->free_io_cache();
1628
delete [] copy; // This is never 0
1630
if (to->cursor->ha_end_bulk_insert() && error <= 0)
1632
to->print_error(errno, MYF(0));
1635
to->cursor->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
1638
Ensure that the new table is saved properly to disk so that we
1641
if (transaction_services.autocommitOrRollback(*session, false))
1644
if (not session->endActiveTransaction())
1649
session->setAbortOnWarning(false);
1372
to->file->is_fatal_error(error, HA_CHECK_DUP))
1374
if (!to->file->is_fatal_error(error, HA_CHECK_DUP))
1376
uint32_t key_nr= to->file->get_dup_key(error);
1377
if ((int) key_nr >= 0)
1379
const char *err_msg= ER(ER_DUP_ENTRY_WITH_KEY_NAME);
1381
(to->key_info[0].key_part[0].field->flags &
1382
AUTO_INCREMENT_FLAG))
1383
err_msg= ER(ER_DUP_ENTRY_AUTOINCREMENT_CASE);
1384
to->file->print_keydup_error(key_nr, err_msg);
1389
to->file->print_error(error,MYF(0));
1392
to->file->restore_auto_increment(prev_insert_id);
1398
end_read_record(&info);
1399
from->free_io_cache();
1400
delete [] copy; // This is never 0
1402
if (to->file->ha_end_bulk_insert() && error <= 0)
1404
to->file->print_error(my_errno,MYF(0));
1407
to->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
1409
if (ha_enable_transaction(session, true))
1416
Ensure that the new table is saved properly to disk so that we
1419
if (ha_autocommit_or_rollback(session, 0))
1421
if (! session->endActiveTransaction())
1425
session->abort_on_warning= 0;
1650
1426
from->free_io_cache();
1651
1427
*copied= found_count;
1652
1428
*deleted=delete_count;
1653
to->cursor->ha_release_auto_increment();
1655
if (to->cursor->ha_external_lock(session, F_UNLCK))
1429
to->file->ha_release_auto_increment();
1430
if (to->file->ha_external_lock(session,F_UNLCK))
1660
1432
return(error > 0 ? -1 : 0);
1663
static Table *open_alter_table(Session *session, Table *table, identifier::Table &identifier)
1667
/* Open the table so we need to copy the data to it. */
1668
if (table->getShare()->getType())
1671
tbl.setSchemaName(const_cast<char *>(identifier.getSchemaName().c_str()));
1672
tbl.alias= const_cast<char *>(identifier.getTableName().c_str());
1673
tbl.setTableName(const_cast<char *>(identifier.getTableName().c_str()));
1675
/* Table is in session->temporary_tables */
1676
new_table= session->openTable(&tbl, (bool*) 0, DRIZZLE_LOCK_IGNORE_FLUSH);
1436
create_temporary_table(Session *session,
1440
HA_CREATE_INFO *create_info,
1441
message::Table *create_proto,
1442
AlterInfo *alter_info)
1445
StorageEngine *old_db_type, *new_db_type;
1446
old_db_type= table->s->db_type();
1447
new_db_type= create_info->db_type;
1449
Create a table with a temporary name.
1450
We don't log the statement, it will be logged later.
1452
create_proto->set_name(tmp_name);
1453
create_proto->set_type(message::Table::TEMPORARY);
1455
message::Table::StorageEngine *protoengine;
1456
protoengine= create_proto->mutable_engine();
1457
protoengine->set_name(new_db_type->getName());
1459
error= mysql_create_table(session, new_db, tmp_name,
1460
create_info, create_proto, alter_info, 1, 0);
1465
/** @TODO This will soon die. */
1466
bool mysql_create_like_schema_frm(Session* session,
1467
TableList* schema_table,
1468
HA_CREATE_INFO *create_info,
1469
message::Table* table_proto)
1471
HA_CREATE_INFO local_create_info;
1472
AlterInfo alter_info;
1473
bool tmp_table= (create_info->options & HA_LEX_CREATE_TMP_TABLE);
1474
uint32_t keys= schema_table->table->s->keys;
1475
uint32_t db_options= 0;
1477
memset(&local_create_info, 0, sizeof(local_create_info));
1478
local_create_info.db_type= schema_table->table->s->db_type();
1479
local_create_info.row_type= schema_table->table->s->row_type;
1480
local_create_info.default_table_charset=default_charset_info;
1481
alter_info.flags.set(ALTER_CHANGE_COLUMN);
1482
alter_info.flags.set(ALTER_RECREATE);
1483
schema_table->table->use_all_columns();
1484
if (mysql_prepare_alter_table(session, schema_table->table,
1485
&local_create_info, table_proto, &alter_info))
1488
/* I_S tables are created with MAX_ROWS for some efficiency drive.
1489
When CREATE LIKE, we don't want to keep it coming across */
1490
message::Table::TableOptions *table_options;
1491
table_options= table_proto->mutable_options();
1492
table_options->clear_max_rows();
1494
if (mysql_prepare_create_table(session, &local_create_info, &alter_info,
1495
tmp_table, &db_options,
1496
schema_table->table->file,
1497
&schema_table->table->s->key_info, &keys, 0))
1500
table_proto->set_name("system_stupid_i_s_fix_nonsense");
1502
table_proto->set_type(message::Table::TEMPORARY);
1504
table_proto->set_type(message::Table::STANDARD);
1680
/* Open our intermediate table */
1681
new_table= session->open_temporary_table(identifier, false);
1507
message::Table::StorageEngine *protoengine;
1508
protoengine= table_proto->mutable_engine();
1510
StorageEngine *engine= local_create_info.db_type;
1512
protoengine->set_name(engine->getName());
1515
if (fill_table_proto(table_proto, "system_stupid_i_s_fix_nonsense",
1516
alter_info.create_list, &local_create_info,
1517
keys, schema_table->table->s->key_info))
1687
} /* namespace drizzled */