3109
pthread_mutex_lock(&LOCK_open);
3110
unlink_open_table(thd, name_lock, false);
2460
pthread_mutex_lock(&LOCK_open); /* unlink open tables for create table like*/
2461
session->unlink_open_table(name_lock);
3111
2462
pthread_mutex_unlock(&LOCK_open);
3117
bool mysql_analyze_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
2468
bool mysql_analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
3119
2470
thr_lock_type lock_type = TL_READ_NO_INSERT;
3121
return(mysql_admin_table(thd, tables, check_opt,
3122
"analyze", lock_type, 1, 0, 0, 0,
3123
&handler::ha_analyze));
2472
return(mysql_admin_table(session, tables, check_opt,
2473
"analyze", lock_type, true,
2474
&Cursor::ha_analyze));
3127
bool mysql_check_table(THD* thd, TABLE_LIST* tables,HA_CHECK_OPT* check_opt)
2478
bool mysql_check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
3129
2480
thr_lock_type lock_type = TL_READ_NO_INSERT;
3131
return(mysql_admin_table(thd, tables, check_opt,
2482
return(mysql_admin_table(session, tables, check_opt,
3132
2483
"check", lock_type,
3133
0, 0, HA_OPEN_FOR_REPAIR, 0,
3134
&handler::ha_check));
3138
/* table_list should contain just one table */
3140
mysql_discard_or_import_tablespace(THD *thd,
3141
TABLE_LIST *table_list,
3142
enum tablespace_op_type tablespace_op)
3149
Note that DISCARD/IMPORT TABLESPACE always is the only operation in an
3153
thd_proc_info(thd, "discard_or_import_tablespace");
3155
discard= test(tablespace_op == DISCARD_TABLESPACE);
3158
We set this flag so that ha_innobase::open and ::external_lock() do
3159
not complain when we lock the table
3161
thd->tablespace_op= true;
3162
if (!(table=open_ltable(thd, table_list, TL_WRITE, 0)))
3164
thd->tablespace_op=false;
3168
error= table->file->ha_discard_or_import_tablespace(discard);
3170
thd_proc_info(thd, "end");
3175
/* The ALTER TABLE is always in its own transaction */
3176
error = ha_autocommit_or_rollback(thd, 0);
3177
if (end_active_trans(thd))
3181
write_bin_log(thd, false, thd->query, thd->query_length);
3184
ha_autocommit_or_rollback(thd, error);
3185
thd->tablespace_op=false;
3193
table->file->print_error(error, MYF(0));
3199
Copy all changes detected by parser to the HA_ALTER_FLAGS
3202
void setup_ha_alter_flags(Alter_info *alter_info, HA_ALTER_FLAGS *alter_flags)
3204
uint flags= alter_info->flags;
3206
if (ALTER_ADD_COLUMN & flags)
3207
*alter_flags|= HA_ADD_COLUMN;
3208
if (ALTER_DROP_COLUMN & flags)
3209
*alter_flags|= HA_DROP_COLUMN;
3210
if (ALTER_RENAME & flags)
3211
*alter_flags|= HA_RENAME_TABLE;
3212
if (ALTER_CHANGE_COLUMN & flags)
3213
*alter_flags|= HA_CHANGE_COLUMN;
3214
if (ALTER_COLUMN_DEFAULT & flags)
3215
*alter_flags|= HA_COLUMN_DEFAULT_VALUE;
3216
if (ALTER_COLUMN_STORAGE & flags)
3217
*alter_flags|= HA_COLUMN_STORAGE;
3218
if (ALTER_COLUMN_FORMAT & flags)
3219
*alter_flags|= HA_COLUMN_FORMAT;
3220
if (ALTER_COLUMN_ORDER & flags)
3221
*alter_flags|= HA_ALTER_COLUMN_ORDER;
3222
if (ALTER_STORAGE & flags)
3223
*alter_flags|= HA_ALTER_STORAGE;
3224
if (ALTER_ROW_FORMAT & flags)
3225
*alter_flags|= HA_ALTER_ROW_FORMAT;
3226
if (ALTER_RECREATE & flags)
3227
*alter_flags|= HA_RECREATE;
3228
if (ALTER_FOREIGN_KEY & flags)
3229
*alter_flags|= HA_ALTER_FOREIGN_KEY;
3235
@param table The original table.
3236
@param alter_info Alter options, fields and keys for the new
3238
@param create_info Create options for the new table.
3239
@param order_num Number of order list elements.
3240
@param[out] ha_alter_flags Flags that indicate what will be changed
3241
@param[out] ha_alter_info Data structures needed for on-line alter
3242
@param[out] table_changes Information about particular change
3244
First argument 'table' contains information of the original
3245
table, which includes all corresponding parts that the new
3246
table has in arguments create_list, key_list and create_info.
3248
By comparing the changes between the original and new table
3249
we can determine how much it has changed after ALTER TABLE
3250
and whether we need to make a copy of the table, or just change
3253
Mark any changes detected in the ha_alter_flags.
3255
If there are no data changes, but index changes, 'index_drop_buffer'
3256
and/or 'index_add_buffer' are populated with offsets into
3257
table->key_info or key_info_buffer respectively for the indexes
3258
that need to be dropped and/or (re-)created.
3261
@retval false success
3266
compare_tables(THD *thd,
3268
Alter_info *alter_info,
3269
HA_CREATE_INFO *create_info,
3271
HA_ALTER_FLAGS *alter_flags,
3272
HA_ALTER_INFO *ha_alter_info,
3273
uint *table_changes)
3275
Field **f_ptr, *field;
3276
uint table_changes_local= 0;
3277
List_iterator_fast<Create_field> new_field_it(alter_info->create_list);
3278
Create_field *new_field;
3279
KEY_PART_INFO *key_part;
3282
Remember if the new definition has new VARCHAR column;
3283
create_info->varchar will be reset in mysql_prepare_create_table.
3285
bool varchar= create_info->varchar;
3289
Create a copy of alter_info.
3290
To compare the new and old table definitions, we need to "prepare"
3291
the new definition - transform it from parser output to a format
3292
that describes the final table layout (all column defaults are
3293
initialized, duplicate columns are removed). This is done by
3294
mysql_prepare_create_table. Unfortunately,
3295
mysql_prepare_create_table performs its transformations
3296
"in-place", that is, modifies the argument. Since we would
3297
like to keep compare_tables() idempotent (not altering any
3298
of the arguments) we create a copy of alter_info here and
3299
pass it to mysql_prepare_create_table, then use the result
3300
to evaluate possibility of fast ALTER TABLE, and then
3303
Alter_info tmp_alter_info(*alter_info, thd->mem_root);
3304
THD *thd= table->in_use;
3305
uint db_options= 0; /* not used */
3306
/* Create the prepared information. */
3307
if (mysql_prepare_create_table(thd, create_info,
3309
(table->s->tmp_table != NO_TMP_TABLE),
3312
&ha_alter_info->key_info_buffer,
3313
&ha_alter_info->key_count,
3314
/* select_field_count */ 0))
3316
/* Allocate result buffers. */
3317
if (! (ha_alter_info->index_drop_buffer=
3318
(uint*) thd->alloc(sizeof(uint) * table->s->keys)) ||
3319
! (ha_alter_info->index_add_buffer=
3320
(uint*) thd->alloc(sizeof(uint) *
3321
tmp_alter_info.key_list.elements)))
3325
First we setup ha_alter_flags based on what was detected
3328
setup_ha_alter_flags(alter_info, alter_flags);
3332
Some very basic checks. If number of fields changes, or the
3333
handler, we need to run full ALTER TABLE. In the future
3334
new fields can be added and old dropped without copy, but
3337
Test also that engine was not given during ALTER TABLE, or
3338
we are force to run regular alter table (copy).
3339
E.g. ALTER TABLE tbl_name ENGINE=MyISAM.
3341
For the following ones we also want to run regular alter table:
3342
ALTER TABLE tbl_name ORDER BY ..
3343
ALTER TABLE tbl_name CONVERT TO CHARACTER SET ..
3345
At the moment we can't handle altering temporary tables without a copy.
3346
We also test if OPTIMIZE TABLE was given and was mapped to alter table.
3347
In that case we always do full copy.
3349
There was a bug prior to mysql-4.0.25. Number of null fields was
3350
calculated incorrectly. As a result frm and data files gets out of
3351
sync after fast alter table. There is no way to determine by which
3352
mysql version (in 4.0 and 4.1 branches) table was created, thus we
3353
disable fast alter table for all tables created by mysql versions
3354
prior to 5.0 branch.
3357
if (table->s->fields != alter_info->create_list.elements ||
3358
table->s->db_type() != create_info->db_type ||
3359
table->s->tmp_table ||
3360
create_info->used_fields & HA_CREATE_USED_ENGINE ||
3361
create_info->used_fields & HA_CREATE_USED_CHARSET ||
3362
create_info->used_fields & HA_CREATE_USED_DEFAULT_CHARSET ||
3363
create_info->used_fields & HA_CREATE_USED_ROW_FORMAT ||
3364
(alter_info->flags & (ALTER_RECREATE | ALTER_FOREIGN_KEY)) ||
3366
!table->s->mysql_version ||
3367
(table->s->frm_version < FRM_VER_TRUE_VARCHAR && varchar))
3369
*table_changes= IS_EQUAL_NO;
3371
Check what has changed and set alter_flags
3373
if (table->s->fields < alter_info->create_list.elements)
3374
*alter_flags|= HA_ADD_COLUMN;
3375
else if (table->s->fields > alter_info->create_list.elements)
3376
*alter_flags|= HA_DROP_COLUMN;
3377
if (create_info->db_type != table->s->db_type() ||
3378
create_info->used_fields & HA_CREATE_USED_ENGINE)
3379
*alter_flags|= HA_ALTER_STORAGE_ENGINE;
3380
if (create_info->used_fields & HA_CREATE_USED_CHARSET)
3381
*alter_flags|= HA_CHANGE_CHARACTER_SET;
3382
if (create_info->used_fields & HA_CREATE_USED_DEFAULT_CHARSET)
3383
*alter_flags|= HA_SET_DEFAULT_CHARACTER_SET;
3384
if (alter_info->flags & ALTER_RECREATE)
3385
*alter_flags|= HA_RECREATE;
3386
/* TODO check for ADD/DROP FOREIGN KEY */
3387
if (alter_info->flags & ALTER_FOREIGN_KEY)
3388
*alter_flags|= HA_ALTER_FOREIGN_KEY;
3389
if (!table->s->mysql_version ||
3390
(table->s->frm_version < FRM_VER_TRUE_VARCHAR && varchar))
3391
*alter_flags|= HA_ALTER_COLUMN_TYPE;
3394
Go through fields and check if the original ones are compatible
3397
for (f_ptr= table->field, new_field= new_field_it++;
3398
(new_field && (field= *f_ptr));
3399
f_ptr++, new_field= new_field_it++)
3401
/* Make sure we have at least the default charset in use. */
3402
if (!new_field->charset)
3403
new_field->charset= create_info->default_table_charset;
3405
/* Don't pack rows in old tables if the user has requested this. */
3406
if (create_info->row_type == ROW_TYPE_DYNAMIC ||
3407
(new_field->flags & BLOB_FLAG) ||
3408
(new_field->sql_type == DRIZZLE_TYPE_VARCHAR && create_info->row_type != ROW_TYPE_FIXED))
3409
create_info->table_options|= HA_OPTION_PACK_RECORD;
3411
/* Check how fields have been modified */
3412
if (alter_info->flags & ALTER_CHANGE_COLUMN)
3414
/* Evaluate changes bitmap and send to check_if_incompatible_data() */
3415
if (!(table_changes_local= field->is_equal(new_field)))
3416
*alter_flags|= HA_ALTER_COLUMN_TYPE;
3418
/* Check if field was renamed */
3419
field->flags&= ~FIELD_IS_RENAMED;
3420
if (my_strcasecmp(system_charset_info,
3422
new_field->field_name))
3424
field->flags|= FIELD_IS_RENAMED;
3425
*alter_flags|= HA_ALTER_COLUMN_NAME;
3428
*table_changes&= table_changes_local;
3429
if (table_changes_local == IS_EQUAL_PACK_LENGTH)
3430
*alter_flags|= HA_ALTER_COLUMN_TYPE;
3432
/* Check that NULL behavior is same for old and new fields */
3433
if ((new_field->flags & NOT_NULL_FLAG) !=
3434
(uint) (field->flags & NOT_NULL_FLAG))
3436
*table_changes= IS_EQUAL_NO;
3437
*alter_flags|= HA_ALTER_COLUMN_NULLABLE;
3441
/* Clear indexed marker */
3442
field->flags&= ~FIELD_IN_ADD_INDEX;
3446
Go through keys and check if the original ones are compatible
3450
KEY *table_key_end= table->key_info + table->s->keys;
3453
ha_alter_info->key_info_buffer + ha_alter_info->key_count;
3456
Step through all keys of the old table and search matching new keys.
3458
ha_alter_info->index_drop_count= 0;
3459
ha_alter_info->index_add_count= 0;
3460
for (table_key= table->key_info; table_key < table_key_end; table_key++)
3462
KEY_PART_INFO *table_part;
3463
KEY_PART_INFO *table_part_end= table_key->key_part + table_key->key_parts;
3464
KEY_PART_INFO *new_part;
3466
/* Search a new key with the same name. */
3467
for (new_key= ha_alter_info->key_info_buffer;
3468
new_key < new_key_end;
3471
if (! strcmp(table_key->name, new_key->name))
3474
if (new_key >= new_key_end)
3476
/* Key not found. Add the offset of the key to the drop buffer. */
3477
ha_alter_info->index_drop_buffer
3478
[ha_alter_info->index_drop_count++]=
3479
table_key - table->key_info;
3480
if (table_key->flags & HA_NOSAME)
3482
/* Unique key. Check for "PRIMARY". */
3483
if (! my_strcasecmp(system_charset_info,
3484
table_key->name, primary_key_name))
3485
*alter_flags|= HA_DROP_PK_INDEX;
3487
*alter_flags|= HA_DROP_UNIQUE_INDEX;
3490
*alter_flags|= HA_DROP_INDEX;
3491
*table_changes= IS_EQUAL_NO;
3495
/* Check that the key types are compatible between old and new tables. */
3496
if ((table_key->algorithm != new_key->algorithm) ||
3497
((table_key->flags & HA_KEYFLAG_MASK) !=
3498
(new_key->flags & HA_KEYFLAG_MASK)) ||
3499
(table_key->key_parts != new_key->key_parts))
3501
if (table_key->flags & HA_NOSAME)
3503
// Unique key. Check for "PRIMARY".
3504
if (! my_strcasecmp(system_charset_info,
3505
table_key->name, primary_key_name))
3506
*alter_flags|= HA_ALTER_PK_INDEX;
3508
*alter_flags|= HA_ALTER_UNIQUE_INDEX;
3511
*alter_flags|= HA_ALTER_INDEX;
3516
Check that the key parts remain compatible between the old and
3519
for (table_part= table_key->key_part, new_part= new_key->key_part;
3520
table_part < table_part_end;
3521
table_part++, new_part++)
3524
Key definition has changed if we are using a different field or
3525
if the used key part length is different. We know that the fields
3526
did not change. Comparing field numbers is sufficient.
3528
if ((table_part->length != new_part->length) ||
3529
(table_part->fieldnr - 1 != new_part->fieldnr))
3531
if (table_key->flags & HA_NOSAME)
3533
/* Unique key. Check for "PRIMARY" */
3534
if (! my_strcasecmp(system_charset_info,
3535
table_key->name, primary_key_name))
3536
*alter_flags|= HA_ALTER_PK_INDEX;
3538
*alter_flags|= HA_ALTER_UNIQUE_INDEX;
3541
*alter_flags|= HA_ALTER_INDEX;
3548
/* Key modified. Add the offset of the key to both buffers. */
3549
ha_alter_info->index_drop_buffer
3550
[ha_alter_info->index_drop_count++]=
3551
table_key - table->key_info;
3552
ha_alter_info->index_add_buffer
3553
[ha_alter_info->index_add_count++]=
3554
new_key - ha_alter_info->key_info_buffer;
3555
key_part= new_key->key_part;
3556
end= key_part + new_key->key_parts;
3557
for(; key_part != end; key_part++)
3559
/* Mark field to be part of new key */
3560
if ((field= table->field[key_part->fieldnr]))
3561
field->flags|= FIELD_IN_ADD_INDEX;
3563
*table_changes= IS_EQUAL_NO;
3565
/*end of for (; table_key < table_key_end;) */
3568
Step through all keys of the new table and find matching old keys.
3570
for (new_key= ha_alter_info->key_info_buffer;
3571
new_key < new_key_end;
3574
/* Search an old key with the same name. */
3575
for (table_key= table->key_info; table_key < table_key_end; table_key++)
3577
if (! strcmp(table_key->name, new_key->name))
3580
if (table_key >= table_key_end)
3582
/* Key not found. Add the offset of the key to the add buffer. */
3583
ha_alter_info->index_add_buffer
3584
[ha_alter_info->index_add_count++]=
3585
new_key - ha_alter_info->key_info_buffer;
3586
key_part= new_key->key_part;
3587
end= key_part + new_key->key_parts;
3588
for(; key_part != end; key_part++)
3590
/* Mark field to be part of new key */
3591
if ((field= table->field[key_part->fieldnr]))
3592
field->flags|= FIELD_IN_ADD_INDEX;
3594
if (new_key->flags & HA_NOSAME)
3596
/* Unique key. Check for "PRIMARY" */
3597
if (! my_strcasecmp(system_charset_info,
3598
new_key->name, primary_key_name))
3599
*alter_flags|= HA_ADD_PK_INDEX;
3601
*alter_flags|= HA_ADD_UNIQUE_INDEX;
3604
*alter_flags|= HA_ADD_INDEX;
3605
*table_changes= IS_EQUAL_NO;
3614
Manages enabling/disabling of indexes for ALTER TABLE
3617
alter_table_manage_keys()
3619
indexes_were_disabled Whether the indexes of the from table
3621
keys_onoff ENABLE | DISABLE | LEAVE_AS_IS
3629
bool alter_table_manage_keys(TABLE *table, int indexes_were_disabled,
3630
enum enum_enable_or_disable keys_onoff)
3633
switch (keys_onoff) {
3635
error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
3638
if (!indexes_were_disabled)
3640
/* fall-through: disabled indexes */
3642
error= table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
3645
if (error == HA_ERR_WRONG_COMMAND)
3647
push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
3648
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
3649
table->s->table_name.str);
3652
table->file->print_error(error, MYF(0));
3657
int create_temporary_table(THD *thd,
3661
HA_CREATE_INFO *create_info,
3662
Alter_info *alter_info,
3666
char index_file[FN_REFLEN], data_file[FN_REFLEN];
3667
handlerton *old_db_type, *new_db_type;
3668
old_db_type= table->s->db_type();
3669
new_db_type= create_info->db_type;
3671
Handling of symlinked tables:
3673
Create new data file and index file on the same disk as the
3674
old data and index files.
3676
Rename new data file over old data file and new index file over
3678
Symlinks are not changed.
3681
Create new data file and index file on the same disk as the
3682
old data and index files. Create also symlinks to point at
3685
At end, rename intermediate tables, and symlinks to intermediate
3686
table, to final table name.
3687
Remove old table and old symlinks
3689
If rename is made to another database:
3690
Create new tables in new database.
3692
Remove old table and symlinks.
3694
if (db_changed) // Ignore symlink if db changed
3696
if (create_info->index_file_name)
3698
/* Fix index_file_name to have 'tmp_name' as basename */
3699
stpcpy(index_file, tmp_name);
3700
create_info->index_file_name=fn_same(index_file,
3701
create_info->index_file_name,
3704
if (create_info->data_file_name)
3706
/* Fix data_file_name to have 'tmp_name' as basename */
3707
stpcpy(data_file, tmp_name);
3708
create_info->data_file_name=fn_same(data_file,
3709
create_info->data_file_name,
3714
create_info->data_file_name=create_info->index_file_name=0;
3717
Create a table with a temporary name.
3718
With create_info->frm_only == 1 this creates a .frm file only.
3719
We don't log the statement, it will be logged later.
3721
tmp_disable_binlog(thd);
3722
error= mysql_create_table(thd, new_db, tmp_name,
3723
create_info, alter_info, 1, 0);
3724
reenable_binlog(thd);
3730
Create a temporary table that reflects what an alter table operation
3734
create_altered_table()
3736
table The original table
3737
create_info Information from the parsing phase about new
3739
alter_info Lists of fields, keys to be changed, added
3741
db_change Specifies if the table is moved to another database
3743
A temporary table with all changes
3746
The temporary table is created without storing it in any storage engine
3747
and is opened only to get the table struct and frm file reference.
3749
TABLE *create_altered_table(THD *thd,
3752
HA_CREATE_INFO *create_info,
3753
Alter_info *alter_info,
3757
HA_CREATE_INFO altered_create_info(*create_info);
3758
TABLE *altered_table;
3760
char path[FN_REFLEN];
3762
snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%lx",
3763
tmp_file_prefix, current_pid, thd->thread_id);
3764
/* Safety fix for InnoDB */
3765
if (lower_case_table_names)
3766
my_casedn_str(files_charset_info, tmp_name);
3767
altered_create_info.options&= ~HA_LEX_CREATE_TMP_TABLE;
3768
altered_create_info.frm_only= 1;
3769
if ((error= create_temporary_table(thd, table, new_db, tmp_name,
3770
&altered_create_info,
3771
alter_info, db_change)))
3776
build_table_filename(path, sizeof(path), new_db, tmp_name, "",
3778
altered_table= open_temporary_table(thd, path, new_db, tmp_name, 1,
3780
return(altered_table);
3787
Perform a fast or on-line alter table
3790
mysql_fast_or_online_alter_table()
3792
table The original table
3793
altered_table A temporary table showing how we will change table
3794
create_info Information from the parsing phase about new
3796
alter_info Storage place for data used during different phases
3797
ha_alter_flags Bitmask that shows what will be changed
3798
keys_onoff Specifies if keys are to be enabled/disabled
3801
>0 An error occured during the on-line alter table operation
3802
-1 Error when re-opening table
3804
If mysql_alter_table does not need to copy the table, it is
3805
either a fast alter table where the storage engine does not
3806
need to know about the change, only the frm will change,
3807
or the storage engine supports performing the alter table
3808
operation directly, on-line without mysql having to copy
3811
int mysql_fast_or_online_alter_table(THD *thd,
3813
TABLE *altered_table,
3814
HA_CREATE_INFO *create_info,
3815
HA_ALTER_INFO *alter_info,
3816
HA_ALTER_FLAGS *ha_alter_flags,
3817
enum enum_enable_or_disable keys_onoff)
3820
bool online= (table->file->ha_table_flags() & HA_ONLINE_ALTER)?true:false;
3826
Tell the handler to prepare for the online alter
3828
if ((error= table->file->alter_table_phase1(thd,
3838
Tell the storage engine to perform the online alter table
3840
if check_if_supported_alter() returned HA_ALTER_SUPPORTED_WAIT_LOCK
3841
we need to wrap the next call with a DDL lock.
3843
if ((error= table->file->alter_table_phase2(thd,
3853
The final .frm file is already created as a temporary file
3854
and will be renamed to the original table name.
3856
VOID(pthread_mutex_lock(&LOCK_open));
3857
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
3858
alter_table_manage_keys(table, table->file->indexes_are_disabled(),
3860
close_data_files_and_morph_locks(thd,
3861
table->pos_in_table_list->db,
3862
table->pos_in_table_list->table_name);
3863
if (mysql_rename_table(NULL,
3864
altered_table->s->db.str,
3865
altered_table->s->table_name.str,
3867
table->s->table_name.str, FN_FROM_IS_TMP))
3870
VOID(pthread_mutex_unlock(&LOCK_open));
3873
broadcast_refresh();
3874
VOID(pthread_mutex_unlock(&LOCK_open));
3877
The ALTER TABLE is always in its own transaction.
3878
Commit must not be called while LOCK_open is locked. It could call
3879
wait_if_global_read_lock(), which could create a deadlock if called
3882
error= ha_autocommit_or_rollback(thd, 0);
3890
VOID(pthread_mutex_lock(&LOCK_open));
3891
if (reopen_table(table))
3896
VOID(pthread_mutex_unlock(&LOCK_open));
3900
Tell the handler that the changed frm is on disk and table
3903
if ((error= t_table->file->alter_table_phase3(thd, t_table)))
3909
We are going to reopen table down on the road, so we have to restore
3910
state of the TABLE object which we used for obtaining of handler
3911
object to make it suitable for reopening.
3913
assert(t_table == table);
3914
table->open_placeholder= 1;
3915
VOID(pthread_mutex_lock(&LOCK_open));
3916
close_handle_and_leave_table_as_lock(table);
3917
VOID(pthread_mutex_unlock(&LOCK_open));
3928
Prepare column and key definitions for CREATE TABLE in ALTER TABLE.
3930
This function transforms parse output of ALTER TABLE - lists of
3931
columns and keys to add, drop or modify into, essentially,
3932
CREATE TABLE definition - a list of columns and keys of the new
3933
table. While doing so, it also performs some (bug not all)
3936
This function is invoked when we know that we're going to
3937
perform ALTER TABLE via a temporary table -- i.e. fast ALTER TABLE
3938
is not possible, perhaps because the ALTER statement contains
3939
instructions that require change in table data, not only in
3940
table definition or indexes.
3942
@param[in,out] thd thread handle. Used as a memory pool
3943
and source of environment information.
3944
@param[in] table the source table, open and locked
3945
Used as an interface to the storage engine
3946
to acquire additional information about
3948
@param[in,out] create_info A blob with CREATE/ALTER TABLE
3950
@param[in,out] alter_info Another blob with ALTER/CREATE parameters.
3951
Originally create_info was used only in
3952
CREATE TABLE and alter_info only in ALTER TABLE.
3953
But since ALTER might end-up doing CREATE,
3954
this distinction is gone and we just carry
3955
around two structures.
3958
Fills various create_info members based on information retrieved
3959
from the storage engine.
3960
Sets create_info->varchar if the table has a VARCHAR column.
3961
Prepares alter_info->create_list and alter_info->key_list with
3962
columns and keys of the new table.
3963
@retval true error, out of memory or a semantical error in ALTER
3965
@retval false success
3969
mysql_prepare_alter_table(THD *thd, TABLE *table,
3970
HA_CREATE_INFO *create_info,
3971
Alter_info *alter_info)
3973
/* New column definitions are added here */
3974
List<Create_field> new_create_list;
3975
/* New key definitions are added here */
3976
List<Key> new_key_list;
3977
List_iterator<Alter_drop> drop_it(alter_info->drop_list);
3978
List_iterator<Create_field> def_it(alter_info->create_list);
3979
List_iterator<Alter_column> alter_it(alter_info->alter_list);
3980
List_iterator<Key> key_it(alter_info->key_list);
3981
List_iterator<Create_field> find_it(new_create_list);
3982
List_iterator<Create_field> field_it(new_create_list);
3983
List<Key_part_spec> key_parts;
3984
uint db_create_options= (table->s->db_create_options
3985
& ~(HA_OPTION_PACK_RECORD));
3986
uint used_fields= create_info->used_fields;
3987
KEY *key_info=table->key_info;
3991
create_info->varchar= false;
3992
/* Let new create options override the old ones */
3993
if (!(used_fields & HA_CREATE_USED_MIN_ROWS))
3994
create_info->min_rows= table->s->min_rows;
3995
if (!(used_fields & HA_CREATE_USED_MAX_ROWS))
3996
create_info->max_rows= table->s->max_rows;
3997
if (!(used_fields & HA_CREATE_USED_AVG_ROW_LENGTH))
3998
create_info->avg_row_length= table->s->avg_row_length;
3999
if (!(used_fields & HA_CREATE_USED_BLOCK_SIZE))
4000
create_info->block_size= table->s->block_size;
4001
if (!(used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
4002
create_info->default_table_charset= table->s->table_charset;
4003
if (!(used_fields & HA_CREATE_USED_AUTO) && table->found_next_number_field)
4005
/* Table has an autoincrement, copy value to new table */
4006
table->file->info(HA_STATUS_AUTO);
4007
create_info->auto_increment_value= table->file->stats.auto_increment_value;
4009
if (!(used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE))
4010
create_info->key_block_size= table->s->key_block_size;
4011
if (!(used_fields & HA_CREATE_USED_TRANSACTIONAL))
4012
create_info->transactional= table->s->transactional;
4014
restore_record(table, s->default_values); // Empty record for DEFAULT
4018
First collect all fields from table which isn't in drop_list
4020
Field **f_ptr,*field;
4021
for (f_ptr=table->field ; (field= *f_ptr) ; f_ptr++)
4023
/* Check if field should be dropped */
4026
while ((drop=drop_it++))
4028
if (drop->type == Alter_drop::COLUMN &&
4029
!my_strcasecmp(system_charset_info,field->field_name, drop->name))
4031
/* Reset auto_increment value if it was dropped */
4032
if (MTYP_TYPENR(field->unireg_check) == Field::NEXT_NUMBER &&
4033
!(used_fields & HA_CREATE_USED_AUTO))
4035
create_info->auto_increment_value=0;
4036
create_info->used_fields|=HA_CREATE_USED_AUTO;
4046
/* Check if field is changed */
4048
while ((def=def_it++))
4051
!my_strcasecmp(system_charset_info,field->field_name, def->change))
4055
{ // Field is changed
4059
new_create_list.push_back(def);
4066
This field was not dropped and not changed, add it to the list
4069
def= new Create_field(field, field);
4070
new_create_list.push_back(def);
4071
alter_it.rewind(); // Change default if ALTER
4072
Alter_column *alter;
4073
while ((alter=alter_it++))
4075
if (!my_strcasecmp(system_charset_info,field->field_name, alter->name))
4080
if (def->sql_type == DRIZZLE_TYPE_BLOB)
4082
my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), def->change);
4085
if ((def->def=alter->def)) // Use new default
4086
def->flags&= ~NO_DEFAULT_VALUE_FLAG;
4088
def->flags|= NO_DEFAULT_VALUE_FLAG;
4094
while ((def=def_it++)) // Add new columns
4096
if (def->change && ! def->field)
4098
my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table->s->table_name.str);
4102
Check that the DATE/DATETIME not null field we are going to add is
4103
either has a default value or the '0000-00-00' is allowed by the
4105
If the '0000-00-00' value isn't allowed then raise the error_if_not_empty
4106
flag to allow ALTER TABLE only if the table to be altered is empty.
4108
if ((def->sql_type == DRIZZLE_TYPE_NEWDATE ||
4109
def->sql_type == DRIZZLE_TYPE_DATETIME) &&
4110
!alter_info->datetime_field &&
4111
!(~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) &&
4112
thd->variables.sql_mode & MODE_NO_ZERO_DATE)
4114
alter_info->datetime_field= def;
4115
alter_info->error_if_not_empty= true;
4118
new_create_list.push_back(def);
4119
else if (def->after == first_keyword)
4120
new_create_list.push_front(def);
4125
while ((find=find_it++)) // Add new columns
4127
if (!my_strcasecmp(system_charset_info,def->after, find->field_name))
4132
my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table->s->table_name.str);
4135
find_it.after(def); // Put element after this
4137
XXX: hack for Bug#28427.
4138
If column order has changed, force OFFLINE ALTER TABLE
4139
without querying engine capabilities. If we ever have an
4140
engine that supports online ALTER TABLE CHANGE COLUMN
4141
<name> AFTER <name1> (Falcon?), this fix will effectively
4142
disable the capability.
4143
TODO: detect the situation in compare_tables, behave based
4144
on engine capabilities.
4146
if (alter_info->build_method == HA_BUILD_ONLINE)
4148
my_error(ER_NOT_SUPPORTED_YET, MYF(0), thd->query);
4151
alter_info->build_method= HA_BUILD_OFFLINE;
4154
if (alter_info->alter_list.elements)
4156
my_error(ER_BAD_FIELD_ERROR, MYF(0),
4157
alter_info->alter_list.head()->name, table->s->table_name.str);
4160
if (!new_create_list.elements)
4162
my_message(ER_CANT_REMOVE_ALL_FIELDS, ER(ER_CANT_REMOVE_ALL_FIELDS),
4168
Collect all keys which isn't in drop list. Add only those
4169
for which some fields exists.
4172
for (uint i=0 ; i < table->s->keys ; i++,key_info++)
4174
char *key_name= key_info->name;
4177
while ((drop=drop_it++))
4179
if (drop->type == Alter_drop::KEY &&
4180
!my_strcasecmp(system_charset_info,key_name, drop->name))
4189
KEY_PART_INFO *key_part= key_info->key_part;
4191
for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
4193
if (!key_part->field)
4194
continue; // Wrong field (from UNIREG)
4195
const char *key_part_name=key_part->field->field_name;
4196
Create_field *cfield;
4198
while ((cfield=field_it++))
4202
if (!my_strcasecmp(system_charset_info, key_part_name,
4206
else if (!my_strcasecmp(system_charset_info,
4207
key_part_name, cfield->field_name))
4211
continue; // Field is removed
4212
uint key_part_length=key_part->length;
4213
if (cfield->field) // Not new field
4216
If the field can't have only a part used in a key according to its
4217
new type, or should not be used partially according to its
4218
previous type, or the field length is less than the key part
4219
length, unset the key part length.
4221
We also unset the key part length if it is the same as the
4222
old field's length, so the whole new field will be used.
4224
BLOBs may have cfield->length == 0, which is why we test it before
4225
checking whether cfield->length < key_part_length (in chars).
4227
if (!Field::type_can_have_key_part(cfield->field->type()) ||
4228
!Field::type_can_have_key_part(cfield->sql_type) ||
4229
(cfield->field->field_length == key_part_length &&
4230
!f_is_blob(key_part->key_type)) ||
4231
(cfield->length && (cfield->length < key_part_length /
4232
key_part->field->charset()->mbmaxlen)))
4233
key_part_length= 0; // Use whole field
4235
key_part_length /= key_part->field->charset()->mbmaxlen;
4236
key_parts.push_back(new Key_part_spec(cfield->field_name,
4237
strlen(cfield->field_name),
4240
if (key_parts.elements)
4242
KEY_CREATE_INFO key_create_info;
4244
enum Key::Keytype key_type;
4245
memset(&key_create_info, 0, sizeof(key_create_info));
4247
key_create_info.algorithm= key_info->algorithm;
4248
if (key_info->flags & HA_USES_BLOCK_SIZE)
4249
key_create_info.block_size= key_info->block_size;
4250
if (key_info->flags & HA_USES_COMMENT)
4251
key_create_info.comment= key_info->comment;
4253
if (key_info->flags & HA_NOSAME)
4255
if (! my_strcasecmp(system_charset_info, key_name, primary_key_name))
4256
key_type= Key::PRIMARY;
4258
key_type= Key::UNIQUE;
4261
key_type= Key::MULTIPLE;
4263
key= new Key(key_type, key_name, strlen(key_name),
4265
test(key_info->flags & HA_GENERATED_KEY),
4267
new_key_list.push_back(key);
4272
while ((key=key_it++)) // Add new keys
4274
if (key->type != Key::FOREIGN_KEY)
4275
new_key_list.push_back(key);
4276
if (key->name.str &&
4277
!my_strcasecmp(system_charset_info, key->name.str, primary_key_name))
4279
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name.str);
4285
if (alter_info->drop_list.elements)
4287
my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
4288
alter_info->drop_list.head()->name);
4291
if (alter_info->alter_list.elements)
4293
my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
4294
alter_info->alter_list.head()->name);
4298
if (!create_info->comment.str)
4300
create_info->comment.str= table->s->comment.str;
4301
create_info->comment.length= table->s->comment.length;
4304
table->file->update_create_info(create_info);
4305
if ((create_info->table_options &
4306
(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS)) ||
4307
(used_fields & HA_CREATE_USED_PACK_KEYS))
4308
db_create_options&= ~(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS);
4309
if (create_info->table_options &
4310
(HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM))
4311
db_create_options&= ~(HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM);
4312
if (create_info->table_options &
4313
(HA_OPTION_DELAY_KEY_WRITE | HA_OPTION_NO_DELAY_KEY_WRITE))
4314
db_create_options&= ~(HA_OPTION_DELAY_KEY_WRITE |
4315
HA_OPTION_NO_DELAY_KEY_WRITE);
4316
create_info->table_options|= db_create_options;
4318
if (table->s->tmp_table)
4319
create_info->options|=HA_LEX_CREATE_TMP_TABLE;
4322
alter_info->create_list.swap(new_create_list);
4323
alter_info->key_list.swap(new_key_list);
4335
new_db If there is a RENAME clause
4336
new_name If there is a RENAME clause
4337
create_info Information from the parsing phase about new
4339
table_list The table to change.
4340
alter_info Lists of fields, keys to be changed, added
4342
order_num How many ORDER BY fields has been specified.
4343
order List of fields to ORDER BY.
4344
ignore Whether we have ALTER IGNORE TABLE
4347
This is a veery long function and is everything but the kitchen sink :)
4348
It is used to alter a table and not only by ALTER TABLE but also
4349
CREATE|DROP INDEX are mapped on this function.
4351
When the ALTER TABLE statement just does a RENAME or ENABLE|DISABLE KEYS,
4352
or both, then this function short cuts its operation by renaming
4353
the table and/or enabling/disabling the keys. In this case, the FRM is
4354
not changed, directly by mysql_alter_table. However, if there is a
4355
RENAME + change of a field, or an index, the short cut is not used.
4356
See how `create_list` is used to generate the new FRM regarding the
4357
structure of the fields. The same is done for the indices of the table.
4359
Important is the fact, that this function tries to do as little work as
4360
possible, by finding out whether a intermediate table is needed to copy
4361
data into and when finishing the altering to use it as the original table.
4362
For this reason the function compare_tables() is called, which decides
4363
based on all kind of data how similar are the new and the original
4371
bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
4372
HA_CREATE_INFO *create_info,
4373
TABLE_LIST *table_list,
4374
Alter_info *alter_info,
4375
uint order_num, ORDER *order, bool ignore)
4377
TABLE *table, *new_table=0, *name_lock= 0;;
4379
char tmp_name[80],old_name[32],new_name_buff[FN_REFLEN];
4380
char new_alias_buff[FN_REFLEN], *table_name, *db, *new_alias, *alias;
4381
char path[FN_REFLEN];
4382
ha_rows copied= 0,deleted= 0;
4383
handlerton *old_db_type, *new_db_type, *save_old_db_type;
4384
legacy_db_type table_type;
4385
frm_type_enum frm_type;
4387
if (table_list && table_list->schema_table)
4389
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.str);
4394
Assign variables table_name, new_name, db, new_db, path
4395
to simplify further comparisons: we want to see if it's a RENAME
4396
later just by comparing the pointers, avoiding the need for strcmp.
4398
thd_proc_info(thd, "init");
4399
table_name=table_list->table_name;
4400
alias= (lower_case_table_names == 2) ? table_list->alias : table_name;
4402
if (!new_db || !my_strcasecmp(table_alias_charset, new_db, db))
4404
build_table_filename(path, sizeof(path), db, table_name, "", 0);
4406
mysql_ha_rm_tables(thd, table_list, false);
4408
/* DISCARD/IMPORT TABLESPACE is always alone in an ALTER TABLE */
4409
if (alter_info->tablespace_op != NO_TABLESPACE_OP)
4410
/* Conditionally writes to binlog. */
4411
return(mysql_discard_or_import_tablespace(thd,table_list,
4412
alter_info->tablespace_op));
4413
strxnmov(new_name_buff, sizeof (new_name_buff) - 1, mysql_data_home, "/", db,
4414
"/", table_name, reg_ext, NullS);
4415
(void) unpack_filename(new_name_buff, new_name_buff);
4417
If this is just a rename of a view, short cut to the
4418
following scenario: 1) lock LOCK_open 2) do a RENAME
4419
2) unlock LOCK_open.
4420
This is a copy-paste added to make sure
4421
ALTER (sic:) TABLE .. RENAME works for views. ALTER VIEW is handled
4422
as an independent branch in mysql_execute_command. The need
4423
for a copy-paste arose because the main code flow of ALTER TABLE
4424
... RENAME tries to use open_ltable, which does not work for views
4425
(open_ltable was never modified to merge table lists of child tables
4426
into the main table list, like open_tables does).
4427
This code is wrong and will be removed, please do not copy.
4429
frm_type= mysql_frm_type(thd, new_name_buff, &table_type);
4431
if (!(table= open_n_lock_single_table(thd, table_list, TL_WRITE_ALLOW_READ)))
4433
table->use_all_columns();
4435
/* Check that we are not trying to rename to an existing table */
4438
stpcpy(new_name_buff,new_name);
4439
stpcpy(new_alias= new_alias_buff, new_name);
4440
if (lower_case_table_names)
4442
if (lower_case_table_names != 2)
4444
my_casedn_str(files_charset_info, new_name_buff);
4445
new_alias= new_name; // Create lower case table name
4447
my_casedn_str(files_charset_info, new_name);
4450
!my_strcasecmp(table_alias_charset, new_name_buff, table_name))
4453
Source and destination table names are equal: make later check
4456
new_alias= new_name= table_name;
4460
if (table->s->tmp_table != NO_TMP_TABLE)
4462
if (find_temporary_table(thd,new_db,new_name_buff))
4464
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name_buff);
4470
if (lock_table_name_if_not_cached(thd, new_db, new_name, &name_lock))
4474
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
4478
build_table_filename(new_name_buff, sizeof(new_name_buff),
4479
new_db, new_name_buff, reg_ext, 0);
4480
if (!access(new_name_buff, F_OK))
4482
/* Table will be closed in do_command() */
4483
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
4491
new_alias= (lower_case_table_names == 2) ? alias : table_name;
4492
new_name= table_name;
4495
old_db_type= table->s->db_type();
4496
if (!create_info->db_type)
4498
create_info->db_type= old_db_type;
4501
if (check_engine(thd, new_name, create_info))
4503
new_db_type= create_info->db_type;
4505
if (new_db_type != old_db_type &&
4506
!table->file->can_switch_engines())
4509
my_error(ER_ROW_IS_REFERENCED, MYF(0));
4513
if (create_info->row_type == ROW_TYPE_NOT_USED)
4514
create_info->row_type= table->s->row_type;
4516
if (ha_check_storage_engine_flag(old_db_type, HTON_ALTER_NOT_SUPPORTED) ||
4517
ha_check_storage_engine_flag(new_db_type, HTON_ALTER_NOT_SUPPORTED))
4519
my_error(ER_ILLEGAL_HA, MYF(0), table_name);
4523
thd_proc_info(thd, "setup");
4524
if (!(alter_info->flags & ~(ALTER_RENAME | ALTER_KEYS_ONOFF)) &&
4525
!table->s->tmp_table) // no need to touch frm
4527
switch (alter_info->keys_onoff) {
4532
wait_while_table_is_used() ensures that table being altered is
4533
opened only by this thread and that TABLE::TABLE_SHARE::version
4534
of TABLE object corresponding to this table is 0.
4535
The latter guarantees that no DML statement will open this table
4536
until ALTER TABLE finishes (i.e. until close_thread_tables())
4537
while the fact that the table is still open gives us protection
4538
from concurrent DDL statements.
4540
VOID(pthread_mutex_lock(&LOCK_open));
4541
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
4542
VOID(pthread_mutex_unlock(&LOCK_open));
4543
error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
4544
/* COND_refresh will be signaled in close_thread_tables() */
4547
VOID(pthread_mutex_lock(&LOCK_open));
4548
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
4549
VOID(pthread_mutex_unlock(&LOCK_open));
4550
error=table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
4551
/* COND_refresh will be signaled in close_thread_tables() */
4558
if (error == HA_ERR_WRONG_COMMAND)
4561
push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
4562
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
4566
VOID(pthread_mutex_lock(&LOCK_open));
4568
Unlike to the above case close_cached_table() below will remove ALL
4569
instances of TABLE from table cache (it will also remove table lock
4570
held by this thread). So to make actual table renaming and writing
4571
to binlog atomic we have to put them into the same critical section
4572
protected by LOCK_open mutex. This also removes gap for races between
4573
access() and mysql_rename_table() calls.
4576
if (!error && (new_name != table_name || new_db != db))
4578
thd_proc_info(thd, "rename");
4580
Then do a 'simple' rename of the table. First we need to close all
4581
instances of 'source' table.
4583
close_cached_table(thd, table);
4585
Then, we want check once again that target table does not exist.
4586
Actually the order of these two steps does not matter since
4587
earlier we took name-lock on the target table, so we do them
4588
in this particular order only to be consistent with 5.0, in which
4589
we don't take this name-lock and where this order really matters.
4590
TODO: Investigate if we need this access() check at all.
4592
if (!access(new_name_buff,F_OK))
4594
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name);
4599
*fn_ext(new_name)=0;
4600
if (mysql_rename_table(old_db_type,db,table_name,new_db,new_alias, 0))
4604
VOID(mysql_rename_table(old_db_type, new_db, new_alias, db,
4611
if (error == HA_ERR_WRONG_COMMAND)
4614
push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
4615
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
4621
write_bin_log(thd, true, thd->query, thd->query_length);
4626
table->file->print_error(error, MYF(0));
4630
unlink_open_table(thd, name_lock, false);
4631
VOID(pthread_mutex_unlock(&LOCK_open));
4632
table_list->table= NULL; // For query cache
4636
/* We have to do full alter table. */
4639
If the old table had partitions and we are doing ALTER TABLE ...
4640
engine= <new_engine>, the new table must preserve the original
4641
partitioning. That means that the new engine is still the
4642
partitioning engine, not the engine specified in the parser.
4643
This is discovered in prep_alter_part_table, which in such case
4644
updates create_info->db_type.
4645
Now we need to update the stack copy of create_info->db_type,
4646
as otherwise we won't be able to correctly move the files of the
4647
temporary table to the result table files.
4649
new_db_type= create_info->db_type;
4651
if (mysql_prepare_alter_table(thd, table, create_info, alter_info))
4654
set_table_default_charset(thd, create_info, db);
4657
if (thd->variables.old_alter_table
4658
|| (table->s->db_type() != create_info->db_type)
4661
if (alter_info->build_method == HA_BUILD_ONLINE)
4663
my_error(ER_NOT_SUPPORTED_YET, MYF(0), thd->query);
4666
alter_info->build_method= HA_BUILD_OFFLINE;
4669
if (alter_info->build_method != HA_BUILD_OFFLINE)
4671
TABLE *altered_table= 0;
4672
HA_ALTER_INFO ha_alter_info;
4673
HA_ALTER_FLAGS ha_alter_flags;
4674
uint table_changes= IS_EQUAL_YES;
4675
bool need_copy_table= true;
4676
/* Check how much the tables differ. */
4677
if (compare_tables(thd, table, alter_info,
4678
create_info, order_num,
4687
Check if storage engine supports altering the table
4693
If table is not renamed, changed database and
4694
some change was detected then check if engine
4695
can do the change on-line
4697
if (new_name == table_name && new_db == db &&
4698
ha_alter_flags.is_set())
4700
Alter_info tmp_alter_info(*alter_info, thd->mem_root);
4704
check if table can be altered on-line
4706
if (!(altered_table= create_altered_table(thd,
4711
!strcmp(db, new_db))))
4714
switch (table->file->check_if_supported_alter(altered_table,
4718
case HA_ALTER_SUPPORTED_WAIT_LOCK:
4719
case HA_ALTER_SUPPORTED_NO_LOCK:
4721
@todo: Currently we always acquire an exclusive name
4722
lock on the table metadata when performing fast or online
4723
ALTER TABLE. In future we may consider this unnecessary,
4724
and narrow the scope of the exclusive name lock to only
4725
cover manipulation with .frms. Storage engine API
4726
call check_if_supported_alter has provision for this
4729
need_copy_table= false;
4731
case HA_ALTER_NOT_SUPPORTED:
4732
if (alter_info->build_method == HA_BUILD_ONLINE)
4734
my_error(ER_NOT_SUPPORTED_YET, MYF(0), thd->query);
4735
close_temporary_table(thd, altered_table, 1, 1);
4738
need_copy_table= true;
4740
case HA_ALTER_ERROR:
4742
close_temporary_table(thd, altered_table, 1, 1);
4747
/* TODO need to check if changes can be handled as fast ALTER TABLE */
4749
need_copy_table= true;
4751
if (!need_copy_table)
4753
error= mysql_fast_or_online_alter_table(thd,
4759
alter_info->keys_onoff);
4762
mysql_unlock_tables(thd, thd->lock);
4765
close_temporary_table(thd, altered_table, 1, 1);
4771
goto err_with_placeholders;
4778
pthread_mutex_lock(&LOCK_open);
4784
close_temporary_table(thd, altered_table, 1, 1);
4787
snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%lx", tmp_file_prefix,
4788
current_pid, thd->thread_id);
4789
/* Safety fix for innodb */
4790
if (lower_case_table_names)
4791
my_casedn_str(files_charset_info, tmp_name);
4794
/* Create a temporary table with the new format */
4795
if ((error= create_temporary_table(thd, table, new_db, tmp_name,
4796
create_info, alter_info,
4797
!strcmp(db, new_db))))
4802
/* Open the table so we need to copy the data to it. */
4803
if (table->s->tmp_table)
4806
memset(&tbl, 0, sizeof(tbl));
4808
tbl.table_name= tbl.alias= tmp_name;
4809
/* Table is in thd->temporary_tables */
4810
new_table= open_table(thd, &tbl, thd->mem_root, (bool*) 0,
4811
DRIZZLE_LOCK_IGNORE_FLUSH);
4815
char path[FN_REFLEN];
4816
/* table is a normal table: Create temporary table in same directory */
4817
build_table_filename(path, sizeof(path), new_db, tmp_name, "",
4819
/* Open our intermediate table */
4820
new_table=open_temporary_table(thd, path, new_db, tmp_name, 0, OTM_OPEN);
4825
/* Copy the data if necessary. */
4826
thd->count_cuted_fields= CHECK_FIELD_WARN; // calc cuted fields
4827
thd->cuted_fields=0L;
4828
thd_proc_info(thd, "copy to tmp table");
4831
We do not copy data for MERGE tables. Only the children have data.
4832
MERGE tables have HA_NO_COPY_ON_ALTER set.
4834
if (new_table && !(new_table->file->ha_table_flags() & HA_NO_COPY_ON_ALTER))
4836
/* We don't want update TIMESTAMP fields during ALTER TABLE. */
4837
new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
4838
new_table->next_number_field=new_table->found_next_number_field;
4839
error= copy_data_between_tables(table, new_table,
4840
alter_info->create_list, ignore,
4841
order_num, order, &copied, &deleted,
4842
alter_info->keys_onoff,
4843
alter_info->error_if_not_empty);
4847
VOID(pthread_mutex_lock(&LOCK_open));
4848
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
4849
VOID(pthread_mutex_unlock(&LOCK_open));
4850
alter_table_manage_keys(table, table->file->indexes_are_disabled(),
4851
alter_info->keys_onoff);
4852
error= ha_autocommit_or_rollback(thd, 0);
4853
if (end_active_trans(thd))
4856
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
4858
if (table->s->tmp_table != NO_TMP_TABLE)
4860
/* We changed a temporary table */
4863
/* Close lock if this is a transactional table */
4866
mysql_unlock_tables(thd, thd->lock);
4869
/* Remove link to old table and rename the new one */
4870
close_temporary_table(thd, table, 1, 1);
4871
/* Should pass the 'new_name' as we store table name in the cache */
4872
if (rename_temporary_table(thd, new_table, new_db, new_name))
4874
/* We don't replicate alter table statement on temporary tables */
4875
if (!thd->current_stmt_binlog_row_based)
4876
write_bin_log(thd, true, thd->query, thd->query_length);
4883
Close the intermediate table that will be the new table.
4884
Note that MERGE tables do not have their children attached here.
4886
intern_close_table(new_table);
4887
my_free(new_table,MYF(0));
4889
VOID(pthread_mutex_lock(&LOCK_open));
4892
VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
4893
VOID(pthread_mutex_unlock(&LOCK_open));
4898
Data is copied. Now we:
4899
1) Wait until all other threads close old version of table.
4900
2) Close instances of table open by this thread and replace them
4901
with exclusive name-locks.
4902
3) Rename the old table to a temp name, rename the new one to the
4904
4) If we are under LOCK TABLES and don't do ALTER TABLE ... RENAME
4905
we reopen new version of table.
4906
5) Write statement to the binary log.
4907
6) If we are under LOCK TABLES and do ALTER TABLE ... RENAME we
4908
remove name-locks from list of open tables and table cache.
4909
7) If we are not not under LOCK TABLES we rely on close_thread_tables()
4910
call to remove name-locks from table cache and list of open table.
4913
thd_proc_info(thd, "rename result table");
4914
snprintf(old_name, sizeof(old_name), "%s2-%lx-%lx", tmp_file_prefix,
4915
current_pid, thd->thread_id);
4916
if (lower_case_table_names)
4917
my_casedn_str(files_charset_info, old_name);
4919
wait_while_table_is_used(thd, table, HA_EXTRA_PREPARE_FOR_RENAME);
4920
close_data_files_and_morph_locks(thd, db, table_name);
4923
save_old_db_type= old_db_type;
4926
This leads to the storage engine (SE) not being notified for renames in
4927
mysql_rename_table(), because we just juggle with the FRM and nothing
4928
more. If we have an intermediate table, then we notify the SE that
4929
it should become the actual table. Later, we will recycle the old table.
4930
However, in case of ALTER TABLE RENAME there might be no intermediate
4931
table. This is when the old and new tables are compatible, according to
4932
compare_table(). Then, we need one additional call to
4933
mysql_rename_table() with flag NO_FRM_RENAME, which does nothing else but
4934
actual rename in the SE and the FRM is not touched. Note that, if the
4935
table is renamed and the SE is also changed, then an intermediate table
4936
is created and the additional call will not take place.
4938
if (mysql_rename_table(old_db_type, db, table_name, db, old_name,
4942
VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
4944
else if (mysql_rename_table(new_db_type, new_db, tmp_name, new_db,
4945
new_alias, FN_FROM_IS_TMP) || ((new_name != table_name || new_db != db) && 0))
4947
/* Try to get everything back. */
4949
VOID(quick_rm_table(new_db_type,new_db,new_alias, 0));
4950
VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
4951
VOID(mysql_rename_table(old_db_type, db, old_name, db, alias,
4957
/* This shouldn't happen. But let us play it safe. */
4958
goto err_with_placeholders;
4961
VOID(quick_rm_table(old_db_type, db, old_name, FN_IS_TMP));
4964
if (thd->locked_tables && new_name == table_name && new_db == db)
4966
thd->in_lock_tables= 1;
4967
error= reopen_tables(thd, 1, 1);
4968
thd->in_lock_tables= 0;
4970
goto err_with_placeholders;
4972
VOID(pthread_mutex_unlock(&LOCK_open));
4974
thd_proc_info(thd, "end");
4976
ha_binlog_log_query(thd, create_info->db_type, LOGCOM_ALTER_TABLE,
4977
thd->query, thd->query_length,
4980
assert(!(mysql_bin_log.is_open() &&
4981
thd->current_stmt_binlog_row_based &&
4982
(create_info->options & HA_LEX_CREATE_TMP_TABLE)));
4983
write_bin_log(thd, true, thd->query, thd->query_length);
4985
if (ha_check_storage_engine_flag(old_db_type, HTON_FLUSH_AFTER_RENAME))
4988
For the alter table to be properly flushed to the logs, we
4989
have to open the new table. If not, we get a problem on server
4990
shutdown. But we do not need to attach MERGE children.
4992
char path[FN_REFLEN];
4994
build_table_filename(path, sizeof(path), new_db, table_name, "", 0);
4995
t_table= open_temporary_table(thd, path, new_db, tmp_name, false, OTM_OPEN);
4998
intern_close_table(t_table);
4999
my_free(t_table, MYF(0));
5002
sql_print_warning("Could not open table %s.%s after rename\n",
5004
ha_flush_logs(old_db_type);
5006
table_list->table=0; // For query cache
5008
if (thd->locked_tables && (new_name != table_name || new_db != db))
5011
If are we under LOCK TABLES and did ALTER TABLE with RENAME we need
5012
to remove placeholders for the old table and for the target table
5013
from the list of open tables and table cache. If we are not under
5014
LOCK TABLES we can rely on close_thread_tables() doing this job.
5016
pthread_mutex_lock(&LOCK_open);
5017
unlink_open_table(thd, table, false);
5018
unlink_open_table(thd, name_lock, false);
5019
pthread_mutex_unlock(&LOCK_open);
5023
snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
5024
(ulong) (copied + deleted), (ulong) deleted,
5025
(ulong) thd->cuted_fields);
5026
my_ok(thd, copied + deleted, 0L, tmp_name);
5027
thd->some_tables_deleted=0;
5033
/* close_temporary_table() frees the new_table pointer. */
5034
close_temporary_table(thd, new_table, 1, 1);
5037
VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
5041
No default value was provided for a DATE/DATETIME field, the
5042
current sql_mode doesn't allow the '0000-00-00' value and
5043
the table to be altered isn't empty.
5046
if (alter_info->error_if_not_empty && thd->row_count)
5048
const char *f_val= 0;
5049
enum enum_drizzle_timestamp_type t_type= DRIZZLE_TIMESTAMP_DATE;
5050
switch (alter_info->datetime_field->sql_type)
5052
case DRIZZLE_TYPE_NEWDATE:
5053
f_val= "0000-00-00";
5054
t_type= DRIZZLE_TIMESTAMP_DATE;
5056
case DRIZZLE_TYPE_DATETIME:
5057
f_val= "0000-00-00 00:00:00";
5058
t_type= DRIZZLE_TIMESTAMP_DATETIME;
5061
/* Shouldn't get here. */
5064
bool save_abort_on_warning= thd->abort_on_warning;
5065
thd->abort_on_warning= true;
5066
make_truncated_value_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5067
f_val, strlength(f_val), t_type,
5068
alter_info->datetime_field->field_name);
5069
thd->abort_on_warning= save_abort_on_warning;
5073
pthread_mutex_lock(&LOCK_open);
5074
unlink_open_table(thd, name_lock, false);
5075
pthread_mutex_unlock(&LOCK_open);
5079
err_with_placeholders:
5081
An error happened while we were holding exclusive name-lock on table
5082
being altered. To be safe under LOCK TABLES we should remove placeholders
5083
from list of open tables list and table cache.
5085
unlink_open_table(thd, table, false);
5087
unlink_open_table(thd, name_lock, false);
5088
VOID(pthread_mutex_unlock(&LOCK_open));
5091
/* mysql_alter_table */
5094
copy_data_between_tables(TABLE *from,TABLE *to,
5095
List<Create_field> &create,
5097
uint order_num, ORDER *order,
5100
enum enum_enable_or_disable keys_onoff,
5101
bool error_if_not_empty)
5104
Copy_field *copy,*copy_end;
5105
ulong found_count,delete_count;
5106
THD *thd= current_thd;
5108
SORT_FIELD *sortorder;
5112
List<Item> all_fields;
5113
ha_rows examined_rows;
5114
bool auto_increment_field_copied= 0;
5115
ulong save_sql_mode;
5116
uint64_t prev_insert_id;
5119
Turn off recovery logging since rollback of an alter table is to
5120
delete the new table so there is no need to log the changes to it.
5122
This needs to be done before external_lock
5124
error= ha_enable_transaction(thd, false);
5128
if (!(copy= new Copy_field[to->s->fields]))
5129
return(-1); /* purecov: inspected */
5131
if (to->file->ha_external_lock(thd, F_WRLCK))
5134
/* We need external lock before we can disable/enable keys */
5135
alter_table_manage_keys(to, from->file->indexes_are_disabled(), keys_onoff);
5137
/* We can abort alter table for any table type */
5138
thd->abort_on_warning= !ignore;
5140
from->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
5141
to->file->ha_start_bulk_insert(from->file->stats.records);
5143
save_sql_mode= thd->variables.sql_mode;
5145
List_iterator<Create_field> it(create);
5148
for (Field **ptr=to->field ; *ptr ; ptr++)
5153
if (*ptr == to->next_number_field)
5155
auto_increment_field_copied= true;
5157
If we are going to copy contents of one auto_increment column to
5158
another auto_increment column it is sensible to preserve zeroes.
5159
This condition also covers case when we are don't actually alter
5160
auto_increment column.
5162
if (def->field == from->found_next_number_field)
5163
thd->variables.sql_mode|= MODE_NO_AUTO_VALUE_ON_ZERO;
5165
(copy_end++)->set(*ptr,def->field,0);
5170
found_count=delete_count=0;
5174
if (to->s->primary_key != MAX_KEY && to->file->primary_key_is_clustered())
5176
char warn_buff[DRIZZLE_ERRMSG_SIZE];
5177
snprintf(warn_buff, sizeof(warn_buff),
5178
"ORDER BY ignored as there is a user-defined clustered index"
5179
" in the table '%-.192s'", from->s->table_name.str);
5180
push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
5185
from->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE),
5186
MYF(MY_FAE | MY_ZEROFILL));
5187
memset(&tables, 0, sizeof(tables));
5189
tables.alias= tables.table_name= from->s->table_name.str;
5190
tables.db= from->s->db.str;
5193
if (thd->lex->select_lex.setup_ref_array(thd, order_num) ||
5194
setup_order(thd, thd->lex->select_lex.ref_pointer_array,
5195
&tables, fields, all_fields, order) ||
5196
!(sortorder= make_unireg_sortorder(order, &length, NULL)) ||
5197
(from->sort.found_records= filesort(thd, from, sortorder, length,
5198
(SQL_SELECT *) 0, HA_POS_ERROR,
5199
1, &examined_rows)) ==
5205
/* Tell handler that we have values for all columns in the to table */
5206
to->use_all_columns();
5207
init_read_record(&info, thd, from, (SQL_SELECT *) 0, 1,1);
5209
to->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
5211
restore_record(to, s->default_values); // Create empty record
5212
while (!(error=info.read_record(&info)))
5216
thd->send_kill_message();
5221
/* Return error if source table isn't empty. */
5222
if (error_if_not_empty)
5227
if (to->next_number_field)
5229
if (auto_increment_field_copied)
5230
to->auto_increment_field_not_null= true;
5232
to->next_number_field->reset();
5235
for (Copy_field *copy_ptr=copy ; copy_ptr != copy_end ; copy_ptr++)
5237
copy_ptr->do_copy(copy_ptr);
5239
prev_insert_id= to->file->next_insert_id;
5240
error=to->file->ha_write_row(to->record[0]);
5241
to->auto_increment_field_not_null= false;
5245
to->file->is_fatal_error(error, HA_CHECK_DUP))
5247
if (!to->file->is_fatal_error(error, HA_CHECK_DUP))
5249
uint key_nr= to->file->get_dup_key(error);
5250
if ((int) key_nr >= 0)
5252
const char *err_msg= ER(ER_DUP_ENTRY_WITH_KEY_NAME);
5254
(to->key_info[0].key_part[0].field->flags &
5255
AUTO_INCREMENT_FLAG))
5256
err_msg= ER(ER_DUP_ENTRY_AUTOINCREMENT_CASE);
5257
to->file->print_keydup_error(key_nr, err_msg);
5262
to->file->print_error(error,MYF(0));
5265
to->file->restore_auto_increment(prev_insert_id);
5271
end_read_record(&info);
5272
free_io_cache(from);
5273
delete [] copy; // This is never 0
5275
if (to->file->ha_end_bulk_insert() && error <= 0)
5277
to->file->print_error(my_errno,MYF(0));
5280
to->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
5282
if (ha_enable_transaction(thd, true))
5289
Ensure that the new table is saved properly to disk so that we
5292
if (ha_autocommit_or_rollback(thd, 0))
5294
if (end_active_trans(thd))
5298
thd->variables.sql_mode= save_sql_mode;
5299
thd->abort_on_warning= 0;
5300
free_io_cache(from);
5301
*copied= found_count;
5302
*deleted=delete_count;
5303
to->file->ha_release_auto_increment();
5304
if (to->file->ha_external_lock(thd,F_UNLCK))
5306
return(error > 0 ? -1 : 0);
5311
Recreates tables by calling mysql_alter_table().
5314
mysql_recreate_table()
5316
tables Tables to recreate
5319
Like mysql_alter_table().
5321
bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list)
5323
HA_CREATE_INFO create_info;
5324
Alter_info alter_info;
5326
assert(!table_list->next_global);
5328
table_list->table has been closed and freed. Do not reference
5329
uninitialized data. open_tables() could fail.
5331
table_list->table= NULL;
5333
memset(&create_info, 0, sizeof(create_info));
5334
create_info.row_type=ROW_TYPE_NOT_USED;
5335
create_info.default_table_charset=default_charset_info;
5336
/* Force alter table to recreate table */
5337
alter_info.flags= (ALTER_CHANGE_COLUMN | ALTER_RECREATE);
5338
return(mysql_alter_table(thd, NullS, NullS, &create_info,
5339
table_list, &alter_info, 0,
5344
bool mysql_checksum_table(THD *thd, TABLE_LIST *tables,
5345
HA_CHECK_OPT *check_opt)
2485
&Cursor::ha_check));
2489
bool mysql_checksum_table(Session *session, TableList *tables,
5348
2493
List<Item> field_list;
5350
Protocol *protocol= thd->protocol;
5352
2496
field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
5353
2497
item->maybe_null= 1;
5354
2498
field_list.push_back(item= new Item_int("Checksum", (int64_t) 1,
5355
2499
MY_INT64_NUM_DECIMAL_DIGITS));
5356
2500
item->maybe_null= 1;
5357
if (protocol->send_fields(&field_list,
5358
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
2501
if (session->client->sendFields(&field_list))
5361
2504
/* Open one table after the other to keep lock time as short as possible. */
5362
2505
for (table= tables; table; table= table->next_local)
5364
2507
char table_name[NAME_LEN*2+2];
5367
strxmov(table_name, table->db ,".", table->table_name, NullS);
5369
t= table->table= open_n_lock_single_table(thd, table, TL_READ);
5370
thd->clear_error(); // these errors shouldn't get client
5372
protocol->prepare_for_resend();
5373
protocol->store(table_name, system_charset_info);
2510
sprintf(table_name,"%s.%s",table->db,table->table_name);
2512
t= table->table= session->openTableLock(table, TL_READ);
2513
session->clear_error(); // these errors shouldn't get client
2515
session->client->store(table_name);
5377
2519
/* Table didn't exist */
5378
protocol->store_null();
2520
session->client->store();
2521
session->clear_error();
5383
if (t->file->ha_table_flags() & HA_HAS_CHECKSUM &&
5384
!(check_opt->flags & T_EXTEND))
5385
protocol->store((uint64_t)t->file->checksum());
5386
else if (!(t->file->ha_table_flags() & HA_HAS_CHECKSUM) &&
5387
(check_opt->flags & T_QUICK))
5388
protocol->store_null();
2526
@note if the engine keeps a checksum then we return the checksum, otherwise we calculate
2528
if (t->cursor->getEngine()->check_flag(HTON_BIT_HAS_CHECKSUM))
2530
session->client->store((uint64_t)t->cursor->checksum());
5391
2534
/* calculating table's checksum */
5392
2535
ha_checksum crc= 0;
5393
uchar null_mask=256 - (1 << t->s->last_null_bit_pos);
2536
unsigned char null_mask=256 - (1 << t->s->last_null_bit_pos);
5395
2538
t->use_all_columns();
5397
if (t->file->ha_rnd_init(1))
5398
protocol->store_null();
2540
if (t->cursor->ha_rnd_init(1))
2541
session->client->store();
5403
2546
ha_checksum row_crc= 0;
5404
int error= t->file->rnd_next(t->record[0]);
2547
int error= t->cursor->rnd_next(t->record[0]);
5405
2548
if (unlikely(error))
5407
2550
if (error == HA_ERR_RECORD_DELETED)