2086
bool create_like_table(Session* session,
2087
identifier::Table::const_reference destination_identifier,
2088
identifier::Table::const_reference source_identifier,
2089
message::Table &create_table_proto,
2090
bool is_if_not_exists,
2913
bool mysql_create_like_table(THD* thd, TableList* table, TableList* src_table,
2914
HA_CREATE_INFO *create_info)
2916
Table *name_lock= 0;
2917
char src_path[FN_REFLEN], dst_path[FN_REFLEN];
2918
uint dst_path_length;
2919
char *db= table->db;
2920
char *table_name= table->table_name;
2093
2922
bool res= true;
2094
bool table_exists= false;
2926
By opening source table we guarantee that it exists and no concurrent
2927
DDL operation will mess with it. Later we also take an exclusive
2928
name-lock on target table name, which makes copying of .frm file,
2929
call to ha_create_table() and binlogging atomic against concurrent DML
2930
and DDL operations on target table. Thus by holding both these "locks"
2931
we ensure that our statement is properly isolated from all concurrent
2932
operations which matter.
2934
if (open_tables(thd, &src_table, ¬_used, 0))
2937
strxmov(src_path, src_table->table->s->path.str, reg_ext, NullS);
2097
2940
Check that destination tables does not exist. Note that its name
2098
2941
was already checked when it was added to the table list.
2100
For temporary tables we don't aim to grab locks.
2102
if (destination_identifier.isTmp())
2104
if (session->find_temporary_table(destination_identifier))
2110
bool was_created= create_table_wrapper(*session,
2112
destination_identifier,
2115
if (not was_created) // This is pretty paranoid, but we assume something might not clean up after itself
2117
(void) session->rm_temporary_table(destination_identifier, true);
2119
else if (not session->open_temporary_table(destination_identifier))
2121
// We created, but we can't open... also, a hack.
2122
(void) session->rm_temporary_table(destination_identifier, true);
2130
else // Standard table which will require locks.
2132
Table *name_lock= 0;
2134
if (session->lock_table_name_if_not_cached(destination_identifier, &name_lock))
2138
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* unlink open tables for create table like*/
2139
session->unlink_open_table(name_lock);
2149
else if (plugin::StorageEngine::doesTableExist(*session, destination_identifier))
2153
else // Otherwise we create the table
2157
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* We lock for CREATE TABLE LIKE to copy table definition */
2158
was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
2159
source_identifier, is_engine_set);
2162
// So we blew the creation of the table, and we scramble to clean up
2163
// anything that might have been created (read... it is a hack)
2164
if (not was_created)
2166
plugin::StorageEngine::dropTable(*session, destination_identifier);
2943
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
2945
if (find_temporary_table(thd, db, table_name))
2947
dst_path_length= build_tmptable_filename(thd, dst_path, sizeof(dst_path));
2948
create_info->table_options|= HA_CREATE_DELAY_KEY_WRITE;
2952
if (lock_table_name_if_not_cached(thd, db, table_name, &name_lock))
2956
dst_path_length= build_table_filename(dst_path, sizeof(dst_path),
2957
db, table_name, reg_ext, 0);
2958
if (!access(dst_path, F_OK))
2963
Create a new table by copying from source table
2965
Altough exclusive name-lock on target table protects us from concurrent
2966
DML and DDL operations on it we still want to wrap .FRM creation and call
2967
to ha_create_table() in critical section protected by LOCK_open in order
2968
to provide minimal atomicity against operations which disregard name-locks,
2969
like I_S implementation, for example. This is a temporary and should not
2970
be copied. Instead we should fix our code to always honor name-locks.
2972
Also some engines (e.g. NDB cluster) require that LOCK_open should be held
2973
during the call to ha_create_table(). See bug #28614 for more info.
2975
VOID(pthread_mutex_lock(&LOCK_open));
2976
if (src_table->schema_table)
2978
if (mysql_create_like_schema_frm(thd, src_table, dst_path, create_info))
2980
VOID(pthread_mutex_unlock(&LOCK_open));
2984
else if (my_copy(src_path, dst_path, MYF(MY_DONT_OVERWRITE_FILE)))
2986
if (my_errno == ENOENT)
2987
my_error(ER_BAD_DB_ERROR,MYF(0),db);
2989
my_error(ER_CANT_CREATE_FILE,MYF(0),dst_path,my_errno);
2990
VOID(pthread_mutex_unlock(&LOCK_open));
2995
As mysql_truncate don't work on a new table at this stage of
2996
creation, instead create the table directly (for both normal
2997
and temporary tables).
2999
dst_path[dst_path_length - reg_ext_length]= '\0'; // Remove .frm
3000
if (thd->variables.keep_files_on_create)
3001
create_info->options|= HA_CREATE_KEEP_FILES;
3002
err= ha_create_table(thd, dst_path, db, table_name, create_info, 1);
3003
VOID(pthread_mutex_unlock(&LOCK_open));
3005
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
3007
if (err || !open_temporary_table(thd, dst_path, db, table_name, 1,
3010
(void) rm_temporary_table(create_info->db_type,
3011
dst_path, false); /* purecov: inspected */
3012
goto err; /* purecov: inspected */
3017
(void) quick_rm_table(create_info->db_type, db,
3018
table_name, 0); /* purecov: inspected */
3019
goto err; /* purecov: inspected */
3023
We have to write the query before we unlock the tables.
3025
if (thd->current_stmt_binlog_row_based)
3028
Since temporary tables are not replicated under row-based
3029
replication, CREATE TABLE ... LIKE ... needs special
3030
treatement. We have four cases to consider, according to the
3031
following decision table:
3033
==== ========= ========= ==============================
3034
Case Target Source Write to binary log
3035
==== ========= ========= ==============================
3036
1 normal normal Original statement
3037
2 normal temporary Generated statement
3038
3 temporary normal Nothing
3039
4 temporary temporary Nothing
3040
==== ========= ========= ==============================
3042
if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
3044
if (src_table->table->s->tmp_table) // Case 2
3047
String query(buf, sizeof(buf), system_charset_info);
3048
query.length(0); // Have to zero it since constructor doesn't
3052
Here we open the destination table, on which we already have
3053
name-lock. This is needed for store_create_info() to work.
3054
The table will be closed by unlink_open_table() at the end
3057
table->table= name_lock;
3058
VOID(pthread_mutex_lock(&LOCK_open));
3059
if (reopen_name_locked_table(thd, table, false))
3061
VOID(pthread_mutex_unlock(&LOCK_open));
3064
VOID(pthread_mutex_unlock(&LOCK_open));
3066
int result= store_create_info(thd, table, &query,
3069
assert(result == 0); // store_create_info() always return 0
3070
write_bin_log(thd, true, query.ptr(), query.length());
3073
write_bin_log(thd, true, thd->query, thd->query_length);
3076
Case 3 and 4 does nothing under RBR
3080
write_bin_log(thd, true, thd->query, thd->query_length);
3086
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
3088
char warn_buff[DRIZZLE_ERRMSG_SIZE];
3089
snprintf(warn_buff, sizeof(warn_buff),
3090
ER(ER_TABLE_EXISTS_ERROR), table_name);
3091
push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
3092
ER_TABLE_EXISTS_ERROR,warn_buff);
3096
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
3101
pthread_mutex_lock(&LOCK_open);
3102
unlink_open_table(thd, name_lock, false);
3103
pthread_mutex_unlock(&LOCK_open);
3109
bool mysql_analyze_table(THD* thd, TableList* tables, HA_CHECK_OPT* check_opt)
3111
thr_lock_type lock_type = TL_READ_NO_INSERT;
3113
return(mysql_admin_table(thd, tables, check_opt,
3114
"analyze", lock_type, 1, 0, 0, 0,
3115
&handler::ha_analyze));
3119
bool mysql_check_table(THD* thd, TableList* tables,HA_CHECK_OPT* check_opt)
3121
thr_lock_type lock_type = TL_READ_NO_INSERT;
3123
return(mysql_admin_table(thd, tables, check_opt,
3125
0, 0, HA_OPEN_FOR_REPAIR, 0,
3126
&handler::ha_check));
3130
/* table_list should contain just one table */
3132
mysql_discard_or_import_tablespace(THD *thd,
3133
TableList *table_list,
3134
enum tablespace_op_type tablespace_op)
3141
Note that DISCARD/IMPORT TABLESPACE always is the only operation in an
3145
thd_proc_info(thd, "discard_or_import_tablespace");
3147
discard= test(tablespace_op == DISCARD_TABLESPACE);
3150
We set this flag so that ha_innobase::open and ::external_lock() do
3151
not complain when we lock the table
3153
thd->tablespace_op= true;
3154
if (!(table=open_ltable(thd, table_list, TL_WRITE, 0)))
3156
thd->tablespace_op=false;
3160
error= table->file->ha_discard_or_import_tablespace(discard);
3162
thd_proc_info(thd, "end");
3167
/* The ALTER Table is always in its own transaction */
3168
error = ha_autocommit_or_rollback(thd, 0);
3169
if (end_active_trans(thd))
3173
write_bin_log(thd, false, thd->query, thd->query_length);
3176
ha_autocommit_or_rollback(thd, error);
3177
thd->tablespace_op=false;
3185
table->file->print_error(error, MYF(0));
3191
Copy all changes detected by parser to the HA_ALTER_FLAGS
3194
void setup_ha_alter_flags(Alter_info *alter_info, HA_ALTER_FLAGS *alter_flags)
3196
uint flags= alter_info->flags;
3198
if (ALTER_ADD_COLUMN & flags)
3199
*alter_flags|= HA_ADD_COLUMN;
3200
if (ALTER_DROP_COLUMN & flags)
3201
*alter_flags|= HA_DROP_COLUMN;
3202
if (ALTER_RENAME & flags)
3203
*alter_flags|= HA_RENAME_TABLE;
3204
if (ALTER_CHANGE_COLUMN & flags)
3205
*alter_flags|= HA_CHANGE_COLUMN;
3206
if (ALTER_COLUMN_DEFAULT & flags)
3207
*alter_flags|= HA_COLUMN_DEFAULT_VALUE;
3208
if (ALTER_COLUMN_STORAGE & flags)
3209
*alter_flags|= HA_COLUMN_STORAGE;
3210
if (ALTER_COLUMN_FORMAT & flags)
3211
*alter_flags|= HA_COLUMN_FORMAT;
3212
if (ALTER_COLUMN_ORDER & flags)
3213
*alter_flags|= HA_ALTER_COLUMN_ORDER;
3214
if (ALTER_STORAGE & flags)
3215
*alter_flags|= HA_ALTER_STORAGE;
3216
if (ALTER_ROW_FORMAT & flags)
3217
*alter_flags|= HA_ALTER_ROW_FORMAT;
3218
if (ALTER_RECREATE & flags)
3219
*alter_flags|= HA_RECREATE;
3220
if (ALTER_FOREIGN_KEY & flags)
3221
*alter_flags|= HA_ALTER_FOREIGN_KEY;
3227
@param table The original table.
3228
@param alter_info Alter options, fields and keys for the new
3230
@param create_info Create options for the new table.
3231
@param order_num Number of order list elements.
3232
@param[out] ha_alter_flags Flags that indicate what will be changed
3233
@param[out] ha_alter_info Data structures needed for on-line alter
3234
@param[out] table_changes Information about particular change
3236
First argument 'table' contains information of the original
3237
table, which includes all corresponding parts that the new
3238
table has in arguments create_list, key_list and create_info.
3240
By comparing the changes between the original and new table
3241
we can determine how much it has changed after ALTER Table
3242
and whether we need to make a copy of the table, or just change
3245
Mark any changes detected in the ha_alter_flags.
3247
If there are no data changes, but index changes, 'index_drop_buffer'
3248
and/or 'index_add_buffer' are populated with offsets into
3249
table->key_info or key_info_buffer respectively for the indexes
3250
that need to be dropped and/or (re-)created.
3253
@retval false success
3258
compare_tables(THD *thd,
3260
Alter_info *alter_info,
3261
HA_CREATE_INFO *create_info,
3263
HA_ALTER_FLAGS *alter_flags,
3264
HA_ALTER_INFO *ha_alter_info,
3265
uint *table_changes)
3267
Field **f_ptr, *field;
3268
uint table_changes_local= 0;
3269
List_iterator_fast<Create_field> new_field_it(alter_info->create_list);
3270
Create_field *new_field;
3271
KEY_PART_INFO *key_part;
3274
Remember if the new definition has new VARCHAR column;
3275
create_info->varchar will be reset in mysql_prepare_create_table.
3277
bool varchar= create_info->varchar;
3281
Create a copy of alter_info.
3282
To compare the new and old table definitions, we need to "prepare"
3283
the new definition - transform it from parser output to a format
3284
that describes the final table layout (all column defaults are
3285
initialized, duplicate columns are removed). This is done by
3286
mysql_prepare_create_table. Unfortunately,
3287
mysql_prepare_create_table performs its transformations
3288
"in-place", that is, modifies the argument. Since we would
3289
like to keep compare_tables() idempotent (not altering any
3290
of the arguments) we create a copy of alter_info here and
3291
pass it to mysql_prepare_create_table, then use the result
3292
to evaluate possibility of fast ALTER Table, and then
3295
Alter_info tmp_alter_info(*alter_info, thd->mem_root);
3296
THD *thd= table->in_use;
3297
uint db_options= 0; /* not used */
3298
/* Create the prepared information. */
3299
if (mysql_prepare_create_table(thd, create_info,
3301
(table->s->tmp_table != NO_TMP_TABLE),
3304
&ha_alter_info->key_info_buffer,
3305
&ha_alter_info->key_count,
3306
/* select_field_count */ 0))
3308
/* Allocate result buffers. */
3309
if (! (ha_alter_info->index_drop_buffer=
3310
(uint*) thd->alloc(sizeof(uint) * table->s->keys)) ||
3311
! (ha_alter_info->index_add_buffer=
3312
(uint*) thd->alloc(sizeof(uint) *
3313
tmp_alter_info.key_list.elements)))
3317
First we setup ha_alter_flags based on what was detected
3320
setup_ha_alter_flags(alter_info, alter_flags);
3324
Some very basic checks. If number of fields changes, or the
3325
handler, we need to run full ALTER Table. In the future
3326
new fields can be added and old dropped without copy, but
3329
Test also that engine was not given during ALTER Table, or
3330
we are force to run regular alter table (copy).
3331
E.g. ALTER Table tbl_name ENGINE=MyISAM.
3333
For the following ones we also want to run regular alter table:
3334
ALTER Table tbl_name order_st BY ..
3335
ALTER Table tbl_name CONVERT TO CHARACTER SET ..
3337
At the moment we can't handle altering temporary tables without a copy.
3338
We also test if OPTIMIZE Table was given and was mapped to alter table.
3339
In that case we always do full copy.
3341
There was a bug prior to mysql-4.0.25. Number of null fields was
3342
calculated incorrectly. As a result frm and data files gets out of
3343
sync after fast alter table. There is no way to determine by which
3344
mysql version (in 4.0 and 4.1 branches) table was created, thus we
3345
disable fast alter table for all tables created by mysql versions
3346
prior to 5.0 branch.
3349
if (table->s->fields != alter_info->create_list.elements ||
3350
table->s->db_type() != create_info->db_type ||
3351
table->s->tmp_table ||
3352
create_info->used_fields & HA_CREATE_USED_ENGINE ||
3353
create_info->used_fields & HA_CREATE_USED_CHARSET ||
3354
create_info->used_fields & HA_CREATE_USED_DEFAULT_CHARSET ||
3355
create_info->used_fields & HA_CREATE_USED_ROW_FORMAT ||
3356
(alter_info->flags & (ALTER_RECREATE | ALTER_FOREIGN_KEY)) ||
3358
!table->s->mysql_version ||
3359
(table->s->frm_version < FRM_VER_TRUE_VARCHAR && varchar))
3361
*table_changes= IS_EQUAL_NO;
3363
Check what has changed and set alter_flags
3365
if (table->s->fields < alter_info->create_list.elements)
3366
*alter_flags|= HA_ADD_COLUMN;
3367
else if (table->s->fields > alter_info->create_list.elements)
3368
*alter_flags|= HA_DROP_COLUMN;
3369
if (create_info->db_type != table->s->db_type() ||
3370
create_info->used_fields & HA_CREATE_USED_ENGINE)
3371
*alter_flags|= HA_ALTER_STORAGE_ENGINE;
3372
if (create_info->used_fields & HA_CREATE_USED_CHARSET)
3373
*alter_flags|= HA_CHANGE_CHARACTER_SET;
3374
if (create_info->used_fields & HA_CREATE_USED_DEFAULT_CHARSET)
3375
*alter_flags|= HA_SET_DEFAULT_CHARACTER_SET;
3376
if (alter_info->flags & ALTER_RECREATE)
3377
*alter_flags|= HA_RECREATE;
3378
/* TODO check for ADD/DROP FOREIGN KEY */
3379
if (alter_info->flags & ALTER_FOREIGN_KEY)
3380
*alter_flags|= HA_ALTER_FOREIGN_KEY;
3381
if (!table->s->mysql_version ||
3382
(table->s->frm_version < FRM_VER_TRUE_VARCHAR && varchar))
3383
*alter_flags|= HA_ALTER_COLUMN_TYPE;
3386
Go through fields and check if the original ones are compatible
3389
for (f_ptr= table->field, new_field= new_field_it++;
3390
(new_field && (field= *f_ptr));
3391
f_ptr++, new_field= new_field_it++)
3393
/* Make sure we have at least the default charset in use. */
3394
if (!new_field->charset)
3395
new_field->charset= create_info->default_table_charset;
3397
/* Don't pack rows in old tables if the user has requested this. */
3398
if (create_info->row_type == ROW_TYPE_DYNAMIC ||
3399
(new_field->flags & BLOB_FLAG) ||
3400
(new_field->sql_type == DRIZZLE_TYPE_VARCHAR && create_info->row_type != ROW_TYPE_FIXED))
3401
create_info->table_options|= HA_OPTION_PACK_RECORD;
3403
/* Check how fields have been modified */
3404
if (alter_info->flags & ALTER_CHANGE_COLUMN)
3406
/* Evaluate changes bitmap and send to check_if_incompatible_data() */
3407
if (!(table_changes_local= field->is_equal(new_field)))
3408
*alter_flags|= HA_ALTER_COLUMN_TYPE;
3410
/* Check if field was renamed */
3411
field->flags&= ~FIELD_IS_RENAMED;
3412
if (my_strcasecmp(system_charset_info,
3414
new_field->field_name))
3416
field->flags|= FIELD_IS_RENAMED;
3417
*alter_flags|= HA_ALTER_COLUMN_NAME;
3420
*table_changes&= table_changes_local;
3421
if (table_changes_local == IS_EQUAL_PACK_LENGTH)
3422
*alter_flags|= HA_ALTER_COLUMN_TYPE;
3424
/* Check that NULL behavior is same for old and new fields */
3425
if ((new_field->flags & NOT_NULL_FLAG) !=
3426
(uint) (field->flags & NOT_NULL_FLAG))
3428
*table_changes= IS_EQUAL_NO;
3429
*alter_flags|= HA_ALTER_COLUMN_NULLABLE;
3433
/* Clear indexed marker */
3434
field->flags&= ~FIELD_IN_ADD_INDEX;
3438
Go through keys and check if the original ones are compatible
3442
KEY *table_key_end= table->key_info + table->s->keys;
3445
ha_alter_info->key_info_buffer + ha_alter_info->key_count;
3448
Step through all keys of the old table and search matching new keys.
3450
ha_alter_info->index_drop_count= 0;
3451
ha_alter_info->index_add_count= 0;
3452
for (table_key= table->key_info; table_key < table_key_end; table_key++)
3454
KEY_PART_INFO *table_part;
3455
KEY_PART_INFO *table_part_end= table_key->key_part + table_key->key_parts;
3456
KEY_PART_INFO *new_part;
3458
/* Search a new key with the same name. */
3459
for (new_key= ha_alter_info->key_info_buffer;
3460
new_key < new_key_end;
3463
if (! strcmp(table_key->name, new_key->name))
3466
if (new_key >= new_key_end)
3468
/* Key not found. Add the offset of the key to the drop buffer. */
3469
ha_alter_info->index_drop_buffer
3470
[ha_alter_info->index_drop_count++]=
3471
table_key - table->key_info;
3472
if (table_key->flags & HA_NOSAME)
3474
/* Unique key. Check for "PRIMARY". */
3475
if (! my_strcasecmp(system_charset_info,
3476
table_key->name, primary_key_name))
3477
*alter_flags|= HA_DROP_PK_INDEX;
3479
*alter_flags|= HA_DROP_UNIQUE_INDEX;
3482
*alter_flags|= HA_DROP_INDEX;
3483
*table_changes= IS_EQUAL_NO;
3487
/* Check that the key types are compatible between old and new tables. */
3488
if ((table_key->algorithm != new_key->algorithm) ||
3489
((table_key->flags & HA_KEYFLAG_MASK) !=
3490
(new_key->flags & HA_KEYFLAG_MASK)) ||
3491
(table_key->key_parts != new_key->key_parts))
3493
if (table_key->flags & HA_NOSAME)
3495
// Unique key. Check for "PRIMARY".
3496
if (! my_strcasecmp(system_charset_info,
3497
table_key->name, primary_key_name))
3498
*alter_flags|= HA_ALTER_PK_INDEX;
3500
*alter_flags|= HA_ALTER_UNIQUE_INDEX;
3503
*alter_flags|= HA_ALTER_INDEX;
3508
Check that the key parts remain compatible between the old and
3511
for (table_part= table_key->key_part, new_part= new_key->key_part;
3512
table_part < table_part_end;
3513
table_part++, new_part++)
3516
Key definition has changed if we are using a different field or
3517
if the used key part length is different. We know that the fields
3518
did not change. Comparing field numbers is sufficient.
3520
if ((table_part->length != new_part->length) ||
3521
(table_part->fieldnr - 1 != new_part->fieldnr))
3523
if (table_key->flags & HA_NOSAME)
3525
/* Unique key. Check for "PRIMARY" */
3526
if (! my_strcasecmp(system_charset_info,
3527
table_key->name, primary_key_name))
3528
*alter_flags|= HA_ALTER_PK_INDEX;
3530
*alter_flags|= HA_ALTER_UNIQUE_INDEX;
3533
*alter_flags|= HA_ALTER_INDEX;
3540
/* Key modified. Add the offset of the key to both buffers. */
3541
ha_alter_info->index_drop_buffer
3542
[ha_alter_info->index_drop_count++]=
3543
table_key - table->key_info;
3544
ha_alter_info->index_add_buffer
3545
[ha_alter_info->index_add_count++]=
3546
new_key - ha_alter_info->key_info_buffer;
3547
key_part= new_key->key_part;
3548
end= key_part + new_key->key_parts;
3549
for(; key_part != end; key_part++)
3551
/* Mark field to be part of new key */
3552
if ((field= table->field[key_part->fieldnr]))
3553
field->flags|= FIELD_IN_ADD_INDEX;
3555
*table_changes= IS_EQUAL_NO;
3557
/*end of for (; table_key < table_key_end;) */
3560
Step through all keys of the new table and find matching old keys.
3562
for (new_key= ha_alter_info->key_info_buffer;
3563
new_key < new_key_end;
3566
/* Search an old key with the same name. */
3567
for (table_key= table->key_info; table_key < table_key_end; table_key++)
3569
if (! strcmp(table_key->name, new_key->name))
3572
if (table_key >= table_key_end)
3574
/* Key not found. Add the offset of the key to the add buffer. */
3575
ha_alter_info->index_add_buffer
3576
[ha_alter_info->index_add_count++]=
3577
new_key - ha_alter_info->key_info_buffer;
3578
key_part= new_key->key_part;
3579
end= key_part + new_key->key_parts;
3580
for(; key_part != end; key_part++)
3582
/* Mark field to be part of new key */
3583
if ((field= table->field[key_part->fieldnr]))
3584
field->flags|= FIELD_IN_ADD_INDEX;
3586
if (new_key->flags & HA_NOSAME)
3588
/* Unique key. Check for "PRIMARY" */
3589
if (! my_strcasecmp(system_charset_info,
3590
new_key->name, primary_key_name))
3591
*alter_flags|= HA_ADD_PK_INDEX;
3593
*alter_flags|= HA_ADD_UNIQUE_INDEX;
3596
*alter_flags|= HA_ADD_INDEX;
3597
*table_changes= IS_EQUAL_NO;
3606
Manages enabling/disabling of indexes for ALTER Table
3609
alter_table_manage_keys()
3611
indexes_were_disabled Whether the indexes of the from table
3613
keys_onoff ENABLE | DISABLE | LEAVE_AS_IS
3621
bool alter_table_manage_keys(Table *table, int indexes_were_disabled,
3622
enum enum_enable_or_disable keys_onoff)
3625
switch (keys_onoff) {
3627
error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
3630
if (!indexes_were_disabled)
3632
/* fall-through: disabled indexes */
3634
error= table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
3637
if (error == HA_ERR_WRONG_COMMAND)
3639
push_warning_printf(current_thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
3640
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
3641
table->s->table_name.str);
3644
table->file->print_error(error, MYF(0));
3649
int create_temporary_table(THD *thd,
3653
HA_CREATE_INFO *create_info,
3654
Alter_info *alter_info,
3658
char index_file[FN_REFLEN], data_file[FN_REFLEN];
3659
handlerton *old_db_type, *new_db_type;
3660
old_db_type= table->s->db_type();
3661
new_db_type= create_info->db_type;
3663
Handling of symlinked tables:
3665
Create new data file and index file on the same disk as the
3666
old data and index files.
3668
Rename new data file over old data file and new index file over
3670
Symlinks are not changed.
3673
Create new data file and index file on the same disk as the
3674
old data and index files. Create also symlinks to point at
3677
At end, rename intermediate tables, and symlinks to intermediate
3678
table, to final table name.
3679
Remove old table and old symlinks
3681
If rename is made to another database:
3682
Create new tables in new database.
3684
Remove old table and symlinks.
3686
if (db_changed) // Ignore symlink if db changed
3688
if (create_info->index_file_name)
3690
/* Fix index_file_name to have 'tmp_name' as basename */
3691
stpcpy(index_file, tmp_name);
3692
create_info->index_file_name=fn_same(index_file,
3693
create_info->index_file_name,
3696
if (create_info->data_file_name)
3698
/* Fix data_file_name to have 'tmp_name' as basename */
3699
stpcpy(data_file, tmp_name);
3700
create_info->data_file_name=fn_same(data_file,
3701
create_info->data_file_name,
3706
create_info->data_file_name=create_info->index_file_name=0;
3709
Create a table with a temporary name.
3710
With create_info->frm_only == 1 this creates a .frm file only.
3711
We don't log the statement, it will be logged later.
3713
tmp_disable_binlog(thd);
3714
error= mysql_create_table(thd, new_db, tmp_name,
3715
create_info, alter_info, 1, 0);
3716
reenable_binlog(thd);
3722
Create a temporary table that reflects what an alter table operation
3726
create_altered_table()
3728
table The original table
3729
create_info Information from the parsing phase about new
3731
alter_info Lists of fields, keys to be changed, added
3733
db_change Specifies if the table is moved to another database
3735
A temporary table with all changes
3738
The temporary table is created without storing it in any storage engine
3739
and is opened only to get the table struct and frm file reference.
3741
Table *create_altered_table(THD *thd,
3744
HA_CREATE_INFO *create_info,
3745
Alter_info *alter_info,
3749
HA_CREATE_INFO altered_create_info(*create_info);
3750
Table *altered_table;
3752
char path[FN_REFLEN];
3754
snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%lx",
3755
tmp_file_prefix, current_pid, thd->thread_id);
3756
/* Safety fix for InnoDB */
3757
if (lower_case_table_names)
3758
my_casedn_str(files_charset_info, tmp_name);
3759
altered_create_info.options&= ~HA_LEX_CREATE_TMP_TABLE;
3760
altered_create_info.frm_only= 1;
3761
if ((error= create_temporary_table(thd, table, new_db, tmp_name,
3762
&altered_create_info,
3763
alter_info, db_change)))
3768
build_table_filename(path, sizeof(path), new_db, tmp_name, "",
3770
altered_table= open_temporary_table(thd, path, new_db, tmp_name, 1,
3772
return(altered_table);
3779
Perform a fast or on-line alter table
3782
mysql_fast_or_online_alter_table()
3784
table The original table
3785
altered_table A temporary table showing how we will change table
3786
create_info Information from the parsing phase about new
3788
alter_info Storage place for data used during different phases
3789
ha_alter_flags Bitmask that shows what will be changed
3790
keys_onoff Specifies if keys are to be enabled/disabled
3793
>0 An error occured during the on-line alter table operation
3794
-1 Error when re-opening table
3796
If mysql_alter_table does not need to copy the table, it is
3797
either a fast alter table where the storage engine does not
3798
need to know about the change, only the frm will change,
3799
or the storage engine supports performing the alter table
3800
operation directly, on-line without mysql having to copy
3803
int mysql_fast_or_online_alter_table(THD *thd,
3805
Table *altered_table,
3806
HA_CREATE_INFO *create_info,
3807
HA_ALTER_INFO *alter_info,
3808
HA_ALTER_FLAGS *ha_alter_flags,
3809
enum enum_enable_or_disable keys_onoff)
3812
bool online= (table->file->ha_table_flags() & HA_ONLINE_ALTER)?true:false;
3818
Tell the handler to prepare for the online alter
3820
if ((error= table->file->alter_table_phase1(thd,
3830
Tell the storage engine to perform the online alter table
3832
if check_if_supported_alter() returned HA_ALTER_SUPPORTED_WAIT_LOCK
3833
we need to wrap the next call with a DDL lock.
3835
if ((error= table->file->alter_table_phase2(thd,
3845
The final .frm file is already created as a temporary file
3846
and will be renamed to the original table name.
3848
VOID(pthread_mutex_lock(&LOCK_open));
3849
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
3850
alter_table_manage_keys(table, table->file->indexes_are_disabled(),
3852
close_data_files_and_morph_locks(thd,
3853
table->pos_in_table_list->db,
3854
table->pos_in_table_list->table_name);
3855
if (mysql_rename_table(NULL,
3856
altered_table->s->db.str,
3857
altered_table->s->table_name.str,
3859
table->s->table_name.str, FN_FROM_IS_TMP))
3862
VOID(pthread_mutex_unlock(&LOCK_open));
3865
broadcast_refresh();
3866
VOID(pthread_mutex_unlock(&LOCK_open));
3869
The ALTER Table is always in its own transaction.
3870
Commit must not be called while LOCK_open is locked. It could call
3871
wait_if_global_read_lock(), which could create a deadlock if called
3874
error= ha_autocommit_or_rollback(thd, 0);
3882
VOID(pthread_mutex_lock(&LOCK_open));
3883
if (reopen_table(table))
3888
VOID(pthread_mutex_unlock(&LOCK_open));
3892
Tell the handler that the changed frm is on disk and table
3895
if ((error= t_table->file->alter_table_phase3(thd, t_table)))
3901
We are going to reopen table down on the road, so we have to restore
3902
state of the Table object which we used for obtaining of handler
3903
object to make it suitable for reopening.
3905
assert(t_table == table);
3906
table->open_placeholder= 1;
3907
VOID(pthread_mutex_lock(&LOCK_open));
3908
close_handle_and_leave_table_as_lock(table);
3909
VOID(pthread_mutex_unlock(&LOCK_open));
3920
Prepare column and key definitions for CREATE TABLE in ALTER Table.
3922
This function transforms parse output of ALTER Table - lists of
3923
columns and keys to add, drop or modify into, essentially,
3924
CREATE TABLE definition - a list of columns and keys of the new
3925
table. While doing so, it also performs some (bug not all)
3928
This function is invoked when we know that we're going to
3929
perform ALTER Table via a temporary table -- i.e. fast ALTER Table
3930
is not possible, perhaps because the ALTER statement contains
3931
instructions that require change in table data, not only in
3932
table definition or indexes.
3934
@param[in,out] thd thread handle. Used as a memory pool
3935
and source of environment information.
3936
@param[in] table the source table, open and locked
3937
Used as an interface to the storage engine
3938
to acquire additional information about
3940
@param[in,out] create_info A blob with CREATE/ALTER Table
3942
@param[in,out] alter_info Another blob with ALTER/CREATE parameters.
3943
Originally create_info was used only in
3944
CREATE TABLE and alter_info only in ALTER Table.
3945
But since ALTER might end-up doing CREATE,
3946
this distinction is gone and we just carry
3947
around two structures.
3950
Fills various create_info members based on information retrieved
3951
from the storage engine.
3952
Sets create_info->varchar if the table has a VARCHAR column.
3953
Prepares alter_info->create_list and alter_info->key_list with
3954
columns and keys of the new table.
3955
@retval true error, out of memory or a semantical error in ALTER
3957
@retval false success
3961
mysql_prepare_alter_table(THD *thd, Table *table,
3962
HA_CREATE_INFO *create_info,
3963
Alter_info *alter_info)
3965
/* New column definitions are added here */
3966
List<Create_field> new_create_list;
3967
/* New key definitions are added here */
3968
List<Key> new_key_list;
3969
List_iterator<Alter_drop> drop_it(alter_info->drop_list);
3970
List_iterator<Create_field> def_it(alter_info->create_list);
3971
List_iterator<Alter_column> alter_it(alter_info->alter_list);
3972
List_iterator<Key> key_it(alter_info->key_list);
3973
List_iterator<Create_field> find_it(new_create_list);
3974
List_iterator<Create_field> field_it(new_create_list);
3975
List<Key_part_spec> key_parts;
3976
uint db_create_options= (table->s->db_create_options
3977
& ~(HA_OPTION_PACK_RECORD));
3978
uint used_fields= create_info->used_fields;
3979
KEY *key_info=table->key_info;
3983
create_info->varchar= false;
3984
/* Let new create options override the old ones */
3985
if (!(used_fields & HA_CREATE_USED_MIN_ROWS))
3986
create_info->min_rows= table->s->min_rows;
3987
if (!(used_fields & HA_CREATE_USED_MAX_ROWS))
3988
create_info->max_rows= table->s->max_rows;
3989
if (!(used_fields & HA_CREATE_USED_AVG_ROW_LENGTH))
3990
create_info->avg_row_length= table->s->avg_row_length;
3991
if (!(used_fields & HA_CREATE_USED_BLOCK_SIZE))
3992
create_info->block_size= table->s->block_size;
3993
if (!(used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
3994
create_info->default_table_charset= table->s->table_charset;
3995
if (!(used_fields & HA_CREATE_USED_AUTO) && table->found_next_number_field)
3997
/* Table has an autoincrement, copy value to new table */
3998
table->file->info(HA_STATUS_AUTO);
3999
create_info->auto_increment_value= table->file->stats.auto_increment_value;
4001
if (!(used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE))
4002
create_info->key_block_size= table->s->key_block_size;
4003
if (!(used_fields & HA_CREATE_USED_TRANSACTIONAL))
4004
create_info->transactional= table->s->transactional;
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 (uint 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 (uint 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
uint 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
uint 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_proc_info(thd, "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, NullS);
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
stpcpy(new_name_buff,new_name);
4430
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_proc_info(thd, "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
VOID(pthread_mutex_lock(&LOCK_open));
4532
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
4533
VOID(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
VOID(pthread_mutex_lock(&LOCK_open));
4539
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
4540
VOID(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
VOID(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_proc_info(thd, "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
VOID(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));
2176
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* unlink open tables for create table like*/
2177
session->unlink_open_table(name_lock);
2183
if (is_if_not_exists)
4621
unlink_open_table(thd, name_lock, false);
4622
VOID(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
uint 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_proc_info(thd, "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
VOID(pthread_mutex_lock(&LOCK_open));
4838
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
4839
VOID(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);
4877
my_free(new_table,MYF(0));
4879
VOID(pthread_mutex_lock(&LOCK_open));
4882
VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
4883
VOID(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_proc_info(thd, "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
VOID(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
VOID(quick_rm_table(new_db_type,new_db,new_alias, 0));
4940
VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
4941
VOID(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
VOID(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
VOID(pthread_mutex_unlock(&LOCK_open));
4964
thd_proc_info(thd, "end");
4966
ha_binlog_log_query(thd, create_info->db_type, LOGCOM_ALTER_TABLE,
4967
thd->query, thd->query_length,
4970
assert(!(mysql_bin_log.is_open() &&
4971
thd->current_stmt_binlog_row_based &&
4972
(create_info->options & HA_LEX_CREATE_TMP_TABLE)));
4973
write_bin_log(thd, true, thd->query, thd->query_length);
4975
if (ha_check_storage_engine_flag(old_db_type, HTON_FLUSH_AFTER_RENAME))
4978
For the alter table to be properly flushed to the logs, we
4979
have to open the new table. If not, we get a problem on server
4980
shutdown. But we do not need to attach MERGE children.
4982
char path[FN_REFLEN];
4984
build_table_filename(path, sizeof(path), new_db, table_name, "", 0);
4985
t_table= open_temporary_table(thd, path, new_db, tmp_name, false, OTM_OPEN);
4988
intern_close_table(t_table);
4989
my_free(t_table, MYF(0));
4992
sql_print_warning(_("Could not open table %s.%s after rename\n"),
4994
ha_flush_logs(old_db_type);
4996
table_list->table=0; // For query cache
4998
if (thd->locked_tables && (new_name != table_name || new_db != db))
5001
If are we under LOCK TABLES and did ALTER Table with RENAME we need
5002
to remove placeholders for the old table and for the target table
5003
from the list of open tables and table cache. If we are not under
5004
LOCK TABLES we can rely on close_thread_tables() doing this job.
5006
pthread_mutex_lock(&LOCK_open);
5007
unlink_open_table(thd, table, false);
5008
unlink_open_table(thd, name_lock, false);
5009
pthread_mutex_unlock(&LOCK_open);
5013
snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
5014
(ulong) (copied + deleted), (ulong) deleted,
5015
(ulong) thd->cuted_fields);
5016
my_ok(thd, copied + deleted, 0L, tmp_name);
5017
thd->some_tables_deleted=0;
5023
/* close_temporary_table() frees the new_table pointer. */
5024
close_temporary_table(thd, new_table, 1, 1);
5027
VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
5031
No default value was provided for a DATE/DATETIME field, the
5032
current sql_mode doesn't allow the '0000-00-00' value and
5033
the table to be altered isn't empty.
5036
if (alter_info->error_if_not_empty && thd->row_count)
5038
const char *f_val= 0;
5039
enum enum_drizzle_timestamp_type t_type= DRIZZLE_TIMESTAMP_DATE;
5040
switch (alter_info->datetime_field->sql_type)
5042
case DRIZZLE_TYPE_NEWDATE:
5043
f_val= "0000-00-00";
5044
t_type= DRIZZLE_TIMESTAMP_DATE;
5046
case DRIZZLE_TYPE_DATETIME:
5047
f_val= "0000-00-00 00:00:00";
5048
t_type= DRIZZLE_TIMESTAMP_DATETIME;
5051
/* Shouldn't get here. */
5054
bool save_abort_on_warning= thd->abort_on_warning;
5055
thd->abort_on_warning= true;
5056
make_truncated_value_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5057
f_val, strlength(f_val), t_type,
5058
alter_info->datetime_field->field_name);
5059
thd->abort_on_warning= save_abort_on_warning;
5063
pthread_mutex_lock(&LOCK_open);
5064
unlink_open_table(thd, name_lock, false);
5065
pthread_mutex_unlock(&LOCK_open);
5069
err_with_placeholders:
5071
An error happened while we were holding exclusive name-lock on table
5072
being altered. To be safe under LOCK TABLES we should remove placeholders
5073
from list of open tables list and table cache.
5075
unlink_open_table(thd, table, false);
5077
unlink_open_table(thd, name_lock, false);
5078
VOID(pthread_mutex_unlock(&LOCK_open));
5081
/* mysql_alter_table */
5084
copy_data_between_tables(Table *from,Table *to,
5085
List<Create_field> &create,
5087
uint order_num, order_st *order,
5090
enum enum_enable_or_disable keys_onoff,
5091
bool error_if_not_empty)
5094
Copy_field *copy,*copy_end;
5095
ulong found_count,delete_count;
5096
THD *thd= current_thd;
5098
SORT_FIELD *sortorder;
5102
List<Item> all_fields;
5103
ha_rows examined_rows;
5104
bool auto_increment_field_copied= 0;
5105
ulong save_sql_mode;
5106
uint64_t prev_insert_id;
5109
Turn off recovery logging since rollback of an alter table is to
5110
delete the new table so there is no need to log the changes to it.
5112
This needs to be done before external_lock
5114
error= ha_enable_transaction(thd, false);
5118
if (!(copy= new Copy_field[to->s->fields]))
5119
return(-1); /* purecov: inspected */
5121
if (to->file->ha_external_lock(thd, F_WRLCK))
5124
/* We need external lock before we can disable/enable keys */
5125
alter_table_manage_keys(to, from->file->indexes_are_disabled(), keys_onoff);
5127
/* We can abort alter table for any table type */
5128
thd->abort_on_warning= !ignore;
5130
from->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
5131
to->file->ha_start_bulk_insert(from->file->stats.records);
5133
save_sql_mode= thd->variables.sql_mode;
5135
List_iterator<Create_field> it(create);
5138
for (Field **ptr=to->field ; *ptr ; ptr++)
5143
if (*ptr == to->next_number_field)
5144
auto_increment_field_copied= true;
5146
(copy_end++)->set(*ptr,def->field,0);
5151
found_count=delete_count=0;
5155
if (to->s->primary_key != MAX_KEY && to->file->primary_key_is_clustered())
2185
5157
char warn_buff[DRIZZLE_ERRMSG_SIZE];
2186
snprintf(warn_buff, sizeof(warn_buff),
2187
ER(ER_TABLE_EXISTS_ERROR), destination_identifier.getTableName().c_str());
2188
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
2189
ER_TABLE_EXISTS_ERROR, warn_buff);
2193
my_error(ER_TABLE_EXISTS_ERROR, destination_identifier);
5158
snprintf(warn_buff, sizeof(warn_buff),
5159
_("order_st BY ignored because there is a user-defined clustered "
5160
"index in the table '%-.192s'"),
5161
from->s->table_name.str);
5162
push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
5167
from->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE),
5168
MYF(MY_FAE | MY_ZEROFILL));
5169
memset(&tables, 0, sizeof(tables));
5171
tables.alias= tables.table_name= from->s->table_name.str;
5172
tables.db= from->s->db.str;
5175
if (thd->lex->select_lex.setup_ref_array(thd, order_num) ||
5176
setup_order(thd, thd->lex->select_lex.ref_pointer_array,
5177
&tables, fields, all_fields, order) ||
5178
!(sortorder= make_unireg_sortorder(order, &length, NULL)) ||
5179
(from->sort.found_records= filesort(thd, from, sortorder, length,
5180
(SQL_SELECT *) 0, HA_POS_ERROR,
5181
1, &examined_rows)) ==
5187
/* Tell handler that we have values for all columns in the to table */
5188
to->use_all_columns();
5189
init_read_record(&info, thd, from, (SQL_SELECT *) 0, 1,1);
5191
to->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
5193
restore_record(to, s->default_values); // Create empty record
5194
while (!(error=info.read_record(&info)))
5198
thd->send_kill_message();
5203
/* Return error if source table isn't empty. */
5204
if (error_if_not_empty)
5209
if (to->next_number_field)
5211
if (auto_increment_field_copied)
5212
to->auto_increment_field_not_null= true;
5214
to->next_number_field->reset();
5217
for (Copy_field *copy_ptr=copy ; copy_ptr != copy_end ; copy_ptr++)
5219
copy_ptr->do_copy(copy_ptr);
5221
prev_insert_id= to->file->next_insert_id;
5222
error=to->file->ha_write_row(to->record[0]);
5223
to->auto_increment_field_not_null= false;
5227
to->file->is_fatal_error(error, HA_CHECK_DUP))
5229
if (!to->file->is_fatal_error(error, HA_CHECK_DUP))
5231
uint key_nr= to->file->get_dup_key(error);
5232
if ((int) key_nr >= 0)
5234
const char *err_msg= ER(ER_DUP_ENTRY_WITH_KEY_NAME);
5236
(to->key_info[0].key_part[0].field->flags &
5237
AUTO_INCREMENT_FLAG))
5238
err_msg= ER(ER_DUP_ENTRY_AUTOINCREMENT_CASE);
5239
to->file->print_keydup_error(key_nr, err_msg);
5244
to->file->print_error(error,MYF(0));
5247
to->file->restore_auto_increment(prev_insert_id);
5253
end_read_record(&info);
5254
free_io_cache(from);
5255
delete [] copy; // This is never 0
5257
if (to->file->ha_end_bulk_insert() && error <= 0)
5259
to->file->print_error(my_errno,MYF(0));
5262
to->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
5264
if (ha_enable_transaction(thd, true))
5271
Ensure that the new table is saved properly to disk so that we
5274
if (ha_autocommit_or_rollback(thd, 0))
5276
if (end_active_trans(thd))
5280
thd->variables.sql_mode= save_sql_mode;
5281
thd->abort_on_warning= 0;
5282
free_io_cache(from);
5283
*copied= found_count;
5284
*deleted=delete_count;
5285
to->file->ha_release_auto_increment();
5286
if (to->file->ha_external_lock(thd,F_UNLCK))
5288
return(error > 0 ? -1 : 0);
5293
Recreates tables by calling mysql_alter_table().
5296
mysql_recreate_table()
5298
tables Tables to recreate
5301
Like mysql_alter_table().
5303
bool mysql_recreate_table(THD *thd, TableList *table_list)
5305
HA_CREATE_INFO create_info;
5306
Alter_info alter_info;
5308
assert(!table_list->next_global);
5310
table_list->table has been closed and freed. Do not reference
5311
uninitialized data. open_tables() could fail.
5313
table_list->table= NULL;
5315
memset(&create_info, 0, sizeof(create_info));
5316
create_info.row_type=ROW_TYPE_NOT_USED;
5317
create_info.default_table_charset=default_charset_info;
5318
/* Force alter table to recreate table */
5319
alter_info.flags= (ALTER_CHANGE_COLUMN | ALTER_RECREATE);
5320
return(mysql_alter_table(thd, NullS, NullS, &create_info,
5321
table_list, &alter_info, 0,
5322
(order_st *) 0, 0));
5326
bool mysql_checksum_table(THD *thd, TableList *tables,
5327
HA_CHECK_OPT *check_opt)
5330
List<Item> field_list;
5332
Protocol *protocol= thd->protocol;
5334
field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
5335
item->maybe_null= 1;
5336
field_list.push_back(item= new Item_int("Checksum", (int64_t) 1,
5337
MY_INT64_NUM_DECIMAL_DIGITS));
5338
item->maybe_null= 1;
5339
if (protocol->send_fields(&field_list,
5340
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
5343
/* Open one table after the other to keep lock time as short as possible. */
5344
for (table= tables; table; table= table->next_local)
5346
char table_name[NAME_LEN*2+2];
5349
strxmov(table_name, table->db ,".", table->table_name, NullS);
5351
t= table->table= open_n_lock_single_table(thd, table, TL_READ);
5352
thd->clear_error(); // these errors shouldn't get client
5354
protocol->prepare_for_resend();
5355
protocol->store(table_name, system_charset_info);
5359
/* Table didn't exist */
5360
protocol->store_null();
5365
if (t->file->ha_table_flags() & HA_HAS_CHECKSUM &&
5366
!(check_opt->flags & T_EXTEND))
5367
protocol->store((uint64_t)t->file->checksum());
5368
else if (!(t->file->ha_table_flags() & HA_HAS_CHECKSUM) &&
5369
(check_opt->flags & T_QUICK))
5370
protocol->store_null();
5373
/* calculating table's checksum */
5375
uchar null_mask=256 - (1 << t->s->last_null_bit_pos);
5377
t->use_all_columns();
5379
if (t->file->ha_rnd_init(1))
5380
protocol->store_null();
5385
ha_checksum row_crc= 0;
5386
int error= t->file->rnd_next(t->record[0]);
5387
if (unlikely(error))
5389
if (error == HA_ERR_RECORD_DELETED)
5393
if (t->s->null_bytes)
5395
/* fix undefined null bits */
5396
t->record[0][t->s->null_bytes-1] |= null_mask;
5397
if (!(t->s->db_create_options & HA_OPTION_PACK_RECORD))
5398
t->record[0][0] |= 1;
5400
row_crc= my_checksum(row_crc, t->record[0], t->s->null_bytes);
5403
for (uint i= 0; i < t->s->fields; i++ )
5405
Field *f= t->field[i];
5406
if ((f->type() == DRIZZLE_TYPE_BLOB) ||
5407
(f->type() == DRIZZLE_TYPE_VARCHAR))
5411
row_crc= my_checksum(row_crc, (uchar*) tmp.ptr(), tmp.length());
5414
row_crc= my_checksum(row_crc, f->ptr,
5420
protocol->store((uint64_t)crc);
5421
t->file->ha_rnd_end();
5425
close_thread_tables(thd);
5426
table->table=0; // For query cache
5428
if (protocol->write())
5436
close_thread_tables(thd); // Shouldn't be needed
5442
static bool check_engine(THD *thd, const char *table_name,
5443
HA_CREATE_INFO *create_info)
5445
handlerton **new_engine= &create_info->db_type;
5446
handlerton *req_engine= *new_engine;
5447
bool no_substitution= 1;
5448
if (!(*new_engine= ha_checktype(thd, ha_legacy_type(req_engine),
5449
no_substitution, 1)))
2202
bool analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
2204
thr_lock_type lock_type = TL_READ_NO_INSERT;
2206
return(admin_table(session, tables, check_opt,
2207
"analyze", lock_type, true,
2208
&Cursor::ha_analyze));
2212
bool check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
2214
thr_lock_type lock_type = TL_READ_NO_INSERT;
2216
return(admin_table(session, tables, check_opt,
2219
&Cursor::ha_check));
2222
} /* namespace drizzled */
5452
if (req_engine && req_engine != *new_engine)
5454
push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
5455
ER_WARN_USING_OTHER_HANDLER,
5456
ER(ER_WARN_USING_OTHER_HANDLER),
5457
ha_resolve_storage_engine_name(*new_engine),
5460
if (create_info->options & HA_LEX_CREATE_TMP_TABLE &&
5461
ha_check_storage_engine_flag(*new_engine, HTON_TEMPORARY_NOT_SUPPORTED))
5463
if (create_info->used_fields & HA_CREATE_USED_ENGINE)
5465
my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
5466
ha_resolve_storage_engine_name(*new_engine), "TEMPORARY");
5470
*new_engine= myisam_hton;