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,
2912
bool mysql_create_like_table(THD* thd, TableList* table, TableList* src_table,
2913
HA_CREATE_INFO *create_info)
2915
Table *name_lock= 0;
2916
char src_path[FN_REFLEN], dst_path[FN_REFLEN];
2917
uint32_t dst_path_length;
2918
char *db= table->db;
2919
char *table_name= table->table_name;
2110
2921
bool res= true;
2111
bool table_exists= false;
2925
By opening source table we guarantee that it exists and no concurrent
2926
DDL operation will mess with it. Later we also take an exclusive
2927
name-lock on target table name, which makes copying of .frm file,
2928
call to ha_create_table() and binlogging atomic against concurrent DML
2929
and DDL operations on target table. Thus by holding both these "locks"
2930
we ensure that our statement is properly isolated from all concurrent
2931
operations which matter.
2933
if (open_tables(thd, &src_table, ¬_used, 0))
2936
strxmov(src_path, src_table->table->s->path.str, reg_ext, NULL);
2114
2939
Check that destination tables does not exist. Note that its name
2115
2940
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);
2942
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
2944
if (find_temporary_table(thd, db, table_name))
2946
dst_path_length= build_tmptable_filename(thd, dst_path, sizeof(dst_path));
2947
create_info->table_options|= HA_CREATE_DELAY_KEY_WRITE;
2951
if (lock_table_name_if_not_cached(thd, db, table_name, &name_lock))
2955
dst_path_length= build_table_filename(dst_path, sizeof(dst_path),
2956
db, table_name, reg_ext, 0);
2957
if (!access(dst_path, F_OK))
2962
Create a new table by copying from source table
2964
Altough exclusive name-lock on target table protects us from concurrent
2965
DML and DDL operations on it we still want to wrap .FRM creation and call
2966
to ha_create_table() in critical section protected by LOCK_open in order
2967
to provide minimal atomicity against operations which disregard name-locks,
2968
like I_S implementation, for example. This is a temporary and should not
2969
be copied. Instead we should fix our code to always honor name-locks.
2971
Also some engines (e.g. NDB cluster) require that LOCK_open should be held
2972
during the call to ha_create_table(). See bug #28614 for more info.
2974
pthread_mutex_lock(&LOCK_open);
2975
if (src_table->schema_table)
2977
if (mysql_create_like_schema_frm(thd, src_table, dst_path, create_info))
2979
pthread_mutex_unlock(&LOCK_open);
2983
else if (my_copy(src_path, dst_path, MYF(MY_DONT_OVERWRITE_FILE)))
2985
if (my_errno == ENOENT)
2986
my_error(ER_BAD_DB_ERROR,MYF(0),db);
2988
my_error(ER_CANT_CREATE_FILE,MYF(0),dst_path,my_errno);
2989
pthread_mutex_unlock(&LOCK_open);
2994
As mysql_truncate don't work on a new table at this stage of
2995
creation, instead create the table directly (for both normal
2996
and temporary tables).
2998
dst_path[dst_path_length - reg_ext_length]= '\0'; // Remove .frm
2999
if (thd->variables.keep_files_on_create)
3000
create_info->options|= HA_CREATE_KEEP_FILES;
3001
err= ha_create_table(thd, dst_path, db, table_name, create_info, 1);
3002
pthread_mutex_unlock(&LOCK_open);
3004
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
3006
if (err || !open_temporary_table(thd, dst_path, db, table_name, 1,
3009
(void) rm_temporary_table(create_info->db_type,
3010
dst_path, false); /* purecov: inspected */
3011
goto err; /* purecov: inspected */
3016
(void) quick_rm_table(create_info->db_type, db,
3017
table_name, 0); /* purecov: inspected */
3018
goto err; /* purecov: inspected */
3022
We have to write the query before we unlock the tables.
3024
if (thd->current_stmt_binlog_row_based)
3027
Since temporary tables are not replicated under row-based
3028
replication, CREATE TABLE ... LIKE ... needs special
3029
treatement. We have four cases to consider, according to the
3030
following decision table:
3032
==== ========= ========= ==============================
3033
Case Target Source Write to binary log
3034
==== ========= ========= ==============================
3035
1 normal normal Original statement
3036
2 normal temporary Generated statement
3037
3 temporary normal Nothing
3038
4 temporary temporary Nothing
3039
==== ========= ========= ==============================
3041
if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
3043
if (src_table->table->s->tmp_table) // Case 2
3046
String query(buf, sizeof(buf), system_charset_info);
3047
query.length(0); // Have to zero it since constructor doesn't
3051
Here we open the destination table, on which we already have
3052
name-lock. This is needed for store_create_info() to work.
3053
The table will be closed by unlink_open_table() at the end
3056
table->table= name_lock;
3057
pthread_mutex_lock(&LOCK_open);
3058
if (reopen_name_locked_table(thd, table, false))
3060
pthread_mutex_unlock(&LOCK_open);
3063
pthread_mutex_unlock(&LOCK_open);
3065
int result= store_create_info(thd, table, &query,
3068
assert(result == 0); // store_create_info() always return 0
3069
write_bin_log(thd, true, query.ptr(), query.length());
3072
write_bin_log(thd, true, thd->query, thd->query_length);
3075
Case 3 and 4 does nothing under RBR
3079
write_bin_log(thd, true, thd->query, thd->query_length);
3085
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
3087
char warn_buff[DRIZZLE_ERRMSG_SIZE];
3088
snprintf(warn_buff, sizeof(warn_buff),
3089
ER(ER_TABLE_EXISTS_ERROR), table_name);
3090
push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
3091
ER_TABLE_EXISTS_ERROR,warn_buff);
3095
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
3100
pthread_mutex_lock(&LOCK_open);
3101
unlink_open_table(thd, name_lock, false);
3102
pthread_mutex_unlock(&LOCK_open);
3108
bool mysql_analyze_table(THD* thd, TableList* tables, HA_CHECK_OPT* check_opt)
3110
thr_lock_type lock_type = TL_READ_NO_INSERT;
3112
return(mysql_admin_table(thd, tables, check_opt,
3113
"analyze", lock_type, 1, 0, 0, 0,
3114
&handler::ha_analyze));
3118
bool mysql_check_table(THD* thd, TableList* tables,HA_CHECK_OPT* check_opt)
3120
thr_lock_type lock_type = TL_READ_NO_INSERT;
3122
return(mysql_admin_table(thd, tables, check_opt,
3124
0, 0, HA_OPEN_FOR_REPAIR, 0,
3125
&handler::ha_check));
3129
/* table_list should contain just one table */
3131
mysql_discard_or_import_tablespace(THD *thd,
3132
TableList *table_list,
3133
enum tablespace_op_type tablespace_op)
3140
Note that DISCARD/IMPORT TABLESPACE always is the only operation in an
3144
thd->set_proc_info("discard_or_import_tablespace");
3146
discard= test(tablespace_op == DISCARD_TABLESPACE);
3149
We set this flag so that ha_innobase::open and ::external_lock() do
3150
not complain when we lock the table
3152
thd->tablespace_op= true;
3153
if (!(table=open_ltable(thd, table_list, TL_WRITE, 0)))
3155
thd->tablespace_op=false;
3159
error= table->file->ha_discard_or_import_tablespace(discard);
3161
thd->set_proc_info("end");
3166
/* The ALTER Table is always in its own transaction */
3167
error = ha_autocommit_or_rollback(thd, 0);
3168
if (end_active_trans(thd))
3172
write_bin_log(thd, false, thd->query, thd->query_length);
3175
ha_autocommit_or_rollback(thd, error);
3176
thd->tablespace_op=false;
3184
table->file->print_error(error, MYF(0));
3190
Copy all changes detected by parser to the HA_ALTER_FLAGS
3193
void setup_ha_alter_flags(Alter_info *alter_info, HA_ALTER_FLAGS *alter_flags)
3195
uint32_t flags= alter_info->flags;
3197
if (ALTER_ADD_COLUMN & flags)
3198
*alter_flags|= HA_ADD_COLUMN;
3199
if (ALTER_DROP_COLUMN & flags)
3200
*alter_flags|= HA_DROP_COLUMN;
3201
if (ALTER_RENAME & flags)
3202
*alter_flags|= HA_RENAME_TABLE;
3203
if (ALTER_CHANGE_COLUMN & flags)
3204
*alter_flags|= HA_CHANGE_COLUMN;
3205
if (ALTER_COLUMN_DEFAULT & flags)
3206
*alter_flags|= HA_COLUMN_DEFAULT_VALUE;
3207
if (ALTER_COLUMN_STORAGE & flags)
3208
*alter_flags|= HA_COLUMN_STORAGE;
3209
if (ALTER_COLUMN_FORMAT & flags)
3210
*alter_flags|= HA_COLUMN_FORMAT;
3211
if (ALTER_COLUMN_ORDER & flags)
3212
*alter_flags|= HA_ALTER_COLUMN_ORDER;
3213
if (ALTER_STORAGE & flags)
3214
*alter_flags|= HA_ALTER_STORAGE;
3215
if (ALTER_ROW_FORMAT & flags)
3216
*alter_flags|= HA_ALTER_ROW_FORMAT;
3217
if (ALTER_RECREATE & flags)
3218
*alter_flags|= HA_RECREATE;
3219
if (ALTER_FOREIGN_KEY & flags)
3220
*alter_flags|= HA_ALTER_FOREIGN_KEY;
3226
@param table The original table.
3227
@param alter_info Alter options, fields and keys for the new
3229
@param create_info Create options for the new table.
3230
@param order_num Number of order list elements.
3231
@param[out] ha_alter_flags Flags that indicate what will be changed
3232
@param[out] ha_alter_info Data structures needed for on-line alter
3233
@param[out] table_changes Information about particular change
3235
First argument 'table' contains information of the original
3236
table, which includes all corresponding parts that the new
3237
table has in arguments create_list, key_list and create_info.
3239
By comparing the changes between the original and new table
3240
we can determine how much it has changed after ALTER Table
3241
and whether we need to make a copy of the table, or just change
3244
Mark any changes detected in the ha_alter_flags.
3246
If there are no data changes, but index changes, 'index_drop_buffer'
3247
and/or 'index_add_buffer' are populated with offsets into
3248
table->key_info or key_info_buffer respectively for the indexes
3249
that need to be dropped and/or (re-)created.
3252
@retval false success
3257
compare_tables(THD *thd,
3259
Alter_info *alter_info,
3260
HA_CREATE_INFO *create_info,
3262
HA_ALTER_FLAGS *alter_flags,
3263
HA_ALTER_INFO *ha_alter_info,
3264
uint32_t *table_changes)
3266
Field **f_ptr, *field;
3267
uint32_t table_changes_local= 0;
3268
List_iterator_fast<Create_field> new_field_it(alter_info->create_list);
3269
Create_field *new_field;
3270
KEY_PART_INFO *key_part;
3273
Remember if the new definition has new VARCHAR column;
3274
create_info->varchar will be reset in mysql_prepare_create_table.
3276
bool varchar= create_info->varchar;
3280
Create a copy of alter_info.
3281
To compare the new and old table definitions, we need to "prepare"
3282
the new definition - transform it from parser output to a format
3283
that describes the final table layout (all column defaults are
3284
initialized, duplicate columns are removed). This is done by
3285
mysql_prepare_create_table. Unfortunately,
3286
mysql_prepare_create_table performs its transformations
3287
"in-place", that is, modifies the argument. Since we would
3288
like to keep compare_tables() idempotent (not altering any
3289
of the arguments) we create a copy of alter_info here and
3290
pass it to mysql_prepare_create_table, then use the result
3291
to evaluate possibility of fast ALTER Table, and then
3294
Alter_info tmp_alter_info(*alter_info, thd->mem_root);
3295
THD *thd= table->in_use;
3296
uint32_t db_options= 0; /* not used */
3297
/* Create the prepared information. */
3298
if (mysql_prepare_create_table(thd, create_info,
3300
(table->s->tmp_table != NO_TMP_TABLE),
3303
&ha_alter_info->key_info_buffer,
3304
&ha_alter_info->key_count,
3305
/* select_field_count */ 0))
3307
/* Allocate result buffers. */
3308
if (! (ha_alter_info->index_drop_buffer=
3309
(uint*) thd->alloc(sizeof(uint) * table->s->keys)) ||
3310
! (ha_alter_info->index_add_buffer=
3311
(uint*) thd->alloc(sizeof(uint) *
3312
tmp_alter_info.key_list.elements)))
3316
First we setup ha_alter_flags based on what was detected
3319
setup_ha_alter_flags(alter_info, alter_flags);
3323
Some very basic checks. If number of fields changes, or the
3324
handler, we need to run full ALTER Table. In the future
3325
new fields can be added and old dropped without copy, but
3328
Test also that engine was not given during ALTER Table, or
3329
we are force to run regular alter table (copy).
3330
E.g. ALTER Table tbl_name ENGINE=MyISAM.
3332
For the following ones we also want to run regular alter table:
3333
ALTER Table tbl_name order_st BY ..
3334
ALTER Table tbl_name CONVERT TO CHARACTER SET ..
3336
At the moment we can't handle altering temporary tables without a copy.
3337
We also test if OPTIMIZE Table was given and was mapped to alter table.
3338
In that case we always do full copy.
3340
There was a bug prior to mysql-4.0.25. Number of null fields was
3341
calculated incorrectly. As a result frm and data files gets out of
3342
sync after fast alter table. There is no way to determine by which
3343
mysql version (in 4.0 and 4.1 branches) table was created, thus we
3344
disable fast alter table for all tables created by mysql versions
3345
prior to 5.0 branch.
3348
if (table->s->fields != alter_info->create_list.elements ||
3349
table->s->db_type() != create_info->db_type ||
3350
table->s->tmp_table ||
3351
create_info->used_fields & HA_CREATE_USED_ENGINE ||
3352
create_info->used_fields & HA_CREATE_USED_CHARSET ||
3353
create_info->used_fields & HA_CREATE_USED_DEFAULT_CHARSET ||
3354
create_info->used_fields & HA_CREATE_USED_ROW_FORMAT ||
3355
(alter_info->flags & (ALTER_RECREATE | ALTER_FOREIGN_KEY)) ||
3357
!table->s->mysql_version ||
3358
(table->s->frm_version < FRM_VER_TRUE_VARCHAR && varchar))
3360
*table_changes= IS_EQUAL_NO;
3362
Check what has changed and set alter_flags
3364
if (table->s->fields < alter_info->create_list.elements)
3365
*alter_flags|= HA_ADD_COLUMN;
3366
else if (table->s->fields > alter_info->create_list.elements)
3367
*alter_flags|= HA_DROP_COLUMN;
3368
if (create_info->db_type != table->s->db_type() ||
3369
create_info->used_fields & HA_CREATE_USED_ENGINE)
3370
*alter_flags|= HA_ALTER_STORAGE_ENGINE;
3371
if (create_info->used_fields & HA_CREATE_USED_CHARSET)
3372
*alter_flags|= HA_CHANGE_CHARACTER_SET;
3373
if (create_info->used_fields & HA_CREATE_USED_DEFAULT_CHARSET)
3374
*alter_flags|= HA_SET_DEFAULT_CHARACTER_SET;
3375
if (alter_info->flags & ALTER_RECREATE)
3376
*alter_flags|= HA_RECREATE;
3377
/* TODO check for ADD/DROP FOREIGN KEY */
3378
if (alter_info->flags & ALTER_FOREIGN_KEY)
3379
*alter_flags|= HA_ALTER_FOREIGN_KEY;
3380
if (!table->s->mysql_version ||
3381
(table->s->frm_version < FRM_VER_TRUE_VARCHAR && varchar))
3382
*alter_flags|= HA_ALTER_COLUMN_TYPE;
3385
Go through fields and check if the original ones are compatible
3388
for (f_ptr= table->field, new_field= new_field_it++;
3389
(new_field && (field= *f_ptr));
3390
f_ptr++, new_field= new_field_it++)
3392
/* Make sure we have at least the default charset in use. */
3393
if (!new_field->charset)
3394
new_field->charset= create_info->default_table_charset;
3396
/* Don't pack rows in old tables if the user has requested this. */
3397
if (create_info->row_type == ROW_TYPE_DYNAMIC ||
3398
(new_field->flags & BLOB_FLAG) ||
3399
(new_field->sql_type == DRIZZLE_TYPE_VARCHAR && create_info->row_type != ROW_TYPE_FIXED))
3400
create_info->table_options|= HA_OPTION_PACK_RECORD;
3402
/* Check how fields have been modified */
3403
if (alter_info->flags & ALTER_CHANGE_COLUMN)
3405
/* Evaluate changes bitmap and send to check_if_incompatible_data() */
3406
if (!(table_changes_local= field->is_equal(new_field)))
3407
*alter_flags|= HA_ALTER_COLUMN_TYPE;
3409
/* Check if field was renamed */
3410
field->flags&= ~FIELD_IS_RENAMED;
3411
if (my_strcasecmp(system_charset_info,
3413
new_field->field_name))
3415
field->flags|= FIELD_IS_RENAMED;
3416
*alter_flags|= HA_ALTER_COLUMN_NAME;
3419
*table_changes&= table_changes_local;
3420
if (table_changes_local == IS_EQUAL_PACK_LENGTH)
3421
*alter_flags|= HA_ALTER_COLUMN_TYPE;
3423
/* Check that NULL behavior is same for old and new fields */
3424
if ((new_field->flags & NOT_NULL_FLAG) !=
3425
(uint) (field->flags & NOT_NULL_FLAG))
3427
*table_changes= IS_EQUAL_NO;
3428
*alter_flags|= HA_ALTER_COLUMN_NULLABLE;
3432
/* Clear indexed marker */
3433
field->flags&= ~FIELD_IN_ADD_INDEX;
3437
Go through keys and check if the original ones are compatible
3441
KEY *table_key_end= table->key_info + table->s->keys;
3444
ha_alter_info->key_info_buffer + ha_alter_info->key_count;
3447
Step through all keys of the old table and search matching new keys.
3449
ha_alter_info->index_drop_count= 0;
3450
ha_alter_info->index_add_count= 0;
3451
for (table_key= table->key_info; table_key < table_key_end; table_key++)
3453
KEY_PART_INFO *table_part;
3454
KEY_PART_INFO *table_part_end= table_key->key_part + table_key->key_parts;
3455
KEY_PART_INFO *new_part;
3457
/* Search a new key with the same name. */
3458
for (new_key= ha_alter_info->key_info_buffer;
3459
new_key < new_key_end;
3462
if (! strcmp(table_key->name, new_key->name))
3465
if (new_key >= new_key_end)
3467
/* Key not found. Add the offset of the key to the drop buffer. */
3468
ha_alter_info->index_drop_buffer
3469
[ha_alter_info->index_drop_count++]=
3470
table_key - table->key_info;
3471
if (table_key->flags & HA_NOSAME)
3473
/* Unique key. Check for "PRIMARY". */
3474
if (! my_strcasecmp(system_charset_info,
3475
table_key->name, primary_key_name))
3476
*alter_flags|= HA_DROP_PK_INDEX;
3478
*alter_flags|= HA_DROP_UNIQUE_INDEX;
3481
*alter_flags|= HA_DROP_INDEX;
3482
*table_changes= IS_EQUAL_NO;
3486
/* Check that the key types are compatible between old and new tables. */
3487
if ((table_key->algorithm != new_key->algorithm) ||
3488
((table_key->flags & HA_KEYFLAG_MASK) !=
3489
(new_key->flags & HA_KEYFLAG_MASK)) ||
3490
(table_key->key_parts != new_key->key_parts))
3492
if (table_key->flags & HA_NOSAME)
3494
// Unique key. Check for "PRIMARY".
3495
if (! my_strcasecmp(system_charset_info,
3496
table_key->name, primary_key_name))
3497
*alter_flags|= HA_ALTER_PK_INDEX;
3499
*alter_flags|= HA_ALTER_UNIQUE_INDEX;
3502
*alter_flags|= HA_ALTER_INDEX;
3507
Check that the key parts remain compatible between the old and
3510
for (table_part= table_key->key_part, new_part= new_key->key_part;
3511
table_part < table_part_end;
3512
table_part++, new_part++)
3515
Key definition has changed if we are using a different field or
3516
if the used key part length is different. We know that the fields
3517
did not change. Comparing field numbers is sufficient.
3519
if ((table_part->length != new_part->length) ||
3520
(table_part->fieldnr - 1 != new_part->fieldnr))
3522
if (table_key->flags & HA_NOSAME)
3524
/* Unique key. Check for "PRIMARY" */
3525
if (! my_strcasecmp(system_charset_info,
3526
table_key->name, primary_key_name))
3527
*alter_flags|= HA_ALTER_PK_INDEX;
3529
*alter_flags|= HA_ALTER_UNIQUE_INDEX;
3532
*alter_flags|= HA_ALTER_INDEX;
3539
/* Key modified. Add the offset of the key to both buffers. */
3540
ha_alter_info->index_drop_buffer
3541
[ha_alter_info->index_drop_count++]=
3542
table_key - table->key_info;
3543
ha_alter_info->index_add_buffer
3544
[ha_alter_info->index_add_count++]=
3545
new_key - ha_alter_info->key_info_buffer;
3546
key_part= new_key->key_part;
3547
end= key_part + new_key->key_parts;
3548
for(; key_part != end; key_part++)
3550
/* Mark field to be part of new key */
3551
if ((field= table->field[key_part->fieldnr]))
3552
field->flags|= FIELD_IN_ADD_INDEX;
3554
*table_changes= IS_EQUAL_NO;
3556
/*end of for (; table_key < table_key_end;) */
3559
Step through all keys of the new table and find matching old keys.
3561
for (new_key= ha_alter_info->key_info_buffer;
3562
new_key < new_key_end;
3565
/* Search an old key with the same name. */
3566
for (table_key= table->key_info; table_key < table_key_end; table_key++)
3568
if (! strcmp(table_key->name, new_key->name))
3571
if (table_key >= table_key_end)
3573
/* Key not found. Add the offset of the key to the add buffer. */
3574
ha_alter_info->index_add_buffer
3575
[ha_alter_info->index_add_count++]=
3576
new_key - ha_alter_info->key_info_buffer;
3577
key_part= new_key->key_part;
3578
end= key_part + new_key->key_parts;
3579
for(; key_part != end; key_part++)
3581
/* Mark field to be part of new key */
3582
if ((field= table->field[key_part->fieldnr]))
3583
field->flags|= FIELD_IN_ADD_INDEX;
3585
if (new_key->flags & HA_NOSAME)
3587
/* Unique key. Check for "PRIMARY" */
3588
if (! my_strcasecmp(system_charset_info,
3589
new_key->name, primary_key_name))
3590
*alter_flags|= HA_ADD_PK_INDEX;
3592
*alter_flags|= HA_ADD_UNIQUE_INDEX;
3595
*alter_flags|= HA_ADD_INDEX;
3596
*table_changes= IS_EQUAL_NO;
3605
Manages enabling/disabling of indexes for ALTER Table
3608
alter_table_manage_keys()
3610
indexes_were_disabled Whether the indexes of the from table
3612
keys_onoff ENABLE | DISABLE | LEAVE_AS_IS
3620
bool alter_table_manage_keys(Table *table, int indexes_were_disabled,
3621
enum enum_enable_or_disable keys_onoff)
3624
switch (keys_onoff) {
3626
error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
3629
if (!indexes_were_disabled)
3631
/* fall-through: disabled indexes */
3633
error= table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
3636
if (error == HA_ERR_WRONG_COMMAND)
3638
push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
3639
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
3640
table->s->table_name.str);
3643
table->file->print_error(error, MYF(0));
3648
int create_temporary_table(THD *thd,
3652
HA_CREATE_INFO *create_info,
3653
Alter_info *alter_info,
3657
char index_file[FN_REFLEN], data_file[FN_REFLEN];
3658
handlerton *old_db_type, *new_db_type;
3659
old_db_type= table->s->db_type();
3660
new_db_type= create_info->db_type;
3662
Handling of symlinked tables:
3664
Create new data file and index file on the same disk as the
3665
old data and index files.
3667
Rename new data file over old data file and new index file over
3669
Symlinks are not changed.
3672
Create new data file and index file on the same disk as the
3673
old data and index files. Create also symlinks to point at
3676
At end, rename intermediate tables, and symlinks to intermediate
3677
table, to final table name.
3678
Remove old table and old symlinks
3680
If rename is made to another database:
3681
Create new tables in new database.
3683
Remove old table and symlinks.
3685
if (db_changed) // Ignore symlink if db changed
3687
if (create_info->index_file_name)
3689
/* Fix index_file_name to have 'tmp_name' as basename */
3690
my_stpcpy(index_file, tmp_name);
3691
create_info->index_file_name=fn_same(index_file,
3692
create_info->index_file_name,
3695
if (create_info->data_file_name)
3697
/* Fix data_file_name to have 'tmp_name' as basename */
3698
my_stpcpy(data_file, tmp_name);
3699
create_info->data_file_name=fn_same(data_file,
3700
create_info->data_file_name,
3705
create_info->data_file_name=create_info->index_file_name=0;
3708
Create a table with a temporary name.
3709
With create_info->frm_only == 1 this creates a .frm file only.
3710
We don't log the statement, it will be logged later.
3712
tmp_disable_binlog(thd);
3713
error= mysql_create_table(thd, new_db, tmp_name,
3714
create_info, alter_info, 1, 0);
3715
reenable_binlog(thd);
3721
Create a temporary table that reflects what an alter table operation
3725
create_altered_table()
3727
table The original table
3728
create_info Information from the parsing phase about new
3730
alter_info Lists of fields, keys to be changed, added
3732
db_change Specifies if the table is moved to another database
3734
A temporary table with all changes
3737
The temporary table is created without storing it in any storage engine
3738
and is opened only to get the table struct and frm file reference.
3740
Table *create_altered_table(THD *thd,
3743
HA_CREATE_INFO *create_info,
3744
Alter_info *alter_info,
3748
HA_CREATE_INFO altered_create_info(*create_info);
3749
Table *altered_table;
3751
char path[FN_REFLEN];
3753
snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%lx",
3754
tmp_file_prefix, current_pid, thd->thread_id);
3755
/* Safety fix for InnoDB */
3756
if (lower_case_table_names)
3757
my_casedn_str(files_charset_info, tmp_name);
3758
altered_create_info.options&= ~HA_LEX_CREATE_TMP_TABLE;
3759
altered_create_info.frm_only= 1;
3760
if ((error= create_temporary_table(thd, table, new_db, tmp_name,
3761
&altered_create_info,
3762
alter_info, db_change)))
3767
build_table_filename(path, sizeof(path), new_db, tmp_name, "",
3769
altered_table= open_temporary_table(thd, path, new_db, tmp_name, 1,
3771
return(altered_table);
3778
Perform a fast or on-line alter table
3781
mysql_fast_or_online_alter_table()
3783
table The original table
3784
altered_table A temporary table showing how we will change table
3785
create_info Information from the parsing phase about new
3787
alter_info Storage place for data used during different phases
3788
ha_alter_flags Bitmask that shows what will be changed
3789
keys_onoff Specifies if keys are to be enabled/disabled
3792
>0 An error occured during the on-line alter table operation
3793
-1 Error when re-opening table
3795
If mysql_alter_table does not need to copy the table, it is
3796
either a fast alter table where the storage engine does not
3797
need to know about the change, only the frm will change,
3798
or the storage engine supports performing the alter table
3799
operation directly, on-line without mysql having to copy
3802
int mysql_fast_or_online_alter_table(THD *thd,
3804
Table *altered_table,
3805
HA_CREATE_INFO *create_info,
3806
HA_ALTER_INFO *alter_info,
3807
HA_ALTER_FLAGS *ha_alter_flags,
3808
enum enum_enable_or_disable keys_onoff)
3811
bool online= (table->file->ha_table_flags() & HA_ONLINE_ALTER)?true:false;
3817
Tell the handler to prepare for the online alter
3819
if ((error= table->file->alter_table_phase1(thd,
3829
Tell the storage engine to perform the online alter table
3831
if check_if_supported_alter() returned HA_ALTER_SUPPORTED_WAIT_LOCK
3832
we need to wrap the next call with a DDL lock.
3834
if ((error= table->file->alter_table_phase2(thd,
3844
The final .frm file is already created as a temporary file
3845
and will be renamed to the original table name.
3847
pthread_mutex_lock(&LOCK_open);
3848
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
3849
alter_table_manage_keys(table, table->file->indexes_are_disabled(),
3851
close_data_files_and_morph_locks(thd,
3852
table->pos_in_table_list->db,
3853
table->pos_in_table_list->table_name);
3854
if (mysql_rename_table(NULL,
3855
altered_table->s->db.str,
3856
altered_table->s->table_name.str,
3858
table->s->table_name.str, FN_FROM_IS_TMP))
3861
pthread_mutex_unlock(&LOCK_open);
3864
broadcast_refresh();
3865
pthread_mutex_unlock(&LOCK_open);
3868
The ALTER Table is always in its own transaction.
3869
Commit must not be called while LOCK_open is locked. It could call
3870
wait_if_global_read_lock(), which could create a deadlock if called
3873
error= ha_autocommit_or_rollback(thd, 0);
3881
pthread_mutex_lock(&LOCK_open);
3882
if (reopen_table(table))
3887
pthread_mutex_unlock(&LOCK_open);
3891
Tell the handler that the changed frm is on disk and table
3894
if ((error= t_table->file->alter_table_phase3(thd, t_table)))
3900
We are going to reopen table down on the road, so we have to restore
3901
state of the Table object which we used for obtaining of handler
3902
object to make it suitable for reopening.
3904
assert(t_table == table);
3905
table->open_placeholder= 1;
3906
pthread_mutex_lock(&LOCK_open);
3907
close_handle_and_leave_table_as_lock(table);
3908
pthread_mutex_unlock(&LOCK_open);
3919
Prepare column and key definitions for CREATE TABLE in ALTER Table.
3921
This function transforms parse output of ALTER Table - lists of
3922
columns and keys to add, drop or modify into, essentially,
3923
CREATE TABLE definition - a list of columns and keys of the new
3924
table. While doing so, it also performs some (bug not all)
3927
This function is invoked when we know that we're going to
3928
perform ALTER Table via a temporary table -- i.e. fast ALTER Table
3929
is not possible, perhaps because the ALTER statement contains
3930
instructions that require change in table data, not only in
3931
table definition or indexes.
3933
@param[in,out] thd thread handle. Used as a memory pool
3934
and source of environment information.
3935
@param[in] table the source table, open and locked
3936
Used as an interface to the storage engine
3937
to acquire additional information about
3939
@param[in,out] create_info A blob with CREATE/ALTER Table
3941
@param[in,out] alter_info Another blob with ALTER/CREATE parameters.
3942
Originally create_info was used only in
3943
CREATE TABLE and alter_info only in ALTER Table.
3944
But since ALTER might end-up doing CREATE,
3945
this distinction is gone and we just carry
3946
around two structures.
3949
Fills various create_info members based on information retrieved
3950
from the storage engine.
3951
Sets create_info->varchar if the table has a VARCHAR column.
3952
Prepares alter_info->create_list and alter_info->key_list with
3953
columns and keys of the new table.
3954
@retval true error, out of memory or a semantical error in ALTER
3956
@retval false success
3960
mysql_prepare_alter_table(THD *thd, Table *table,
3961
HA_CREATE_INFO *create_info,
3962
Alter_info *alter_info)
3964
/* New column definitions are added here */
3965
List<Create_field> new_create_list;
3966
/* New key definitions are added here */
3967
List<Key> new_key_list;
3968
List_iterator<Alter_drop> drop_it(alter_info->drop_list);
3969
List_iterator<Create_field> def_it(alter_info->create_list);
3970
List_iterator<Alter_column> alter_it(alter_info->alter_list);
3971
List_iterator<Key> key_it(alter_info->key_list);
3972
List_iterator<Create_field> find_it(new_create_list);
3973
List_iterator<Create_field> field_it(new_create_list);
3974
List<Key_part_spec> key_parts;
3975
uint32_t db_create_options= (table->s->db_create_options
3976
& ~(HA_OPTION_PACK_RECORD));
3977
uint32_t used_fields= create_info->used_fields;
3978
KEY *key_info=table->key_info;
3982
create_info->varchar= false;
3983
/* Let new create options override the old ones */
3984
if (!(used_fields & HA_CREATE_USED_MIN_ROWS))
3985
create_info->min_rows= table->s->min_rows;
3986
if (!(used_fields & HA_CREATE_USED_MAX_ROWS))
3987
create_info->max_rows= table->s->max_rows;
3988
if (!(used_fields & HA_CREATE_USED_AVG_ROW_LENGTH))
3989
create_info->avg_row_length= table->s->avg_row_length;
3990
if (!(used_fields & HA_CREATE_USED_BLOCK_SIZE))
3991
create_info->block_size= table->s->block_size;
3992
if (!(used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
3993
create_info->default_table_charset= table->s->table_charset;
3994
if (!(used_fields & HA_CREATE_USED_AUTO) && table->found_next_number_field)
3996
/* Table has an autoincrement, copy value to new table */
3997
table->file->info(HA_STATUS_AUTO);
3998
create_info->auto_increment_value= table->file->stats.auto_increment_value;
4000
if (!(used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE))
4001
create_info->key_block_size= table->s->key_block_size;
4003
restore_record(table, s->default_values); // Empty record for DEFAULT
4007
First collect all fields from table which isn't in drop_list
4009
Field **f_ptr,*field;
4010
for (f_ptr=table->field ; (field= *f_ptr) ; f_ptr++)
4012
/* Check if field should be dropped */
4015
while ((drop=drop_it++))
4017
if (drop->type == Alter_drop::COLUMN &&
4018
!my_strcasecmp(system_charset_info,field->field_name, drop->name))
4020
/* Reset auto_increment value if it was dropped */
4021
if (MTYP_TYPENR(field->unireg_check) == Field::NEXT_NUMBER &&
4022
!(used_fields & HA_CREATE_USED_AUTO))
4024
create_info->auto_increment_value=0;
4025
create_info->used_fields|=HA_CREATE_USED_AUTO;
4035
/* Check if field is changed */
4037
while ((def=def_it++))
4040
!my_strcasecmp(system_charset_info,field->field_name, def->change))
4044
{ // Field is changed
4048
new_create_list.push_back(def);
4055
This field was not dropped and not changed, add it to the list
4058
def= new Create_field(field, field);
4059
new_create_list.push_back(def);
4060
alter_it.rewind(); // Change default if ALTER
4061
Alter_column *alter;
4062
while ((alter=alter_it++))
4064
if (!my_strcasecmp(system_charset_info,field->field_name, alter->name))
4069
if (def->sql_type == DRIZZLE_TYPE_BLOB)
4071
my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), def->change);
4074
if ((def->def=alter->def)) // Use new default
4075
def->flags&= ~NO_DEFAULT_VALUE_FLAG;
4077
def->flags|= NO_DEFAULT_VALUE_FLAG;
4083
while ((def=def_it++)) // Add new columns
4085
if (def->change && ! def->field)
4087
my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table->s->table_name.str);
4091
Check that the DATE/DATETIME not null field we are going to add is
4092
either has a default value or the '0000-00-00' is allowed by the
4094
If the '0000-00-00' value isn't allowed then raise the error_if_not_empty
4095
flag to allow ALTER Table only if the table to be altered is empty.
4097
if ((def->sql_type == DRIZZLE_TYPE_NEWDATE ||
4098
def->sql_type == DRIZZLE_TYPE_DATETIME) &&
4099
!alter_info->datetime_field &&
4100
!(~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) &&
4101
thd->variables.sql_mode & MODE_NO_ZERO_DATE)
4103
alter_info->datetime_field= def;
4104
alter_info->error_if_not_empty= true;
4107
new_create_list.push_back(def);
4108
else if (def->after == first_keyword)
4109
new_create_list.push_front(def);
4114
while ((find=find_it++)) // Add new columns
4116
if (!my_strcasecmp(system_charset_info,def->after, find->field_name))
4121
my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table->s->table_name.str);
4124
find_it.after(def); // Put element after this
4126
XXX: hack for Bug#28427.
4127
If column order has changed, force OFFLINE ALTER Table
4128
without querying engine capabilities. If we ever have an
4129
engine that supports online ALTER Table CHANGE COLUMN
4130
<name> AFTER <name1> (Falcon?), this fix will effectively
4131
disable the capability.
4132
TODO: detect the situation in compare_tables, behave based
4133
on engine capabilities.
4135
if (alter_info->build_method == HA_BUILD_ONLINE)
4137
my_error(ER_NOT_SUPPORTED_YET, MYF(0), thd->query);
4140
alter_info->build_method= HA_BUILD_OFFLINE;
4143
if (alter_info->alter_list.elements)
4145
my_error(ER_BAD_FIELD_ERROR, MYF(0),
4146
alter_info->alter_list.head()->name, table->s->table_name.str);
4149
if (!new_create_list.elements)
4151
my_message(ER_CANT_REMOVE_ALL_FIELDS, ER(ER_CANT_REMOVE_ALL_FIELDS),
4157
Collect all keys which isn't in drop list. Add only those
4158
for which some fields exists.
4161
for (uint32_t i=0 ; i < table->s->keys ; i++,key_info++)
4163
char *key_name= key_info->name;
4166
while ((drop=drop_it++))
4168
if (drop->type == Alter_drop::KEY &&
4169
!my_strcasecmp(system_charset_info,key_name, drop->name))
4178
KEY_PART_INFO *key_part= key_info->key_part;
4180
for (uint32_t j=0 ; j < key_info->key_parts ; j++,key_part++)
4182
if (!key_part->field)
4183
continue; // Wrong field (from UNIREG)
4184
const char *key_part_name=key_part->field->field_name;
4185
Create_field *cfield;
4187
while ((cfield=field_it++))
4191
if (!my_strcasecmp(system_charset_info, key_part_name,
4195
else if (!my_strcasecmp(system_charset_info,
4196
key_part_name, cfield->field_name))
4200
continue; // Field is removed
4201
uint32_t key_part_length=key_part->length;
4202
if (cfield->field) // Not new field
4205
If the field can't have only a part used in a key according to its
4206
new type, or should not be used partially according to its
4207
previous type, or the field length is less than the key part
4208
length, unset the key part length.
4210
We also unset the key part length if it is the same as the
4211
old field's length, so the whole new field will be used.
4213
BLOBs may have cfield->length == 0, which is why we test it before
4214
checking whether cfield->length < key_part_length (in chars).
4216
if (!Field::type_can_have_key_part(cfield->field->type()) ||
4217
!Field::type_can_have_key_part(cfield->sql_type) ||
4218
(cfield->field->field_length == key_part_length &&
4219
!f_is_blob(key_part->key_type)) ||
4220
(cfield->length && (cfield->length < key_part_length /
4221
key_part->field->charset()->mbmaxlen)))
4222
key_part_length= 0; // Use whole field
4224
key_part_length /= key_part->field->charset()->mbmaxlen;
4225
key_parts.push_back(new Key_part_spec(cfield->field_name,
4226
strlen(cfield->field_name),
4229
if (key_parts.elements)
4231
KEY_CREATE_INFO key_create_info;
4233
enum Key::Keytype key_type;
4234
memset(&key_create_info, 0, sizeof(key_create_info));
4236
key_create_info.algorithm= key_info->algorithm;
4237
if (key_info->flags & HA_USES_BLOCK_SIZE)
4238
key_create_info.block_size= key_info->block_size;
4239
if (key_info->flags & HA_USES_COMMENT)
4240
key_create_info.comment= key_info->comment;
4242
if (key_info->flags & HA_NOSAME)
4244
if (! my_strcasecmp(system_charset_info, key_name, primary_key_name))
4245
key_type= Key::PRIMARY;
4247
key_type= Key::UNIQUE;
4250
key_type= Key::MULTIPLE;
4252
key= new Key(key_type, key_name, strlen(key_name),
4254
test(key_info->flags & HA_GENERATED_KEY),
4256
new_key_list.push_back(key);
4261
while ((key=key_it++)) // Add new keys
4263
if (key->type != Key::FOREIGN_KEY)
4264
new_key_list.push_back(key);
4265
if (key->name.str &&
4266
!my_strcasecmp(system_charset_info, key->name.str, primary_key_name))
4268
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name.str);
4274
if (alter_info->drop_list.elements)
4276
my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
4277
alter_info->drop_list.head()->name);
4280
if (alter_info->alter_list.elements)
4282
my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
4283
alter_info->alter_list.head()->name);
4287
if (!create_info->comment.str)
4289
create_info->comment.str= table->s->comment.str;
4290
create_info->comment.length= table->s->comment.length;
4293
table->file->update_create_info(create_info);
4294
if ((create_info->table_options &
4295
(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS)) ||
4296
(used_fields & HA_CREATE_USED_PACK_KEYS))
4297
db_create_options&= ~(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS);
4298
if (create_info->table_options &
4299
(HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM))
4300
db_create_options&= ~(HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM);
4301
if (create_info->table_options &
4302
(HA_OPTION_DELAY_KEY_WRITE | HA_OPTION_NO_DELAY_KEY_WRITE))
4303
db_create_options&= ~(HA_OPTION_DELAY_KEY_WRITE |
4304
HA_OPTION_NO_DELAY_KEY_WRITE);
4305
create_info->table_options|= db_create_options;
4307
if (table->s->tmp_table)
4308
create_info->options|=HA_LEX_CREATE_TMP_TABLE;
4311
alter_info->create_list.swap(new_create_list);
4312
alter_info->key_list.swap(new_key_list);
4324
new_db If there is a RENAME clause
4325
new_name If there is a RENAME clause
4326
create_info Information from the parsing phase about new
4328
table_list The table to change.
4329
alter_info Lists of fields, keys to be changed, added
4331
order_num How many order_st BY fields has been specified.
4332
order List of fields to order_st BY.
4333
ignore Whether we have ALTER IGNORE Table
4336
This is a veery long function and is everything but the kitchen sink :)
4337
It is used to alter a table and not only by ALTER Table but also
4338
CREATE|DROP INDEX are mapped on this function.
4340
When the ALTER Table statement just does a RENAME or ENABLE|DISABLE KEYS,
4341
or both, then this function short cuts its operation by renaming
4342
the table and/or enabling/disabling the keys. In this case, the FRM is
4343
not changed, directly by mysql_alter_table. However, if there is a
4344
RENAME + change of a field, or an index, the short cut is not used.
4345
See how `create_list` is used to generate the new FRM regarding the
4346
structure of the fields. The same is done for the indices of the table.
4348
Important is the fact, that this function tries to do as little work as
4349
possible, by finding out whether a intermediate table is needed to copy
4350
data into and when finishing the altering to use it as the original table.
4351
For this reason the function compare_tables() is called, which decides
4352
based on all kind of data how similar are the new and the original
4360
bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
4361
HA_CREATE_INFO *create_info,
4362
TableList *table_list,
4363
Alter_info *alter_info,
4364
uint32_t order_num, order_st *order, bool ignore)
4366
Table *table, *new_table=0, *name_lock= 0;;
4368
char tmp_name[80],old_name[32],new_name_buff[FN_REFLEN];
4369
char new_alias_buff[FN_REFLEN], *table_name, *db, *new_alias, *alias;
4370
char path[FN_REFLEN];
4371
ha_rows copied= 0,deleted= 0;
4372
handlerton *old_db_type, *new_db_type, *save_old_db_type;
4373
legacy_db_type table_type;
4375
if (table_list && table_list->schema_table)
4377
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.str);
4382
Assign variables table_name, new_name, db, new_db, path
4383
to simplify further comparisons: we want to see if it's a RENAME
4384
later just by comparing the pointers, avoiding the need for strcmp.
4386
thd->set_proc_info("init");
4387
table_name=table_list->table_name;
4388
alias= (lower_case_table_names == 2) ? table_list->alias : table_name;
4390
if (!new_db || !my_strcasecmp(table_alias_charset, new_db, db))
4392
build_table_filename(path, sizeof(path), db, table_name, "", 0);
4394
mysql_ha_rm_tables(thd, table_list, false);
4396
/* DISCARD/IMPORT TABLESPACE is always alone in an ALTER Table */
4397
if (alter_info->tablespace_op != NO_TABLESPACE_OP)
4398
/* Conditionally writes to binlog. */
4399
return(mysql_discard_or_import_tablespace(thd,table_list,
4400
alter_info->tablespace_op));
4401
strxnmov(new_name_buff, sizeof (new_name_buff) - 1, mysql_data_home, "/", db,
4402
"/", table_name, reg_ext, NULL);
4403
(void) unpack_filename(new_name_buff, new_name_buff);
4405
If this is just a rename of a view, short cut to the
4406
following scenario: 1) lock LOCK_open 2) do a RENAME
4407
2) unlock LOCK_open.
4408
This is a copy-paste added to make sure
4409
ALTER (sic:) Table .. RENAME works for views. ALTER VIEW is handled
4410
as an independent branch in mysql_execute_command. The need
4411
for a copy-paste arose because the main code flow of ALTER Table
4412
... RENAME tries to use open_ltable, which does not work for views
4413
(open_ltable was never modified to merge table lists of child tables
4414
into the main table list, like open_tables does).
4415
This code is wrong and will be removed, please do not copy.
4417
(void)mysql_frm_type(thd, new_name_buff, &table_type);
4419
if (!(table= open_n_lock_single_table(thd, table_list, TL_WRITE_ALLOW_READ)))
4421
table->use_all_columns();
4423
/* Check that we are not trying to rename to an existing table */
4426
my_stpcpy(new_name_buff,new_name);
4427
my_stpcpy(new_alias= new_alias_buff, new_name);
4428
if (lower_case_table_names)
4430
if (lower_case_table_names != 2)
4432
my_casedn_str(files_charset_info, new_name_buff);
4433
new_alias= new_name; // Create lower case table name
4435
my_casedn_str(files_charset_info, new_name);
4438
!my_strcasecmp(table_alias_charset, new_name_buff, table_name))
4441
Source and destination table names are equal: make later check
4444
new_alias= new_name= table_name;
4448
if (table->s->tmp_table != NO_TMP_TABLE)
4450
if (find_temporary_table(thd,new_db,new_name_buff))
4452
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name_buff);
4458
if (lock_table_name_if_not_cached(thd, new_db, new_name, &name_lock))
4462
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
4466
build_table_filename(new_name_buff, sizeof(new_name_buff),
4467
new_db, new_name_buff, reg_ext, 0);
4468
if (!access(new_name_buff, F_OK))
4470
/* Table will be closed in do_command() */
4471
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
4479
new_alias= (lower_case_table_names == 2) ? alias : table_name;
4480
new_name= table_name;
4483
old_db_type= table->s->db_type();
4484
if (!create_info->db_type)
4486
create_info->db_type= old_db_type;
4489
if (check_engine(thd, new_name, create_info))
4491
new_db_type= create_info->db_type;
4493
if (new_db_type != old_db_type &&
4494
!table->file->can_switch_engines())
4497
my_error(ER_ROW_IS_REFERENCED, MYF(0));
4501
if (create_info->row_type == ROW_TYPE_NOT_USED)
4502
create_info->row_type= table->s->row_type;
4504
if (ha_check_storage_engine_flag(old_db_type, HTON_ALTER_NOT_SUPPORTED) ||
4505
ha_check_storage_engine_flag(new_db_type, HTON_ALTER_NOT_SUPPORTED))
4507
my_error(ER_ILLEGAL_HA, MYF(0), table_name);
4511
thd->set_proc_info("setup");
4512
if (!(alter_info->flags & ~(ALTER_RENAME | ALTER_KEYS_ONOFF)) &&
4513
!table->s->tmp_table) // no need to touch frm
4515
switch (alter_info->keys_onoff) {
4520
wait_while_table_is_used() ensures that table being altered is
4521
opened only by this thread and that Table::TABLE_SHARE::version
4522
of Table object corresponding to this table is 0.
4523
The latter guarantees that no DML statement will open this table
4524
until ALTER Table finishes (i.e. until close_thread_tables())
4525
while the fact that the table is still open gives us protection
4526
from concurrent DDL statements.
4528
pthread_mutex_lock(&LOCK_open);
4529
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
4530
pthread_mutex_unlock(&LOCK_open);
4531
error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
4532
/* COND_refresh will be signaled in close_thread_tables() */
4535
pthread_mutex_lock(&LOCK_open);
4536
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
4537
pthread_mutex_unlock(&LOCK_open);
4538
error=table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
4539
/* COND_refresh will be signaled in close_thread_tables() */
4546
if (error == HA_ERR_WRONG_COMMAND)
4549
push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
4550
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
4554
pthread_mutex_lock(&LOCK_open);
4556
Unlike to the above case close_cached_table() below will remove ALL
4557
instances of Table from table cache (it will also remove table lock
4558
held by this thread). So to make actual table renaming and writing
4559
to binlog atomic we have to put them into the same critical section
4560
protected by LOCK_open mutex. This also removes gap for races between
4561
access() and mysql_rename_table() calls.
4564
if (!error && (new_name != table_name || new_db != db))
4566
thd->set_proc_info("rename");
4568
Then do a 'simple' rename of the table. First we need to close all
4569
instances of 'source' table.
4571
close_cached_table(thd, table);
4573
Then, we want check once again that target table does not exist.
4574
Actually the order of these two steps does not matter since
4575
earlier we took name-lock on the target table, so we do them
4576
in this particular order only to be consistent with 5.0, in which
4577
we don't take this name-lock and where this order really matters.
4578
TODO: Investigate if we need this access() check at all.
4580
if (!access(new_name_buff,F_OK))
4582
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name);
4587
*fn_ext(new_name)=0;
4588
if (mysql_rename_table(old_db_type,db,table_name,new_db,new_alias, 0))
4592
mysql_rename_table(old_db_type, new_db, new_alias, db,
4599
if (error == HA_ERR_WRONG_COMMAND)
4602
push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
4603
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
4609
write_bin_log(thd, true, thd->query, thd->query_length);
4614
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)
4618
unlink_open_table(thd, name_lock, false);
4619
pthread_mutex_unlock(&LOCK_open);
4620
table_list->table= NULL; // For query cache
4624
/* We have to do full alter table. */
4627
If the old table had partitions and we are doing ALTER Table ...
4628
engine= <new_engine>, the new table must preserve the original
4629
partitioning. That means that the new engine is still the
4630
partitioning engine, not the engine specified in the parser.
4631
This is discovered in prep_alter_part_table, which in such case
4632
updates create_info->db_type.
4633
Now we need to update the stack copy of create_info->db_type,
4634
as otherwise we won't be able to correctly move the files of the
4635
temporary table to the result table files.
4637
new_db_type= create_info->db_type;
4639
if (mysql_prepare_alter_table(thd, table, create_info, alter_info))
4642
set_table_default_charset(thd, create_info, db);
4645
if (thd->variables.old_alter_table
4646
|| (table->s->db_type() != create_info->db_type)
4649
if (alter_info->build_method == HA_BUILD_ONLINE)
4651
my_error(ER_NOT_SUPPORTED_YET, MYF(0), thd->query);
4654
alter_info->build_method= HA_BUILD_OFFLINE;
4657
if (alter_info->build_method != HA_BUILD_OFFLINE)
4659
Table *altered_table= 0;
4660
HA_ALTER_INFO ha_alter_info;
4661
HA_ALTER_FLAGS ha_alter_flags;
4662
uint32_t table_changes= IS_EQUAL_YES;
4663
bool need_copy_table= true;
4664
/* Check how much the tables differ. */
4665
if (compare_tables(thd, table, alter_info,
4666
create_info, order_num,
4675
Check if storage engine supports altering the table
4681
If table is not renamed, changed database and
4682
some change was detected then check if engine
4683
can do the change on-line
4685
if (new_name == table_name && new_db == db &&
4686
ha_alter_flags.is_set())
4688
Alter_info tmp_alter_info(*alter_info, thd->mem_root);
4692
check if table can be altered on-line
4694
if (!(altered_table= create_altered_table(thd,
4699
!strcmp(db, new_db))))
4702
switch (table->file->check_if_supported_alter(altered_table,
4706
case HA_ALTER_SUPPORTED_WAIT_LOCK:
4707
case HA_ALTER_SUPPORTED_NO_LOCK:
4709
@todo: Currently we always acquire an exclusive name
4710
lock on the table metadata when performing fast or online
4711
ALTER Table. In future we may consider this unnecessary,
4712
and narrow the scope of the exclusive name lock to only
4713
cover manipulation with .frms. Storage engine API
4714
call check_if_supported_alter has provision for this
4717
need_copy_table= false;
4719
case HA_ALTER_NOT_SUPPORTED:
4720
if (alter_info->build_method == HA_BUILD_ONLINE)
4722
my_error(ER_NOT_SUPPORTED_YET, MYF(0), thd->query);
4723
close_temporary_table(thd, altered_table, 1, 1);
4726
need_copy_table= true;
4728
case HA_ALTER_ERROR:
4730
close_temporary_table(thd, altered_table, 1, 1);
4735
/* TODO need to check if changes can be handled as fast ALTER Table */
4737
need_copy_table= true;
4739
if (!need_copy_table)
4741
error= mysql_fast_or_online_alter_table(thd,
4747
alter_info->keys_onoff);
4750
mysql_unlock_tables(thd, thd->lock);
4753
close_temporary_table(thd, altered_table, 1, 1);
4759
goto err_with_placeholders;
4766
pthread_mutex_lock(&LOCK_open);
4772
close_temporary_table(thd, altered_table, 1, 1);
4775
snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%lx", tmp_file_prefix,
4776
current_pid, thd->thread_id);
4777
/* Safety fix for innodb */
4778
if (lower_case_table_names)
4779
my_casedn_str(files_charset_info, tmp_name);
4782
/* Create a temporary table with the new format */
4783
if ((error= create_temporary_table(thd, table, new_db, tmp_name,
4784
create_info, alter_info,
4785
!strcmp(db, new_db))))
4790
/* Open the table so we need to copy the data to it. */
4791
if (table->s->tmp_table)
4794
memset(&tbl, 0, sizeof(tbl));
4796
tbl.table_name= tbl.alias= tmp_name;
4797
/* Table is in thd->temporary_tables */
4798
new_table= open_table(thd, &tbl, (bool*) 0, DRIZZLE_LOCK_IGNORE_FLUSH);
4802
char path[FN_REFLEN];
4803
/* table is a normal table: Create temporary table in same directory */
4804
build_table_filename(path, sizeof(path), new_db, tmp_name, "",
4806
/* Open our intermediate table */
4807
new_table=open_temporary_table(thd, path, new_db, tmp_name, 0, OTM_OPEN);
4812
/* Copy the data if necessary. */
4813
thd->count_cuted_fields= CHECK_FIELD_WARN; // calc cuted fields
4814
thd->cuted_fields=0L;
4815
thd->set_proc_info("copy to tmp table");
4818
We do not copy data for MERGE tables. Only the children have data.
4819
MERGE tables have HA_NO_COPY_ON_ALTER set.
4821
if (new_table && !(new_table->file->ha_table_flags() & HA_NO_COPY_ON_ALTER))
4823
/* We don't want update TIMESTAMP fields during ALTER Table. */
4824
new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
4825
new_table->next_number_field=new_table->found_next_number_field;
4826
error= copy_data_between_tables(table, new_table,
4827
alter_info->create_list, ignore,
4828
order_num, order, &copied, &deleted,
4829
alter_info->keys_onoff,
4830
alter_info->error_if_not_empty);
4834
pthread_mutex_lock(&LOCK_open);
4835
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
4836
pthread_mutex_unlock(&LOCK_open);
4837
alter_table_manage_keys(table, table->file->indexes_are_disabled(),
4838
alter_info->keys_onoff);
4839
error= ha_autocommit_or_rollback(thd, 0);
4840
if (end_active_trans(thd))
4843
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
4845
if (table->s->tmp_table != NO_TMP_TABLE)
4847
/* We changed a temporary table */
4850
/* Close lock if this is a transactional table */
4853
mysql_unlock_tables(thd, thd->lock);
4856
/* Remove link to old table and rename the new one */
4857
close_temporary_table(thd, table, 1, 1);
4858
/* Should pass the 'new_name' as we store table name in the cache */
4859
if (rename_temporary_table(thd, new_table, new_db, new_name))
4861
/* We don't replicate alter table statement on temporary tables */
4862
if (!thd->current_stmt_binlog_row_based)
4863
write_bin_log(thd, true, thd->query, thd->query_length);
4870
Close the intermediate table that will be the new table.
4871
Note that MERGE tables do not have their children attached here.
4873
intern_close_table(new_table);
4876
pthread_mutex_lock(&LOCK_open);
4879
quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP);
4880
pthread_mutex_unlock(&LOCK_open);
4885
Data is copied. Now we:
4886
1) Wait until all other threads close old version of table.
4887
2) Close instances of table open by this thread and replace them
4888
with exclusive name-locks.
4889
3) Rename the old table to a temp name, rename the new one to the
4891
4) If we are under LOCK TABLES and don't do ALTER Table ... RENAME
4892
we reopen new version of table.
4893
5) Write statement to the binary log.
4894
6) If we are under LOCK TABLES and do ALTER Table ... RENAME we
4895
remove name-locks from list of open tables and table cache.
4896
7) If we are not not under LOCK TABLES we rely on close_thread_tables()
4897
call to remove name-locks from table cache and list of open table.
4900
thd->set_proc_info("rename result table");
4901
snprintf(old_name, sizeof(old_name), "%s2-%lx-%lx", tmp_file_prefix,
4902
current_pid, thd->thread_id);
4903
if (lower_case_table_names)
4904
my_casedn_str(files_charset_info, old_name);
4906
wait_while_table_is_used(thd, table, HA_EXTRA_PREPARE_FOR_RENAME);
4907
close_data_files_and_morph_locks(thd, db, table_name);
4910
save_old_db_type= old_db_type;
4913
This leads to the storage engine (SE) not being notified for renames in
4914
mysql_rename_table(), because we just juggle with the FRM and nothing
4915
more. If we have an intermediate table, then we notify the SE that
4916
it should become the actual table. Later, we will recycle the old table.
4917
However, in case of ALTER Table RENAME there might be no intermediate
4918
table. This is when the old and new tables are compatible, according to
4919
compare_table(). Then, we need one additional call to
4920
mysql_rename_table() with flag NO_FRM_RENAME, which does nothing else but
4921
actual rename in the SE and the FRM is not touched. Note that, if the
4922
table is renamed and the SE is also changed, then an intermediate table
4923
is created and the additional call will not take place.
4925
if (mysql_rename_table(old_db_type, db, table_name, db, old_name,
4929
quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP);
4931
else if (mysql_rename_table(new_db_type, new_db, tmp_name, new_db,
4932
new_alias, FN_FROM_IS_TMP) || ((new_name != table_name || new_db != db) && 0))
4934
/* Try to get everything back. */
4936
quick_rm_table(new_db_type,new_db,new_alias, 0);
4937
quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP);
4938
mysql_rename_table(old_db_type, db, old_name, db, alias,
4944
/* This shouldn't happen. But let us play it safe. */
4945
goto err_with_placeholders;
4948
quick_rm_table(old_db_type, db, old_name, FN_IS_TMP);
4951
if (thd->locked_tables && new_name == table_name && new_db == db)
4953
thd->in_lock_tables= 1;
4954
error= reopen_tables(thd, 1, 1);
4955
thd->in_lock_tables= 0;
4957
goto err_with_placeholders;
4959
pthread_mutex_unlock(&LOCK_open);
4961
thd->set_proc_info("end");
4963
assert(!(mysql_bin_log.is_open() &&
4964
thd->current_stmt_binlog_row_based &&
4965
(create_info->options & HA_LEX_CREATE_TMP_TABLE)));
4966
write_bin_log(thd, true, thd->query, thd->query_length);
4968
if (ha_check_storage_engine_flag(old_db_type, HTON_FLUSH_AFTER_RENAME))
4971
For the alter table to be properly flushed to the logs, we
4972
have to open the new table. If not, we get a problem on server
4973
shutdown. But we do not need to attach MERGE children.
4975
char path[FN_REFLEN];
4977
build_table_filename(path, sizeof(path), new_db, table_name, "", 0);
4978
t_table= open_temporary_table(thd, path, new_db, tmp_name, false, OTM_OPEN);
4981
intern_close_table(t_table);
4985
sql_print_warning(_("Could not open table %s.%s after rename\n"),
4987
ha_flush_logs(old_db_type);
4989
table_list->table=0; // For query cache
4991
if (thd->locked_tables && (new_name != table_name || new_db != db))
4994
If are we under LOCK TABLES and did ALTER Table with RENAME we need
4995
to remove placeholders for the old table and for the target table
4996
from the list of open tables and table cache. If we are not under
4997
LOCK TABLES we can rely on close_thread_tables() doing this job.
4999
pthread_mutex_lock(&LOCK_open);
5000
unlink_open_table(thd, table, false);
5001
unlink_open_table(thd, name_lock, false);
5002
pthread_mutex_unlock(&LOCK_open);
5006
snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
5007
(ulong) (copied + deleted), (ulong) deleted,
5008
(ulong) thd->cuted_fields);
5009
my_ok(thd, copied + deleted, 0L, tmp_name);
5010
thd->some_tables_deleted=0;
5016
/* close_temporary_table() frees the new_table pointer. */
5017
close_temporary_table(thd, new_table, 1, 1);
5020
quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP);
5024
No default value was provided for a DATE/DATETIME field, the
5025
current sql_mode doesn't allow the '0000-00-00' value and
5026
the table to be altered isn't empty.
5029
if (alter_info->error_if_not_empty && thd->row_count)
5031
const char *f_val= 0;
5032
enum enum_drizzle_timestamp_type t_type= DRIZZLE_TIMESTAMP_DATE;
5033
switch (alter_info->datetime_field->sql_type)
5035
case DRIZZLE_TYPE_NEWDATE:
5036
f_val= "0000-00-00";
5037
t_type= DRIZZLE_TIMESTAMP_DATE;
5039
case DRIZZLE_TYPE_DATETIME:
5040
f_val= "0000-00-00 00:00:00";
5041
t_type= DRIZZLE_TIMESTAMP_DATETIME;
5044
/* Shouldn't get here. */
5047
bool save_abort_on_warning= thd->abort_on_warning;
5048
thd->abort_on_warning= true;
5049
make_truncated_value_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5050
f_val, strlength(f_val), t_type,
5051
alter_info->datetime_field->field_name);
5052
thd->abort_on_warning= save_abort_on_warning;
5056
pthread_mutex_lock(&LOCK_open);
5057
unlink_open_table(thd, name_lock, false);
5058
pthread_mutex_unlock(&LOCK_open);
5062
err_with_placeholders:
5064
An error happened while we were holding exclusive name-lock on table
5065
being altered. To be safe under LOCK TABLES we should remove placeholders
5066
from list of open tables list and table cache.
5068
unlink_open_table(thd, table, false);
5070
unlink_open_table(thd, name_lock, false);
5071
pthread_mutex_unlock(&LOCK_open);
5074
/* mysql_alter_table */
5077
copy_data_between_tables(Table *from,Table *to,
5078
List<Create_field> &create,
5080
uint32_t order_num, order_st *order,
5083
enum enum_enable_or_disable keys_onoff,
5084
bool error_if_not_empty)
5087
Copy_field *copy,*copy_end;
5088
ulong found_count,delete_count;
5089
THD *thd= current_thd;
5091
SORT_FIELD *sortorder;
5095
List<Item> all_fields;
5096
ha_rows examined_rows;
5097
bool auto_increment_field_copied= 0;
5098
ulong save_sql_mode;
5099
uint64_t prev_insert_id;
5102
Turn off recovery logging since rollback of an alter table is to
5103
delete the new table so there is no need to log the changes to it.
5105
This needs to be done before external_lock
5107
error= ha_enable_transaction(thd, false);
5111
if (!(copy= new Copy_field[to->s->fields]))
5112
return(-1); /* purecov: inspected */
5114
if (to->file->ha_external_lock(thd, F_WRLCK))
5117
/* We need external lock before we can disable/enable keys */
5118
alter_table_manage_keys(to, from->file->indexes_are_disabled(), keys_onoff);
5120
/* We can abort alter table for any table type */
5121
thd->abort_on_warning= !ignore;
5123
from->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
5124
to->file->ha_start_bulk_insert(from->file->stats.records);
5126
save_sql_mode= thd->variables.sql_mode;
5128
List_iterator<Create_field> it(create);
5131
for (Field **ptr=to->field ; *ptr ; ptr++)
5136
if (*ptr == to->next_number_field)
5137
auto_increment_field_copied= true;
5139
(copy_end++)->set(*ptr,def->field,0);
5144
found_count=delete_count=0;
5148
if (to->s->primary_key != MAX_KEY && to->file->primary_key_is_clustered())
2202
5150
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);
5151
snprintf(warn_buff, sizeof(warn_buff),
5152
_("order_st BY ignored because there is a user-defined clustered "
5153
"index in the table '%-.192s'"),
5154
from->s->table_name.str);
5155
push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
5160
from->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE),
5161
MYF(MY_FAE | MY_ZEROFILL));
5162
memset(&tables, 0, sizeof(tables));
5164
tables.alias= tables.table_name= from->s->table_name.str;
5165
tables.db= from->s->db.str;
5168
if (thd->lex->select_lex.setup_ref_array(thd, order_num) ||
5169
setup_order(thd, thd->lex->select_lex.ref_pointer_array,
5170
&tables, fields, all_fields, order) ||
5171
!(sortorder= make_unireg_sortorder(order, &length, NULL)) ||
5172
(from->sort.found_records= filesort(thd, from, sortorder, length,
5173
(SQL_SELECT *) 0, HA_POS_ERROR,
5174
1, &examined_rows)) ==
5180
/* Tell handler that we have values for all columns in the to table */
5181
to->use_all_columns();
5182
init_read_record(&info, thd, from, (SQL_SELECT *) 0, 1,1);
5184
to->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
5186
restore_record(to, s->default_values); // Create empty record
5187
while (!(error=info.read_record(&info)))
5191
thd->send_kill_message();
5196
/* Return error if source table isn't empty. */
5197
if (error_if_not_empty)
5202
if (to->next_number_field)
5204
if (auto_increment_field_copied)
5205
to->auto_increment_field_not_null= true;
5207
to->next_number_field->reset();
5210
for (Copy_field *copy_ptr=copy ; copy_ptr != copy_end ; copy_ptr++)
5212
copy_ptr->do_copy(copy_ptr);
5214
prev_insert_id= to->file->next_insert_id;
5215
error=to->file->ha_write_row(to->record[0]);
5216
to->auto_increment_field_not_null= false;
5220
to->file->is_fatal_error(error, HA_CHECK_DUP))
5222
if (!to->file->is_fatal_error(error, HA_CHECK_DUP))
5224
uint32_t key_nr= to->file->get_dup_key(error);
5225
if ((int) key_nr >= 0)
5227
const char *err_msg= ER(ER_DUP_ENTRY_WITH_KEY_NAME);
5229
(to->key_info[0].key_part[0].field->flags &
5230
AUTO_INCREMENT_FLAG))
5231
err_msg= ER(ER_DUP_ENTRY_AUTOINCREMENT_CASE);
5232
to->file->print_keydup_error(key_nr, err_msg);
5237
to->file->print_error(error,MYF(0));
5240
to->file->restore_auto_increment(prev_insert_id);
5246
end_read_record(&info);
5247
free_io_cache(from);
5248
delete [] copy; // This is never 0
5250
if (to->file->ha_end_bulk_insert() && error <= 0)
5252
to->file->print_error(my_errno,MYF(0));
5255
to->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
5257
if (ha_enable_transaction(thd, true))
5264
Ensure that the new table is saved properly to disk so that we
5267
if (ha_autocommit_or_rollback(thd, 0))
5269
if (end_active_trans(thd))
5273
thd->variables.sql_mode= save_sql_mode;
5274
thd->abort_on_warning= 0;
5275
free_io_cache(from);
5276
*copied= found_count;
5277
*deleted=delete_count;
5278
to->file->ha_release_auto_increment();
5279
if (to->file->ha_external_lock(thd,F_UNLCK))
5281
return(error > 0 ? -1 : 0);
5286
Recreates tables by calling mysql_alter_table().
5289
mysql_recreate_table()
5291
tables Tables to recreate
5294
Like mysql_alter_table().
5296
bool mysql_recreate_table(THD *thd, TableList *table_list)
5298
HA_CREATE_INFO create_info;
5299
Alter_info alter_info;
5301
assert(!table_list->next_global);
5303
table_list->table has been closed and freed. Do not reference
5304
uninitialized data. open_tables() could fail.
5306
table_list->table= NULL;
5308
memset(&create_info, 0, sizeof(create_info));
5309
create_info.row_type=ROW_TYPE_NOT_USED;
5310
create_info.default_table_charset=default_charset_info;
5311
/* Force alter table to recreate table */
5312
alter_info.flags= (ALTER_CHANGE_COLUMN | ALTER_RECREATE);
5313
return(mysql_alter_table(thd, NULL, NULL, &create_info,
5314
table_list, &alter_info, 0,
5315
(order_st *) 0, 0));
5319
bool mysql_checksum_table(THD *thd, TableList *tables,
5320
HA_CHECK_OPT *check_opt)
5323
List<Item> field_list;
5325
Protocol *protocol= thd->protocol;
5327
field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
5328
item->maybe_null= 1;
5329
field_list.push_back(item= new Item_int("Checksum", (int64_t) 1,
5330
MY_INT64_NUM_DECIMAL_DIGITS));
5331
item->maybe_null= 1;
5332
if (protocol->send_fields(&field_list,
5333
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
5336
/* Open one table after the other to keep lock time as short as possible. */
5337
for (table= tables; table; table= table->next_local)
5339
char table_name[NAME_LEN*2+2];
5342
strxmov(table_name, table->db ,".", table->table_name, NULL);
5344
t= table->table= open_n_lock_single_table(thd, table, TL_READ);
5345
thd->clear_error(); // these errors shouldn't get client
5347
protocol->prepare_for_resend();
5348
protocol->store(table_name, system_charset_info);
5352
/* Table didn't exist */
5353
protocol->store_null();
5358
if (t->file->ha_table_flags() & HA_HAS_CHECKSUM &&
5359
!(check_opt->flags & T_EXTEND))
5360
protocol->store((uint64_t)t->file->checksum());
5361
else if (!(t->file->ha_table_flags() & HA_HAS_CHECKSUM) &&
5362
(check_opt->flags & T_QUICK))
5363
protocol->store_null();
5366
/* calculating table's checksum */
5368
unsigned char null_mask=256 - (1 << t->s->last_null_bit_pos);
5370
t->use_all_columns();
5372
if (t->file->ha_rnd_init(1))
5373
protocol->store_null();
5378
ha_checksum row_crc= 0;
5379
int error= t->file->rnd_next(t->record[0]);
5380
if (unlikely(error))
5382
if (error == HA_ERR_RECORD_DELETED)
5386
if (t->s->null_bytes)
5388
/* fix undefined null bits */
5389
t->record[0][t->s->null_bytes-1] |= null_mask;
5390
if (!(t->s->db_create_options & HA_OPTION_PACK_RECORD))
5391
t->record[0][0] |= 1;
5393
row_crc= my_checksum(row_crc, t->record[0], t->s->null_bytes);
5396
for (uint32_t i= 0; i < t->s->fields; i++ )
5398
Field *f= t->field[i];
5399
if ((f->type() == DRIZZLE_TYPE_BLOB) ||
5400
(f->type() == DRIZZLE_TYPE_VARCHAR))
5404
row_crc= my_checksum(row_crc, (unsigned char*) tmp.ptr(), tmp.length());
5407
row_crc= my_checksum(row_crc, f->ptr,
5413
protocol->store((uint64_t)crc);
5414
t->file->ha_rnd_end();
5418
close_thread_tables(thd);
5419
table->table=0; // For query cache
5421
if (protocol->write())
5429
close_thread_tables(thd); // Shouldn't be needed
5435
static bool check_engine(THD *thd, const char *table_name,
5436
HA_CREATE_INFO *create_info)
5438
handlerton **new_engine= &create_info->db_type;
5439
handlerton *req_engine= *new_engine;
5440
bool no_substitution= 1;
5441
if (!(*new_engine= ha_checktype(thd, ha_legacy_type(req_engine),
5442
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 */
5445
if (req_engine && req_engine != *new_engine)
5447
push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
5448
ER_WARN_USING_OTHER_HANDLER,
5449
ER(ER_WARN_USING_OTHER_HANDLER),
5450
ha_resolve_storage_engine_name(*new_engine),
5453
if (create_info->options & HA_LEX_CREATE_TMP_TABLE &&
5454
ha_check_storage_engine_flag(*new_engine, HTON_TEMPORARY_NOT_SUPPORTED))
5456
if (create_info->used_fields & HA_CREATE_USED_ENGINE)
5458
my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
5459
ha_resolve_storage_engine_name(*new_engine), "TEMPORARY");
5463
*new_engine= myisam_hton;