2799
2698
&handler::ha_check));
2803
/* table_list should contain just one table */
2805
mysql_discard_or_import_tablespace(Session *session,
2806
TableList *table_list,
2807
enum tablespace_op_type tablespace_op)
2814
Note that DISCARD/IMPORT TABLESPACE always is the only operation in an
2818
session->set_proc_info("discard_or_import_tablespace");
2820
discard= test(tablespace_op == DISCARD_TABLESPACE);
2823
We set this flag so that ha_innobase::open and ::external_lock() do
2824
not complain when we lock the table
2826
session->tablespace_op= true;
2827
if (!(table= session->openTableLock(table_list, TL_WRITE)))
2829
session->tablespace_op= false;
2833
error= table->file->ha_discard_or_import_tablespace(discard);
2835
session->set_proc_info("end");
2840
/* The ALTER Table is always in its own transaction */
2841
error = ha_autocommit_or_rollback(session, 0);
2842
if (! session->endActiveTransaction())
2846
write_bin_log(session, false, session->query, session->query_length);
2849
ha_autocommit_or_rollback(session, error);
2850
session->tablespace_op=false;
2858
table->file->print_error(error, MYF(0));
2865
Manages enabling/disabling of indexes for ALTER Table
2868
alter_table_manage_keys()
2870
indexes_were_disabled Whether the indexes of the from table
2872
keys_onoff ENABLE | DISABLE | LEAVE_AS_IS
2880
bool alter_table_manage_keys(Table *table, int indexes_were_disabled,
2881
enum enum_enable_or_disable keys_onoff)
2884
switch (keys_onoff) {
2886
error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
2889
if (!indexes_were_disabled)
2891
/* fall-through: disabled indexes */
2893
error= table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
2896
if (error == HA_ERR_WRONG_COMMAND)
2898
push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
2899
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
2900
table->s->table_name.str);
2903
table->file->print_error(error, MYF(0));
2909
create_temporary_table(Session *session,
2913
HA_CREATE_INFO *create_info,
2914
message::Table *create_proto,
2915
Alter_info *alter_info)
2918
StorageEngine *old_db_type, *new_db_type;
2919
old_db_type= table->s->db_type();
2920
new_db_type= create_info->db_type;
2922
Create a table with a temporary name.
2923
We don't log the statement, it will be logged later.
2925
create_proto->set_name(tmp_name);
2926
create_proto->set_type(message::Table::TEMPORARY);
2928
message::Table::StorageEngine *protoengine;
2929
protoengine= create_proto->mutable_engine();
2930
protoengine->set_name(new_db_type->getName());
2932
error= mysql_create_table(session, new_db, tmp_name,
2933
create_info, create_proto, alter_info, 1, 0);
2940
Prepare column and key definitions for CREATE TABLE in ALTER Table.
2942
This function transforms parse output of ALTER Table - lists of
2943
columns and keys to add, drop or modify into, essentially,
2944
CREATE TABLE definition - a list of columns and keys of the new
2945
table. While doing so, it also performs some (bug not all)
2948
This function is invoked when we know that we're going to
2949
perform ALTER Table via a temporary table -- i.e. fast ALTER Table
2950
is not possible, perhaps because the ALTER statement contains
2951
instructions that require change in table data, not only in
2952
table definition or indexes.
2954
@param[in,out] session thread handle. Used as a memory pool
2955
and source of environment information.
2956
@param[in] table the source table, open and locked
2957
Used as an interface to the storage engine
2958
to acquire additional information about
2960
@param[in,out] create_info A blob with CREATE/ALTER Table
2962
@param[in,out] alter_info Another blob with ALTER/CREATE parameters.
2963
Originally create_info was used only in
2964
CREATE TABLE and alter_info only in ALTER Table.
2965
But since ALTER might end-up doing CREATE,
2966
this distinction is gone and we just carry
2967
around two structures.
2970
Fills various create_info members based on information retrieved
2971
from the storage engine.
2972
Sets create_info->varchar if the table has a VARCHAR column.
2973
Prepares alter_info->create_list and alter_info->key_list with
2974
columns and keys of the new table.
2975
@retval true error, out of memory or a semantical error in ALTER
2977
@retval false success
2981
mysql_prepare_alter_table(Session *session, Table *table,
2982
HA_CREATE_INFO *create_info,
2983
message::Table *table_proto,
2984
Alter_info *alter_info)
2986
/* New column definitions are added here */
2987
List<CreateField> new_create_list;
2988
/* New key definitions are added here */
2989
List<Key> new_key_list;
2990
List_iterator<Alter_drop> drop_it(alter_info->drop_list);
2991
List_iterator<CreateField> def_it(alter_info->create_list);
2992
List_iterator<Alter_column> alter_it(alter_info->alter_list);
2993
List_iterator<Key> key_it(alter_info->key_list);
2994
List_iterator<CreateField> find_it(new_create_list);
2995
List_iterator<CreateField> field_it(new_create_list);
2996
List<Key_part_spec> key_parts;
2997
uint32_t used_fields= create_info->used_fields;
2998
KEY *key_info=table->key_info;
3002
/* Let new create options override the old ones */
3003
message::Table::TableOptions *table_options;
3004
table_options= table_proto->mutable_options();
3006
if (!(used_fields & HA_CREATE_USED_BLOCK_SIZE))
3007
create_info->block_size= table->s->block_size;
3008
if (!(used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
3009
create_info->default_table_charset= table->s->table_charset;
3010
if (!(used_fields & HA_CREATE_USED_AUTO) && table->found_next_number_field)
3012
/* Table has an autoincrement, copy value to new table */
3013
table->file->info(HA_STATUS_AUTO);
3014
create_info->auto_increment_value= table->file->stats.auto_increment_value;
3016
if (!(used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE))
3017
create_info->key_block_size= table->s->key_block_size;
3019
table->restoreRecordAsDefault(); // Empty record for DEFAULT
3023
First collect all fields from table which isn't in drop_list
3025
Field **f_ptr,*field;
3026
for (f_ptr=table->field ; (field= *f_ptr) ; f_ptr++)
3028
/* Check if field should be dropped */
3031
while ((drop=drop_it++))
3033
if (drop->type == Alter_drop::COLUMN &&
3034
!my_strcasecmp(system_charset_info,field->field_name, drop->name))
3036
/* Reset auto_increment value if it was dropped */
3037
if (MTYP_TYPENR(field->unireg_check) == Field::NEXT_NUMBER &&
3038
!(used_fields & HA_CREATE_USED_AUTO))
3040
create_info->auto_increment_value=0;
3041
create_info->used_fields|=HA_CREATE_USED_AUTO;
3052
/* Mark that we will read the field */
3053
field->setReadSet();
3055
/* Check if field is changed */
3057
while ((def=def_it++))
3060
!my_strcasecmp(system_charset_info,field->field_name, def->change))
3064
{ // Field is changed
3068
new_create_list.push_back(def);
3075
This field was not dropped and not changed, add it to the list
3078
def= new CreateField(field, field);
3079
new_create_list.push_back(def);
3080
alter_it.rewind(); // Change default if ALTER
3081
Alter_column *alter;
3082
while ((alter=alter_it++))
3084
if (!my_strcasecmp(system_charset_info,field->field_name, alter->name))
3089
if (def->sql_type == DRIZZLE_TYPE_BLOB)
3091
my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), def->change);
3094
if ((def->def=alter->def)) // Use new default
3095
def->flags&= ~NO_DEFAULT_VALUE_FLAG;
3097
def->flags|= NO_DEFAULT_VALUE_FLAG;
3103
while ((def=def_it++)) // Add new columns
3105
if (def->change && ! def->field)
3107
my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table->s->table_name.str);
3111
Check that the DATE/DATETIME not null field we are going to add is
3112
either has a default value or the '0000-00-00' is allowed by the
3114
If the '0000-00-00' value isn't allowed then raise the error_if_not_empty
3115
flag to allow ALTER Table only if the table to be altered is empty.
3117
if ((def->sql_type == DRIZZLE_TYPE_DATE ||
3118
def->sql_type == DRIZZLE_TYPE_DATETIME) &&
3119
!alter_info->datetime_field &&
3120
!(~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) &&
3121
session->variables.sql_mode & MODE_NO_ZERO_DATE)
3123
alter_info->datetime_field= def;
3124
alter_info->error_if_not_empty= true;
3127
new_create_list.push_back(def);
3128
else if (def->after == first_keyword)
3129
new_create_list.push_front(def);
3134
while ((find=find_it++)) // Add new columns
3136
if (!my_strcasecmp(system_charset_info,def->after, find->field_name))
3141
my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table->s->table_name.str);
3144
find_it.after(def); // Put element after this
3146
XXX: hack for Bug#28427.
3147
If column order has changed, force OFFLINE ALTER Table
3148
without querying engine capabilities. If we ever have an
3149
engine that supports online ALTER Table CHANGE COLUMN
3150
<name> AFTER <name1> (Falcon?), this fix will effectively
3151
disable the capability.
3152
TODO: detect the situation in compare_tables, behave based
3153
on engine capabilities.
3155
if (alter_info->build_method == HA_BUILD_ONLINE)
3157
my_error(ER_NOT_SUPPORTED_YET, MYF(0), session->query);
3160
alter_info->build_method= HA_BUILD_OFFLINE;
3163
if (alter_info->alter_list.elements)
3165
my_error(ER_BAD_FIELD_ERROR, MYF(0),
3166
alter_info->alter_list.head()->name, table->s->table_name.str);
3169
if (!new_create_list.elements)
3171
my_message(ER_CANT_REMOVE_ALL_FIELDS, ER(ER_CANT_REMOVE_ALL_FIELDS),
3177
Collect all keys which isn't in drop list. Add only those
3178
for which some fields exists.
3181
for (uint32_t i=0 ; i < table->s->keys ; i++,key_info++)
3183
char *key_name= key_info->name;
3186
while ((drop=drop_it++))
3188
if (drop->type == Alter_drop::KEY &&
3189
!my_strcasecmp(system_charset_info,key_name, drop->name))
3198
KEY_PART_INFO *key_part= key_info->key_part;
3200
for (uint32_t j=0 ; j < key_info->key_parts ; j++,key_part++)
3202
if (!key_part->field)
3203
continue; // Wrong field (from UNIREG)
3204
const char *key_part_name=key_part->field->field_name;
3205
CreateField *cfield;
3207
while ((cfield=field_it++))
3211
if (!my_strcasecmp(system_charset_info, key_part_name,
3215
else if (!my_strcasecmp(system_charset_info,
3216
key_part_name, cfield->field_name))
3220
continue; // Field is removed
3221
uint32_t key_part_length=key_part->length;
3222
if (cfield->field) // Not new field
3225
If the field can't have only a part used in a key according to its
3226
new type, or should not be used partially according to its
3227
previous type, or the field length is less than the key part
3228
length, unset the key part length.
3230
We also unset the key part length if it is the same as the
3231
old field's length, so the whole new field will be used.
3233
BLOBs may have cfield->length == 0, which is why we test it before
3234
checking whether cfield->length < key_part_length (in chars).
3236
if (!Field::type_can_have_key_part(cfield->field->type()) ||
3237
!Field::type_can_have_key_part(cfield->sql_type) ||
3238
(cfield->field->field_length == key_part_length &&
3239
!f_is_blob(key_part->key_type)) ||
3240
(cfield->length && (cfield->length < key_part_length /
3241
key_part->field->charset()->mbmaxlen)))
3242
key_part_length= 0; // Use whole field
3244
key_part_length /= key_part->field->charset()->mbmaxlen;
3245
key_parts.push_back(new Key_part_spec(cfield->field_name,
3246
strlen(cfield->field_name),
3249
if (key_parts.elements)
3251
KEY_CREATE_INFO key_create_info;
3253
enum Key::Keytype key_type;
3254
memset(&key_create_info, 0, sizeof(key_create_info));
3256
key_create_info.algorithm= key_info->algorithm;
3257
if (key_info->flags & HA_USES_BLOCK_SIZE)
3258
key_create_info.block_size= key_info->block_size;
3259
if (key_info->flags & HA_USES_COMMENT)
3260
key_create_info.comment= key_info->comment;
3262
if (key_info->flags & HA_NOSAME)
3264
if (is_primary_key_name(key_name))
3265
key_type= Key::PRIMARY;
3267
key_type= Key::UNIQUE;
3270
key_type= Key::MULTIPLE;
3272
key= new Key(key_type, key_name, strlen(key_name),
3274
test(key_info->flags & HA_GENERATED_KEY),
3276
new_key_list.push_back(key);
3281
while ((key=key_it++)) // Add new keys
3283
if (key->type == Key::FOREIGN_KEY &&
3284
((Foreign_key *)key)->validate(new_create_list))
3286
if (key->type != Key::FOREIGN_KEY)
3287
new_key_list.push_back(key);
3288
if (key->name.str && is_primary_key_name(key->name.str))
3290
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name.str);
3296
if (alter_info->drop_list.elements)
3298
my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
3299
alter_info->drop_list.head()->name);
3302
if (alter_info->alter_list.elements)
3304
my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
3305
alter_info->alter_list.head()->name);
3309
if (! table_proto->options().has_comment()
3310
&& table->s->hasComment())
3311
table_options->set_comment(table->s->getComment());
3313
if (table->s->tmp_table)
3314
create_info->options|=HA_LEX_CREATE_TMP_TABLE;
3317
alter_info->create_list.swap(new_create_list);
3318
alter_info->key_list.swap(new_key_list);
3329
session Thread handle
3330
new_db If there is a RENAME clause
3331
new_name If there is a RENAME clause
3332
create_info Information from the parsing phase about new
3334
table_list The table to change.
3335
alter_info Lists of fields, keys to be changed, added
3337
order_num How many order_st BY fields has been specified.
3338
order List of fields to order_st BY.
3339
ignore Whether we have ALTER IGNORE Table
3342
This is a veery long function and is everything but the kitchen sink :)
3343
It is used to alter a table and not only by ALTER Table but also
3344
CREATE|DROP INDEX are mapped on this function.
3346
When the ALTER Table statement just does a RENAME or ENABLE|DISABLE KEYS,
3347
or both, then this function short cuts its operation by renaming
3348
the table and/or enabling/disabling the keys. In this case, the FRM is
3349
not changed, directly by mysql_alter_table. However, if there is a
3350
RENAME + change of a field, or an index, the short cut is not used.
3351
See how `create_list` is used to generate the new FRM regarding the
3352
structure of the fields. The same is done for the indices of the table.
3354
Important is the fact, that this function tries to do as little work as
3355
possible, by finding out whether a intermediate table is needed to copy
3356
data into and when finishing the altering to use it as the original table.
3357
For this reason the function compare_tables() is called, which decides
3358
based on all kind of data how similar are the new and the original
3366
bool mysql_alter_table(Session *session,
3369
HA_CREATE_INFO *create_info,
3370
message::Table *create_proto,
3371
TableList *table_list,
3372
Alter_info *alter_info,
3378
Table *new_table= NULL;
3379
Table *name_lock= NULL;
3380
string new_name_str;
3384
char new_name_buff[FN_REFLEN];
3385
char new_alias_buff[FN_REFLEN];
3388
const char *new_alias;
3389
char path[FN_REFLEN];
3392
StorageEngine *old_db_type;
3393
StorageEngine *new_db_type;
3394
StorageEngine *save_old_db_type;
3397
new_name_buff[0]= '\0';
3399
if (table_list && table_list->schema_table)
3401
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.c_str());
3405
session->set_proc_info("init");
3408
Assign variables table_name, new_name, db, new_db, path
3409
to simplify further comparisons: we want to see if it's a RENAME
3410
later just by comparing the pointers, avoiding the need for strcmp.
3412
table_name= table_list->table_name;
3414
if (! new_db || ! my_strcasecmp(table_alias_charset, new_db, db))
3417
if (alter_info->tablespace_op != NO_TABLESPACE_OP)
3419
/* DISCARD/IMPORT TABLESPACE is always alone in an ALTER Table */
3420
return mysql_discard_or_import_tablespace(session, table_list, alter_info->tablespace_op);
3423
build_table_filename(path, sizeof(path), db, table_name, false);
3426
oss << drizzle_data_home << "/" << db << "/" << table_name;
3428
(void) unpack_filename(new_name_buff, oss.str().c_str());
3431
If this is just a rename of a view, short cut to the
3432
following scenario: 1) lock LOCK_open 2) do a RENAME
3433
2) unlock LOCK_open.
3434
This is a copy-paste added to make sure
3435
ALTER (sic:) Table .. RENAME works for views. ALTER VIEW is handled
3436
as an independent branch in mysql_execute_command. The need
3437
for a copy-paste arose because the main code flow of ALTER Table
3438
... RENAME tries to use openTableLock, which does not work for views
3439
(openTableLock was never modified to merge table lists of child tables
3440
into the main table list, like open_tables does).
3441
This code is wrong and will be removed, please do not copy.
3444
if (!(table= session->openTableLock(table_list, TL_WRITE_ALLOW_READ)))
3447
table->use_all_columns();
3449
/* Check that we are not trying to rename to an existing table */
3452
strcpy(new_name_buff, new_name);
3453
strcpy(new_alias_buff, new_name);
3454
new_alias= new_alias_buff;
3456
my_casedn_str(files_charset_info, new_name_buff);
3457
new_alias= new_name; // Create lower case table name
3458
my_casedn_str(files_charset_info, new_name);
3461
! my_strcasecmp(table_alias_charset, new_name_buff, table_name))
3464
Source and destination table names are equal: make later check
3467
new_alias= new_name= table_name;
3471
if (table->s->tmp_table != NO_TMP_TABLE)
3473
if (session->find_temporary_table(new_db, new_name_buff))
3475
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name_buff);
3481
if (session->lock_table_name_if_not_cached(new_db, new_name, &name_lock))
3486
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
3490
build_table_filename(new_name_buff, sizeof(new_name_buff), new_db, new_name_buff, false);
3492
if (StorageEngine::getTableProto(new_name_buff, NULL) == EEXIST)
3494
/* Table will be closed by Session::executeCommand() */
3495
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
3503
new_alias= table_name;
3504
new_name= table_name;
3507
old_db_type= table->s->db_type();
3508
if (! create_info->db_type)
3510
create_info->db_type= old_db_type;
3513
if (table->s->tmp_table != NO_TMP_TABLE)
3514
create_info->options|= HA_LEX_CREATE_TMP_TABLE;
3516
if (check_engine(session, new_name, create_info))
3519
new_db_type= create_info->db_type;
3521
if (new_db_type != old_db_type &&
3522
!table->file->can_switch_engines())
3525
my_error(ER_ROW_IS_REFERENCED, MYF(0));
3529
if (create_info->row_type == ROW_TYPE_NOT_USED)
3530
create_info->row_type= table->s->row_type;
3532
if (old_db_type->check_flag(HTON_BIT_ALTER_NOT_SUPPORTED) ||
3533
new_db_type->check_flag(HTON_BIT_ALTER_NOT_SUPPORTED))
3535
my_error(ER_ILLEGAL_HA, MYF(0), table_name);
3539
session->set_proc_info("setup");
3542
* test if no other bits except ALTER_RENAME and ALTER_KEYS_ONOFF are set
3545
tmp.reset(ALTER_RENAME);
3546
tmp.reset(ALTER_KEYS_ONOFF);
3547
tmp&= alter_info->flags;
3548
if (! (tmp.any()) &&
3549
! table->s->tmp_table) // no need to touch frm
3551
switch (alter_info->keys_onoff)
3557
wait_while_table_is_used() ensures that table being altered is
3558
opened only by this thread and that Table::TableShare::version
3559
of Table object corresponding to this table is 0.
3560
The latter guarantees that no DML statement will open this table
3561
until ALTER Table finishes (i.e. until close_thread_tables())
3562
while the fact that the table is still open gives us protection
3563
from concurrent DDL statements.
3565
pthread_mutex_lock(&LOCK_open); /* DDL wait for/blocker */
3566
wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
3567
pthread_mutex_unlock(&LOCK_open);
3568
error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
3569
/* COND_refresh will be signaled in close_thread_tables() */
3572
pthread_mutex_lock(&LOCK_open); /* DDL wait for/blocker */
3573
wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
3574
pthread_mutex_unlock(&LOCK_open);
3575
error=table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
3576
/* COND_refresh will be signaled in close_thread_tables() */
3584
if (error == HA_ERR_WRONG_COMMAND)
3587
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
3588
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
3592
pthread_mutex_lock(&LOCK_open); /* Lock to remove all instances of table from table cache before ALTER */
3594
Unlike to the above case close_cached_table() below will remove ALL
3595
instances of Table from table cache (it will also remove table lock
3596
held by this thread). So to make actual table renaming and writing
3597
to binlog atomic we have to put them into the same critical section
3598
protected by LOCK_open mutex. This also removes gap for races between
3599
access() and mysql_rename_table() calls.
3603
(new_name != table_name || new_db != db))
3605
session->set_proc_info("rename");
3607
Then do a 'simple' rename of the table. First we need to close all
3608
instances of 'source' table.
3610
session->close_cached_table(table);
3612
Then, we want check once again that target table does not exist.
3613
Actually the order of these two steps does not matter since
3614
earlier we took name-lock on the target table, so we do them
3615
in this particular order only to be consistent with 5.0, in which
3616
we don't take this name-lock and where this order really matters.
3617
TODO: Investigate if we need this access() check at all.
3619
if (StorageEngine::getTableProto(new_name, NULL) == EEXIST)
3621
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name);
3626
*fn_ext(new_name)= 0;
3627
if (mysql_rename_table(old_db_type, db, table_name, new_db, new_alias, 0))
3632
if (error == HA_ERR_WRONG_COMMAND)
3635
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
3636
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
3642
write_bin_log(session, true, session->query, session->query_length);
3647
table->file->print_error(error, MYF(0));
3652
session->unlink_open_table(name_lock);
3654
pthread_mutex_unlock(&LOCK_open);
3655
table_list->table= NULL;
3659
/* We have to do full alter table. */
3662
If the old table had partitions and we are doing ALTER Table ...
3663
engine= <new_engine>, the new table must preserve the original
3664
partitioning. That means that the new engine is still the
3665
partitioning engine, not the engine specified in the parser.
3666
This is discovered in prep_alter_part_table, which in such case
3667
updates create_info->db_type.
3668
Now we need to update the stack copy of create_info->db_type,
3669
as otherwise we won't be able to correctly move the files of the
3670
temporary table to the result table files.
3672
new_db_type= create_info->db_type;
3674
if (mysql_prepare_alter_table(session, table, create_info, create_proto,
3678
set_table_default_charset(create_info, db);
3680
alter_info->build_method= HA_BUILD_OFFLINE;
3682
snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%"PRIx64, TMP_FILE_PREFIX, (unsigned long) current_pid, session->thread_id);
3684
/* Safety fix for innodb */
3685
my_casedn_str(files_charset_info, tmp_name);
3687
/* Create a temporary table with the new format */
3688
error= create_temporary_table(session, table, new_db, tmp_name, create_info, create_proto, alter_info);
3692
/* Open the table so we need to copy the data to it. */
3693
if (table->s->tmp_table)
3697
tbl.alias= tmp_name;
3698
tbl.table_name= tmp_name;
3700
/* Table is in session->temporary_tables */
3701
new_table= session->openTable(&tbl, (bool*) 0, DRIZZLE_LOCK_IGNORE_FLUSH);
3705
char tmp_path[FN_REFLEN];
3706
/* table is a normal table: Create temporary table in same directory */
3707
build_table_filename(tmp_path, sizeof(tmp_path), new_db, tmp_name, true);
3708
/* Open our intermediate table */
3709
new_table= session->open_temporary_table(tmp_path, new_db, tmp_name, 0, OTM_OPEN);
3712
if (new_table == NULL)
3715
/* Copy the data if necessary. */
3716
session->count_cuted_fields= CHECK_FIELD_WARN; // calc cuted fields
3717
session->cuted_fields= 0L;
3718
session->set_proc_info("copy to tmp table");
3723
/* We don't want update TIMESTAMP fields during ALTER Table. */
3724
new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
3725
new_table->next_number_field= new_table->found_next_number_field;
3726
error= copy_data_between_tables(table,
3728
alter_info->create_list,
3734
alter_info->keys_onoff,
3735
alter_info->error_if_not_empty);
3737
/* We must not ignore bad input! */
3738
session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
3740
if (table->s->tmp_table != NO_TMP_TABLE)
3742
/* We changed a temporary table */
3746
/* Close lock if this is a transactional table */
3749
mysql_unlock_tables(session, session->lock);
3753
/* Remove link to old table and rename the new one */
3754
session->close_temporary_table(table, true, true);
3756
/* Should pass the 'new_name' as we store table name in the cache */
3757
if (new_table->rename_temporary_table(new_db, new_name))
3766
Close the intermediate table that will be the new table.
3767
Note that MERGE tables do not have their children attached here.
3769
new_table->intern_close_table();
3773
pthread_mutex_lock(&LOCK_open); /* ALTER TABLE */
3777
quick_rm_table(new_db_type, new_db, tmp_name, true);
3778
pthread_mutex_unlock(&LOCK_open);
3783
Data is copied. Now we:
3784
1) Wait until all other threads close old version of table.
3785
2) Close instances of table open by this thread and replace them
3786
with exclusive name-locks.
3787
3) Rename the old table to a temp name, rename the new one to the
3789
4) If we are under LOCK TABLES and don't do ALTER Table ... RENAME
3790
we reopen new version of table.
3791
5) Write statement to the binary log.
3792
6) If we are under LOCK TABLES and do ALTER Table ... RENAME we
3793
remove name-locks from list of open tables and table cache.
3794
7) If we are not not under LOCK TABLES we rely on close_thread_tables()
3795
call to remove name-locks from table cache and list of open table.
3798
session->set_proc_info("rename result table");
3800
snprintf(old_name, sizeof(old_name), "%s2-%lx-%"PRIx64, TMP_FILE_PREFIX, (unsigned long) current_pid, session->thread_id);
3802
my_casedn_str(files_charset_info, old_name);
3804
wait_while_table_is_used(session, table, HA_EXTRA_PREPARE_FOR_RENAME);
3805
session->close_data_files_and_morph_locks(db, table_name);
3808
save_old_db_type= old_db_type;
3811
This leads to the storage engine (SE) not being notified for renames in
3812
mysql_rename_table(), because we just juggle with the FRM and nothing
3813
more. If we have an intermediate table, then we notify the SE that
3814
it should become the actual table. Later, we will recycle the old table.
3815
However, in case of ALTER Table RENAME there might be no intermediate
3816
table. This is when the old and new tables are compatible, according to
3817
compare_table(). Then, we need one additional call to
3818
mysql_rename_table() with flag NO_FRM_RENAME, which does nothing else but
3819
actual rename in the SE and the FRM is not touched. Note that, if the
3820
table is renamed and the SE is also changed, then an intermediate table
3821
is created and the additional call will not take place.
3823
if (mysql_rename_table(old_db_type, db, table_name, db, old_name, FN_TO_IS_TMP))
3826
quick_rm_table(new_db_type, new_db, tmp_name, true);
3830
if (mysql_rename_table(new_db_type, new_db, tmp_name, new_db, new_alias, FN_FROM_IS_TMP) != 0)
3832
/* Try to get everything back. */
3834
quick_rm_table(new_db_type, new_db, new_alias, false);
3835
quick_rm_table(new_db_type, new_db, tmp_name, true);
3836
mysql_rename_table(old_db_type, db, old_name, db, table_name, FN_FROM_IS_TMP);
3842
/* This shouldn't happen. But let us play it safe. */
3843
goto err_with_placeholders;
3846
quick_rm_table(old_db_type, db, old_name, true);
3848
pthread_mutex_unlock(&LOCK_open);
3850
session->set_proc_info("end");
3852
write_bin_log(session, true, session->query, session->query_length);
3854
if (old_db_type->check_flag(HTON_BIT_FLUSH_AFTER_RENAME))
3857
For the alter table to be properly flushed to the logs, we
3858
have to open the new table. If not, we get a problem on server
3859
shutdown. But we do not need to attach MERGE children.
3861
char table_path[FN_REFLEN];
3863
build_table_filename(table_path, sizeof(table_path), new_db, table_name, false);
3864
t_table= session->open_temporary_table(table_path, new_db, tmp_name, false, OTM_OPEN);
3867
t_table->intern_close_table();
3871
errmsg_printf(ERRMSG_LVL_WARN, _("Could not open table %s.%s after rename\n"), new_db, table_name);
3873
ha_flush_logs(old_db_type);
3875
table_list->table= NULL;
3879
* Field::store() may have called my_error(). If this is
3880
* the case, we must not send an ok packet, since
3881
* Diagnostics_area::is_set() will fail an assert.
3883
if (! session->is_error())
3885
snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
3886
(ulong) (copied + deleted), (ulong) deleted,
3887
(ulong) session->cuted_fields);
3888
session->my_ok(copied + deleted, 0, 0L, tmp_name);
3889
session->some_tables_deleted=0;
3894
/* my_error() was called. Return true (which means error...) */
3901
/* close_temporary_table() frees the new_table pointer. */
3902
session->close_temporary_table(new_table, true, true);
3905
quick_rm_table(new_db_type, new_db, tmp_name, true);
3909
No default value was provided for a DATE/DATETIME field, the
3910
current sql_mode doesn't allow the '0000-00-00' value and
3911
the table to be altered isn't empty.
3914
if (alter_info->error_if_not_empty && session->row_count)
3916
const char *f_val= 0;
3917
enum enum_drizzle_timestamp_type t_type= DRIZZLE_TIMESTAMP_DATE;
3918
switch (alter_info->datetime_field->sql_type)
3920
case DRIZZLE_TYPE_DATE:
3921
f_val= "0000-00-00";
3922
t_type= DRIZZLE_TIMESTAMP_DATE;
3924
case DRIZZLE_TYPE_DATETIME:
3925
f_val= "0000-00-00 00:00:00";
3926
t_type= DRIZZLE_TIMESTAMP_DATETIME;
3929
/* Shouldn't get here. */
3932
bool save_abort_on_warning= session->abort_on_warning;
3933
session->abort_on_warning= true;
3934
make_truncated_value_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
3935
f_val, strlength(f_val), t_type,
3936
alter_info->datetime_field->field_name);
3937
session->abort_on_warning= save_abort_on_warning;
3941
pthread_mutex_lock(&LOCK_open); /* ALTER TABLe */
3942
session->unlink_open_table(name_lock);
3943
pthread_mutex_unlock(&LOCK_open);
3947
err_with_placeholders:
3949
An error happened while we were holding exclusive name-lock on table
3950
being altered. To be safe under LOCK TABLES we should remove placeholders
3951
from list of open tables list and table cache.
3953
session->unlink_open_table(table);
3955
session->unlink_open_table(name_lock);
3956
pthread_mutex_unlock(&LOCK_open);
3959
/* mysql_alter_table */
3962
copy_data_between_tables(Table *from,Table *to,
3963
List<CreateField> &create,
3965
uint32_t order_num, order_st *order,
3968
enum enum_enable_or_disable keys_onoff,
3969
bool error_if_not_empty)
3972
CopyField *copy,*copy_end;
3973
ulong found_count,delete_count;
3974
Session *session= current_session;
3976
SORT_FIELD *sortorder;
3980
List<Item> all_fields;
3981
ha_rows examined_rows;
3982
bool auto_increment_field_copied= 0;
3983
uint64_t prev_insert_id;
3986
Turn off recovery logging since rollback of an alter table is to
3987
delete the new table so there is no need to log the changes to it.
3989
This needs to be done before external_lock
3991
error= ha_enable_transaction(session, false);
3995
if (!(copy= new CopyField[to->s->fields]))
3996
return -1; /* purecov: inspected */
3998
if (to->file->ha_external_lock(session, F_WRLCK))
4001
/* We need external lock before we can disable/enable keys */
4002
alter_table_manage_keys(to, from->file->indexes_are_disabled(), keys_onoff);
4004
/* We can abort alter table for any table type */
4005
session->abort_on_warning= !ignore;
4007
from->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
4008
to->file->ha_start_bulk_insert(from->file->stats.records);
4010
List_iterator<CreateField> it(create);
4013
for (Field **ptr=to->field ; *ptr ; ptr++)
4018
if (*ptr == to->next_number_field)
4019
auto_increment_field_copied= true;
4021
(copy_end++)->set(*ptr,def->field,0);
4026
found_count=delete_count=0;
4030
if (to->s->primary_key != MAX_KEY && to->file->primary_key_is_clustered())
4032
char warn_buff[DRIZZLE_ERRMSG_SIZE];
4033
snprintf(warn_buff, sizeof(warn_buff),
4034
_("order_st BY ignored because there is a user-defined clustered "
4035
"index in the table '%-.192s'"),
4036
from->s->table_name.str);
4037
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
4042
from->sort.io_cache= new IO_CACHE;
4043
memset(from->sort.io_cache, 0, sizeof(IO_CACHE));
4045
memset(&tables, 0, sizeof(tables));
4047
tables.alias= tables.table_name= from->s->table_name.str;
4048
tables.db= from->s->db.str;
4051
if (session->lex->select_lex.setup_ref_array(session, order_num) ||
4052
setup_order(session, session->lex->select_lex.ref_pointer_array,
4053
&tables, fields, all_fields, order) ||
4054
!(sortorder= make_unireg_sortorder(order, &length, NULL)) ||
4055
(from->sort.found_records= filesort(session, from, sortorder, length,
4056
(SQL_SELECT *) 0, HA_POS_ERROR,
4057
1, &examined_rows)) ==
4063
/* Tell handler that we have values for all columns in the to table */
4064
to->use_all_columns();
4065
init_read_record(&info, session, from, (SQL_SELECT *) 0, 1,1);
4067
to->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
4068
session->row_count= 0;
4069
to->restoreRecordAsDefault(); // Create empty record
4070
while (!(error=info.read_record(&info)))
4072
if (session->killed)
4074
session->send_kill_message();
4078
session->row_count++;
4079
/* Return error if source table isn't empty. */
4080
if (error_if_not_empty)
4085
if (to->next_number_field)
4087
if (auto_increment_field_copied)
4088
to->auto_increment_field_not_null= true;
4090
to->next_number_field->reset();
4093
for (CopyField *copy_ptr=copy ; copy_ptr != copy_end ; copy_ptr++)
4095
copy_ptr->do_copy(copy_ptr);
4097
prev_insert_id= to->file->next_insert_id;
4098
error=to->file->ha_write_row(to->record[0]);
4099
to->auto_increment_field_not_null= false;
4103
to->file->is_fatal_error(error, HA_CHECK_DUP))
4105
if (!to->file->is_fatal_error(error, HA_CHECK_DUP))
4107
uint32_t key_nr= to->file->get_dup_key(error);
4108
if ((int) key_nr >= 0)
4110
const char *err_msg= ER(ER_DUP_ENTRY_WITH_KEY_NAME);
4112
(to->key_info[0].key_part[0].field->flags &
4113
AUTO_INCREMENT_FLAG))
4114
err_msg= ER(ER_DUP_ENTRY_AUTOINCREMENT_CASE);
4115
to->file->print_keydup_error(key_nr, err_msg);
4120
to->file->print_error(error,MYF(0));
4123
to->file->restore_auto_increment(prev_insert_id);
4129
end_read_record(&info);
4130
from->free_io_cache();
4131
delete [] copy; // This is never 0
4133
if (to->file->ha_end_bulk_insert() && error <= 0)
4135
to->file->print_error(my_errno,MYF(0));
4138
to->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
4140
if (ha_enable_transaction(session, true))
4147
Ensure that the new table is saved properly to disk so that we
4150
if (ha_autocommit_or_rollback(session, 0))
4152
if (! session->endActiveTransaction())
4156
session->abort_on_warning= 0;
4157
from->free_io_cache();
4158
*copied= found_count;
4159
*deleted=delete_count;
4160
to->file->ha_release_auto_increment();
4161
if (to->file->ha_external_lock(session,F_UNLCK))
4163
return(error > 0 ? -1 : 0);
4168
2702
Recreates tables by calling mysql_alter_table().