summaryrefslogtreecommitdiff
path: root/sql/sql_table.cc
diff options
context:
space:
mode:
authorMichael Widenius <monty@askmonty.org>2011-04-28 19:56:10 +0300
committerMichael Widenius <monty@askmonty.org>2011-04-28 19:56:10 +0300
commit2721e912ba45f42f3ddf7c8366f6abbeef060833 (patch)
tree80c1fc27d71fa58e963c729657e383cf4b4d2c86 /sql/sql_table.cc
parent6da8ac5f71a6501cb0fb1304ff144ec41b4d9389 (diff)
downloadmariadb-git-2721e912ba45f42f3ddf7c8366f6abbeef060833.tar.gz
Added ALTER ONLINE TABLE, which will give an error if the change can't be done 'instantly' (without a table copy)
mysql-test/r/alter_table_online.result: Test new feature mysql-test/t/alter_table_online.test: Test new feature sql/handler.cc: Added comment sql/lex.h: Added ONLINE keyword sql/mysql_priv.h: Added option to alter table to require online operation sql/share/errmsg.txt: Added error message if ONLINE can't be done sql/sql_lex.h: Added online option sql/sql_parse.cc: Added online option to mysql_alter_table() sql/sql_table.cc: Added test that gives error if table can't be done instantly when requsted to be online. Fixed wrong test if table includes a VARCHAR Fixed wrong (but unlikely) handling of error conditions in ALTER table sql/sql_yacc.yy: Added ALTER ONLINE TABLE syntax storage/maria/ha_maria.cc: Fixed bug where 'start_bulk_insert' used too small buffer if used with unknown number of rows
Diffstat (limited to 'sql/sql_table.cc')
-rw-r--r--sql/sql_table.cc53
1 files changed, 37 insertions, 16 deletions
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index f2b267eadb1..222991b1ed2 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -5741,8 +5741,8 @@ is_index_maintenance_unique (TABLE *table, Alter_info *alter_info)
that need to be dropped and/or (re-)created.
RETURN VALUES
- TRUE error
- FALSE success
+ TRUE The tables are not compatible; We have to do a full alter table
+ FALSE The tables are compatible; We only have to modify the .frm
*/
static
@@ -5882,6 +5882,9 @@ compare_tables(TABLE *table,
DBUG_ASSERT(i < table->s->fields);
create_info->fileds_option_struct[i]= tmp_new_field->option_struct;
+ /* reset common markers of how field changed */
+ field->flags&= ~(FIELD_IS_RENAMED | FIELD_IN_ADD_INDEX);
+
/* Make sure we have at least the default charset in use. */
if (!new_field->charset)
new_field->charset= create_info->default_table_charset;
@@ -5916,7 +5919,6 @@ compare_tables(TABLE *table,
create_info->table_options|= HA_OPTION_PACK_RECORD;
/* Check if field was renamed */
- field->flags&= ~FIELD_IS_RENAMED;
if (my_strcasecmp(system_charset_info,
field->field_name,
tmp_new_field->field_name))
@@ -5929,8 +5931,6 @@ compare_tables(TABLE *table,
new_field->field_name));
DBUG_RETURN(0);
}
- // Clear indexed marker
- field->flags&= ~FIELD_IN_ADD_INDEX;
changes|= tmp;
}
@@ -6244,7 +6244,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
for (f_ptr=table->field ; (field= *f_ptr) ; f_ptr++)
{
Alter_drop *drop;
- if (field->type() == MYSQL_TYPE_STRING)
+ if (field->type() == MYSQL_TYPE_VARCHAR)
create_info->varchar= TRUE;
/* Check if field should be dropped */
drop_it.rewind();
@@ -6570,6 +6570,7 @@ err:
order_num How many ORDER BY fields has been specified.
order List of fields to ORDER BY.
ignore Whether we have ALTER IGNORE TABLE
+ require_online Give an error if we can't do operation online
DESCRIPTION
This is a veery long function and is everything but the kitchen sink :)
@@ -6600,7 +6601,8 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
HA_CREATE_INFO *create_info,
TABLE_LIST *table_list,
Alter_info *alter_info,
- uint order_num, ORDER *order, bool ignore)
+ uint order_num, ORDER *order, bool ignore,
+ bool require_online)
{
TABLE *table, *new_table= 0, *name_lock= 0;
int error= 0;
@@ -7400,10 +7402,23 @@ view_err:
*/
}
+ /* Check if we can do the ALTER TABLE as online */
+ if (require_online)
+ {
+ if (index_add_count || index_drop_count ||
+ (new_table &&
+ !(new_table->file->ha_table_flags() & HA_NO_COPY_ON_ALTER)))
+ {
+ my_error(ER_CANT_DO_ONLINE, MYF(0), "ALTER");
+ goto close_table_and_return_error;
+ }
+ }
+
/* Copy the data if necessary. */
thd->count_cuted_fields= CHECK_FIELD_WARN; // calc cuted fields
thd->cuted_fields=0L;
copied=deleted=0;
+
/*
We do not copy data for MERGE tables. Only the children have data.
MERGE tables have HA_NO_COPY_ON_ALTER set.
@@ -7435,6 +7450,8 @@ view_err:
error= 1;
}
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
+ if (error)
+ goto close_table_and_return_error;
/* If we did not need to copy, we might still need to add/drop indexes. */
if (! new_table)
@@ -7528,11 +7545,11 @@ view_err:
}
/*end of if (! new_table) for add/drop index*/
+ DBUG_ASSERT(error == 0);
+
if (table->s->tmp_table != NO_TMP_TABLE)
{
/* We changed a temporary table */
- if (error)
- goto err1;
/* Close lock if this is a transactional table */
if (thd->lock)
{
@@ -7567,12 +7584,6 @@ view_err:
}
DEBUG_SYNC(thd, "alter_table_before_rename_result_table");
VOID(pthread_mutex_lock(&LOCK_open));
- if (error)
- {
- VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
- VOID(pthread_mutex_unlock(&LOCK_open));
- goto err;
- }
/*
Data is copied. Now we:
@@ -7745,6 +7756,16 @@ end_temporary:
thd->some_tables_deleted=0;
DBUG_RETURN(FALSE);
+close_table_and_return_error:
+ if (new_table && table->s->tmp_table == NO_TMP_TABLE)
+ {
+ /* This is not a temporary table, so close it the normal way */
+ new_table->s->deleting= TRUE;
+ intern_close_table(new_table);
+ my_free(new_table,MYF(0));
+ new_table= 0; // This forces call to quick_rm_table() below
+ }
+
err1:
if (new_table)
{
@@ -8098,7 +8119,7 @@ bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list)
alter_info.flags= (ALTER_CHANGE_COLUMN | ALTER_RECREATE);
DBUG_RETURN(mysql_alter_table(thd, NullS, NullS, &create_info,
table_list, &alter_info, 0,
- (ORDER *) 0, 0));
+ (ORDER *) 0, 0, 0));
}