3459
bool mysql_alter_table(Session *session, char *new_db, char *new_name,
3459
bool mysql_alter_table(Session *session,
3460
3462
HA_CREATE_INFO *create_info,
3461
3463
TableList *table_list,
3462
3464
Alter_info *alter_info,
3463
uint32_t order_num, order_st *order, bool ignore)
3465
Table *table, *new_table=0, *name_lock= 0;;
3470
Table *new_table= NULL;
3471
Table *name_lock= NULL;
3466
3472
string new_name_str;
3468
char tmp_name[80],old_name[32],new_name_buff[FN_REFLEN];
3469
char new_alias_buff[FN_REFLEN], *table_name, *db;
3476
char new_name_buff[FN_REFLEN];
3477
char new_alias_buff[FN_REFLEN];
3470
3480
const char *new_alias;
3471
3481
char path[FN_REFLEN];
3472
ha_rows copied= 0,deleted= 0;
3473
StorageEngine *old_db_type, *new_db_type, *save_old_db_type;
3484
StorageEngine *old_db_type;
3485
StorageEngine *new_db_type;
3486
StorageEngine *save_old_db_type;
3474
3487
bitset<32> tmp;
3476
3489
new_name_buff[0]= '\0';
3497
session->set_proc_info("init");
3485
3500
Assign variables table_name, new_name, db, new_db, path
3486
3501
to simplify further comparisons: we want to see if it's a RENAME
3487
3502
later just by comparing the pointers, avoiding the need for strcmp.
3489
session->set_proc_info("init");
3490
3504
table_name= table_list->table_name;
3492
if (!new_db || !my_strcasecmp(table_alias_charset, new_db, db))
3506
if (! new_db || ! my_strcasecmp(table_alias_charset, new_db, db))
3509
if (alter_info->tablespace_op != NO_TABLESPACE_OP)
3511
/* DISCARD/IMPORT TABLESPACE is always alone in an ALTER Table */
3512
return mysql_discard_or_import_tablespace(session, table_list, alter_info->tablespace_op);
3494
3515
build_table_filename(path, sizeof(path), db, table_name, false);
3496
/* DISCARD/IMPORT TABLESPACE is always alone in an ALTER Table */
3497
if (alter_info->tablespace_op != NO_TABLESPACE_OP)
3498
/* Conditionally writes to binlog. */
3499
return(mysql_discard_or_import_tablespace(session,table_list,
3500
alter_info->tablespace_op));
3501
3517
ostringstream oss;
3502
3518
oss << drizzle_data_home << "/" << db << "/" << table_name;
3504
3520
(void) unpack_filename(new_name_buff, oss.str().c_str());
3506
3523
If this is just a rename of a view, short cut to the
3507
3524
following scenario: 1) lock LOCK_open 2) do a RENAME
3528
3546
new_alias= new_alias_buff;
3530
3548
my_casedn_str(files_charset_info, new_name_buff);
3531
new_alias= new_name; // Create lower case table name
3549
new_alias= new_name; // Create lower case table name
3532
3550
my_casedn_str(files_charset_info, new_name);
3534
3552
if (new_db == db &&
3535
!my_strcasecmp(table_alias_charset, new_name_buff, table_name))
3553
! my_strcasecmp(table_alias_charset, new_name_buff, table_name))
3538
Source and destination table names are equal: make later check
3556
Source and destination table names are equal: make later check
3541
3559
new_alias= new_name= table_name;
3545
3563
if (table->s->tmp_table != NO_TMP_TABLE)
3547
if (session->find_temporary_table(new_db, new_name_buff))
3549
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name_buff);
3565
if (session->find_temporary_table(new_db, new_name_buff))
3567
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name_buff);
3555
3573
if (session->lock_table_name_if_not_cached(new_db, new_name, &name_lock))
3560
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
3578
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
3564
build_table_filename(new_name_buff, sizeof(new_name_buff),
3565
new_db, new_name_buff, false);
3582
build_table_filename(new_name_buff, sizeof(new_name_buff), new_db, new_name_buff, false);
3566
3584
if (StorageEngine::getTableProto(new_name_buff, NULL) == EEXIST)
3568
/* Table will be closed by Session::executeCommand() */
3569
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
3586
/* Table will be closed by Session::executeCommand() */
3587
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
3581
3599
old_db_type= table->s->db_type();
3582
if (!create_info->db_type)
3600
if (! create_info->db_type)
3584
3602
create_info->db_type= old_db_type;
3587
if(table->s->tmp_table != NO_TMP_TABLE)
3605
if (table->s->tmp_table != NO_TMP_TABLE)
3588
3606
create_info->options|= HA_LEX_CREATE_TMP_TABLE;
3590
3608
if (check_engine(session, new_name, create_info))
3592
3611
new_db_type= create_info->db_type;
3594
3613
if (new_db_type != old_db_type &&
3695
*fn_ext(new_name)=0;
3718
*fn_ext(new_name)= 0;
3696
3719
if (mysql_rename_table(old_db_type, db, table_name, new_db, new_alias, 0))
3700
mysql_rename_table(old_db_type, new_db, new_alias, db,
3717
3734
write_bin_log(session, true, session->query, session->query_length);
3718
3735
session->my_ok();
3720
3737
else if (error > 0)
3722
3739
table->file->print_error(error, MYF(0));
3726
3744
session->unlink_open_table(name_lock);
3727
3746
pthread_mutex_unlock(&LOCK_open);
3728
table_list->table= NULL; // For query cache
3747
table_list->table= NULL;
3732
3751
/* We have to do full alter table. */
3735
3754
If the old table had partitions and we are doing ALTER Table ...
3736
3755
engine= <new_engine>, the new table must preserve the original
3737
3756
partitioning. That means that the new engine is still the
3745
3764
new_db_type= create_info->db_type;
3747
3766
if (mysql_prepare_alter_table(session, table, create_info, alter_info))
3750
3769
set_table_default_charset(create_info, db);
3752
3771
alter_info->build_method= HA_BUILD_OFFLINE;
3754
snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%"PRIx64, TMP_FILE_PREFIX,
3755
(unsigned long)current_pid, session->thread_id);
3773
snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%"PRIx64, TMP_FILE_PREFIX, (unsigned long) current_pid, session->thread_id);
3756
3775
/* Safety fix for innodb */
3757
3776
my_casedn_str(files_charset_info, tmp_name);
3760
3778
/* Create a temporary table with the new format */
3761
if ((error= create_temporary_table(session, table, new_db, tmp_name,
3762
create_info, alter_info,
3763
!strcmp(db, new_db))))
3779
error= create_temporary_table(session, table, new_db, tmp_name, create_info, alter_info, ! strcmp(db, new_db));
3768
3784
/* Open the table so we need to copy the data to it. */
3769
3785
if (table->s->tmp_table)
3791
3807
/* Copy the data if necessary. */
3792
3808
session->count_cuted_fields= CHECK_FIELD_WARN; // calc cuted fields
3793
session->cuted_fields=0L;
3809
session->cuted_fields= 0L;
3794
3810
session->set_proc_info("copy to tmp table");
3795
3811
copied= deleted= 0;
3799
3815
/* We don't want update TIMESTAMP fields during ALTER Table. */
3800
3816
new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
3801
new_table->next_number_field=new_table->found_next_number_field;
3802
error= copy_data_between_tables(table, new_table,
3803
alter_info->create_list, ignore,
3804
order_num, order, &copied, &deleted,
3817
new_table->next_number_field= new_table->found_next_number_field;
3818
error= copy_data_between_tables(table,
3820
alter_info->create_list,
3805
3826
alter_info->keys_onoff,
3806
3827
alter_info->error_if_not_empty);
3808
/* We must not ignore bad input! */;
3829
/* We must not ignore bad input! */
3809
3830
session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
3811
3832
if (table->s->tmp_table != NO_TMP_TABLE)
3813
3834
/* We changed a temporary table */
3816
3838
/* Close lock if this is a transactional table */
3817
3839
if (session->lock)
3819
3841
mysql_unlock_tables(session, session->lock);
3822
3845
/* Remove link to old table and rename the new one */
3823
3846
session->close_temporary_table(table, true, true);
3824
3848
/* Should pass the 'new_name' as we store table name in the cache */
3825
3849
if (new_table->rename_temporary_table(new_db, new_name))
3827
3852
goto end_temporary;
3836
3861
new_table->intern_close_table();
3837
3862
free(new_table);
3839
3865
pthread_mutex_lock(&LOCK_open); /* ALTER TABLE */
3842
3869
quick_rm_table(new_db_type, new_db, tmp_name, true);
3863
3890
session->set_proc_info("rename result table");
3864
snprintf(old_name, sizeof(old_name), "%s2-%lx-%"PRIx64, TMP_FILE_PREFIX,
3865
(unsigned long)current_pid, session->thread_id);
3892
snprintf(old_name, sizeof(old_name), "%s2-%lx-%"PRIx64, TMP_FILE_PREFIX, (unsigned long) current_pid, session->thread_id);
3866
3894
my_casedn_str(files_charset_info, old_name);
3868
3896
wait_while_table_is_used(session, table, HA_EXTRA_PREPARE_FOR_RENAME);
3869
3897
session->close_data_files_and_morph_locks(db, table_name);
3872
3900
save_old_db_type= old_db_type;
3884
3912
table is renamed and the SE is also changed, then an intermediate table
3885
3913
is created and the additional call will not take place.
3887
if (mysql_rename_table(old_db_type, db, table_name, db, old_name,
3891
quick_rm_table(new_db_type, new_db, tmp_name, true);
3893
else if (mysql_rename_table(new_db_type, new_db, tmp_name, new_db,
3894
new_alias, FN_FROM_IS_TMP) || ((new_name != table_name || new_db != db) && 0))
3896
/* Try to get everything back. */
3915
if (mysql_rename_table(old_db_type, db, table_name, db, old_name, FN_TO_IS_TMP))
3898
quick_rm_table(new_db_type, new_db, new_alias, false);
3899
3918
quick_rm_table(new_db_type, new_db, tmp_name, true);
3900
mysql_rename_table(old_db_type, db, old_name, db, table_name,
3922
if (mysql_rename_table(new_db_type, new_db, tmp_name, new_db, new_alias, FN_FROM_IS_TMP) != 0)
3924
/* Try to get everything back. */
3926
quick_rm_table(new_db_type, new_db, new_alias, false);
3927
quick_rm_table(new_db_type, new_db, tmp_name, true);
3928
mysql_rename_table(old_db_type, db, old_name, db, table_name, FN_FROM_IS_TMP);
3935
errmsg_printf(ERRMSG_LVL_WARN,
3936
_("Could not open table %s.%s after rename\n"),
3963
errmsg_printf(ERRMSG_LVL_WARN, _("Could not open table %s.%s after rename\n"), new_db, table_name);
3938
3965
ha_flush_logs(old_db_type);
3940
table_list->table=0; // For query cache
3967
table_list->table= NULL;