summaryrefslogtreecommitdiff
path: root/sql/sql_table.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_table.cc')
-rw-r--r--sql/sql_table.cc71
1 files changed, 58 insertions, 13 deletions
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index bafd5706346..d9e00602dfc 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -4774,6 +4774,10 @@ int create_table_impl(THD *thd,
{
if (create_info->options & HA_LEX_CREATE_REPLACE)
{
+ LEX_STRING db_name= {(char *) db, strlen(db)};
+ LEX_STRING tab_name= {(char *) table_name, strlen(table_name)};
+ (void) delete_statistics_for_table(thd, &db_name, &tab_name);
+
TABLE_LIST table_list;
table_list.init_one_table(db, strlen(db), table_name,
strlen(table_name), table_name,
@@ -5265,6 +5269,8 @@ mysql_rename_table(handlerton *base, const char *old_db,
delete file;
if (error == HA_ERR_WRONG_COMMAND)
my_error(ER_NOT_SUPPORTED_YET, MYF(0), "ALTER TABLE");
+ else if (error == ENOTDIR)
+ my_error(ER_BAD_DB_ERROR, MYF(0), new_db);
else if (error)
my_error(ER_ERROR_ON_RENAME, MYF(0), from, to, error);
else if (!(flags & FN_IS_TMP))
@@ -5883,10 +5889,28 @@ drop_create_field:
List_iterator<Alter_drop> drop_it(alter_info->drop_list);
Alter_drop *drop;
bool remove_drop;
+ ulonglong left_flags= 0;
while ((drop= drop_it++))
{
+ ulonglong cur_flag= 0;
+ switch (drop->type) {
+ case Alter_drop::COLUMN:
+ cur_flag= Alter_info::ALTER_DROP_COLUMN;
+ break;
+ case Alter_drop::FOREIGN_KEY:
+ cur_flag= Alter_info::DROP_FOREIGN_KEY;
+ break;
+ case Alter_drop::KEY:
+ cur_flag= Alter_info::ALTER_DROP_INDEX;
+ break;
+ default:
+ break;
+ }
if (!drop->drop_if_exists)
+ {
+ left_flags|= cur_flag;
continue;
+ }
remove_drop= TRUE;
if (drop->type == Alter_drop::COLUMN)
{
@@ -5962,12 +5986,15 @@ drop_create_field:
ER_CANT_DROP_FIELD_OR_KEY, ER(ER_CANT_DROP_FIELD_OR_KEY),
drop->name);
drop_it.remove();
- if (alter_info->drop_list.is_empty())
- alter_info->flags&= ~(Alter_info::ALTER_DROP_COLUMN |
- Alter_info::ALTER_DROP_INDEX |
- Alter_info::DROP_FOREIGN_KEY);
}
+ else
+ left_flags|= cur_flag;
}
+ /* Reset state to what's left in drop list */
+ alter_info->flags&= ~(Alter_info::ALTER_DROP_COLUMN |
+ Alter_info::ALTER_DROP_INDEX |
+ Alter_info::DROP_FOREIGN_KEY);
+ alter_info->flags|= left_flags;
}
/* ALTER TABLE ADD KEY IF NOT EXISTS */
@@ -5984,7 +6011,9 @@ drop_create_field:
/* Check if the table already has a PRIMARY KEY */
if (key->type == Key::PRIMARY &&
- table->s->primary_key != MAX_KEY)
+ table->s->primary_key != MAX_KEY &&
+ (keyname= table->s->key_info[table->s->primary_key].name) &&
+ my_strcasecmp(system_charset_info, keyname, primary_key_name) == 0)
{
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_DUP_KEYNAME, ER(ER_MULTIPLE_PRI_KEY));
@@ -9453,9 +9482,7 @@ bool mysql_trans_prepare_alter_copy_data(THD *thd)
This needs to be done before external_lock.
*/
- if (ha_enable_transaction(thd, FALSE))
- DBUG_RETURN(TRUE);
- DBUG_RETURN(FALSE);
+ DBUG_RETURN(ha_enable_transaction(thd, FALSE) != 0);
}
@@ -9506,6 +9533,7 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
ha_rows examined_rows;
ha_rows found_rows;
bool auto_increment_field_copied= 0;
+ bool cleanup_done= 0;
ulonglong save_sql_mode= thd->variables.sql_mode;
ulonglong prev_insert_id, time_to_report_progress;
Field **dfield_ptr= to->default_field;
@@ -9514,15 +9542,23 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
/* Two or 3 stages; Sorting, copying data and update indexes */
thd_progress_init(thd, 2 + MY_TEST(order));
- if (mysql_trans_prepare_alter_copy_data(thd))
- DBUG_RETURN(-1);
-
if (!(copy= new Copy_field[to->s->fields]))
DBUG_RETURN(-1); /* purecov: inspected */
+ if (mysql_trans_prepare_alter_copy_data(thd))
+ {
+ delete [] copy;
+ DBUG_RETURN(-1);
+ }
+
/* We need external lock before we can disable/enable keys */
if (to->file->ha_external_lock(thd, F_WRLCK))
+ {
+ /* Undo call to mysql_trans_prepare_alter_copy_data() */
+ ha_enable_transaction(thd, TRUE);
+ delete [] copy;
DBUG_RETURN(-1);
+ }
alter_table_manage_keys(to, from->file->indexes_are_disabled(), keys_onoff);
@@ -9532,7 +9568,6 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
from->file->info(HA_STATUS_VARIABLE);
to->file->ha_start_bulk_insert(from->file->stats.records,
ignore ? 0 : HA_CREATE_UNIQUE_INDEX_BY_SORT);
-
List_iterator<Create_field> it(create);
Create_field *def;
copy_end=copy;
@@ -9734,7 +9769,6 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
}
end_read_record(&info);
free_io_cache(from);
- delete [] copy;
THD_STAGE_INFO(thd, stage_enabling_keys);
thd_progress_next_stage(thd);
@@ -9749,6 +9783,7 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
to->file->print_error(my_errno,MYF(0));
error= 1;
}
+ cleanup_done= 1;
to->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
if (mysql_trans_commit_alter_copy_data(thd))
@@ -9760,6 +9795,16 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
*copied= found_count;
*deleted=delete_count;
to->file->ha_release_auto_increment();
+ delete [] copy;
+
+ if (!cleanup_done)
+ {
+ /* This happens if we get an error during initialzation of data */
+ DBUG_ASSERT(error);
+ to->file->ha_end_bulk_insert();
+ ha_enable_transaction(thd, TRUE);
+ }
+
if (to->file->ha_external_lock(thd,F_UNLCK))
error=1;
if (error < 0 && to->file->extra(HA_EXTRA_PREPARE_FOR_RENAME))