2103
bool create_like_table(Session* session,
2104
identifier::Table::const_reference destination_identifier,
2105
identifier::Table::const_reference source_identifier,
2106
message::Table &create_table_proto,
2107
bool is_if_not_exists,
2915
bool mysql_create_like_table(THD* thd, TableList* table, TableList* src_table,
2916
HA_CREATE_INFO *create_info)
2918
Table *name_lock= 0;
2919
char src_path[FN_REFLEN], dst_path[FN_REFLEN];
2920
uint32_t dst_path_length;
2921
char *db= table->db;
2922
char *table_name= table->table_name;
2110
2924
bool res= true;
2111
bool table_exists= false;
2928
By opening source table we guarantee that it exists and no concurrent
2929
DDL operation will mess with it. Later we also take an exclusive
2930
name-lock on target table name, which makes copying of .frm file,
2931
call to ha_create_table() and binlogging atomic against concurrent DML
2932
and DDL operations on target table. Thus by holding both these "locks"
2933
we ensure that our statement is properly isolated from all concurrent
2934
operations which matter.
2936
if (open_tables(thd, &src_table, ¬_used, 0))
2939
strxmov(src_path, src_table->table->s->path.str, reg_ext, NULL);
2114
2942
Check that destination tables does not exist. Note that its name
2115
2943
was already checked when it was added to the table list.
2117
For temporary tables we don't aim to grab locks.
2119
if (destination_identifier.isTmp())
2121
if (session->find_temporary_table(destination_identifier))
2127
bool was_created= create_table_wrapper(*session,
2129
destination_identifier,
2132
if (not was_created) // This is pretty paranoid, but we assume something might not clean up after itself
2134
(void) session->rm_temporary_table(destination_identifier, true);
2136
else if (not session->open_temporary_table(destination_identifier))
2138
// We created, but we can't open... also, a hack.
2139
(void) session->rm_temporary_table(destination_identifier, true);
2147
else // Standard table which will require locks.
2149
Table *name_lock= 0;
2151
if (session->lock_table_name_if_not_cached(destination_identifier, &name_lock))
2155
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* unlink open tables for create table like*/
2156
session->unlink_open_table(name_lock);
2166
else if (plugin::StorageEngine::doesTableExist(*session, destination_identifier))
2170
else // Otherwise we create the table
2174
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* We lock for CREATE TABLE LIKE to copy table definition */
2175
was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
2176
source_identifier, is_engine_set);
2179
// So we blew the creation of the table, and we scramble to clean up
2180
// anything that might have been created (read... it is a hack)
2181
if (not was_created)
2183
plugin::StorageEngine::dropTable(*session, destination_identifier);
2945
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
2947
if (find_temporary_table(thd, db, table_name))
2949
dst_path_length= build_tmptable_filename(thd, dst_path, sizeof(dst_path));
2950
create_info->table_options|= HA_CREATE_DELAY_KEY_WRITE;
2954
if (lock_table_name_if_not_cached(thd, db, table_name, &name_lock))
2958
dst_path_length= build_table_filename(dst_path, sizeof(dst_path),
2959
db, table_name, reg_ext, 0);
2960
if (!access(dst_path, F_OK))
2965
Create a new table by copying from source table
2967
Altough exclusive name-lock on target table protects us from concurrent
2968
DML and DDL operations on it we still want to wrap .FRM creation and call
2969
to ha_create_table() in critical section protected by LOCK_open in order
2970
to provide minimal atomicity against operations which disregard name-locks,
2971
like I_S implementation, for example. This is a temporary and should not
2972
be copied. Instead we should fix our code to always honor name-locks.
2974
Also some engines (e.g. NDB cluster) require that LOCK_open should be held
2975
during the call to ha_create_table(). See bug #28614 for more info.
2977
pthread_mutex_lock(&LOCK_open);
2978
if (src_table->schema_table)
2980
if (mysql_create_like_schema_frm(thd, src_table, dst_path, create_info))
2982
pthread_mutex_unlock(&LOCK_open);
2986
else if (my_copy(src_path, dst_path, MYF(MY_DONT_OVERWRITE_FILE)))
2988
if (my_errno == ENOENT)
2989
my_error(ER_BAD_DB_ERROR,MYF(0),db);
2991
my_error(ER_CANT_CREATE_FILE,MYF(0),dst_path,my_errno);
2992
pthread_mutex_unlock(&LOCK_open);
2997
As mysql_truncate don't work on a new table at this stage of
2998
creation, instead create the table directly (for both normal
2999
and temporary tables).
3001
dst_path[dst_path_length - reg_ext_length]= '\0'; // Remove .frm
3002
if (thd->variables.keep_files_on_create)
3003
create_info->options|= HA_CREATE_KEEP_FILES;
3004
err= ha_create_table(thd, dst_path, db, table_name, create_info, 1);
3005
pthread_mutex_unlock(&LOCK_open);
3007
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
3009
if (err || !open_temporary_table(thd, dst_path, db, table_name, 1,
3012
(void) rm_temporary_table(create_info->db_type,
3013
dst_path, false); /* purecov: inspected */
3014
goto err; /* purecov: inspected */
3019
(void) quick_rm_table(create_info->db_type, db,
3020
table_name, 0); /* purecov: inspected */
3021
goto err; /* purecov: inspected */
3025
We have to write the query before we unlock the tables.
3027
if (thd->current_stmt_binlog_row_based)
3030
Since temporary tables are not replicated under row-based
3031
replication, CREATE TABLE ... LIKE ... needs special
3032
treatement. We have four cases to consider, according to the
3033
following decision table:
3035
==== ========= ========= ==============================
3036
Case Target Source Write to binary log
3037
==== ========= ========= ==============================
3038
1 normal normal Original statement
3039
2 normal temporary Generated statement
3040
3 temporary normal Nothing
3041
4 temporary temporary Nothing
3042
==== ========= ========= ==============================
3044
if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
3046
if (src_table->table->s->tmp_table) // Case 2
3049
String query(buf, sizeof(buf), system_charset_info);
3050
query.length(0); // Have to zero it since constructor doesn't
3054
Here we open the destination table, on which we already have
3055
name-lock. This is needed for store_create_info() to work.
3056
The table will be closed by unlink_open_table() at the end
3059
table->table= name_lock;
3060
pthread_mutex_lock(&LOCK_open);
3061
if (reopen_name_locked_table(thd, table, false))
3063
pthread_mutex_unlock(&LOCK_open);
3066
pthread_mutex_unlock(&LOCK_open);
3068
int result= store_create_info(thd, table, &query,
3071
assert(result == 0); // store_create_info() always return 0
3072
write_bin_log(thd, true, query.ptr(), query.length());
3075
write_bin_log(thd, true, thd->query, thd->query_length);
3078
Case 3 and 4 does nothing under RBR
3082
write_bin_log(thd, true, thd->query, thd->query_length);
3088
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
3090
char warn_buff[DRIZZLE_ERRMSG_SIZE];
3091
snprintf(warn_buff, sizeof(warn_buff),
3092
ER(ER_TABLE_EXISTS_ERROR), table_name);
3093
push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
3094
ER_TABLE_EXISTS_ERROR,warn_buff);
3098
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
3103
pthread_mutex_lock(&LOCK_open);
3104
unlink_open_table(thd, name_lock, false);
3105
pthread_mutex_unlock(&LOCK_open);
3111
bool mysql_analyze_table(THD* thd, TableList* tables, HA_CHECK_OPT* check_opt)
3113
thr_lock_type lock_type = TL_READ_NO_INSERT;
3115
return(mysql_admin_table(thd, tables, check_opt,
3116
"analyze", lock_type, 1, 0, 0, 0,
3117
&handler::ha_analyze));
3121
bool mysql_check_table(THD* thd, TableList* tables,HA_CHECK_OPT* check_opt)
3123
thr_lock_type lock_type = TL_READ_NO_INSERT;
3125
return(mysql_admin_table(thd, tables, check_opt,
3127
0, 0, HA_OPEN_FOR_REPAIR, 0,
3128
&handler::ha_check));
3132
/* table_list should contain just one table */
3134
mysql_discard_or_import_tablespace(THD *thd,
3135
TableList *table_list,
3136
enum tablespace_op_type tablespace_op)
3143
Note that DISCARD/IMPORT TABLESPACE always is the only operation in an
3147
thd->set_proc_info("discard_or_import_tablespace");
3149
discard= test(tablespace_op == DISCARD_TABLESPACE);
3152
We set this flag so that ha_innobase::open and ::external_lock() do
3153
not complain when we lock the table
3155
thd->tablespace_op= true;
3156
if (!(table=open_ltable(thd, table_list, TL_WRITE, 0)))
3158
thd->tablespace_op=false;
3162
error= table->file->ha_discard_or_import_tablespace(discard);
3164
thd->set_proc_info("end");
3169
/* The ALTER Table is always in its own transaction */
3170
error = ha_autocommit_or_rollback(thd, 0);
3171
if (end_active_trans(thd))
3175
write_bin_log(thd, false, thd->query, thd->query_length);
3178
ha_autocommit_or_rollback(thd, error);
3179
thd->tablespace_op=false;
3187
table->file->print_error(error, MYF(0));
3193
Copy all changes detected by parser to the HA_ALTER_FLAGS
3196
void setup_ha_alter_flags(Alter_info *alter_info, HA_ALTER_FLAGS *alter_flags)
3198
uint32_t flags= alter_info->flags;
3200
if (ALTER_ADD_COLUMN & flags)
3201
*alter_flags|= HA_ADD_COLUMN;
3202
if (ALTER_DROP_COLUMN & flags)
3203
*alter_flags|= HA_DROP_COLUMN;
3204
if (ALTER_RENAME & flags)
3205
*alter_flags|= HA_RENAME_TABLE;
3206
if (ALTER_CHANGE_COLUMN & flags)
3207
*alter_flags|= HA_CHANGE_COLUMN;
3208
if (ALTER_COLUMN_DEFAULT & flags)
3209
*alter_flags|= HA_COLUMN_DEFAULT_VALUE;
3210
if (ALTER_COLUMN_STORAGE & flags)
3211
*alter_flags|= HA_COLUMN_STORAGE;
3212
if (ALTER_COLUMN_FORMAT & flags)
3213
*alter_flags|= HA_COLUMN_FORMAT;
3214
if (ALTER_COLUMN_ORDER & flags)
3215
*alter_flags|= HA_ALTER_COLUMN_ORDER;
3216
if (ALTER_STORAGE & flags)
3217
*alter_flags|= HA_ALTER_STORAGE;
3218
if (ALTER_ROW_FORMAT & flags)
3219
*alter_flags|= HA_ALTER_ROW_FORMAT;
3220
if (ALTER_RECREATE & flags)
3221
*alter_flags|= HA_RECREATE;
3222
if (ALTER_FOREIGN_KEY & flags)
3223
*alter_flags|= HA_ALTER_FOREIGN_KEY;
3229
@param table The original table.
3230
@param alter_info Alter options, fields and keys for the new
3232
@param create_info Create options for the new table.
3233
@param order_num Number of order list elements.
3234
@param[out] ha_alter_flags Flags that indicate what will be changed
3235
@param[out] ha_alter_info Data structures needed for on-line alter
3236
@param[out] table_changes Information about particular change
3238
First argument 'table' contains information of the original
3239
table, which includes all corresponding parts that the new
3240
table has in arguments create_list, key_list and create_info.
3242
By comparing the changes between the original and new table
3243
we can determine how much it has changed after ALTER Table
3244
and whether we need to make a copy of the table, or just change
3247
Mark any changes detected in the ha_alter_flags.
3249
If there are no data changes, but index changes, 'index_drop_buffer'
3250
and/or 'index_add_buffer' are populated with offsets into
3251
table->key_info or key_info_buffer respectively for the indexes
3252
that need to be dropped and/or (re-)created.
3255
@retval false success
3260
compare_tables(THD *thd,
3262
Alter_info *alter_info,
3263
HA_CREATE_INFO *create_info,
3265
HA_ALTER_FLAGS *alter_flags,
3266
HA_ALTER_INFO *ha_alter_info,
3267
uint32_t *table_changes)
3269
Field **f_ptr, *field;
3270
uint32_t table_changes_local= 0;
3271
List_iterator_fast<Create_field> new_field_it(alter_info->create_list);
3272
Create_field *new_field;
3273
KEY_PART_INFO *key_part;
3276
Remember if the new definition has new VARCHAR column;
3277
create_info->varchar will be reset in mysql_prepare_create_table.
3279
bool varchar= create_info->varchar;
3283
Create a copy of alter_info.
3284
To compare the new and old table definitions, we need to "prepare"
3285
the new definition - transform it from parser output to a format
3286
that describes the final table layout (all column defaults are
3287
initialized, duplicate columns are removed). This is done by
3288
mysql_prepare_create_table. Unfortunately,
3289
mysql_prepare_create_table performs its transformations
3290
"in-place", that is, modifies the argument. Since we would
3291
like to keep compare_tables() idempotent (not altering any
3292
of the arguments) we create a copy of alter_info here and
3293
pass it to mysql_prepare_create_table, then use the result
3294
to evaluate possibility of fast ALTER Table, and then
3297
Alter_info tmp_alter_info(*alter_info, thd->mem_root);
3298
THD *thd= table->in_use;
3299
uint32_t db_options= 0; /* not used */
3300
/* Create the prepared information. */
3301
if (mysql_prepare_create_table(thd, create_info,
3303
(table->s->tmp_table != NO_TMP_TABLE),
3306
&ha_alter_info->key_info_buffer,
3307
&ha_alter_info->key_count,
3308
/* select_field_count */ 0))
3310
/* Allocate result buffers. */
3311
if (! (ha_alter_info->index_drop_buffer=
3312
(uint*) thd->alloc(sizeof(uint) * table->s->keys)) ||
3313
! (ha_alter_info->index_add_buffer=
3314
(uint*) thd->alloc(sizeof(uint) *
3315
tmp_alter_info.key_list.elements)))
3319
First we setup ha_alter_flags based on what was detected
3322
setup_ha_alter_flags(alter_info, alter_flags);
3326
Some very basic checks. If number of fields changes, or the
3327
handler, we need to run full ALTER Table. In the future
3328
new fields can be added and old dropped without copy, but
3331
Test also that engine was not given during ALTER Table, or
3332
we are force to run regular alter table (copy).
3333
E.g. ALTER Table tbl_name ENGINE=MyISAM.
3335
For the following ones we also want to run regular alter table:
3336
ALTER Table tbl_name order_st BY ..
3337
ALTER Table tbl_name CONVERT TO CHARACTER SET ..
3339
At the moment we can't handle altering temporary tables without a copy.
3340
We also test if OPTIMIZE Table was given and was mapped to alter table.
3341
In that case we always do full copy.
3343
There was a bug prior to mysql-4.0.25. Number of null fields was
3344
calculated incorrectly. As a result frm and data files gets out of
3345
sync after fast alter table. There is no way to determine by which
3346
mysql version (in 4.0 and 4.1 branches) table was created, thus we
3347
disable fast alter table for all tables created by mysql versions
3348
prior to 5.0 branch.
3351
if (table->s->fields != alter_info->create_list.elements ||
3352
table->s->db_type() != create_info->db_type ||
3353
table->s->tmp_table ||
3354
create_info->used_fields & HA_CREATE_USED_ENGINE ||
3355
create_info->used_fields & HA_CREATE_USED_CHARSET ||
3356
create_info->used_fields & HA_CREATE_USED_DEFAULT_CHARSET ||
3357
create_info->used_fields & HA_CREATE_USED_ROW_FORMAT ||
3358
(alter_info->flags & (ALTER_RECREATE | ALTER_FOREIGN_KEY)) ||
3360
!table->s->mysql_version ||
3361
(table->s->frm_version < FRM_VER_TRUE_VARCHAR && varchar))
3363
*table_changes= IS_EQUAL_NO;
3365
Check what has changed and set alter_flags
3367
if (table->s->fields < alter_info->create_list.elements)
3368
*alter_flags|= HA_ADD_COLUMN;
3369
else if (table->s->fields > alter_info->create_list.elements)
3370
*alter_flags|= HA_DROP_COLUMN;
3371
if (create_info->db_type != table->s->db_type() ||
3372
create_info->used_fields & HA_CREATE_USED_ENGINE)
3373
*alter_flags|= HA_ALTER_STORAGE_ENGINE;
3374
if (create_info->used_fields & HA_CREATE_USED_CHARSET)
3375
*alter_flags|= HA_CHANGE_CHARACTER_SET;
3376
if (create_info->used_fields & HA_CREATE_USED_DEFAULT_CHARSET)
3377
*alter_flags|= HA_SET_DEFAULT_CHARACTER_SET;
3378
if (alter_info->flags & ALTER_RECREATE)
3379
*alter_flags|= HA_RECREATE;
3380
/* TODO check for ADD/DROP FOREIGN KEY */
3381
if (alter_info->flags & ALTER_FOREIGN_KEY)
3382
*alter_flags|= HA_ALTER_FOREIGN_KEY;
3383
if (!table->s->mysql_version ||
3384
(table->s->frm_version < FRM_VER_TRUE_VARCHAR && varchar))
3385
*alter_flags|= HA_ALTER_COLUMN_TYPE;
3388
Go through fields and check if the original ones are compatible
3391
for (f_ptr= table->field, new_field= new_field_it++;
3392
(new_field && (field= *f_ptr));
3393
f_ptr++, new_field= new_field_it++)
3395
/* Make sure we have at least the default charset in use. */
3396
if (!new_field->charset)
3397
new_field->charset= create_info->default_table_charset;
3399
/* Don't pack rows in old tables if the user has requested this. */
3400
if (create_info->row_type == ROW_TYPE_DYNAMIC ||
3401
(new_field->flags & BLOB_FLAG) ||
3402
(new_field->sql_type == DRIZZLE_TYPE_VARCHAR && create_info->row_type != ROW_TYPE_FIXED))
3403
create_info->table_options|= HA_OPTION_PACK_RECORD;
3405
/* Check how fields have been modified */
3406
if (alter_info->flags & ALTER_CHANGE_COLUMN)
3408
/* Evaluate changes bitmap and send to check_if_incompatible_data() */
3409
if (!(table_changes_local= field->is_equal(new_field)))
3410
*alter_flags|= HA_ALTER_COLUMN_TYPE;
3412
/* Check if field was renamed */
3413
field->flags&= ~FIELD_IS_RENAMED;
3414
if (my_strcasecmp(system_charset_info,
3416
new_field->field_name))
3418
field->flags|= FIELD_IS_RENAMED;
3419
*alter_flags|= HA_ALTER_COLUMN_NAME;
3422
*table_changes&= table_changes_local;
3423
if (table_changes_local == IS_EQUAL_PACK_LENGTH)
3424
*alter_flags|= HA_ALTER_COLUMN_TYPE;
3426
/* Check that NULL behavior is same for old and new fields */
3427
if ((new_field->flags & NOT_NULL_FLAG) !=
3428
(uint) (field->flags & NOT_NULL_FLAG))
3430
*table_changes= IS_EQUAL_NO;
3431
*alter_flags|= HA_ALTER_COLUMN_NULLABLE;
3435
/* Clear indexed marker */
3436
field->flags&= ~FIELD_IN_ADD_INDEX;
3440
Go through keys and check if the original ones are compatible
3444
KEY *table_key_end= table->key_info + table->s->keys;
3447
ha_alter_info->key_info_buffer + ha_alter_info->key_count;
3450
Step through all keys of the old table and search matching new keys.
3452
ha_alter_info->index_drop_count= 0;
3453
ha_alter_info->index_add_count= 0;
3454
for (table_key= table->key_info; table_key < table_key_end; table_key++)
3456
KEY_PART_INFO *table_part;
3457
KEY_PART_INFO *table_part_end= table_key->key_part + table_key->key_parts;
3458
KEY_PART_INFO *new_part;
3460
/* Search a new key with the same name. */
3461
for (new_key= ha_alter_info->key_info_buffer;
3462
new_key < new_key_end;
3465
if (! strcmp(table_key->name, new_key->name))
3468
if (new_key >= new_key_end)
3470
/* Key not found. Add the offset of the key to the drop buffer. */
3471
ha_alter_info->index_drop_buffer
3472
[ha_alter_info->index_drop_count++]=
3473
table_key - table->key_info;
3474
if (table_key->flags & HA_NOSAME)
3476
/* Unique key. Check for "PRIMARY". */
3477
if (! my_strcasecmp(system_charset_info,
3478
table_key->name, primary_key_name))
3479
*alter_flags|= HA_DROP_PK_INDEX;
3481
*alter_flags|= HA_DROP_UNIQUE_INDEX;
3484
*alter_flags|= HA_DROP_INDEX;
3485
*table_changes= IS_EQUAL_NO;
3489
/* Check that the key types are compatible between old and new tables. */
3490
if ((table_key->algorithm != new_key->algorithm) ||
3491
((table_key->flags & HA_KEYFLAG_MASK) !=
3492
(new_key->flags & HA_KEYFLAG_MASK)) ||
3493
(table_key->key_parts != new_key->key_parts))
3495
if (table_key->flags & HA_NOSAME)
3497
// Unique key. Check for "PRIMARY".
3498
if (! my_strcasecmp(system_charset_info,
3499
table_key->name, primary_key_name))
3500
*alter_flags|= HA_ALTER_PK_INDEX;
3502
*alter_flags|= HA_ALTER_UNIQUE_INDEX;
3505
*alter_flags|= HA_ALTER_INDEX;
3510
Check that the key parts remain compatible between the old and
3513
for (table_part= table_key->key_part, new_part= new_key->key_part;
3514
table_part < table_part_end;
3515
table_part++, new_part++)
3518
Key definition has changed if we are using a different field or
3519
if the used key part length is different. We know that the fields
3520
did not change. Comparing field numbers is sufficient.
3522
if ((table_part->length != new_part->length) ||
3523
(table_part->fieldnr - 1 != new_part->fieldnr))
3525
if (table_key->flags & HA_NOSAME)
3527
/* Unique key. Check for "PRIMARY" */
3528
if (! my_strcasecmp(system_charset_info,
3529
table_key->name, primary_key_name))
3530
*alter_flags|= HA_ALTER_PK_INDEX;
3532
*alter_flags|= HA_ALTER_UNIQUE_INDEX;
3535
*alter_flags|= HA_ALTER_INDEX;
3542
/* Key modified. Add the offset of the key to both buffers. */
3543
ha_alter_info->index_drop_buffer
3544
[ha_alter_info->index_drop_count++]=
3545
table_key - table->key_info;
3546
ha_alter_info->index_add_buffer
3547
[ha_alter_info->index_add_count++]=
3548
new_key - ha_alter_info->key_info_buffer;
3549
key_part= new_key->key_part;
3550
end= key_part + new_key->key_parts;
3551
for(; key_part != end; key_part++)
3553
/* Mark field to be part of new key */
3554
if ((field= table->field[key_part->fieldnr]))
3555
field->flags|= FIELD_IN_ADD_INDEX;
3557
*table_changes= IS_EQUAL_NO;
3559
/*end of for (; table_key < table_key_end;) */
3562
Step through all keys of the new table and find matching old keys.
3564
for (new_key= ha_alter_info->key_info_buffer;
3565
new_key < new_key_end;
3568
/* Search an old key with the same name. */
3569
for (table_key= table->key_info; table_key < table_key_end; table_key++)
3571
if (! strcmp(table_key->name, new_key->name))
3574
if (table_key >= table_key_end)
3576
/* Key not found. Add the offset of the key to the add buffer. */
3577
ha_alter_info->index_add_buffer
3578
[ha_alter_info->index_add_count++]=
3579
new_key - ha_alter_info->key_info_buffer;
3580
key_part= new_key->key_part;
3581
end= key_part + new_key->key_parts;
3582
for(; key_part != end; key_part++)
3584
/* Mark field to be part of new key */
3585
if ((field= table->field[key_part->fieldnr]))
3586
field->flags|= FIELD_IN_ADD_INDEX;
3588
if (new_key->flags & HA_NOSAME)
3590
/* Unique key. Check for "PRIMARY" */
3591
if (! my_strcasecmp(system_charset_info,
3592
new_key->name, primary_key_name))
3593
*alter_flags|= HA_ADD_PK_INDEX;
3595
*alter_flags|= HA_ADD_UNIQUE_INDEX;
3598
*alter_flags|= HA_ADD_INDEX;
3599
*table_changes= IS_EQUAL_NO;
3608
Manages enabling/disabling of indexes for ALTER Table
3611
alter_table_manage_keys()
3613
indexes_were_disabled Whether the indexes of the from table
3615
keys_onoff ENABLE | DISABLE | LEAVE_AS_IS
3623
bool alter_table_manage_keys(Table *table, int indexes_were_disabled,
3624
enum enum_enable_or_disable keys_onoff)
3627
switch (keys_onoff) {
3629
error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
3632
if (!indexes_were_disabled)
3634
/* fall-through: disabled indexes */
3636
error= table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
3639
if (error == HA_ERR_WRONG_COMMAND)
3641
push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
3642
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
3643
table->s->table_name.str);
3646
table->file->print_error(error, MYF(0));
3651
int create_temporary_table(THD *thd,
3655
HA_CREATE_INFO *create_info,
3656
Alter_info *alter_info,
3660
char index_file[FN_REFLEN], data_file[FN_REFLEN];
3661
handlerton *old_db_type, *new_db_type;
3662
old_db_type= table->s->db_type();
3663
new_db_type= create_info->db_type;
3665
Handling of symlinked tables:
3667
Create new data file and index file on the same disk as the
3668
old data and index files.
3670
Rename new data file over old data file and new index file over
3672
Symlinks are not changed.
3675
Create new data file and index file on the same disk as the
3676
old data and index files. Create also symlinks to point at
3679
At end, rename intermediate tables, and symlinks to intermediate
3680
table, to final table name.
3681
Remove old table and old symlinks
3683
If rename is made to another database:
3684
Create new tables in new database.
3686
Remove old table and symlinks.
3688
if (db_changed) // Ignore symlink if db changed
3690
if (create_info->index_file_name)
3692
/* Fix index_file_name to have 'tmp_name' as basename */
3693
my_stpcpy(index_file, tmp_name);
3694
create_info->index_file_name=fn_same(index_file,
3695
create_info->index_file_name,
3698
if (create_info->data_file_name)
3700
/* Fix data_file_name to have 'tmp_name' as basename */
3701
my_stpcpy(data_file, tmp_name);
3702
create_info->data_file_name=fn_same(data_file,
3703
create_info->data_file_name,
3708
create_info->data_file_name=create_info->index_file_name=0;
3711
Create a table with a temporary name.
3712
With create_info->frm_only == 1 this creates a .frm file only.
3713
We don't log the statement, it will be logged later.
3715
tmp_disable_binlog(thd);
3716
error= mysql_create_table(thd, new_db, tmp_name,
3717
create_info, alter_info, 1, 0);
3718
reenable_binlog(thd);
3724
Create a temporary table that reflects what an alter table operation
3728
create_altered_table()
3730
table The original table
3731
create_info Information from the parsing phase about new
3733
alter_info Lists of fields, keys to be changed, added
3735
db_change Specifies if the table is moved to another database
3737
A temporary table with all changes
3740
The temporary table is created without storing it in any storage engine
3741
and is opened only to get the table struct and frm file reference.
3743
Table *create_altered_table(THD *thd,
3746
HA_CREATE_INFO *create_info,
3747
Alter_info *alter_info,
3751
HA_CREATE_INFO altered_create_info(*create_info);
3752
Table *altered_table;
3754
char path[FN_REFLEN];
3756
snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%lx",
3757
tmp_file_prefix, current_pid, thd->thread_id);
3758
/* Safety fix for InnoDB */
3759
if (lower_case_table_names)
3760
my_casedn_str(files_charset_info, tmp_name);
3761
altered_create_info.options&= ~HA_LEX_CREATE_TMP_TABLE;
3762
altered_create_info.frm_only= 1;
3763
if ((error= create_temporary_table(thd, table, new_db, tmp_name,
3764
&altered_create_info,
3765
alter_info, db_change)))
3770
build_table_filename(path, sizeof(path), new_db, tmp_name, "",
3772
altered_table= open_temporary_table(thd, path, new_db, tmp_name, 1,
3774
return(altered_table);
3781
Perform a fast or on-line alter table
3784
mysql_fast_or_online_alter_table()
3786
table The original table
3787
altered_table A temporary table showing how we will change table
3788
create_info Information from the parsing phase about new
3790
alter_info Storage place for data used during different phases
3791
ha_alter_flags Bitmask that shows what will be changed
3792
keys_onoff Specifies if keys are to be enabled/disabled
3795
>0 An error occured during the on-line alter table operation
3796
-1 Error when re-opening table
3798
If mysql_alter_table does not need to copy the table, it is
3799
either a fast alter table where the storage engine does not
3800
need to know about the change, only the frm will change,
3801
or the storage engine supports performing the alter table
3802
operation directly, on-line without mysql having to copy
3805
int mysql_fast_or_online_alter_table(THD *thd,
3807
Table *altered_table,
3808
HA_CREATE_INFO *create_info,
3809
HA_ALTER_INFO *alter_info,
3810
HA_ALTER_FLAGS *ha_alter_flags,
3811
enum enum_enable_or_disable keys_onoff)
3814
bool online= (table->file->ha_table_flags() & HA_ONLINE_ALTER)?true:false;
3820
Tell the handler to prepare for the online alter
3822
if ((error= table->file->alter_table_phase1(thd,
3832
Tell the storage engine to perform the online alter table
3834
if check_if_supported_alter() returned HA_ALTER_SUPPORTED_WAIT_LOCK
3835
we need to wrap the next call with a DDL lock.
3837
if ((error= table->file->alter_table_phase2(thd,
3847
The final .frm file is already created as a temporary file
3848
and will be renamed to the original table name.
3850
pthread_mutex_lock(&LOCK_open);
3851
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
3852
alter_table_manage_keys(table, table->file->indexes_are_disabled(),
3854
close_data_files_and_morph_locks(thd,
3855
table->pos_in_table_list->db,
3856
table->pos_in_table_list->table_name);
3857
if (mysql_rename_table(NULL,
3858
altered_table->s->db.str,
3859
altered_table->s->table_name.str,
3861
table->s->table_name.str, FN_FROM_IS_TMP))
3864
pthread_mutex_unlock(&LOCK_open);
3867
broadcast_refresh();
3868
pthread_mutex_unlock(&LOCK_open);
3871
The ALTER Table is always in its own transaction.
3872
Commit must not be called while LOCK_open is locked. It could call
3873
wait_if_global_read_lock(), which could create a deadlock if called
3876
error= ha_autocommit_or_rollback(thd, 0);
3884
pthread_mutex_lock(&LOCK_open);
3885
if (reopen_table(table))
3890
pthread_mutex_unlock(&LOCK_open);
3894
Tell the handler that the changed frm is on disk and table
3897
if ((error= t_table->file->alter_table_phase3(thd, t_table)))
3903
We are going to reopen table down on the road, so we have to restore
3904
state of the Table object which we used for obtaining of handler
3905
object to make it suitable for reopening.
3907
assert(t_table == table);
3908
table->open_placeholder= 1;
3909
pthread_mutex_lock(&LOCK_open);
3910
close_handle_and_leave_table_as_lock(table);
3911
pthread_mutex_unlock(&LOCK_open);
3922
Prepare column and key definitions for CREATE TABLE in ALTER Table.
3924
This function transforms parse output of ALTER Table - lists of
3925
columns and keys to add, drop or modify into, essentially,
3926
CREATE TABLE definition - a list of columns and keys of the new
3927
table. While doing so, it also performs some (bug not all)
3930
This function is invoked when we know that we're going to
3931
perform ALTER Table via a temporary table -- i.e. fast ALTER Table
3932
is not possible, perhaps because the ALTER statement contains
3933
instructions that require change in table data, not only in
3934
table definition or indexes.
3936
@param[in,out] thd thread handle. Used as a memory pool
3937
and source of environment information.
3938
@param[in] table the source table, open and locked
3939
Used as an interface to the storage engine
3940
to acquire additional information about
3942
@param[in,out] create_info A blob with CREATE/ALTER Table
3944
@param[in,out] alter_info Another blob with ALTER/CREATE parameters.
3945
Originally create_info was used only in
3946
CREATE TABLE and alter_info only in ALTER Table.
3947
But since ALTER might end-up doing CREATE,
3948
this distinction is gone and we just carry
3949
around two structures.
3952
Fills various create_info members based on information retrieved
3953
from the storage engine.
3954
Sets create_info->varchar if the table has a VARCHAR column.
3955
Prepares alter_info->create_list and alter_info->key_list with
3956
columns and keys of the new table.
3957
@retval true error, out of memory or a semantical error in ALTER
3959
@retval false success
3963
mysql_prepare_alter_table(THD *thd, Table *table,
3964
HA_CREATE_INFO *create_info,
3965
Alter_info *alter_info)
3967
/* New column definitions are added here */
3968
List<Create_field> new_create_list;
3969
/* New key definitions are added here */
3970
List<Key> new_key_list;
3971
List_iterator<Alter_drop> drop_it(alter_info->drop_list);
3972
List_iterator<Create_field> def_it(alter_info->create_list);
3973
List_iterator<Alter_column> alter_it(alter_info->alter_list);
3974
List_iterator<Key> key_it(alter_info->key_list);
3975
List_iterator<Create_field> find_it(new_create_list);
3976
List_iterator<Create_field> field_it(new_create_list);
3977
List<Key_part_spec> key_parts;
3978
uint32_t db_create_options= (table->s->db_create_options
3979
& ~(HA_OPTION_PACK_RECORD));
3980
uint32_t used_fields= create_info->used_fields;
3981
KEY *key_info=table->key_info;
3985
create_info->varchar= false;
3986
/* Let new create options override the old ones */
3987
if (!(used_fields & HA_CREATE_USED_MIN_ROWS))
3988
create_info->min_rows= table->s->min_rows;
3989
if (!(used_fields & HA_CREATE_USED_MAX_ROWS))
3990
create_info->max_rows= table->s->max_rows;
3991
if (!(used_fields & HA_CREATE_USED_AVG_ROW_LENGTH))
3992
create_info->avg_row_length= table->s->avg_row_length;
3993
if (!(used_fields & HA_CREATE_USED_BLOCK_SIZE))
3994
create_info->block_size= table->s->block_size;
3995
if (!(used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
3996
create_info->default_table_charset= table->s->table_charset;
3997
if (!(used_fields & HA_CREATE_USED_AUTO) && table->found_next_number_field)
3999
/* Table has an autoincrement, copy value to new table */
4000
table->file->info(HA_STATUS_AUTO);
4001
create_info->auto_increment_value= table->file->stats.auto_increment_value;
4003
if (!(used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE))
4004
create_info->key_block_size= table->s->key_block_size;
4006
restore_record(table, s->default_values); // Empty record for DEFAULT
4010
First collect all fields from table which isn't in drop_list
4012
Field **f_ptr,*field;
4013
for (f_ptr=table->field ; (field= *f_ptr) ; f_ptr++)
4015
/* Check if field should be dropped */
4018
while ((drop=drop_it++))
4020
if (drop->type == Alter_drop::COLUMN &&
4021
!my_strcasecmp(system_charset_info,field->field_name, drop->name))
4023
/* Reset auto_increment value if it was dropped */
4024
if (MTYP_TYPENR(field->unireg_check) == Field::NEXT_NUMBER &&
4025
!(used_fields & HA_CREATE_USED_AUTO))
4027
create_info->auto_increment_value=0;
4028
create_info->used_fields|=HA_CREATE_USED_AUTO;
4038
/* Check if field is changed */
4040
while ((def=def_it++))
4043
!my_strcasecmp(system_charset_info,field->field_name, def->change))
4047
{ // Field is changed
4051
new_create_list.push_back(def);
4058
This field was not dropped and not changed, add it to the list
4061
def= new Create_field(field, field);
4062
new_create_list.push_back(def);
4063
alter_it.rewind(); // Change default if ALTER
4064
Alter_column *alter;
4065
while ((alter=alter_it++))
4067
if (!my_strcasecmp(system_charset_info,field->field_name, alter->name))
4072
if (def->sql_type == DRIZZLE_TYPE_BLOB)
4074
my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), def->change);
4077
if ((def->def=alter->def)) // Use new default
4078
def->flags&= ~NO_DEFAULT_VALUE_FLAG;
4080
def->flags|= NO_DEFAULT_VALUE_FLAG;
4086
while ((def=def_it++)) // Add new columns
4088
if (def->change && ! def->field)
4090
my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table->s->table_name.str);
4094
Check that the DATE/DATETIME not null field we are going to add is
4095
either has a default value or the '0000-00-00' is allowed by the
4097
If the '0000-00-00' value isn't allowed then raise the error_if_not_empty
4098
flag to allow ALTER Table only if the table to be altered is empty.
4100
if ((def->sql_type == DRIZZLE_TYPE_NEWDATE ||
4101
def->sql_type == DRIZZLE_TYPE_DATETIME) &&
4102
!alter_info->datetime_field &&
4103
!(~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) &&
4104
thd->variables.sql_mode & MODE_NO_ZERO_DATE)
4106
alter_info->datetime_field= def;
4107
alter_info->error_if_not_empty= true;
4110
new_create_list.push_back(def);
4111
else if (def->after == first_keyword)
4112
new_create_list.push_front(def);
4117
while ((find=find_it++)) // Add new columns
4119
if (!my_strcasecmp(system_charset_info,def->after, find->field_name))
4124
my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table->s->table_name.str);
4127
find_it.after(def); // Put element after this
4129
XXX: hack for Bug#28427.
4130
If column order has changed, force OFFLINE ALTER Table
4131
without querying engine capabilities. If we ever have an
4132
engine that supports online ALTER Table CHANGE COLUMN
4133
<name> AFTER <name1> (Falcon?), this fix will effectively
4134
disable the capability.
4135
TODO: detect the situation in compare_tables, behave based
4136
on engine capabilities.
4138
if (alter_info->build_method == HA_BUILD_ONLINE)
4140
my_error(ER_NOT_SUPPORTED_YET, MYF(0), thd->query);
4143
alter_info->build_method= HA_BUILD_OFFLINE;
4146
if (alter_info->alter_list.elements)
4148
my_error(ER_BAD_FIELD_ERROR, MYF(0),
4149
alter_info->alter_list.head()->name, table->s->table_name.str);
4152
if (!new_create_list.elements)
4154
my_message(ER_CANT_REMOVE_ALL_FIELDS, ER(ER_CANT_REMOVE_ALL_FIELDS),
4160
Collect all keys which isn't in drop list. Add only those
4161
for which some fields exists.
4164
for (uint32_t i=0 ; i < table->s->keys ; i++,key_info++)
4166
char *key_name= key_info->name;
4169
while ((drop=drop_it++))
4171
if (drop->type == Alter_drop::KEY &&
4172
!my_strcasecmp(system_charset_info,key_name, drop->name))
4181
KEY_PART_INFO *key_part= key_info->key_part;
4183
for (uint32_t j=0 ; j < key_info->key_parts ; j++,key_part++)
4185
if (!key_part->field)
4186
continue; // Wrong field (from UNIREG)
4187
const char *key_part_name=key_part->field->field_name;
4188
Create_field *cfield;
4190
while ((cfield=field_it++))
4194
if (!my_strcasecmp(system_charset_info, key_part_name,
4198
else if (!my_strcasecmp(system_charset_info,
4199
key_part_name, cfield->field_name))
4203
continue; // Field is removed
4204
uint32_t key_part_length=key_part->length;
4205
if (cfield->field) // Not new field
4208
If the field can't have only a part used in a key according to its
4209
new type, or should not be used partially according to its
4210
previous type, or the field length is less than the key part
4211
length, unset the key part length.
4213
We also unset the key part length if it is the same as the
4214
old field's length, so the whole new field will be used.
4216
BLOBs may have cfield->length == 0, which is why we test it before
4217
checking whether cfield->length < key_part_length (in chars).
4219
if (!Field::type_can_have_key_part(cfield->field->type()) ||
4220
!Field::type_can_have_key_part(cfield->sql_type) ||
4221
(cfield->field->field_length == key_part_length &&
4222
!f_is_blob(key_part->key_type)) ||
4223
(cfield->length && (cfield->length < key_part_length /
4224
key_part->field->charset()->mbmaxlen)))
4225
key_part_length= 0; // Use whole field
4227
key_part_length /= key_part->field->charset()->mbmaxlen;
4228
key_parts.push_back(new Key_part_spec(cfield->field_name,
4229
strlen(cfield->field_name),
4232
if (key_parts.elements)
4234
KEY_CREATE_INFO key_create_info;
4236
enum Key::Keytype key_type;
4237
memset(&key_create_info, 0, sizeof(key_create_info));
4239
key_create_info.algorithm= key_info->algorithm;
4240
if (key_info->flags & HA_USES_BLOCK_SIZE)
4241
key_create_info.block_size= key_info->block_size;
4242
if (key_info->flags & HA_USES_COMMENT)
4243
key_create_info.comment= key_info->comment;
4245
if (key_info->flags & HA_NOSAME)
4247
if (! my_strcasecmp(system_charset_info, key_name, primary_key_name))
4248
key_type= Key::PRIMARY;
4250
key_type= Key::UNIQUE;
4253
key_type= Key::MULTIPLE;
4255
key= new Key(key_type, key_name, strlen(key_name),
4257
test(key_info->flags & HA_GENERATED_KEY),
4259
new_key_list.push_back(key);
4264
while ((key=key_it++)) // Add new keys
4266
if (key->type != Key::FOREIGN_KEY)
4267
new_key_list.push_back(key);
4268
if (key->name.str &&
4269
!my_strcasecmp(system_charset_info, key->name.str, primary_key_name))
4271
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name.str);
4277
if (alter_info->drop_list.elements)
4279
my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
4280
alter_info->drop_list.head()->name);
4283
if (alter_info->alter_list.elements)
4285
my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
4286
alter_info->alter_list.head()->name);
4290
if (!create_info->comment.str)
4292
create_info->comment.str= table->s->comment.str;
4293
create_info->comment.length= table->s->comment.length;
4296
table->file->update_create_info(create_info);
4297
if ((create_info->table_options &
4298
(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS)) ||
4299
(used_fields & HA_CREATE_USED_PACK_KEYS))
4300
db_create_options&= ~(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS);
4301
if (create_info->table_options &
4302
(HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM))
4303
db_create_options&= ~(HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM);
4304
if (create_info->table_options &
4305
(HA_OPTION_DELAY_KEY_WRITE | HA_OPTION_NO_DELAY_KEY_WRITE))
4306
db_create_options&= ~(HA_OPTION_DELAY_KEY_WRITE |
4307
HA_OPTION_NO_DELAY_KEY_WRITE);
4308
create_info->table_options|= db_create_options;
4310
if (table->s->tmp_table)
4311
create_info->options|=HA_LEX_CREATE_TMP_TABLE;
4314
alter_info->create_list.swap(new_create_list);
4315
alter_info->key_list.swap(new_key_list);
4327
new_db If there is a RENAME clause
4328
new_name If there is a RENAME clause
4329
create_info Information from the parsing phase about new
4331
table_list The table to change.
4332
alter_info Lists of fields, keys to be changed, added
4334
order_num How many order_st BY fields has been specified.
4335
order List of fields to order_st BY.
4336
ignore Whether we have ALTER IGNORE Table
4339
This is a veery long function and is everything but the kitchen sink :)
4340
It is used to alter a table and not only by ALTER Table but also
4341
CREATE|DROP INDEX are mapped on this function.
4343
When the ALTER Table statement just does a RENAME or ENABLE|DISABLE KEYS,
4344
or both, then this function short cuts its operation by renaming
4345
the table and/or enabling/disabling the keys. In this case, the FRM is
4346
not changed, directly by mysql_alter_table. However, if there is a
4347
RENAME + change of a field, or an index, the short cut is not used.
4348
See how `create_list` is used to generate the new FRM regarding the
4349
structure of the fields. The same is done for the indices of the table.
4351
Important is the fact, that this function tries to do as little work as
4352
possible, by finding out whether a intermediate table is needed to copy
4353
data into and when finishing the altering to use it as the original table.
4354
For this reason the function compare_tables() is called, which decides
4355
based on all kind of data how similar are the new and the original
4363
bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
4364
HA_CREATE_INFO *create_info,
4365
TableList *table_list,
4366
Alter_info *alter_info,
4367
uint32_t order_num, order_st *order, bool ignore)
4369
Table *table, *new_table=0, *name_lock= 0;;
4371
char tmp_name[80],old_name[32],new_name_buff[FN_REFLEN];
4372
char new_alias_buff[FN_REFLEN], *table_name, *db, *new_alias, *alias;
4373
char path[FN_REFLEN];
4374
ha_rows copied= 0,deleted= 0;
4375
handlerton *old_db_type, *new_db_type, *save_old_db_type;
4376
legacy_db_type table_type;
4378
if (table_list && table_list->schema_table)
4380
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.str);
4385
Assign variables table_name, new_name, db, new_db, path
4386
to simplify further comparisons: we want to see if it's a RENAME
4387
later just by comparing the pointers, avoiding the need for strcmp.
4389
thd->set_proc_info("init");
4390
table_name=table_list->table_name;
4391
alias= (lower_case_table_names == 2) ? table_list->alias : table_name;
4393
if (!new_db || !my_strcasecmp(table_alias_charset, new_db, db))
4395
build_table_filename(path, sizeof(path), db, table_name, "", 0);
4397
mysql_ha_rm_tables(thd, table_list, false);
4399
/* DISCARD/IMPORT TABLESPACE is always alone in an ALTER Table */
4400
if (alter_info->tablespace_op != NO_TABLESPACE_OP)
4401
/* Conditionally writes to binlog. */
4402
return(mysql_discard_or_import_tablespace(thd,table_list,
4403
alter_info->tablespace_op));
4404
strxnmov(new_name_buff, sizeof (new_name_buff) - 1, mysql_data_home, "/", db,
4405
"/", table_name, reg_ext, NULL);
4406
(void) unpack_filename(new_name_buff, new_name_buff);
4408
If this is just a rename of a view, short cut to the
4409
following scenario: 1) lock LOCK_open 2) do a RENAME
4410
2) unlock LOCK_open.
4411
This is a copy-paste added to make sure
4412
ALTER (sic:) Table .. RENAME works for views. ALTER VIEW is handled
4413
as an independent branch in mysql_execute_command. The need
4414
for a copy-paste arose because the main code flow of ALTER Table
4415
... RENAME tries to use open_ltable, which does not work for views
4416
(open_ltable was never modified to merge table lists of child tables
4417
into the main table list, like open_tables does).
4418
This code is wrong and will be removed, please do not copy.
4420
(void)mysql_frm_type(thd, new_name_buff, &table_type);
4422
if (!(table= open_n_lock_single_table(thd, table_list, TL_WRITE_ALLOW_READ)))
4424
table->use_all_columns();
4426
/* Check that we are not trying to rename to an existing table */
4429
my_stpcpy(new_name_buff,new_name);
4430
my_stpcpy(new_alias= new_alias_buff, new_name);
4431
if (lower_case_table_names)
4433
if (lower_case_table_names != 2)
4435
my_casedn_str(files_charset_info, new_name_buff);
4436
new_alias= new_name; // Create lower case table name
4438
my_casedn_str(files_charset_info, new_name);
4441
!my_strcasecmp(table_alias_charset, new_name_buff, table_name))
4444
Source and destination table names are equal: make later check
4447
new_alias= new_name= table_name;
4451
if (table->s->tmp_table != NO_TMP_TABLE)
4453
if (find_temporary_table(thd,new_db,new_name_buff))
4455
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name_buff);
4461
if (lock_table_name_if_not_cached(thd, new_db, new_name, &name_lock))
4465
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
4469
build_table_filename(new_name_buff, sizeof(new_name_buff),
4470
new_db, new_name_buff, reg_ext, 0);
4471
if (!access(new_name_buff, F_OK))
4473
/* Table will be closed in do_command() */
4474
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
4482
new_alias= (lower_case_table_names == 2) ? alias : table_name;
4483
new_name= table_name;
4486
old_db_type= table->s->db_type();
4487
if (!create_info->db_type)
4489
create_info->db_type= old_db_type;
4492
if (check_engine(thd, new_name, create_info))
4494
new_db_type= create_info->db_type;
4496
if (new_db_type != old_db_type &&
4497
!table->file->can_switch_engines())
4500
my_error(ER_ROW_IS_REFERENCED, MYF(0));
4504
if (create_info->row_type == ROW_TYPE_NOT_USED)
4505
create_info->row_type= table->s->row_type;
4507
if (ha_check_storage_engine_flag(old_db_type, HTON_ALTER_NOT_SUPPORTED) ||
4508
ha_check_storage_engine_flag(new_db_type, HTON_ALTER_NOT_SUPPORTED))
4510
my_error(ER_ILLEGAL_HA, MYF(0), table_name);
4514
thd->set_proc_info("setup");
4515
if (!(alter_info->flags & ~(ALTER_RENAME | ALTER_KEYS_ONOFF)) &&
4516
!table->s->tmp_table) // no need to touch frm
4518
switch (alter_info->keys_onoff) {
4523
wait_while_table_is_used() ensures that table being altered is
4524
opened only by this thread and that Table::TABLE_SHARE::version
4525
of Table object corresponding to this table is 0.
4526
The latter guarantees that no DML statement will open this table
4527
until ALTER Table finishes (i.e. until close_thread_tables())
4528
while the fact that the table is still open gives us protection
4529
from concurrent DDL statements.
4531
pthread_mutex_lock(&LOCK_open);
4532
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
4533
pthread_mutex_unlock(&LOCK_open);
4534
error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
4535
/* COND_refresh will be signaled in close_thread_tables() */
4538
pthread_mutex_lock(&LOCK_open);
4539
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
4540
pthread_mutex_unlock(&LOCK_open);
4541
error=table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
4542
/* COND_refresh will be signaled in close_thread_tables() */
4549
if (error == HA_ERR_WRONG_COMMAND)
4552
push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
4553
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
4557
pthread_mutex_lock(&LOCK_open);
4559
Unlike to the above case close_cached_table() below will remove ALL
4560
instances of Table from table cache (it will also remove table lock
4561
held by this thread). So to make actual table renaming and writing
4562
to binlog atomic we have to put them into the same critical section
4563
protected by LOCK_open mutex. This also removes gap for races between
4564
access() and mysql_rename_table() calls.
4567
if (!error && (new_name != table_name || new_db != db))
4569
thd->set_proc_info("rename");
4571
Then do a 'simple' rename of the table. First we need to close all
4572
instances of 'source' table.
4574
close_cached_table(thd, table);
4576
Then, we want check once again that target table does not exist.
4577
Actually the order of these two steps does not matter since
4578
earlier we took name-lock on the target table, so we do them
4579
in this particular order only to be consistent with 5.0, in which
4580
we don't take this name-lock and where this order really matters.
4581
TODO: Investigate if we need this access() check at all.
4583
if (!access(new_name_buff,F_OK))
4585
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name);
4590
*fn_ext(new_name)=0;
4591
if (mysql_rename_table(old_db_type,db,table_name,new_db,new_alias, 0))
4595
mysql_rename_table(old_db_type, new_db, new_alias, db,
4602
if (error == HA_ERR_WRONG_COMMAND)
4605
push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
4606
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
4612
write_bin_log(thd, true, thd->query, thd->query_length);
4617
table->file->print_error(error, MYF(0));
2193
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* unlink open tables for create table like*/
2194
session->unlink_open_table(name_lock);
2200
if (is_if_not_exists)
4621
unlink_open_table(thd, name_lock, false);
4622
pthread_mutex_unlock(&LOCK_open);
4623
table_list->table= NULL; // For query cache
4627
/* We have to do full alter table. */
4630
If the old table had partitions and we are doing ALTER Table ...
4631
engine= <new_engine>, the new table must preserve the original
4632
partitioning. That means that the new engine is still the
4633
partitioning engine, not the engine specified in the parser.
4634
This is discovered in prep_alter_part_table, which in such case
4635
updates create_info->db_type.
4636
Now we need to update the stack copy of create_info->db_type,
4637
as otherwise we won't be able to correctly move the files of the
4638
temporary table to the result table files.
4640
new_db_type= create_info->db_type;
4642
if (mysql_prepare_alter_table(thd, table, create_info, alter_info))
4645
set_table_default_charset(thd, create_info, db);
4648
if (thd->variables.old_alter_table
4649
|| (table->s->db_type() != create_info->db_type)
4652
if (alter_info->build_method == HA_BUILD_ONLINE)
4654
my_error(ER_NOT_SUPPORTED_YET, MYF(0), thd->query);
4657
alter_info->build_method= HA_BUILD_OFFLINE;
4660
if (alter_info->build_method != HA_BUILD_OFFLINE)
4662
Table *altered_table= 0;
4663
HA_ALTER_INFO ha_alter_info;
4664
HA_ALTER_FLAGS ha_alter_flags;
4665
uint32_t table_changes= IS_EQUAL_YES;
4666
bool need_copy_table= true;
4667
/* Check how much the tables differ. */
4668
if (compare_tables(thd, table, alter_info,
4669
create_info, order_num,
4678
Check if storage engine supports altering the table
4684
If table is not renamed, changed database and
4685
some change was detected then check if engine
4686
can do the change on-line
4688
if (new_name == table_name && new_db == db &&
4689
ha_alter_flags.is_set())
4691
Alter_info tmp_alter_info(*alter_info, thd->mem_root);
4695
check if table can be altered on-line
4697
if (!(altered_table= create_altered_table(thd,
4702
!strcmp(db, new_db))))
4705
switch (table->file->check_if_supported_alter(altered_table,
4709
case HA_ALTER_SUPPORTED_WAIT_LOCK:
4710
case HA_ALTER_SUPPORTED_NO_LOCK:
4712
@todo: Currently we always acquire an exclusive name
4713
lock on the table metadata when performing fast or online
4714
ALTER Table. In future we may consider this unnecessary,
4715
and narrow the scope of the exclusive name lock to only
4716
cover manipulation with .frms. Storage engine API
4717
call check_if_supported_alter has provision for this
4720
need_copy_table= false;
4722
case HA_ALTER_NOT_SUPPORTED:
4723
if (alter_info->build_method == HA_BUILD_ONLINE)
4725
my_error(ER_NOT_SUPPORTED_YET, MYF(0), thd->query);
4726
close_temporary_table(thd, altered_table, 1, 1);
4729
need_copy_table= true;
4731
case HA_ALTER_ERROR:
4733
close_temporary_table(thd, altered_table, 1, 1);
4738
/* TODO need to check if changes can be handled as fast ALTER Table */
4740
need_copy_table= true;
4742
if (!need_copy_table)
4744
error= mysql_fast_or_online_alter_table(thd,
4750
alter_info->keys_onoff);
4753
mysql_unlock_tables(thd, thd->lock);
4756
close_temporary_table(thd, altered_table, 1, 1);
4762
goto err_with_placeholders;
4769
pthread_mutex_lock(&LOCK_open);
4775
close_temporary_table(thd, altered_table, 1, 1);
4778
snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%lx", tmp_file_prefix,
4779
current_pid, thd->thread_id);
4780
/* Safety fix for innodb */
4781
if (lower_case_table_names)
4782
my_casedn_str(files_charset_info, tmp_name);
4785
/* Create a temporary table with the new format */
4786
if ((error= create_temporary_table(thd, table, new_db, tmp_name,
4787
create_info, alter_info,
4788
!strcmp(db, new_db))))
4793
/* Open the table so we need to copy the data to it. */
4794
if (table->s->tmp_table)
4797
memset(&tbl, 0, sizeof(tbl));
4799
tbl.table_name= tbl.alias= tmp_name;
4800
/* Table is in thd->temporary_tables */
4801
new_table= open_table(thd, &tbl, (bool*) 0, DRIZZLE_LOCK_IGNORE_FLUSH);
4805
char path[FN_REFLEN];
4806
/* table is a normal table: Create temporary table in same directory */
4807
build_table_filename(path, sizeof(path), new_db, tmp_name, "",
4809
/* Open our intermediate table */
4810
new_table=open_temporary_table(thd, path, new_db, tmp_name, 0, OTM_OPEN);
4815
/* Copy the data if necessary. */
4816
thd->count_cuted_fields= CHECK_FIELD_WARN; // calc cuted fields
4817
thd->cuted_fields=0L;
4818
thd->set_proc_info("copy to tmp table");
4821
We do not copy data for MERGE tables. Only the children have data.
4822
MERGE tables have HA_NO_COPY_ON_ALTER set.
4824
if (new_table && !(new_table->file->ha_table_flags() & HA_NO_COPY_ON_ALTER))
4826
/* We don't want update TIMESTAMP fields during ALTER Table. */
4827
new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
4828
new_table->next_number_field=new_table->found_next_number_field;
4829
error= copy_data_between_tables(table, new_table,
4830
alter_info->create_list, ignore,
4831
order_num, order, &copied, &deleted,
4832
alter_info->keys_onoff,
4833
alter_info->error_if_not_empty);
4837
pthread_mutex_lock(&LOCK_open);
4838
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
4839
pthread_mutex_unlock(&LOCK_open);
4840
alter_table_manage_keys(table, table->file->indexes_are_disabled(),
4841
alter_info->keys_onoff);
4842
error= ha_autocommit_or_rollback(thd, 0);
4843
if (end_active_trans(thd))
4846
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
4848
if (table->s->tmp_table != NO_TMP_TABLE)
4850
/* We changed a temporary table */
4853
/* Close lock if this is a transactional table */
4856
mysql_unlock_tables(thd, thd->lock);
4859
/* Remove link to old table and rename the new one */
4860
close_temporary_table(thd, table, 1, 1);
4861
/* Should pass the 'new_name' as we store table name in the cache */
4862
if (rename_temporary_table(thd, new_table, new_db, new_name))
4864
/* We don't replicate alter table statement on temporary tables */
4865
if (!thd->current_stmt_binlog_row_based)
4866
write_bin_log(thd, true, thd->query, thd->query_length);
4873
Close the intermediate table that will be the new table.
4874
Note that MERGE tables do not have their children attached here.
4876
intern_close_table(new_table);
4879
pthread_mutex_lock(&LOCK_open);
4882
quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP);
4883
pthread_mutex_unlock(&LOCK_open);
4888
Data is copied. Now we:
4889
1) Wait until all other threads close old version of table.
4890
2) Close instances of table open by this thread and replace them
4891
with exclusive name-locks.
4892
3) Rename the old table to a temp name, rename the new one to the
4894
4) If we are under LOCK TABLES and don't do ALTER Table ... RENAME
4895
we reopen new version of table.
4896
5) Write statement to the binary log.
4897
6) If we are under LOCK TABLES and do ALTER Table ... RENAME we
4898
remove name-locks from list of open tables and table cache.
4899
7) If we are not not under LOCK TABLES we rely on close_thread_tables()
4900
call to remove name-locks from table cache and list of open table.
4903
thd->set_proc_info("rename result table");
4904
snprintf(old_name, sizeof(old_name), "%s2-%lx-%lx", tmp_file_prefix,
4905
current_pid, thd->thread_id);
4906
if (lower_case_table_names)
4907
my_casedn_str(files_charset_info, old_name);
4909
wait_while_table_is_used(thd, table, HA_EXTRA_PREPARE_FOR_RENAME);
4910
close_data_files_and_morph_locks(thd, db, table_name);
4913
save_old_db_type= old_db_type;
4916
This leads to the storage engine (SE) not being notified for renames in
4917
mysql_rename_table(), because we just juggle with the FRM and nothing
4918
more. If we have an intermediate table, then we notify the SE that
4919
it should become the actual table. Later, we will recycle the old table.
4920
However, in case of ALTER Table RENAME there might be no intermediate
4921
table. This is when the old and new tables are compatible, according to
4922
compare_table(). Then, we need one additional call to
4923
mysql_rename_table() with flag NO_FRM_RENAME, which does nothing else but
4924
actual rename in the SE and the FRM is not touched. Note that, if the
4925
table is renamed and the SE is also changed, then an intermediate table
4926
is created and the additional call will not take place.
4928
if (mysql_rename_table(old_db_type, db, table_name, db, old_name,
4932
quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP);
4934
else if (mysql_rename_table(new_db_type, new_db, tmp_name, new_db,
4935
new_alias, FN_FROM_IS_TMP) || ((new_name != table_name || new_db != db) && 0))
4937
/* Try to get everything back. */
4939
quick_rm_table(new_db_type,new_db,new_alias, 0);
4940
quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP);
4941
mysql_rename_table(old_db_type, db, old_name, db, alias,
4947
/* This shouldn't happen. But let us play it safe. */
4948
goto err_with_placeholders;
4951
quick_rm_table(old_db_type, db, old_name, FN_IS_TMP);
4954
if (thd->locked_tables && new_name == table_name && new_db == db)
4956
thd->in_lock_tables= 1;
4957
error= reopen_tables(thd, 1, 1);
4958
thd->in_lock_tables= 0;
4960
goto err_with_placeholders;
4962
pthread_mutex_unlock(&LOCK_open);
4964
thd->set_proc_info("end");
4966
assert(!(mysql_bin_log.is_open() &&
4967
thd->current_stmt_binlog_row_based &&
4968
(create_info->options & HA_LEX_CREATE_TMP_TABLE)));
4969
write_bin_log(thd, true, thd->query, thd->query_length);
4971
if (ha_check_storage_engine_flag(old_db_type, HTON_FLUSH_AFTER_RENAME))
4974
For the alter table to be properly flushed to the logs, we
4975
have to open the new table. If not, we get a problem on server
4976
shutdown. But we do not need to attach MERGE children.
4978
char path[FN_REFLEN];
4980
build_table_filename(path, sizeof(path), new_db, table_name, "", 0);
4981
t_table= open_temporary_table(thd, path, new_db, tmp_name, false, OTM_OPEN);
4984
intern_close_table(t_table);
4988
sql_print_warning(_("Could not open table %s.%s after rename\n"),
4990
ha_flush_logs(old_db_type);
4992
table_list->table=0; // For query cache
4994
if (thd->locked_tables && (new_name != table_name || new_db != db))
4997
If are we under LOCK TABLES and did ALTER Table with RENAME we need
4998
to remove placeholders for the old table and for the target table
4999
from the list of open tables and table cache. If we are not under
5000
LOCK TABLES we can rely on close_thread_tables() doing this job.
5002
pthread_mutex_lock(&LOCK_open);
5003
unlink_open_table(thd, table, false);
5004
unlink_open_table(thd, name_lock, false);
5005
pthread_mutex_unlock(&LOCK_open);
5009
snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
5010
(ulong) (copied + deleted), (ulong) deleted,
5011
(ulong) thd->cuted_fields);
5012
my_ok(thd, copied + deleted, 0L, tmp_name);
5013
thd->some_tables_deleted=0;
5019
/* close_temporary_table() frees the new_table pointer. */
5020
close_temporary_table(thd, new_table, 1, 1);
5023
quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP);
5027
No default value was provided for a DATE/DATETIME field, the
5028
current sql_mode doesn't allow the '0000-00-00' value and
5029
the table to be altered isn't empty.
5032
if (alter_info->error_if_not_empty && thd->row_count)
5034
const char *f_val= 0;
5035
enum enum_drizzle_timestamp_type t_type= DRIZZLE_TIMESTAMP_DATE;
5036
switch (alter_info->datetime_field->sql_type)
5038
case DRIZZLE_TYPE_NEWDATE:
5039
f_val= "0000-00-00";
5040
t_type= DRIZZLE_TIMESTAMP_DATE;
5042
case DRIZZLE_TYPE_DATETIME:
5043
f_val= "0000-00-00 00:00:00";
5044
t_type= DRIZZLE_TIMESTAMP_DATETIME;
5047
/* Shouldn't get here. */
5050
bool save_abort_on_warning= thd->abort_on_warning;
5051
thd->abort_on_warning= true;
5052
make_truncated_value_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5053
f_val, strlength(f_val), t_type,
5054
alter_info->datetime_field->field_name);
5055
thd->abort_on_warning= save_abort_on_warning;
5059
pthread_mutex_lock(&LOCK_open);
5060
unlink_open_table(thd, name_lock, false);
5061
pthread_mutex_unlock(&LOCK_open);
5065
err_with_placeholders:
5067
An error happened while we were holding exclusive name-lock on table
5068
being altered. To be safe under LOCK TABLES we should remove placeholders
5069
from list of open tables list and table cache.
5071
unlink_open_table(thd, table, false);
5073
unlink_open_table(thd, name_lock, false);
5074
pthread_mutex_unlock(&LOCK_open);
5077
/* mysql_alter_table */
5080
copy_data_between_tables(Table *from,Table *to,
5081
List<Create_field> &create,
5083
uint32_t order_num, order_st *order,
5086
enum enum_enable_or_disable keys_onoff,
5087
bool error_if_not_empty)
5090
Copy_field *copy,*copy_end;
5091
ulong found_count,delete_count;
5092
THD *thd= current_thd;
5094
SORT_FIELD *sortorder;
5098
List<Item> all_fields;
5099
ha_rows examined_rows;
5100
bool auto_increment_field_copied= 0;
5101
ulong save_sql_mode;
5102
uint64_t prev_insert_id;
5105
Turn off recovery logging since rollback of an alter table is to
5106
delete the new table so there is no need to log the changes to it.
5108
This needs to be done before external_lock
5110
error= ha_enable_transaction(thd, false);
5114
if (!(copy= new Copy_field[to->s->fields]))
5115
return(-1); /* purecov: inspected */
5117
if (to->file->ha_external_lock(thd, F_WRLCK))
5120
/* We need external lock before we can disable/enable keys */
5121
alter_table_manage_keys(to, from->file->indexes_are_disabled(), keys_onoff);
5123
/* We can abort alter table for any table type */
5124
thd->abort_on_warning= !ignore;
5126
from->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
5127
to->file->ha_start_bulk_insert(from->file->stats.records);
5129
save_sql_mode= thd->variables.sql_mode;
5131
List_iterator<Create_field> it(create);
5134
for (Field **ptr=to->field ; *ptr ; ptr++)
5139
if (*ptr == to->next_number_field)
5140
auto_increment_field_copied= true;
5142
(copy_end++)->set(*ptr,def->field,0);
5147
found_count=delete_count=0;
5151
if (to->s->primary_key != MAX_KEY && to->file->primary_key_is_clustered())
2202
5153
char warn_buff[DRIZZLE_ERRMSG_SIZE];
2203
snprintf(warn_buff, sizeof(warn_buff),
2204
ER(ER_TABLE_EXISTS_ERROR), destination_identifier.getTableName().c_str());
2205
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
2206
ER_TABLE_EXISTS_ERROR, warn_buff);
2210
my_error(ER_TABLE_EXISTS_ERROR, destination_identifier);
5154
snprintf(warn_buff, sizeof(warn_buff),
5155
_("order_st BY ignored because there is a user-defined clustered "
5156
"index in the table '%-.192s'"),
5157
from->s->table_name.str);
5158
push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
5163
from->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE),
5164
MYF(MY_FAE | MY_ZEROFILL));
5165
memset(&tables, 0, sizeof(tables));
5167
tables.alias= tables.table_name= from->s->table_name.str;
5168
tables.db= from->s->db.str;
5171
if (thd->lex->select_lex.setup_ref_array(thd, order_num) ||
5172
setup_order(thd, thd->lex->select_lex.ref_pointer_array,
5173
&tables, fields, all_fields, order) ||
5174
!(sortorder= make_unireg_sortorder(order, &length, NULL)) ||
5175
(from->sort.found_records= filesort(thd, from, sortorder, length,
5176
(SQL_SELECT *) 0, HA_POS_ERROR,
5177
1, &examined_rows)) ==
5183
/* Tell handler that we have values for all columns in the to table */
5184
to->use_all_columns();
5185
init_read_record(&info, thd, from, (SQL_SELECT *) 0, 1,1);
5187
to->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
5189
restore_record(to, s->default_values); // Create empty record
5190
while (!(error=info.read_record(&info)))
5194
thd->send_kill_message();
5199
/* Return error if source table isn't empty. */
5200
if (error_if_not_empty)
5205
if (to->next_number_field)
5207
if (auto_increment_field_copied)
5208
to->auto_increment_field_not_null= true;
5210
to->next_number_field->reset();
5213
for (Copy_field *copy_ptr=copy ; copy_ptr != copy_end ; copy_ptr++)
5215
copy_ptr->do_copy(copy_ptr);
5217
prev_insert_id= to->file->next_insert_id;
5218
error=to->file->ha_write_row(to->record[0]);
5219
to->auto_increment_field_not_null= false;
5223
to->file->is_fatal_error(error, HA_CHECK_DUP))
5225
if (!to->file->is_fatal_error(error, HA_CHECK_DUP))
5227
uint32_t key_nr= to->file->get_dup_key(error);
5228
if ((int) key_nr >= 0)
5230
const char *err_msg= ER(ER_DUP_ENTRY_WITH_KEY_NAME);
5232
(to->key_info[0].key_part[0].field->flags &
5233
AUTO_INCREMENT_FLAG))
5234
err_msg= ER(ER_DUP_ENTRY_AUTOINCREMENT_CASE);
5235
to->file->print_keydup_error(key_nr, err_msg);
5240
to->file->print_error(error,MYF(0));
5243
to->file->restore_auto_increment(prev_insert_id);
5249
end_read_record(&info);
5250
free_io_cache(from);
5251
delete [] copy; // This is never 0
5253
if (to->file->ha_end_bulk_insert() && error <= 0)
5255
to->file->print_error(my_errno,MYF(0));
5258
to->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
5260
if (ha_enable_transaction(thd, true))
5267
Ensure that the new table is saved properly to disk so that we
5270
if (ha_autocommit_or_rollback(thd, 0))
5272
if (end_active_trans(thd))
5276
thd->variables.sql_mode= save_sql_mode;
5277
thd->abort_on_warning= 0;
5278
free_io_cache(from);
5279
*copied= found_count;
5280
*deleted=delete_count;
5281
to->file->ha_release_auto_increment();
5282
if (to->file->ha_external_lock(thd,F_UNLCK))
5284
return(error > 0 ? -1 : 0);
5289
Recreates tables by calling mysql_alter_table().
5292
mysql_recreate_table()
5294
tables Tables to recreate
5297
Like mysql_alter_table().
5299
bool mysql_recreate_table(THD *thd, TableList *table_list)
5301
HA_CREATE_INFO create_info;
5302
Alter_info alter_info;
5304
assert(!table_list->next_global);
5306
table_list->table has been closed and freed. Do not reference
5307
uninitialized data. open_tables() could fail.
5309
table_list->table= NULL;
5311
memset(&create_info, 0, sizeof(create_info));
5312
create_info.row_type=ROW_TYPE_NOT_USED;
5313
create_info.default_table_charset=default_charset_info;
5314
/* Force alter table to recreate table */
5315
alter_info.flags= (ALTER_CHANGE_COLUMN | ALTER_RECREATE);
5316
return(mysql_alter_table(thd, NULL, NULL, &create_info,
5317
table_list, &alter_info, 0,
5318
(order_st *) 0, 0));
5322
bool mysql_checksum_table(THD *thd, TableList *tables,
5323
HA_CHECK_OPT *check_opt)
5326
List<Item> field_list;
5328
Protocol *protocol= thd->protocol;
5330
field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
5331
item->maybe_null= 1;
5332
field_list.push_back(item= new Item_int("Checksum", (int64_t) 1,
5333
MY_INT64_NUM_DECIMAL_DIGITS));
5334
item->maybe_null= 1;
5335
if (protocol->send_fields(&field_list,
5336
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
5339
/* Open one table after the other to keep lock time as short as possible. */
5340
for (table= tables; table; table= table->next_local)
5342
char table_name[NAME_LEN*2+2];
5345
strxmov(table_name, table->db ,".", table->table_name, NULL);
5347
t= table->table= open_n_lock_single_table(thd, table, TL_READ);
5348
thd->clear_error(); // these errors shouldn't get client
5350
protocol->prepare_for_resend();
5351
protocol->store(table_name, system_charset_info);
5355
/* Table didn't exist */
5356
protocol->store_null();
5361
if (t->file->ha_table_flags() & HA_HAS_CHECKSUM &&
5362
!(check_opt->flags & T_EXTEND))
5363
protocol->store((uint64_t)t->file->checksum());
5364
else if (!(t->file->ha_table_flags() & HA_HAS_CHECKSUM) &&
5365
(check_opt->flags & T_QUICK))
5366
protocol->store_null();
5369
/* calculating table's checksum */
5371
unsigned char null_mask=256 - (1 << t->s->last_null_bit_pos);
5373
t->use_all_columns();
5375
if (t->file->ha_rnd_init(1))
5376
protocol->store_null();
5381
ha_checksum row_crc= 0;
5382
int error= t->file->rnd_next(t->record[0]);
5383
if (unlikely(error))
5385
if (error == HA_ERR_RECORD_DELETED)
5389
if (t->s->null_bytes)
5391
/* fix undefined null bits */
5392
t->record[0][t->s->null_bytes-1] |= null_mask;
5393
if (!(t->s->db_create_options & HA_OPTION_PACK_RECORD))
5394
t->record[0][0] |= 1;
5396
row_crc= my_checksum(row_crc, t->record[0], t->s->null_bytes);
5399
for (uint32_t i= 0; i < t->s->fields; i++ )
5401
Field *f= t->field[i];
5402
if ((f->type() == DRIZZLE_TYPE_BLOB) ||
5403
(f->type() == DRIZZLE_TYPE_VARCHAR))
5407
row_crc= my_checksum(row_crc, (unsigned char*) tmp.ptr(), tmp.length());
5410
row_crc= my_checksum(row_crc, f->ptr,
5416
protocol->store((uint64_t)crc);
5417
t->file->ha_rnd_end();
5421
close_thread_tables(thd);
5422
table->table=0; // For query cache
5424
if (protocol->write())
5432
close_thread_tables(thd); // Shouldn't be needed
5438
static bool check_engine(THD *thd, const char *table_name,
5439
HA_CREATE_INFO *create_info)
5441
handlerton **new_engine= &create_info->db_type;
5442
handlerton *req_engine= *new_engine;
5443
bool no_substitution= 1;
5444
if (!(*new_engine= ha_checktype(thd, ha_legacy_type(req_engine),
5445
no_substitution, 1)))
2219
bool analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
2221
thr_lock_type lock_type = TL_READ_NO_INSERT;
2223
return(admin_table(session, tables, check_opt,
2224
"analyze", lock_type, true,
2225
&Cursor::ha_analyze));
2229
bool check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
2231
thr_lock_type lock_type = TL_READ_NO_INSERT;
2233
return(admin_table(session, tables, check_opt,
2236
&Cursor::ha_check));
2239
} /* namespace drizzled */
5448
if (req_engine && req_engine != *new_engine)
5450
push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
5451
ER_WARN_USING_OTHER_HANDLER,
5452
ER(ER_WARN_USING_OTHER_HANDLER),
5453
ha_resolve_storage_engine_name(*new_engine),
5456
if (create_info->options & HA_LEX_CREATE_TMP_TABLE &&
5457
ha_check_storage_engine_flag(*new_engine, HTON_TEMPORARY_NOT_SUPPORTED))
5459
if (create_info->used_fields & HA_CREATE_USED_ENGINE)
5461
my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
5462
ha_resolve_storage_engine_name(*new_engine), "TEMPORARY");
5466
*new_engine= myisam_hton;