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.cc121
1 files changed, 91 insertions, 30 deletions
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 207f9dd324d..a7ef6c30c4c 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -1098,12 +1098,15 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
List<Alter_column> &alter_list,
ORDER *order,
bool drop_primary,
- enum enum_duplicates handle_duplicates)
+ enum enum_duplicates handle_duplicates,
+ enum enum_enable_or_disable keys_onoff,
+ bool simple_alter)
{
TABLE *table,*new_table;
int error;
char tmp_name[80],old_name[32],new_name_buff[FN_REFLEN],
- *table_name,*db;
+ *table_name,*db;
+ char index_file[FN_REFLEN], data_file[FN_REFLEN];
bool use_timestamp=0;
ha_rows copied,deleted;
ulonglong next_insert_id;
@@ -1125,10 +1128,11 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
{
strmov(new_name_buff,new_name);
fn_same(new_name_buff,table_name,3);
+ // Check if name changed
#ifdef FN_LOWER_CASE
- if (!my_strcasecmp(new_name_buff,table_name))// Check if name changed
+ if (!strcmp(db,new_db) && !my_strcasecmp(new_name_buff,table_name))
#else
- if (!strcmp(new_name_buff,table_name)) // Check if name changed
+ if (!strcmp(db,new_db) && !strcmp(new_name_buff,table_name))
#endif
new_name=table_name; // No. Make later check easier
else
@@ -1163,39 +1167,50 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
if (create_info->row_type == ROW_TYPE_DEFAULT)
create_info->row_type=table->row_type;
- /* Check if the user only wants to do a simple RENAME */
+ /* In some simple cases we need not to recreate the table */
thd->proc_info="setup";
- if (new_name != table_name &&
- !fields.elements && !keys.elements && ! drop_list.elements &&
- !alter_list.elements && !drop_primary &&
- new_db_type == old_db_type && create_info->max_rows == 0 &&
- create_info->auto_increment_value == 0 && !table->tmp_table)
+ if (simple_alter)
{
- thd->proc_info="rename";
- VOID(pthread_mutex_lock(&LOCK_open));
- /* Then do a 'simple' rename of the table */
error=0;
- if (!access(new_name_buff,F_OK))
- {
- my_error(ER_TABLE_EXISTS_ERROR,MYF(0),new_name);
- error= -1;
- }
- else
+ if (new_name != table_name)
{
- *fn_ext(new_name)=0;
- close_cached_table(thd,table);
- if (mysql_rename_table(old_db_type,db,table_name,new_db,new_name))
- error= -1;
+ thd->proc_info="rename";
+ VOID(pthread_mutex_lock(&LOCK_open));
+ /* Then do a 'simple' rename of the table */
+ error=0;
+ if (!access(new_name_buff,F_OK))
+ {
+ my_error(ER_TABLE_EXISTS_ERROR,MYF(0),new_name);
+ error= -1;
+ }
+ else
+ {
+ *fn_ext(new_name)=0;
+ close_cached_table(thd,table);
+ if (mysql_rename_table(old_db_type,db,table_name,new_db,new_name))
+ error= -1;
+ }
+ if (!error && (error=ha_commit_rename(thd)))
+ {
+ my_error(ER_GET_ERRNO,MYF(0),error);
+ error=1;
+ }
+
+ VOID(pthread_cond_broadcast(&COND_refresh));
+ VOID(pthread_mutex_unlock(&LOCK_open));
}
- if (!error && (error=ha_commit_rename(thd)))
+ if (!error)
{
- my_error(ER_GET_ERRNO,MYF(0),error);
- error=1;
+ switch (keys_onoff)
+ {
+ case LEAVE_AS_IS: break;
+ case ENABLE: error=table->file->activate_all_index(thd); break;
+ case DISABLE:
+ table->file->deactivate_non_unique_index(table->file->records);
+ break;
+ }
}
-
- VOID(pthread_cond_broadcast(&COND_refresh));
- VOID(pthread_mutex_unlock(&LOCK_open));
if (!error)
{
mysql_update_log.write(thd, thd->query, thd->query_length);
@@ -1206,7 +1221,6 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
}
send_ok(&thd->net);
}
-
DBUG_RETURN(error);
}
@@ -1449,6 +1463,53 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
if (table->tmp_table)
create_info->options|=HA_LEX_CREATE_TMP_TABLE;
+ /*
+ Handling of symlinked tables:
+ If no rename:
+ Create new data file and index file on the same disk as the
+ old data and index files.
+ Copy data.
+ Rename new data file over old data file and new index file over
+ old index file.
+ Symlinks are not changed.
+
+ If rename:
+ Create new data file and index file on the same disk as the
+ old data and index files. Create also symlinks to point at
+ the new tables.
+ Copy data.
+ At end, rename temporary tables and symlinks to temporary table
+ to final table name.
+ Remove old table and old symlinks
+
+ If rename is made to another database:
+ Create new tables in new database.
+ Copy data.
+ Remove old table and symlinks.
+ */
+
+ if (!strcmp(db, new_db)) // Ignore symlink if db changed
+ {
+ if (create_info->index_file_name)
+ {
+ /* Fix index_file_name to have 'tmp_name' as basename */
+ strmov(index_file, tmp_name);
+ create_info->index_file_name=fn_same(index_file,
+ create_info->index_file_name,
+ 1);
+ }
+ if (create_info->data_file_name)
+ {
+ /* Fix data_file_name to have 'tmp_name' as basename */
+ strmov(data_file, tmp_name);
+ create_info->data_file_name=fn_same(data_file,
+ create_info->data_file_name,
+ 1);
+ }
+ }
+ else
+ create_info->data_file_name=create_info->index_file_name=0;
+
if ((error=mysql_create_table(thd, new_db, tmp_name,
create_info,
create_list,key_list,1,1))) // no logging