Below is the list of changes that have just been committed into a local
5.1 repository of marty. When marty does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet@stripped, 2007-09-06 16:39:40+02:00, mskold@stripped +3 -0
sql_table.cc, ha_ndbcluster.cc:
WL3749 On-line DDL, new handler interface: Fixed fast alter table
handler.h:
WL3749 On-line DDL, new handler interface: Added better comments for new calls
sql/ha_ndbcluster.cc@stripped, 2007-09-06 16:39:12+02:00, mskold@stripped +2 -6
WL3749 On-line DDL, new handler interface: Fixed fast alter table
sql/handler.h@stripped, 2007-09-06 16:38:42+02:00, mskold@stripped +69 -0
WL3749 On-line DDL, new handler interface: Added better comments for new calls
sql/sql_table.cc@stripped, 2007-09-06 16:39:11+02:00, mskold@stripped +141 -45
WL3749 On-line DDL, new handler interface: Fixed fast alter table
diff -Nrup a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc
--- a/sql/ha_ndbcluster.cc 2007-09-05 19:40:27 +02:00
+++ b/sql/ha_ndbcluster.cc 2007-09-06 16:39:12 +02:00
@@ -10940,11 +10940,6 @@ int ha_ndbcluster::check_if_supported_al
if (field->flags & FIELD_IN_ADD_INDEX)
ai=1;
}
- if (table_changes != IS_EQUAL_YES)
- {
- DBUG_PRINT("info", ("table_changes != IS_EQUAL_YES"));
- DBUG_RETURN(HA_ALTER_NOT_SUPPORTED);
- }
if (alter_flags->is_set(HA_ADD_COLUMN) && !any_var_dyn_attr)
{
@@ -11138,7 +11133,8 @@ int ha_ndbcluster::alter_table_phase1(TH
DBUG_RETURN(error);
}
-int ha_ndbcluster::alter_frm(THD *thd, const char *file, NDB_ALTER_DATA *alter_data)
+int ha_ndbcluster::alter_frm(THD *thd, const char *file,
+ NDB_ALTER_DATA *alter_data)
{
uchar *data= NULL, *pack_data= NULL;
size_t length, pack_length;
diff -Nrup a/sql/handler.h b/sql/handler.h
--- a/sql/handler.h 2007-09-05 15:21:30 +02:00
+++ b/sql/handler.h 2007-09-06 16:38:42 +02:00
@@ -1776,10 +1776,41 @@ public:
Pops the top if condition stack, if stack is not empty
*/
virtual void cond_pop() { return; };
+ /*
+ Part of old fast alter table, to be depricated
+ */
virtual bool check_if_incompatible_data(HA_CREATE_INFO *create_info,
uint table_changes)
{ return COMPATIBLE_DATA_NO; }
+
+ /*
+ On-line ALTER TABLE interface
+ */
+
+ /*
+ Check if a storage engine supports a particular alter table on-line
+ SYNOPSIS
+ check_if_supported_alter()
+ altered_table A temporary table show what table is to change to
+ create_info Information from the parsing phase about new
+ table properties.
+ alter_flags Bitmask that shows what will be changed
+ table_changes Shows if table layout has changed (for backwards
+ compatibility with check_if_incompatible_data
+ RETURN
+ HA_ALTER_ERROR Unexpected error
+ HA_ALTER_SUPPORTED_WAIT_LOCK Supported, but requires DDL lock
+ HA_ALTER_SUPPORTED_NO_LOCK Supported
+ HA_ALTER_NOT_SUPPORTED Not supported
+
+
+ NOTES
+ The default implementation is implemented to support fast
+ alter table (storage engines that support some changes by
+ just changing the frm file) without any change in the handler
+ implementation.
+ */
virtual int check_if_supported_alter(TABLE *altered_table,
HA_CREATE_INFO *create_info,
HA_ALTER_FLAGS *alter_flags,
@@ -1792,6 +1823,19 @@ public:
else
DBUG_RETURN(HA_ALTER_SUPPORTED_WAIT_LOCK);
}
+ /*
+ Tell storage engine to prepare for the on-line alter table (pre-alter)
+ SYNOPSIS
+ alter_table_phase1()
+ thd The thread handle
+ altered_table A temporary table show what table is to change to
+ alter_info Storage place for data used during phase1 and phase2
+ alter_flags Bitmask that shows what will be changed
+ RETURN
+ 0 OK
+ error error code passed from storage engine
+ NOTES
+ */
virtual int alter_table_phase1(THD *thd,
TABLE *altered_table,
HA_CREATE_INFO *create_info,
@@ -1800,6 +1844,22 @@ public:
{
return HA_ERR_UNSUPPORTED;
}
+ /*
+ Tell storage engine to perform the on-line alter table (alter)
+ SYNOPSIS
+ alter_table_phase2()
+ thd The thread handle
+ altered_table A temporary table show what table is to change to
+ alter_info Storage place for data used during phase1 and phase2
+ alter_flags Bitmask that shows what will be changed
+ RETURN
+ 0 OK
+ error error code passed from storage engine
+ NOTES
+ If check_if_supported_alter returns HA_ALTER_SUPPORTED_WAIT_LOCK
+ this call is to be wrapped with a DDL lock. This is currently NOT
+ supported.
+ */
virtual int alter_table_phase2(THD *thd,
TABLE *altered_table,
HA_CREATE_INFO *create_info,
@@ -1808,6 +1868,15 @@ public:
{
return HA_ERR_UNSUPPORTED;
}
+ /*
+ Tell storage engine that changed frm file is now on disk and table
+ has been re-opened (post-alter)
+ SYNOPSIS
+ alter_table_phase3()
+ thd The thread handle
+ table The altered table, re-opened
+ NOTES
+ */
virtual int alter_table_phase3(THD *thd, TABLE *table)
{
return HA_ERR_UNSUPPORTED;
diff -Nrup a/sql/sql_table.cc b/sql/sql_table.cc
--- a/sql/sql_table.cc 2007-09-05 15:21:31 +02:00
+++ b/sql/sql_table.cc 2007-09-06 16:39:11 +02:00
@@ -3641,7 +3641,6 @@ mysql_rename_table(handlerton *base, con
flags & FN_TO_IS_TMP);
to_base= lc_to;
}
-
if (!file || !(error=file->rename_table(from_base, to_base)))
{
if (!(flags & NO_FRM_RENAME) && rename_file_ext(from,to,reg_ext))
@@ -5019,6 +5018,7 @@ compare_tables(THD *thd,
!table->s->mysql_version ||
(table->s->frm_version < FRM_VER_TRUE_VARCHAR && varchar))
{
+ *table_changes= IS_EQUAL_NO;
/*
Check what has changed and set alter_flags
*/
@@ -5078,7 +5078,7 @@ compare_tables(THD *thd,
*alter_flags|= HA_ALTER_COLUMN_NAME;
}
- *table_changes|= table_changes_local;
+ *table_changes&= table_changes_local;
if (table_changes_local == IS_EQUAL_PACK_LENGTH)
*alter_flags|= HA_ALTER_COLUMN_TYPE;
@@ -5140,6 +5140,7 @@ compare_tables(THD *thd,
}
else
*alter_flags|= HA_DROP_INDEX;
+ *table_changes= IS_EQUAL_NO;
DBUG_PRINT("info", ("index dropped: '%s'", table_key->name));
continue;
}
@@ -5212,6 +5213,7 @@ compare_tables(THD *thd,
if ((field= table->field[key_part->fieldnr]))
field->flags|= FIELD_IN_ADD_INDEX;
}
+ *table_changes= IS_EQUAL_NO;
DBUG_PRINT("info", ("index changed: '%s'", table_key->name));
}
/*end of for (; table_key < table_key_end;) */
@@ -5254,6 +5256,7 @@ compare_tables(THD *thd,
}
else
*alter_flags|= HA_ADD_INDEX;
+ *table_changes= IS_EQUAL_NO;
DBUG_PRINT("info", ("index added: '%s'", new_key->name));
}
}
@@ -5404,6 +5407,26 @@ int create_temporary_table(THD *thd,
DBUG_RETURN(error);
}
+/*
+ Create a temporary table that reflects what an alter table operation
+ will accomplish.
+
+ SYNOPSIS
+ create_altered_table()
+ thd Thread handle
+ table The original table
+ create_info Information from the parsing phase about new
+ table properties.
+ alter_info Lists of fields, keys to be changed, added
+ or dropped.
+ db_change Specifies if the table is moved to another database
+ RETURN
+ A temporary table with all changes
+ NULL if error
+ NOTES
+ The temporary table is created without storing it in any storage engine
+ and is opened only to get the table struct and frm file reference.
+*/
TABLE *create_altered_table(THD *thd,
TABLE *table,
char *new_db,
@@ -5440,47 +5463,80 @@ TABLE *create_altered_table(THD *thd,
/*
- If mysql_alter_table does not need to copy the table, it is
- either a fast alter table where the storage engine does not
- need to know about the change, only the frm will change,
- or the storage engine supports performing the alter table
- operation directly, on-line without mysql having to copy
- the table.
+ Perform a fast or on-line alter table
+
+ SYNOPSIS
+ mysql_fast_or_online_alter_table()
+ thd Thread handle
+ table The original table
+ altered_table A temporary table showing how we will change table
+ create_info Information from the parsing phase about new
+ table properties.
+ alter_info Storage place for data used during different phases
+ ha_alter_flags Bitmask that shows what will be changed
+ keys_onoff Specifies if keys are to be enabled/disabled
+ RETURN
+ 0 OK
+ >0 An error occured during the on-line alter table operation
+ -1 Error when re-opening table
+ NOTES
+ If mysql_alter_table does not need to copy the table, it is
+ either a fast alter table where the storage engine does not
+ need to know about the change, only the frm will change,
+ or the storage engine supports performing the alter table
+ operation directly, on-line without mysql having to copy
+ the table.
*/
int mysql_fast_or_online_alter_table(THD *thd,
- char *path,
TABLE *table,
TABLE *altered_table,
HA_CREATE_INFO *create_info,
HA_ALTER_INFO *alter_info,
- HA_ALTER_FLAGS *ha_alter_flags)
+ HA_ALTER_FLAGS *ha_alter_flags,
+ enum enum_enable_or_disable keys_onoff)
{
int error= 0;
+ bool online= (table->file->ha_table_flags() & HA_ONLINE_ALTER);
+ TABLE *t_table;
+
DBUG_ENTER(" mysql_fast_or_online_alter_table");
- if ((error= table->file->alter_table_phase1(thd,
- altered_table,
- create_info,
- alter_info,
- ha_alter_flags)))
+ if (online)
{
- goto err;
- }
+ /*
+ Tell the handler to prepare for the online alter
+ */
+ if ((error= table->file->alter_table_phase1(thd,
+ altered_table,
+ create_info,
+ alter_info,
+ ha_alter_flags)))
+ {
+ goto err;
+ }
- if ((error= table->file->alter_table_phase2(thd,
- altered_table,
- create_info,
- alter_info,
- ha_alter_flags)))
- {
- goto err;
+ /*
+ Tell the storage engine to perform the online alter table
+ TODO:
+ if check_if_supported_alter() returned HA_ALTER_SUPPORTED_WAIT_LOCK
+ we need to wrap the next call with a DDL lock.
+ */
+ if ((error= table->file->alter_table_phase2(thd,
+ altered_table,
+ create_info,
+ alter_info,
+ ha_alter_flags)))
+ {
+ goto err;
+ }
}
-
/*
The final .frm file is already created as a temporary file
and will be renamed to the original table name.
*/
VOID(pthread_mutex_lock(&LOCK_open));
- wait_while_table_is_used(thd, table, HA_EXTRA_PREPARE_FOR_DELETE);
+ wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
+ alter_table_manage_keys(table, table->file->indexes_are_disabled(),
+ keys_onoff);
close_data_files_and_morph_locks(thd,
table->pos_in_table_list->db,
table->pos_in_table_list->table_name);
@@ -5490,18 +5546,13 @@ int mysql_fast_or_online_alter_table(THD
table->s->db.str,
table->s->table_name.str, FN_FROM_IS_TMP))
{
- error= 1;
- VOID(pthread_mutex_unlock(&LOCK_open));
- goto err;
+ error= 1;
+ VOID(pthread_mutex_unlock(&LOCK_open));
+ goto err;
}
broadcast_refresh();
VOID(pthread_mutex_unlock(&LOCK_open));
- if ((error= table->file->alter_table_phase3(thd, table)))
- {
- goto err;
- }
-
/*
The ALTER TABLE is always in its own transaction.
Commit must not be called while LOCK_open is locked. It could call
@@ -5509,13 +5560,46 @@ int mysql_fast_or_online_alter_table(THD
with LOCK_open.
*/
error= ha_commit_stmt(thd);
+
if (ha_commit(thd))
error=1;
if (error)
goto err;
- thd->proc_info="end";
+ if (online)
+ {
+ VOID(pthread_mutex_lock(&LOCK_open));
+ if (reopen_table(table))
+ {
+ error= -1;
+ goto err;
+ }
+ VOID(pthread_mutex_unlock(&LOCK_open));
+ t_table= table;
+
+ /*
+ Tell the handler that the changed frm is on disk and table
+ has been re-opened
+ */
+ if ((error= t_table->file->alter_table_phase3(thd, t_table)))
+ {
+ goto err;
+ }
+
+ /*
+ We are going to reopen table down on the road, so we have to restore
+ state of the TABLE object which we used for obtaining of handler
+ object to make it suitable for reopening.
+ */
+ DBUG_ASSERT(t_table == table);
+ table->open_placeholder= 1;
+ VOID(pthread_mutex_lock(&LOCK_open));
+ close_handle_and_leave_table_as_lock(table);
+ VOID(pthread_mutex_unlock(&LOCK_open));
+ }
err:
+ if (error)
+ DBUG_PRINT("info", ("Got error %u", error));
DBUG_RETURN(error);
}
@@ -6409,8 +6493,8 @@ view_err:
{
char dbug_string[HA_MAX_ALTER_FLAGS+1];
ha_alter_flags.print(dbug_string);
- DBUG_PRINT("info", ("need_copy_table: %u, Real alter_flags: %s",
- need_copy_table,
+ DBUG_PRINT("info", ("need_copy_table: %u, table_changes: %u, Real alter_flags: %s",
+ need_copy_table, table_changes,
(char *) dbug_string));
}
#endif
@@ -6424,6 +6508,7 @@ view_err:
ha_alter_flags.is_set())
{
Alter_info tmp_alter_info(*alter_info, thd->mem_root);
+
/*
If no table rename,
check if table can be altered on-line
@@ -6435,6 +6520,7 @@ view_err:
&tmp_alter_info,
!strcmp(db, new_db))))
goto err;
+
switch (table->file->check_if_supported_alter(altered_table,
create_info,
&ha_alter_flags,
@@ -6468,27 +6554,26 @@ view_err:
{
char dbug_string[HA_MAX_ALTER_FLAGS+1];
ha_alter_flags.print(dbug_string);
- DBUG_PRINT("info", ("need_copy_table: %u, Real alter_flags: %s",
- need_copy_table,
+ DBUG_PRINT("info", ("need_copy_table: %u, table_changes: %u, Real alter_flags: %s",
+ need_copy_table, table_changes,
(char *) dbug_string));
}
#endif
}
/* TODO need to check if changes can be handled as fast ALTER TABLE */
- if (!altered_table ||
- !(table->file->ha_table_flags() & HA_ONLINE_ALTER))
+ if (!altered_table)
need_copy_table= TRUE;
if (!need_copy_table)
{
error= mysql_fast_or_online_alter_table(thd,
- path,
table,
altered_table,
create_info,
&ha_alter_info,
- &ha_alter_flags);
+ &ha_alter_flags,
+ alter_info->keys_onoff);
if (thd->lock)
{
mysql_unlock_tables(thd, thd->lock);
@@ -6497,9 +6582,19 @@ view_err:
close_temporary_table(thd, altered_table, 1, 1);
if (error)
- goto err;
+ {
+ switch (error) {
+ case(-1):
+ goto err_with_placeholders;
+ default:
+ goto err;
+ }
+ }
else
+ {
+ pthread_mutex_lock(&LOCK_open);
goto end_online;
+ }
}
if (altered_table)
@@ -6674,6 +6769,8 @@ view_err:
VOID(quick_rm_table(old_db_type, db, old_name, FN_IS_TMP));
+end_online:
+
if (thd->locked_tables && new_name == table_name && new_db == db)
{
thd->in_lock_tables= 1;
@@ -6687,7 +6784,6 @@ view_err:
thd->proc_info="end";
DBUG_EXECUTE_IF("sleep_alter_before_main_binlog", my_sleep(6000000););
-end_online:
ha_binlog_log_query(thd, create_info->db_type, LOGCOM_ALTER_TABLE,
thd->query, thd->query_length,
| Thread |
|---|
| • bk commit into 5.1 tree (mskold:1.2602) | Martin Skold | 6 Sep |