86
106
start_waiting_global_read_lock(session);
111
Prepare column and key definitions for CREATE TABLE in ALTER Table.
113
This function transforms parse output of ALTER Table - lists of
114
columns and keys to add, drop or modify into, essentially,
115
CREATE TABLE definition - a list of columns and keys of the new
116
table. While doing so, it also performs some (bug not all)
119
This function is invoked when we know that we're going to
120
perform ALTER Table via a temporary table -- i.e. fast ALTER Table
121
is not possible, perhaps because the ALTER statement contains
122
instructions that require change in table data, not only in
123
table definition or indexes.
125
@param[in,out] session thread handle. Used as a memory pool
126
and source of environment information.
127
@param[in] table the source table, open and locked
128
Used as an interface to the storage engine
129
to acquire additional information about
131
@param[in,out] create_info A blob with CREATE/ALTER Table
133
@param[in,out] alter_info Another blob with ALTER/CREATE parameters.
134
Originally create_info was used only in
135
CREATE TABLE and alter_info only in ALTER Table.
136
But since ALTER might end-up doing CREATE,
137
this distinction is gone and we just carry
138
around two structures.
141
Fills various create_info members based on information retrieved
142
from the storage engine.
143
Sets create_info->varchar if the table has a VARCHAR column.
144
Prepares alter_info->create_list and alter_info->key_list with
145
columns and keys of the new table.
146
@retval true error, out of memory or a semantical error in ALTER
148
@retval false success
150
static bool mysql_prepare_alter_table(Session *session,
152
HA_CREATE_INFO *create_info,
153
message::Table *table_proto,
154
AlterInfo *alter_info)
156
/* New column definitions are added here */
157
List<CreateField> new_create_list;
158
/* New key definitions are added here */
159
List<Key> new_key_list;
160
List_iterator<AlterDrop> drop_it(alter_info->drop_list);
161
List_iterator<CreateField> def_it(alter_info->create_list);
162
List_iterator<AlterColumn> alter_it(alter_info->alter_list);
163
List_iterator<Key> key_it(alter_info->key_list);
164
List_iterator<CreateField> find_it(new_create_list);
165
List_iterator<CreateField> field_it(new_create_list);
166
List<Key_part_spec> key_parts;
167
uint32_t used_fields= create_info->used_fields;
168
KEY *key_info= table->key_info;
171
/* Let new create options override the old ones */
172
message::Table::TableOptions *table_options;
173
table_options= table_proto->mutable_options();
175
if (! (used_fields & HA_CREATE_USED_BLOCK_SIZE))
176
table_options->set_block_size(table->s->block_size);
177
if (! (used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
178
create_info->default_table_charset= table->s->table_charset;
179
if (! (used_fields & HA_CREATE_USED_AUTO) &&
180
table->found_next_number_field)
182
/* Table has an autoincrement, copy value to new table */
183
table->file->info(HA_STATUS_AUTO);
184
create_info->auto_increment_value= table->file->stats.auto_increment_value;
186
if (! (used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE))
187
create_info->key_block_size= table->s->key_block_size;
189
table->restoreRecordAsDefault(); /* Empty record for DEFAULT */
192
/* First collect all fields from table which isn't in drop_list */
195
for (f_ptr= table->field; (field= *f_ptr); f_ptr++)
197
/* Check if field should be dropped */
200
while ((drop= drop_it++))
202
if (drop->type == AlterDrop::COLUMN &&
203
! my_strcasecmp(system_charset_info, field->field_name, drop->name))
205
/* Reset auto_increment value if it was dropped */
206
if (MTYP_TYPENR(field->unireg_check) == Field::NEXT_NUMBER &&
207
! (used_fields & HA_CREATE_USED_AUTO))
209
create_info->auto_increment_value= 0;
210
create_info->used_fields|= HA_CREATE_USED_AUTO;
221
/* Mark that we will read the field */
224
/* Check if field is changed */
226
while ((def= def_it++))
229
! my_strcasecmp(system_charset_info, field->field_name, def->change))
234
/* Field is changed */
238
new_create_list.push_back(def);
245
This field was not dropped and not changed, add it to the list
248
def= new CreateField(field, field);
249
new_create_list.push_back(def);
250
alter_it.rewind(); /* Change default if ALTER */
252
while ((alter= alter_it++))
254
if (! my_strcasecmp(system_charset_info,field->field_name, alter->name))
259
if (def->sql_type == DRIZZLE_TYPE_BLOB)
261
my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), def->change);
264
if ((def->def= alter->def))
266
/* Use new default */
267
def->flags&= ~NO_DEFAULT_VALUE_FLAG;
270
def->flags|= NO_DEFAULT_VALUE_FLAG;
276
while ((def= def_it++)) /* Add new columns */
278
if (def->change && ! def->field)
280
my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table->s->table_name.str);
284
Check that the DATE/DATETIME not null field we are going to add is
285
either has a default value or the '0000-00-00' is allowed by the
287
If the '0000-00-00' value isn't allowed then raise the error_if_not_empty
288
flag to allow ALTER Table only if the table to be altered is empty.
290
if ((def->sql_type == DRIZZLE_TYPE_DATE ||
291
def->sql_type == DRIZZLE_TYPE_DATETIME) &&
292
! alter_info->datetime_field &&
293
! (~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) &&
294
session->variables.sql_mode & MODE_NO_ZERO_DATE)
296
alter_info->datetime_field= def;
297
alter_info->error_if_not_empty= true;
300
new_create_list.push_back(def);
301
else if (def->after == first_keyword)
302
new_create_list.push_front(def);
307
while ((find= find_it++)) /* Add new columns */
309
if (! my_strcasecmp(system_charset_info,def->after, find->field_name))
314
my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table->s->table_name.str);
317
find_it.after(def); /* Put element after this */
319
XXX: hack for Bug#28427.
320
If column order has changed, force OFFLINE ALTER Table
321
without querying engine capabilities. If we ever have an
322
engine that supports online ALTER Table CHANGE COLUMN
323
<name> AFTER <name1> (Falcon?), this fix will effectively
324
disable the capability.
325
TODO: detect the situation in compare_tables, behave based
326
on engine capabilities.
328
if (alter_info->build_method == HA_BUILD_ONLINE)
330
my_error(ER_NOT_SUPPORTED_YET, MYF(0), session->query);
333
alter_info->build_method= HA_BUILD_OFFLINE;
336
if (alter_info->alter_list.elements)
338
my_error(ER_BAD_FIELD_ERROR,
340
alter_info->alter_list.head()->name,
341
table->s->table_name.str);
344
if (! new_create_list.elements)
346
my_message(ER_CANT_REMOVE_ALL_FIELDS,
347
ER(ER_CANT_REMOVE_ALL_FIELDS),
353
Collect all keys which isn't in drop list. Add only those
354
for which some fields exists.
356
for (uint32_t i= 0; i < table->s->keys; i++, key_info++)
358
char *key_name= key_info->name;
361
while ((drop= drop_it++))
363
if (drop->type == AlterDrop::KEY &&
364
! my_strcasecmp(system_charset_info, key_name, drop->name))
373
KEY_PART_INFO *key_part= key_info->key_part;
375
for (uint32_t j= 0; j < key_info->key_parts; j++, key_part++)
377
if (! key_part->field)
378
continue; /* Wrong field (from UNIREG) */
380
const char *key_part_name= key_part->field->field_name;
383
while ((cfield= field_it++))
387
if (! my_strcasecmp(system_charset_info, key_part_name, cfield->change))
390
else if (! my_strcasecmp(system_charset_info, key_part_name, cfield->field_name))
394
continue; /* Field is removed */
396
uint32_t key_part_length= key_part->length;
397
if (cfield->field) /* Not new field */
400
If the field can't have only a part used in a key according to its
401
new type, or should not be used partially according to its
402
previous type, or the field length is less than the key part
403
length, unset the key part length.
405
We also unset the key part length if it is the same as the
406
old field's length, so the whole new field will be used.
408
BLOBs may have cfield->length == 0, which is why we test it before
409
checking whether cfield->length < key_part_length (in chars).
411
if (! Field::type_can_have_key_part(cfield->field->type()) ||
412
! Field::type_can_have_key_part(cfield->sql_type) ||
413
(cfield->field->field_length == key_part_length &&
414
! f_is_blob(key_part->key_type)) ||
416
(cfield->length < key_part_length / key_part->field->charset()->mbmaxlen)))
417
key_part_length= 0; /* Use whole field */
419
key_part_length/= key_part->field->charset()->mbmaxlen;
420
key_parts.push_back(new Key_part_spec(cfield->field_name,
421
strlen(cfield->field_name),
424
if (key_parts.elements)
426
KEY_CREATE_INFO key_create_info;
428
enum Key::Keytype key_type;
429
memset(&key_create_info, 0, sizeof(key_create_info));
431
key_create_info.algorithm= key_info->algorithm;
432
if (key_info->flags & HA_USES_BLOCK_SIZE)
433
key_create_info.block_size= key_info->block_size;
434
if (key_info->flags & HA_USES_COMMENT)
435
key_create_info.comment= key_info->comment;
437
if (key_info->flags & HA_NOSAME)
439
if (is_primary_key_name(key_name))
440
key_type= Key::PRIMARY;
442
key_type= Key::UNIQUE;
445
key_type= Key::MULTIPLE;
447
key= new Key(key_type,
451
test(key_info->flags & HA_GENERATED_KEY),
453
new_key_list.push_back(key);
458
while ((key= key_it++)) /* Add new keys */
460
if (key->type == Key::FOREIGN_KEY &&
461
((Foreign_key *)key)->validate(new_create_list))
463
if (key->type != Key::FOREIGN_KEY)
464
new_key_list.push_back(key);
465
if (key->name.str && is_primary_key_name(key->name.str))
467
my_error(ER_WRONG_NAME_FOR_INDEX,
475
if (alter_info->drop_list.elements)
477
my_error(ER_CANT_DROP_FIELD_OR_KEY,
479
alter_info->drop_list.head()->name);
482
if (alter_info->alter_list.elements)
484
my_error(ER_CANT_DROP_FIELD_OR_KEY,
486
alter_info->alter_list.head()->name);
490
if (! table_proto->options().has_comment()
491
&& table->s->hasComment())
492
table_options->set_comment(table->s->getComment());
494
if (table->s->tmp_table)
495
create_info->options|= HA_LEX_CREATE_TMP_TABLE;
498
alter_info->create_list.swap(new_create_list);
499
alter_info->key_list.swap(new_key_list);
504
/* table_list should contain just one table */
505
static int mysql_discard_or_import_tablespace(Session *session,
506
TableList *table_list,
507
enum tablespace_op_type tablespace_op)
514
Note that DISCARD/IMPORT TABLESPACE always is the only operation in an
518
session->set_proc_info("discard_or_import_tablespace");
520
discard= test(tablespace_op == DISCARD_TABLESPACE);
523
We set this flag so that ha_innobase::open and ::external_lock() do
524
not complain when we lock the table
526
session->tablespace_op= true;
527
if (!(table= session->openTableLock(table_list, TL_WRITE)))
529
session->tablespace_op= false;
533
error= table->file->ha_discard_or_import_tablespace(discard);
535
session->set_proc_info("end");
540
/* The ALTER Table is always in its own transaction */
541
error = ha_autocommit_or_rollback(session, 0);
542
if (! session->endActiveTransaction())
546
write_bin_log(session, false, session->query, session->query_length);
549
ha_autocommit_or_rollback(session, error);
550
session->tablespace_op=false;
558
table->file->print_error(error, MYF(0));
564
Manages enabling/disabling of indexes for ALTER Table
567
alter_table_manage_keys()
569
indexes_were_disabled Whether the indexes of the from table
571
keys_onoff ENABLE | DISABLE | LEAVE_AS_IS
577
static bool alter_table_manage_keys(Table *table, int indexes_were_disabled,
578
enum enum_enable_or_disable keys_onoff)
581
switch (keys_onoff) {
583
error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
586
if (!indexes_were_disabled)
588
/* fall-through: disabled indexes */
590
error= table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
593
if (error == HA_ERR_WRONG_COMMAND)
595
push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
596
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
597
table->s->table_name.str);
600
table->file->print_error(error, MYF(0));
610
session Thread handle
611
new_db If there is a RENAME clause
612
new_name If there is a RENAME clause
613
create_info Information from the parsing phase about new
615
table_list The table to change.
616
alter_info Lists of fields, keys to be changed, added
618
order_num How many order_st BY fields has been specified.
619
order List of fields to order_st BY.
620
ignore Whether we have ALTER IGNORE Table
623
This is a veery long function and is everything but the kitchen sink :)
624
It is used to alter a table and not only by ALTER Table but also
625
CREATE|DROP INDEX are mapped on this function.
627
When the ALTER Table statement just does a RENAME or ENABLE|DISABLE KEYS,
628
or both, then this function short cuts its operation by renaming
629
the table and/or enabling/disabling the keys. In this case, the FRM is
630
not changed, directly by mysql_alter_table. However, if there is a
631
RENAME + change of a field, or an index, the short cut is not used.
632
See how `create_list` is used to generate the new FRM regarding the
633
structure of the fields. The same is done for the indices of the table.
635
Important is the fact, that this function tries to do as little work as
636
possible, by finding out whether a intermediate table is needed to copy
637
data into and when finishing the altering to use it as the original table.
638
For this reason the function compare_tables() is called, which decides
639
based on all kind of data how similar are the new and the original
646
bool mysql_alter_table(Session *session,
649
HA_CREATE_INFO *create_info,
650
message::Table *create_proto,
651
TableList *table_list,
652
AlterInfo *alter_info,
658
Table *new_table= NULL;
659
Table *name_lock= NULL;
664
char new_name_buff[FN_REFLEN];
665
char new_alias_buff[FN_REFLEN];
668
const char *new_alias;
669
char path[FN_REFLEN];
672
StorageEngine *old_db_type;
673
StorageEngine *new_db_type;
674
StorageEngine *save_old_db_type;
677
new_name_buff[0]= '\0';
679
if (table_list && table_list->schema_table)
681
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.c_str());
685
session->set_proc_info("init");
688
Assign variables table_name, new_name, db, new_db, path
689
to simplify further comparisons: we want to see if it's a RENAME
690
later just by comparing the pointers, avoiding the need for strcmp.
692
table_name= table_list->table_name;
694
if (! new_db || ! my_strcasecmp(table_alias_charset, new_db, db))
697
if (alter_info->tablespace_op != NO_TABLESPACE_OP)
699
/* DISCARD/IMPORT TABLESPACE is always alone in an ALTER Table */
700
return mysql_discard_or_import_tablespace(session, table_list, alter_info->tablespace_op);
703
build_table_filename(path, sizeof(path), db, table_name, false);
706
oss << drizzle_data_home << "/" << db << "/" << table_name;
708
(void) unpack_filename(new_name_buff, oss.str().c_str());
711
If this is just a rename of a view, short cut to the
712
following scenario: 1) lock LOCK_open 2) do a RENAME
714
This is a copy-paste added to make sure
715
ALTER (sic:) Table .. RENAME works for views. ALTER VIEW is handled
716
as an independent branch in mysql_execute_command. The need
717
for a copy-paste arose because the main code flow of ALTER Table
718
... RENAME tries to use openTableLock, which does not work for views
719
(openTableLock was never modified to merge table lists of child tables
720
into the main table list, like open_tables does).
721
This code is wrong and will be removed, please do not copy.
724
if (!(table= session->openTableLock(table_list, TL_WRITE_ALLOW_READ)))
727
table->use_all_columns();
729
/* Check that we are not trying to rename to an existing table */
732
strcpy(new_name_buff, new_name);
733
strcpy(new_alias_buff, new_name);
734
new_alias= new_alias_buff;
736
my_casedn_str(files_charset_info, new_name_buff);
737
new_alias= new_name; // Create lower case table name
738
my_casedn_str(files_charset_info, new_name);
741
! my_strcasecmp(table_alias_charset, new_name_buff, table_name))
744
Source and destination table names are equal: make later check
747
new_alias= new_name= table_name;
751
if (table->s->tmp_table != NO_TMP_TABLE)
753
if (session->find_temporary_table(new_db, new_name_buff))
755
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name_buff);
761
if (session->lock_table_name_if_not_cached(new_db, new_name, &name_lock))
766
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
770
build_table_filename(new_name_buff, sizeof(new_name_buff), new_db, new_name_buff, false);
772
if (StorageEngine::getTableProto(new_name_buff, NULL) == EEXIST)
774
/* Table will be closed by Session::executeCommand() */
775
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
783
new_alias= table_name;
784
new_name= table_name;
787
old_db_type= table->s->db_type();
788
if (! create_info->db_type)
790
create_info->db_type= old_db_type;
793
if (table->s->tmp_table != NO_TMP_TABLE)
794
create_info->options|= HA_LEX_CREATE_TMP_TABLE;
796
if (check_engine(session, new_name, create_info))
799
new_db_type= create_info->db_type;
801
if (new_db_type != old_db_type &&
802
!table->file->can_switch_engines())
805
my_error(ER_ROW_IS_REFERENCED, MYF(0));
809
if (create_info->row_type == ROW_TYPE_NOT_USED)
810
create_info->row_type= table->s->row_type;
812
if (old_db_type->check_flag(HTON_BIT_ALTER_NOT_SUPPORTED) ||
813
new_db_type->check_flag(HTON_BIT_ALTER_NOT_SUPPORTED))
815
my_error(ER_ILLEGAL_HA, MYF(0), table_name);
819
session->set_proc_info("setup");
822
* test if no other bits except ALTER_RENAME and ALTER_KEYS_ONOFF are set
825
tmp.reset(ALTER_RENAME);
826
tmp.reset(ALTER_KEYS_ONOFF);
827
tmp&= alter_info->flags;
829
! table->s->tmp_table) // no need to touch frm
831
switch (alter_info->keys_onoff)
837
wait_while_table_is_used() ensures that table being altered is
838
opened only by this thread and that Table::TableShare::version
839
of Table object corresponding to this table is 0.
840
The latter guarantees that no DML statement will open this table
841
until ALTER Table finishes (i.e. until close_thread_tables())
842
while the fact that the table is still open gives us protection
843
from concurrent DDL statements.
845
pthread_mutex_lock(&LOCK_open); /* DDL wait for/blocker */
846
wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
847
pthread_mutex_unlock(&LOCK_open);
848
error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
849
/* COND_refresh will be signaled in close_thread_tables() */
852
pthread_mutex_lock(&LOCK_open); /* DDL wait for/blocker */
853
wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
854
pthread_mutex_unlock(&LOCK_open);
855
error=table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
856
/* COND_refresh will be signaled in close_thread_tables() */
864
if (error == HA_ERR_WRONG_COMMAND)
867
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
868
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
872
pthread_mutex_lock(&LOCK_open); /* Lock to remove all instances of table from table cache before ALTER */
874
Unlike to the above case close_cached_table() below will remove ALL
875
instances of Table from table cache (it will also remove table lock
876
held by this thread). So to make actual table renaming and writing
877
to binlog atomic we have to put them into the same critical section
878
protected by LOCK_open mutex. This also removes gap for races between
879
access() and mysql_rename_table() calls.
883
(new_name != table_name || new_db != db))
885
session->set_proc_info("rename");
887
Then do a 'simple' rename of the table. First we need to close all
888
instances of 'source' table.
890
session->close_cached_table(table);
892
Then, we want check once again that target table does not exist.
893
Actually the order of these two steps does not matter since
894
earlier we took name-lock on the target table, so we do them
895
in this particular order only to be consistent with 5.0, in which
896
we don't take this name-lock and where this order really matters.
897
TODO: Investigate if we need this access() check at all.
899
if (StorageEngine::getTableProto(new_name, NULL) == EEXIST)
901
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name);
906
*fn_ext(new_name)= 0;
907
if (mysql_rename_table(old_db_type, db, table_name, new_db, new_alias, 0))
912
if (error == HA_ERR_WRONG_COMMAND)
915
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
916
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
922
write_bin_log(session, true, session->query, session->query_length);
927
table->file->print_error(error, MYF(0));
932
session->unlink_open_table(name_lock);
934
pthread_mutex_unlock(&LOCK_open);
935
table_list->table= NULL;
939
/* We have to do full alter table. */
942
If the old table had partitions and we are doing ALTER Table ...
943
engine= <new_engine>, the new table must preserve the original
944
partitioning. That means that the new engine is still the
945
partitioning engine, not the engine specified in the parser.
946
This is discovered in prep_alter_part_table, which in such case
947
updates create_info->db_type.
948
Now we need to update the stack copy of create_info->db_type,
949
as otherwise we won't be able to correctly move the files of the
950
temporary table to the result table files.
952
new_db_type= create_info->db_type;
954
if (mysql_prepare_alter_table(session, table, create_info, create_proto,
958
set_table_default_charset(create_info, db);
960
alter_info->build_method= HA_BUILD_OFFLINE;
962
snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%"PRIx64, TMP_FILE_PREFIX, (unsigned long) current_pid, session->thread_id);
964
/* Safety fix for innodb */
965
my_casedn_str(files_charset_info, tmp_name);
967
/* Create a temporary table with the new format */
968
error= create_temporary_table(session, table, new_db, tmp_name, create_info, create_proto, alter_info);
972
/* Open the table so we need to copy the data to it. */
973
if (table->s->tmp_table)
978
tbl.table_name= tmp_name;
980
/* Table is in session->temporary_tables */
981
new_table= session->openTable(&tbl, (bool*) 0, DRIZZLE_LOCK_IGNORE_FLUSH);
985
char tmp_path[FN_REFLEN];
986
/* table is a normal table: Create temporary table in same directory */
987
build_table_filename(tmp_path, sizeof(tmp_path), new_db, tmp_name, true);
988
/* Open our intermediate table */
989
new_table= session->open_temporary_table(tmp_path, new_db, tmp_name, 0, OTM_OPEN);
992
if (new_table == NULL)
995
/* Copy the data if necessary. */
996
session->count_cuted_fields= CHECK_FIELD_WARN; // calc cuted fields
997
session->cuted_fields= 0L;
998
session->set_proc_info("copy to tmp table");
1003
/* We don't want update TIMESTAMP fields during ALTER Table. */
1004
new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
1005
new_table->next_number_field= new_table->found_next_number_field;
1006
error= copy_data_between_tables(table,
1008
alter_info->create_list,
1014
alter_info->keys_onoff,
1015
alter_info->error_if_not_empty);
1017
/* We must not ignore bad input! */
1018
session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
1020
if (table->s->tmp_table != NO_TMP_TABLE)
1022
/* We changed a temporary table */
1026
/* Close lock if this is a transactional table */
1029
mysql_unlock_tables(session, session->lock);
1033
/* Remove link to old table and rename the new one */
1034
session->close_temporary_table(table, true, true);
1036
/* Should pass the 'new_name' as we store table name in the cache */
1037
if (new_table->rename_temporary_table(new_db, new_name))
1046
Close the intermediate table that will be the new table.
1047
Note that MERGE tables do not have their children attached here.
1049
new_table->intern_close_table();
1053
pthread_mutex_lock(&LOCK_open); /* ALTER TABLE */
1057
quick_rm_table(new_db_type, new_db, tmp_name, true);
1058
pthread_mutex_unlock(&LOCK_open);
1063
Data is copied. Now we:
1064
1) Wait until all other threads close old version of table.
1065
2) Close instances of table open by this thread and replace them
1066
with exclusive name-locks.
1067
3) Rename the old table to a temp name, rename the new one to the
1069
4) If we are under LOCK TABLES and don't do ALTER Table ... RENAME
1070
we reopen new version of table.
1071
5) Write statement to the binary log.
1072
6) If we are under LOCK TABLES and do ALTER Table ... RENAME we
1073
remove name-locks from list of open tables and table cache.
1074
7) If we are not not under LOCK TABLES we rely on close_thread_tables()
1075
call to remove name-locks from table cache and list of open table.
1078
session->set_proc_info("rename result table");
1080
snprintf(old_name, sizeof(old_name), "%s2-%lx-%"PRIx64, TMP_FILE_PREFIX, (unsigned long) current_pid, session->thread_id);
1082
my_casedn_str(files_charset_info, old_name);
1084
wait_while_table_is_used(session, table, HA_EXTRA_PREPARE_FOR_RENAME);
1085
session->close_data_files_and_morph_locks(db, table_name);
1088
save_old_db_type= old_db_type;
1091
This leads to the storage engine (SE) not being notified for renames in
1092
mysql_rename_table(), because we just juggle with the FRM and nothing
1093
more. If we have an intermediate table, then we notify the SE that
1094
it should become the actual table. Later, we will recycle the old table.
1095
However, in case of ALTER Table RENAME there might be no intermediate
1096
table. This is when the old and new tables are compatible, according to
1097
compare_table(). Then, we need one additional call to
1098
mysql_rename_table() with flag NO_FRM_RENAME, which does nothing else but
1099
actual rename in the SE and the FRM is not touched. Note that, if the
1100
table is renamed and the SE is also changed, then an intermediate table
1101
is created and the additional call will not take place.
1103
if (mysql_rename_table(old_db_type, db, table_name, db, old_name, FN_TO_IS_TMP))
1106
quick_rm_table(new_db_type, new_db, tmp_name, true);
1110
if (mysql_rename_table(new_db_type, new_db, tmp_name, new_db, new_alias, FN_FROM_IS_TMP) != 0)
1112
/* Try to get everything back. */
1114
quick_rm_table(new_db_type, new_db, new_alias, false);
1115
quick_rm_table(new_db_type, new_db, tmp_name, true);
1116
mysql_rename_table(old_db_type, db, old_name, db, table_name, FN_FROM_IS_TMP);
1122
/* This shouldn't happen. But let us play it safe. */
1123
goto err_with_placeholders;
1126
quick_rm_table(old_db_type, db, old_name, true);
1128
pthread_mutex_unlock(&LOCK_open);
1130
session->set_proc_info("end");
1132
write_bin_log(session, true, session->query, session->query_length);
1134
if (old_db_type->check_flag(HTON_BIT_FLUSH_AFTER_RENAME))
1137
For the alter table to be properly flushed to the logs, we
1138
have to open the new table. If not, we get a problem on server
1139
shutdown. But we do not need to attach MERGE children.
1141
char table_path[FN_REFLEN];
1143
build_table_filename(table_path, sizeof(table_path), new_db, table_name, false);
1144
t_table= session->open_temporary_table(table_path, new_db, tmp_name, false, OTM_OPEN);
1147
t_table->intern_close_table();
1151
errmsg_printf(ERRMSG_LVL_WARN, _("Could not open table %s.%s after rename\n"), new_db, table_name);
1153
ha_flush_logs(old_db_type);
1155
table_list->table= NULL;
1159
* Field::store() may have called my_error(). If this is
1160
* the case, we must not send an ok packet, since
1161
* Diagnostics_area::is_set() will fail an assert.
1163
if (! session->is_error())
1165
snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
1166
(ulong) (copied + deleted), (ulong) deleted,
1167
(ulong) session->cuted_fields);
1168
session->my_ok(copied + deleted, 0, 0L, tmp_name);
1169
session->some_tables_deleted=0;
1174
/* my_error() was called. Return true (which means error...) */
1181
/* close_temporary_table() frees the new_table pointer. */
1182
session->close_temporary_table(new_table, true, true);
1185
quick_rm_table(new_db_type, new_db, tmp_name, true);
1189
No default value was provided for a DATE/DATETIME field, the
1190
current sql_mode doesn't allow the '0000-00-00' value and
1191
the table to be altered isn't empty.
1194
if (alter_info->error_if_not_empty && session->row_count)
1196
const char *f_val= 0;
1197
enum enum_drizzle_timestamp_type t_type= DRIZZLE_TIMESTAMP_DATE;
1198
switch (alter_info->datetime_field->sql_type)
1200
case DRIZZLE_TYPE_DATE:
1201
f_val= "0000-00-00";
1202
t_type= DRIZZLE_TIMESTAMP_DATE;
1204
case DRIZZLE_TYPE_DATETIME:
1205
f_val= "0000-00-00 00:00:00";
1206
t_type= DRIZZLE_TIMESTAMP_DATETIME;
1209
/* Shouldn't get here. */
1212
bool save_abort_on_warning= session->abort_on_warning;
1213
session->abort_on_warning= true;
1214
make_truncated_value_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1215
f_val, strlength(f_val), t_type,
1216
alter_info->datetime_field->field_name);
1217
session->abort_on_warning= save_abort_on_warning;
1221
pthread_mutex_lock(&LOCK_open); /* ALTER TABLe */
1222
session->unlink_open_table(name_lock);
1223
pthread_mutex_unlock(&LOCK_open);
1227
err_with_placeholders:
1229
An error happened while we were holding exclusive name-lock on table
1230
being altered. To be safe under LOCK TABLES we should remove placeholders
1231
from list of open tables list and table cache.
1233
session->unlink_open_table(table);
1235
session->unlink_open_table(name_lock);
1236
pthread_mutex_unlock(&LOCK_open);
1239
/* mysql_alter_table */
1242
copy_data_between_tables(Table *from,Table *to,
1243
List<CreateField> &create,
1245
uint32_t order_num, order_st *order,
1248
enum enum_enable_or_disable keys_onoff,
1249
bool error_if_not_empty)
1252
CopyField *copy,*copy_end;
1253
ulong found_count,delete_count;
1254
Session *session= current_session;
1256
SORT_FIELD *sortorder;
1260
List<Item> all_fields;
1261
ha_rows examined_rows;
1262
bool auto_increment_field_copied= 0;
1263
uint64_t prev_insert_id;
1266
Turn off recovery logging since rollback of an alter table is to
1267
delete the new table so there is no need to log the changes to it.
1269
This needs to be done before external_lock
1271
error= ha_enable_transaction(session, false);
1275
if (!(copy= new CopyField[to->s->fields]))
1276
return -1; /* purecov: inspected */
1278
if (to->file->ha_external_lock(session, F_WRLCK))
1281
/* We need external lock before we can disable/enable keys */
1282
alter_table_manage_keys(to, from->file->indexes_are_disabled(), keys_onoff);
1284
/* We can abort alter table for any table type */
1285
session->abort_on_warning= !ignore;
1287
from->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
1288
to->file->ha_start_bulk_insert(from->file->stats.records);
1290
List_iterator<CreateField> it(create);
1293
for (Field **ptr=to->field ; *ptr ; ptr++)
1298
if (*ptr == to->next_number_field)
1299
auto_increment_field_copied= true;
1301
(copy_end++)->set(*ptr,def->field,0);
1306
found_count=delete_count=0;
1310
if (to->s->primary_key != MAX_KEY && to->file->primary_key_is_clustered())
1312
char warn_buff[DRIZZLE_ERRMSG_SIZE];
1313
snprintf(warn_buff, sizeof(warn_buff),
1314
_("order_st BY ignored because there is a user-defined clustered "
1315
"index in the table '%-.192s'"),
1316
from->s->table_name.str);
1317
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
1322
from->sort.io_cache= new IO_CACHE;
1323
memset(from->sort.io_cache, 0, sizeof(IO_CACHE));
1325
memset(&tables, 0, sizeof(tables));
1327
tables.alias= tables.table_name= from->s->table_name.str;
1328
tables.db= from->s->db.str;
1331
if (session->lex->select_lex.setup_ref_array(session, order_num) ||
1332
setup_order(session, session->lex->select_lex.ref_pointer_array,
1333
&tables, fields, all_fields, order) ||
1334
!(sortorder= make_unireg_sortorder(order, &length, NULL)) ||
1335
(from->sort.found_records= filesort(session, from, sortorder, length,
1336
(SQL_SELECT *) 0, HA_POS_ERROR,
1337
1, &examined_rows)) ==
1343
/* Tell handler that we have values for all columns in the to table */
1344
to->use_all_columns();
1345
init_read_record(&info, session, from, (SQL_SELECT *) 0, 1,1);
1347
to->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
1348
session->row_count= 0;
1349
to->restoreRecordAsDefault(); // Create empty record
1350
while (!(error=info.read_record(&info)))
1352
if (session->killed)
1354
session->send_kill_message();
1358
session->row_count++;
1359
/* Return error if source table isn't empty. */
1360
if (error_if_not_empty)
1365
if (to->next_number_field)
1367
if (auto_increment_field_copied)
1368
to->auto_increment_field_not_null= true;
1370
to->next_number_field->reset();
1373
for (CopyField *copy_ptr=copy ; copy_ptr != copy_end ; copy_ptr++)
1375
copy_ptr->do_copy(copy_ptr);
1377
prev_insert_id= to->file->next_insert_id;
1378
error=to->file->ha_write_row(to->record[0]);
1379
to->auto_increment_field_not_null= false;
1383
to->file->is_fatal_error(error, HA_CHECK_DUP))
1385
if (!to->file->is_fatal_error(error, HA_CHECK_DUP))
1387
uint32_t key_nr= to->file->get_dup_key(error);
1388
if ((int) key_nr >= 0)
1390
const char *err_msg= ER(ER_DUP_ENTRY_WITH_KEY_NAME);
1392
(to->key_info[0].key_part[0].field->flags &
1393
AUTO_INCREMENT_FLAG))
1394
err_msg= ER(ER_DUP_ENTRY_AUTOINCREMENT_CASE);
1395
to->file->print_keydup_error(key_nr, err_msg);
1400
to->file->print_error(error,MYF(0));
1403
to->file->restore_auto_increment(prev_insert_id);
1409
end_read_record(&info);
1410
from->free_io_cache();
1411
delete [] copy; // This is never 0
1413
if (to->file->ha_end_bulk_insert() && error <= 0)
1415
to->file->print_error(my_errno,MYF(0));
1418
to->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
1420
if (ha_enable_transaction(session, true))
1427
Ensure that the new table is saved properly to disk so that we
1430
if (ha_autocommit_or_rollback(session, 0))
1432
if (! session->endActiveTransaction())
1436
session->abort_on_warning= 0;
1437
from->free_io_cache();
1438
*copied= found_count;
1439
*deleted=delete_count;
1440
to->file->ha_release_auto_increment();
1441
if (to->file->ha_external_lock(session,F_UNLCK))
1443
return(error > 0 ? -1 : 0);
1447
create_temporary_table(Session *session,
1451
HA_CREATE_INFO *create_info,
1452
message::Table *create_proto,
1453
AlterInfo *alter_info)
1456
StorageEngine *old_db_type, *new_db_type;
1457
old_db_type= table->s->db_type();
1458
new_db_type= create_info->db_type;
1460
Create a table with a temporary name.
1461
We don't log the statement, it will be logged later.
1463
create_proto->set_name(tmp_name);
1464
create_proto->set_type(message::Table::TEMPORARY);
1466
message::Table::StorageEngine *protoengine;
1467
protoengine= create_proto->mutable_engine();
1468
protoengine->set_name(new_db_type->getName());
1470
error= mysql_create_table(session, new_db, tmp_name,
1471
create_info, create_proto, alter_info, 1, 0);
1476
/** @TODO This will soon die. */
1477
bool mysql_create_like_schema_frm(Session* session,
1478
TableList* schema_table,
1479
HA_CREATE_INFO *create_info,
1480
message::Table* table_proto)
1482
HA_CREATE_INFO local_create_info;
1483
AlterInfo alter_info;
1484
bool tmp_table= (create_info->options & HA_LEX_CREATE_TMP_TABLE);
1485
uint32_t keys= schema_table->table->s->keys;
1486
uint32_t db_options= 0;
1488
memset(&local_create_info, 0, sizeof(local_create_info));
1489
local_create_info.db_type= schema_table->table->s->db_type();
1490
local_create_info.row_type= schema_table->table->s->row_type;
1491
local_create_info.default_table_charset=default_charset_info;
1492
alter_info.flags.set(ALTER_CHANGE_COLUMN);
1493
alter_info.flags.set(ALTER_RECREATE);
1494
schema_table->table->use_all_columns();
1495
if (mysql_prepare_alter_table(session, schema_table->table,
1496
&local_create_info, table_proto, &alter_info))
1499
/* I_S tables are created with MAX_ROWS for some efficiency drive.
1500
When CREATE LIKE, we don't want to keep it coming across */
1501
message::Table::TableOptions *table_options;
1502
table_options= table_proto->mutable_options();
1503
table_options->clear_max_rows();
1505
if (mysql_prepare_create_table(session, &local_create_info, &alter_info,
1506
tmp_table, &db_options,
1507
schema_table->table->file,
1508
&schema_table->table->s->key_info, &keys, 0))
1511
table_proto->set_name("system_stupid_i_s_fix_nonsense");
1513
table_proto->set_type(message::Table::TEMPORARY);
1515
table_proto->set_type(message::Table::STANDARD);
1518
message::Table::StorageEngine *protoengine;
1519
protoengine= table_proto->mutable_engine();
1521
StorageEngine *engine= local_create_info.db_type;
1523
protoengine->set_name(engine->getName());
1526
if (fill_table_proto(table_proto, "system_stupid_i_s_fix_nonsense",
1527
alter_info.create_list, &local_create_info,
1528
keys, schema_table->table->s->key_info))