mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
Bug#20129: ALTER TABLE ... REPAIR PARTITION ... complains that
partition is corrupt The main problem was that ALTER TABLE t ANALYZE/CHECK/OPTIMIZE/REPAIR PARTITION took another code path (over mysql_alter_table instead of mysql_admin_table) which differs in two ways: 1) alter table opens the tables in a different way than admin tables do resulting in returning with error before it tried the command 2) alter table does not start to send any diagnostic rows to the client which the lower admin functions continue to use -> resulting in assertion crash The fix: Remapped ALTER TABLE t ANALYZE/CHECK/OPTIMIZE/REPAIR PARTITION to use the same code path as ANALYZE/CHECK/OPTIMIZE/REPAIR TABLE t. Adding check in mysql_admin_table to setup the partition list for which partitions that should be used. Partitioned tables will still not work with REPAIR TABLE/PARTITION USE_FRM, since that requires moving partitions to tables, REPAIR TABLE t USE_FRM, and check that the data still fulfills the partitioning function and then move the table back to being a partition. NOTE: I have removed the following functions from the handler interface: analyze_partitions, check_partitions, optimize_partitions, repair_partitions Since they are not longer needed. THIS ALTERS THE STORAGE ENGINE API
This commit is contained in:
@ -4194,6 +4194,46 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
|
||||
table->next_global= save_next_global;
|
||||
table->next_local= save_next_local;
|
||||
thd->open_options&= ~extra_open_options;
|
||||
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||
if (table->table && table->table->part_info)
|
||||
{
|
||||
/*
|
||||
Set up which partitions that should be processed
|
||||
if ALTER TABLE t ANALYZE/CHECK/OPTIMIZE/REPAIR PARTITION ..
|
||||
*/
|
||||
Alter_info *alter_info= &lex->alter_info;
|
||||
|
||||
if (alter_info->flags & ALTER_ANALYZE_PARTITION ||
|
||||
alter_info->flags & ALTER_CHECK_PARTITION ||
|
||||
alter_info->flags & ALTER_OPTIMIZE_PARTITION ||
|
||||
alter_info->flags & ALTER_REPAIR_PARTITION)
|
||||
{
|
||||
uint no_parts_found;
|
||||
uint no_parts_opt= alter_info->partition_names.elements;
|
||||
no_parts_found= set_part_state(alter_info, table->table->part_info,
|
||||
PART_CHANGED);
|
||||
if (no_parts_found != no_parts_opt &&
|
||||
(!(alter_info->flags & ALTER_ALL_PARTITION)))
|
||||
{
|
||||
char buff[FN_REFLEN + MYSQL_ERRMSG_SIZE];
|
||||
uint length;
|
||||
DBUG_PRINT("admin", ("sending non existent partition error"));
|
||||
protocol->prepare_for_resend();
|
||||
protocol->store(table_name, system_charset_info);
|
||||
protocol->store(operator_name, system_charset_info);
|
||||
protocol->store(STRING_WITH_LEN("error"), system_charset_info);
|
||||
length= my_snprintf(buff, sizeof(buff),
|
||||
ER(ER_DROP_PARTITION_NON_EXISTENT),
|
||||
table_name);
|
||||
protocol->store(buff, length, system_charset_info);
|
||||
if(protocol->write())
|
||||
goto err;
|
||||
my_eof(thd);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
DBUG_PRINT("admin", ("table: 0x%lx", (long) table->table));
|
||||
|
||||
@ -4428,9 +4468,17 @@ send_result_message:
|
||||
This is currently used only by InnoDB. ha_innobase::optimize() answers
|
||||
"try with alter", so here we close the table, do an ALTER TABLE,
|
||||
reopen the table and do ha_innobase::analyze() on it.
|
||||
We have to end the row, so analyze could return more rows.
|
||||
*/
|
||||
protocol->store(STRING_WITH_LEN("note"), system_charset_info);
|
||||
protocol->store(STRING_WITH_LEN(
|
||||
"Table does not support optimize, doing recreate + analyze instead"),
|
||||
system_charset_info);
|
||||
if (protocol->write())
|
||||
goto err;
|
||||
ha_autocommit_or_rollback(thd, 0);
|
||||
close_thread_tables(thd);
|
||||
DBUG_PRINT("info", ("HA_ADMIN_TRY_ALTER, trying analyze..."));
|
||||
TABLE_LIST *save_next_local= table->next_local,
|
||||
*save_next_global= table->next_global;
|
||||
table->next_local= table->next_global= 0;
|
||||
@ -4453,6 +4501,10 @@ send_result_message:
|
||||
((result_code= table->table->file->ha_analyze(thd, check_opt)) > 0))
|
||||
result_code= 0; // analyze went ok
|
||||
}
|
||||
/* Start a new row for the final status row */
|
||||
protocol->prepare_for_resend();
|
||||
protocol->store(table_name, system_charset_info);
|
||||
protocol->store(operator_name, system_charset_info);
|
||||
if (result_code) // either mysql_recreate_table or analyze failed
|
||||
{
|
||||
DBUG_ASSERT(thd->is_error());
|
||||
@ -4468,7 +4520,8 @@ send_result_message:
|
||||
/* Hijack the row already in-progress. */
|
||||
protocol->store(STRING_WITH_LEN("error"), system_charset_info);
|
||||
protocol->store(err_msg, system_charset_info);
|
||||
(void)protocol->write();
|
||||
if (protocol->write())
|
||||
goto err;
|
||||
/* Start off another row for HA_ADMIN_FAILED */
|
||||
protocol->prepare_for_resend();
|
||||
protocol->store(table_name, system_charset_info);
|
||||
|
Reference in New Issue
Block a user