mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
smarter ALTER TABLE - don't copy the table if only comment or default values are changed
sql/handler.cc: do not delete the table in the "unkonwn" handler (makes no sense anyway) sql/handler.h: more HA_CREATE_USED flags sql/sql_lex.h: more ALTER_ flags, no alter_info->is_simple anymore sql/sql_parse.cc: no alter_info->is_simple anymore sql/sql_table.cc: do not rename the table in the "unkonwn" handler (makes no sense anyway) smarter ALTER TABLE - don't copy the table if only comment or default values are changed sql/sql_yacc.yy: specify what ALTER is todo with flags, not alter_info->is_simple sql/unireg.cc: create frm only (but not in the handler) if requested
This commit is contained in:
122
sql/sql_table.cc
122
sql/sql_table.cc
@ -1093,7 +1093,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
|
||||
(From ALTER TABLE)
|
||||
|
||||
DESCRIPTION
|
||||
If one creates a temporary table, this is automaticly opened
|
||||
If one creates a temporary table, this is automatically opened
|
||||
|
||||
no_log is needed for the case of CREATE ... SELECT,
|
||||
as the logging will be done later in sql_insert.cc
|
||||
@ -1424,11 +1424,12 @@ mysql_rename_table(enum db_type base,
|
||||
{
|
||||
char from[FN_REFLEN], to[FN_REFLEN];
|
||||
char tmp_from[NAME_LEN+1], tmp_to[NAME_LEN+1];
|
||||
handler *file=get_new_handler((TABLE*) 0, base);
|
||||
handler *file=(base == DB_TYPE_UNKNOWN ? 0 : get_new_handler((TABLE*) 0, base));
|
||||
int error=0;
|
||||
DBUG_ENTER("mysql_rename_table");
|
||||
|
||||
if (lower_case_table_names == 2 && !(file->table_flags() & HA_FILE_BASED))
|
||||
if (lower_case_table_names == 2 && file &&
|
||||
!(file->table_flags() & HA_FILE_BASED))
|
||||
{
|
||||
/* Table handler expects to get all file names as lower case */
|
||||
strmov(tmp_from, old_name);
|
||||
@ -1446,13 +1447,15 @@ mysql_rename_table(enum db_type base,
|
||||
fn_format(from,from,"","",4);
|
||||
fn_format(to,to, "","",4);
|
||||
|
||||
if (!(error=file->rename_table((const char*) from,(const char *) to)))
|
||||
if (!file ||
|
||||
!(error=file->rename_table((const char*) from,(const char *) to)))
|
||||
{
|
||||
if (rename_file_ext(from,to,reg_ext))
|
||||
{
|
||||
error=my_errno;
|
||||
/* Restore old file name */
|
||||
file->rename_table((const char*) to,(const char *) from);
|
||||
if (file)
|
||||
file->rename_table((const char*) to,(const char *) from);
|
||||
}
|
||||
}
|
||||
delete file;
|
||||
@ -2536,7 +2539,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
||||
enum enum_duplicates handle_duplicates,
|
||||
ALTER_INFO *alter_info, bool do_send_ok)
|
||||
{
|
||||
TABLE *table,*new_table;
|
||||
TABLE *table,*new_table=0;
|
||||
int error;
|
||||
char tmp_name[80],old_name[32],new_name_buff[FN_REFLEN];
|
||||
char new_alias_buff[FN_REFLEN], *table_name, *db, *new_alias, *alias;
|
||||
@ -2545,6 +2548,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
||||
ulonglong next_insert_id;
|
||||
uint db_create_options, used_fields;
|
||||
enum db_type old_db_type,new_db_type;
|
||||
bool need_copy_table;
|
||||
DBUG_ENTER("mysql_alter_table");
|
||||
|
||||
thd->proc_info="init";
|
||||
@ -2633,7 +2637,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
||||
create_info->row_type=table->row_type;
|
||||
|
||||
thd->proc_info="setup";
|
||||
if (alter_info->is_simple && !table->tmp_table)
|
||||
if (!(alter_info->flags & ~(ALTER_RENAME | ALTER_KEYS_ONOFF)) &&
|
||||
!table->tmp_table) // no need to touch frm
|
||||
{
|
||||
error=0;
|
||||
if (new_name != table_name || new_db != db)
|
||||
@ -2661,23 +2666,24 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
||||
{
|
||||
switch (alter_info->keys_onoff) {
|
||||
case LEAVE_AS_IS:
|
||||
break;
|
||||
break;
|
||||
case ENABLE:
|
||||
VOID(pthread_mutex_lock(&LOCK_open));
|
||||
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
|
||||
VOID(pthread_mutex_unlock(&LOCK_open));
|
||||
error= table->file->enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
|
||||
/* COND_refresh will be signaled in close_thread_tables() */
|
||||
break;
|
||||
VOID(pthread_mutex_lock(&LOCK_open));
|
||||
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
|
||||
VOID(pthread_mutex_unlock(&LOCK_open));
|
||||
error= table->file->enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
|
||||
/* COND_refresh will be signaled in close_thread_tables() */
|
||||
break;
|
||||
case DISABLE:
|
||||
VOID(pthread_mutex_lock(&LOCK_open));
|
||||
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
|
||||
VOID(pthread_mutex_unlock(&LOCK_open));
|
||||
error=table->file->disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
|
||||
/* COND_refresh will be signaled in close_thread_tables() */
|
||||
break;
|
||||
VOID(pthread_mutex_lock(&LOCK_open));
|
||||
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
|
||||
VOID(pthread_mutex_unlock(&LOCK_open));
|
||||
error=table->file->disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
|
||||
/* COND_refresh will be signaled in close_thread_tables() */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (error == HA_ERR_WRONG_COMMAND)
|
||||
{
|
||||
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
|
||||
@ -2708,7 +2714,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
||||
|
||||
/* Full alter table */
|
||||
|
||||
/* let new create options override the old ones */
|
||||
/* Let new create options override the old ones */
|
||||
if (!(used_fields & HA_CREATE_USED_MIN_ROWS))
|
||||
create_info->min_rows=table->min_rows;
|
||||
if (!(used_fields & HA_CREATE_USED_MAX_ROWS))
|
||||
@ -2968,6 +2974,16 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
||||
if (table->tmp_table)
|
||||
create_info->options|=HA_LEX_CREATE_TMP_TABLE;
|
||||
|
||||
/*
|
||||
better have a negative test here, instead of positive, like
|
||||
alter_info->flags & ALTER_ADD_COLUMN|ALTER_ADD_INDEX|...
|
||||
so that ALTER TABLE won't break when somebody will add new flag
|
||||
*/
|
||||
need_copy_table=(alter_info->flags & ~(ALTER_CHANGE_COLUMN_DEFAULT|ALTER_OPTIONS) ||
|
||||
create_info->used_fields & ~(HA_CREATE_USED_COMMENT|HA_CREATE_USED_PASSWORD) ||
|
||||
table->tmp_table);
|
||||
create_info->frm_only= !need_copy_table;
|
||||
|
||||
/*
|
||||
Handling of symlinked tables:
|
||||
If no rename:
|
||||
@ -3022,45 +3038,49 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
||||
create_list,key_list,1,0)))
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
if (table->tmp_table)
|
||||
if (need_copy_table)
|
||||
{
|
||||
TABLE_LIST tbl;
|
||||
bzero((void*) &tbl, sizeof(tbl));
|
||||
tbl.db= new_db;
|
||||
tbl.real_name= tbl.alias= tmp_name;
|
||||
new_table= open_table(thd, &tbl, &thd->mem_root, 0);
|
||||
if (table->tmp_table)
|
||||
{
|
||||
TABLE_LIST tbl;
|
||||
bzero((void*) &tbl, sizeof(tbl));
|
||||
tbl.db= new_db;
|
||||
tbl.real_name= tbl.alias= tmp_name;
|
||||
new_table= open_table(thd, &tbl, &thd->mem_root, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
char path[FN_REFLEN];
|
||||
my_snprintf(path, sizeof(path), "%s/%s/%s", mysql_data_home,
|
||||
new_db, tmp_name);
|
||||
fn_format(path,path,"","",4);
|
||||
new_table=open_temporary_table(thd, path, new_db, tmp_name,0);
|
||||
}
|
||||
if (!new_table)
|
||||
{
|
||||
VOID(quick_rm_table(new_db_type,new_db,tmp_name));
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char path[FN_REFLEN];
|
||||
my_snprintf(path, sizeof(path), "%s/%s/%s", mysql_data_home,
|
||||
new_db, tmp_name);
|
||||
fn_format(path,path,"","",4);
|
||||
new_table=open_temporary_table(thd, path, new_db, tmp_name,0);
|
||||
}
|
||||
if (!new_table)
|
||||
{
|
||||
VOID(quick_rm_table(new_db_type,new_db,tmp_name));
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
We don't want update TIMESTAMP fields during ALTER TABLE
|
||||
and copy_data_between_tables uses only write_row() for new_table so
|
||||
don't need to set up timestamp_on_update_now member.
|
||||
*/
|
||||
new_table->timestamp_default_now= 0;
|
||||
new_table->next_number_field=new_table->found_next_number_field;
|
||||
thd->count_cuted_fields= CHECK_FIELD_WARN; // calc cuted fields
|
||||
thd->cuted_fields=0L;
|
||||
thd->proc_info="copy to tmp table";
|
||||
next_insert_id=thd->next_insert_id; // Remember for loggin
|
||||
next_insert_id=thd->next_insert_id; // Remember for logging
|
||||
copied=deleted=0;
|
||||
if (!new_table->is_view)
|
||||
if (new_table && !new_table->is_view)
|
||||
{
|
||||
new_table->timestamp_default_now= 0;
|
||||
new_table->next_number_field=new_table->found_next_number_field;
|
||||
error=copy_data_between_tables(table,new_table,create_list,
|
||||
handle_duplicates,
|
||||
order_num, order, &copied, &deleted);
|
||||
}
|
||||
thd->last_insert_id=next_insert_id; // Needed for correct log
|
||||
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
|
||||
|
||||
@ -3099,8 +3119,11 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
||||
goto end_temporary;
|
||||
}
|
||||
|
||||
intern_close_table(new_table); /* close temporary table */
|
||||
my_free((gptr) new_table,MYF(0));
|
||||
if (new_table)
|
||||
{
|
||||
intern_close_table(new_table); /* close temporary table */
|
||||
my_free((gptr) new_table,MYF(0));
|
||||
}
|
||||
VOID(pthread_mutex_lock(&LOCK_open));
|
||||
if (error)
|
||||
{
|
||||
@ -3112,7 +3135,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
||||
/*
|
||||
Data is copied. Now we rename the old table to a temp name,
|
||||
rename the new one to the old name, remove all entries from the old table
|
||||
from the cash, free all locks, close the old table and remove it.
|
||||
from the cache, free all locks, close the old table and remove it.
|
||||
*/
|
||||
|
||||
thd->proc_info="rename result table";
|
||||
@ -3151,6 +3174,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
||||
|
||||
|
||||
error=0;
|
||||
if (!need_copy_table)
|
||||
new_db_type=old_db_type=DB_TYPE_UNKNOWN; // this type cannot happen in regular ALTER
|
||||
if (mysql_rename_table(old_db_type,db,table_name,db,old_name))
|
||||
{
|
||||
error=1;
|
||||
@ -3443,7 +3468,6 @@ int mysql_recreate_table(THD *thd, TABLE_LIST *table_list,
|
||||
lex->key_list.empty();
|
||||
lex->col_list.empty();
|
||||
lex->alter_info.reset();
|
||||
lex->alter_info.is_simple= 0; // Force full recreate
|
||||
bzero((char*) &create_info,sizeof(create_info));
|
||||
create_info.db_type=DB_TYPE_DEFAULT;
|
||||
create_info.row_type=ROW_TYPE_DEFAULT;
|
||||
|
Reference in New Issue
Block a user