Commit 3faf4f76 authored by Mattias Jonsson's avatar Mattias Jonsson

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

mysql-test/r/handler_innodb.result:
  Bug#20129: ALTER TABLE ... REPAIR PARTITION ... complains that
  partition is corrupt
  
  Added a note result row.
mysql-test/r/innodb.result:
  Bug#20129: ALTER TABLE ... REPAIR PARTITION ... complains that
  partition is corrupt
  
  Added a note result row.
mysql-test/r/innodb_mysql.result:
  Bug#20129: ALTER TABLE ... REPAIR PARTITION ... complains that
  partition is corrupt
  
  Added a note result row.
mysql-test/r/partition.result:
  Bug#20129: ALTER TABLE ... REPAIR PARTITION ... complains that
  partition is corrupt
  
  Updated after fixing ANALYZE/CHECK/OPTIMIZE/REPAIR partitioned
  tables.
mysql-test/r/trigger-trans.result:
  Bug#20129: ALTER TABLE ... REPAIR PARTITION ... complains that
  partition is corrupt
  
  Added a note result row.
mysql-test/suite/ndb/r/ndb_partition_key.result:
  Bug#20129: ALTER TABLE ... REPAIR PARTITION ... complains that
  partition is corrupt
  
  Updated after fixing ANALYZE/CHECK/OPTIMIZE/REPAIR partitioned
  tables.
mysql-test/suite/ndb/t/ndb_partition_key.test:
  Bug#20129: ALTER TABLE ... REPAIR PARTITION ... complains that
  partition is corrupt
  
  Updated after fixing ANALYZE/CHECK/OPTIMIZE/REPAIR partitioned
  tables.
mysql-test/suite/parts/inc/partition_alter4.inc:
  Bug#20129: ALTER TABLE ... REPAIR PARTITION ... complains that
  partition is corrupt
  
  Updated after fixing ANALYZE/CHECK/OPTIMIZE/REPAIR partitioned
  tables.
mysql-test/suite/parts/r/partition_alter4_innodb.result:
  Bug#20129: ALTER TABLE ... REPAIR PARTITION ... complains that
  partition is corrupt
  
  Updated after fixing ANALYZE/CHECK/OPTIMIZE/REPAIR partitioned
  tables.
mysql-test/suite/parts/r/partition_alter4_myisam.result:
  Bug#20129: ALTER TABLE ... REPAIR PARTITION ... complains that
  partition is corrupt
  
  Updated after fixing ANALYZE/CHECK/OPTIMIZE/REPAIR partitioned
  tables.
mysql-test/suite/rpl/r/rpl_failed_optimize.result:
  Bug#20129: ALTER TABLE ... REPAIR PARTITION ... complains that
  partition is corrupt
  
  Added a note result row.
mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result:
  Bug#20129: ALTER TABLE ... REPAIR PARTITION ... complains that
  partition is corrupt
  
  Added a note result row.
mysql-test/t/partition.test:
  Bug#20129: ALTER TABLE ... REPAIR PARTITION ... complains that
  partition is corrupt
  
  Updated after fixing ANALYZE/CHECK/OPTIMIZE/REPAIR partitioned
  tables.
sql/ha_partition.cc:
  Bug#20129: ALTER TABLE ... REPAIR PARTITION ... complains that
  partition is corrupt
  
  Added a function for returning admin commands result rows
  Updated handle_opt_partitions to handle admin commands result rows,
  and some error filtering (as mysql_admin_table do).
  
  Removed the functions analyze/check/optimize/repair_partitions
  since they have no longer any use.
sql/ha_partition.h:
  Bug#20129: ALTER TABLE ... REPAIR PARTITION ... complains that
  partition is corrupt
  
  Removed analyze/check/optimize/repair_partitions since they
  are no longer are needed.
sql/handler.cc:
  Bug#20129: ALTER TABLE ... REPAIR PARTITION ... complains that
  partition is corrupt
  
  Removed analyze/check/optimize/repair_partitions since they
  are no longer are needed.
sql/handler.h:
  Bug#20129: ALTER TABLE ... REPAIR PARTITION ... complains that
  partition is corrupt
  
  Removed analyze/check/optimize/repair_partitions since they
  are no longer are needed.
sql/mysql_priv.h:
  Bug#20129: ALTER TABLE ... REPAIR PARTITION ... complains that
  partition is corrupt
  
  Added set_part_state for reuse of code in mysql_admin_table.
  (Originally fond in sql/sql_partition.cc:prep_alter_part_table)
sql/protocol.cc:
  Bug#20129: ALTER TABLE ... REPAIR PARTITION ... complains that
  partition is corrupt
  
  Added one assert and a debug print.
sql/sql_partition.cc:
  Bug#20129: ALTER TABLE ... REPAIR PARTITION ... complains that
  partition is corrupt
  
  Refactored code for setting up partition state, set_part_state,
  now used in both prep_alter_part_table and
  sql_table.cc:mysql_admin_table.
  Removed code for handling ANALYZE/CHECK/OPTIMIZE/REPAIR partitions,
  since it is now handled by mysql_admin_table.
sql/sql_table.cc:
  Bug#20129: ALTER TABLE ... REPAIR PARTITION ... complains that
  partition is corrupt
  
  Added functionality in mysql_admin_table to work with partitioned
  tables.
  Fixed a possible assertion bug for HA_ADMIN_TRY_ALTER
  (If analyze would output a row, it fails since the row was already
  started).
sql/sql_yacc.yy:
  Bug#20129: ALTER TABLE ... REPAIR PARTITION ... complains that
  partition is corrupt
  
  Remapped ALTER TABLE t ANALYZE/CHECK/OPTIMIZE/REPAIR PARTITION
  to use the same code path as ANALYZE/CHECK/OPTIMIZE/REPAIR TABLE
  instead of taking the ALTER TABLE path.
  Added reset of alter_info for ANALYZE/CHECK/OPTIMIZE/REPAIR TABLE
  since it is now used by partitioned tables.
storage/myisam/mi_check.c:
  Bug#20129: ALTER TABLE ... REPAIR PARTITION ... complains that
  partition is corrupt
  
  Changed warning message from "Found X parts  Should be: Y parts"
  to "Found X key parts. Should be Y", since it could be confusing
  with partitioned tables.
parent b65b1ca3
......@@ -484,6 +484,7 @@ c1
handler t1 close;
read the result from the other connection
Table Op Msg_type Msg_text
test.t1 optimize note Table does not support optimize, doing recreate + analyze instead
test.t1 optimize status OK
proceed with the normal connection
drop table t1;
......@@ -698,6 +699,7 @@ handler a2 read a first;
a
optimize table t1;
Table Op Msg_type Msg_text
test.t1 optimize note Table does not support optimize, doing recreate + analyze instead
test.t1 optimize status OK
handler a1 close;
ERROR 42S02: Unknown table 'a1' in HANDLER
......
......@@ -166,6 +166,7 @@ level id parent_id
1 1007 101
optimize table t1;
Table Op Msg_type Msg_text
test.t1 optimize note Table does not support optimize, doing recreate + analyze instead
test.t1 optimize status OK
show keys from t1;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
......@@ -190,6 +191,7 @@ create table t1 (a int) engine=innodb;
insert into t1 values (1), (2);
optimize table t1;
Table Op Msg_type Msg_text
test.t1 optimize note Table does not support optimize, doing recreate + analyze instead
test.t1 optimize status OK
delete from t1 where a = 1;
select * from t1;
......@@ -738,6 +740,7 @@ world 2
hello 1
optimize table t1;
Table Op Msg_type Msg_text
test.t1 optimize note Table does not support optimize, doing recreate + analyze instead
test.t1 optimize status OK
show keys from t1;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
......@@ -3109,6 +3112,7 @@ BEGIN;
INSERT INTO t1 VALUES (1);
OPTIMIZE TABLE t1;
Table Op Msg_type Msg_text
test.t1 optimize note Table does not support optimize, doing recreate + analyze instead
test.t1 optimize status OK
DROP TABLE t1;
CREATE TABLE t1 (id int PRIMARY KEY, f int NOT NULL, INDEX(f)) ENGINE=InnoDB;
......
......@@ -577,6 +577,7 @@ id select_type table type possible_keys key key_len ref rows Extra
INSERT INTO t2 SELECT * FROM t1;
OPTIMIZE TABLE t2;
Table Op Msg_type Msg_text
test.t2 optimize note Table does not support optimize, doing recreate + analyze instead
test.t2 optimize status OK
EXPLAIN SELECT COUNT(*) FROM t2 WHERE stat_id IN (1,3) AND acct_id=785;
id select_type table type possible_keys key key_len ref rows Extra
......
......@@ -538,7 +538,7 @@ PARTITION BY LIST (a)
(PARTITION x1 VALUES IN (10), PARTITION x2 VALUES IN (20));
analyze table t1;
Table Op Msg_type Msg_text
test.t1 analyze note The storage engine for the table doesn't support analyze
test.t1 analyze status OK
drop table t1;
create table t1
(a int)
......@@ -1239,7 +1239,11 @@ SHOW TABLE STATUS;
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
t1 MyISAM 10 Fixed 1 14 14 0 0 7 NULL NULL NULL NULL latin1_swedish_ci NULL partitioned
ALTER TABLE t1 OPTIMIZE PARTITION p0;
ERROR 42000: The storage engine for the table doesn't support optimize partition
Table Op Msg_type Msg_text
test.t1 optimize status OK
SHOW TABLE STATUS;
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
t1 MyISAM 10 Fixed 1 7 7 0 1024 0 NULL NULL NULL NULL latin1_swedish_ci NULL partitioned
DROP TABLE t1;
CREATE TABLE t1 (a int, index(a)) PARTITION BY KEY(a);
ALTER TABLE t1 DISABLE KEYS;
......@@ -1499,13 +1503,17 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp
ALTER TABLE t1 ANALYZE PARTITION p1 EXTENDED;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'EXTENDED' at line 1
ALTER TABLE t1 ANALYZE PARTITION p1;
ERROR 42000: The storage engine for the table doesn't support analyze partition
Table Op Msg_type Msg_text
test.t1 analyze status OK
ALTER TABLE t1 CHECK PARTITION p1;
ERROR 42000: The storage engine for the table doesn't support check partition
Table Op Msg_type Msg_text
test.t1 check status OK
ALTER TABLE t1 REPAIR PARTITION p1;
ERROR 42000: The storage engine for the table doesn't support repair partition
Table Op Msg_type Msg_text
test.t1 repair status OK
ALTER TABLE t1 OPTIMIZE PARTITION p1;
ERROR 42000: The storage engine for the table doesn't support optimize partition
Table Op Msg_type Msg_text
test.t1 optimize status OK
DROP TABLE t1;
CREATE TABLE t1 (s1 BIGINT UNSIGNED)
PARTITION BY RANGE (s1) (
......
......@@ -19,6 +19,7 @@ a b
THE LION 13
optimize table t1;
Table Op Msg_type Msg_text
test.t1 optimize note Table does not support optimize, doing recreate + analyze instead
test.t1 optimize status OK
select trigger_schema, trigger_name, event_object_schema,
event_object_table, action_statement from information_schema.triggers
......
......@@ -192,14 +192,30 @@ DROP TABLE t1;
CREATE TABLE t1 (a int primary key)
ENGINE=NDB
PARTITION BY KEY(a);
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
test.t1 analyze note The storage engine for the table doesn't support analyze
CHECK TABLE t1;
Table Op Msg_type Msg_text
test.t1 check note The storage engine for the table doesn't support check
OPTIMIZE TABLE t1;
Table Op Msg_type Msg_text
test.t1 optimize note The storage engine for the table doesn't support optimize
REPAIR TABLE t1;
Table Op Msg_type Msg_text
test.t1 repair note The storage engine for the table doesn't support repair
ALTER TABLE t1 OPTIMIZE PARTITION p0;
ERROR HY000: Table storage engine for 't1' doesn't have this option
Table Op Msg_type Msg_text
test.t1 optimize note The storage engine for the table doesn't support optimize
ALTER TABLE t1 CHECK PARTITION p0;
ERROR HY000: Table storage engine for 't1' doesn't have this option
Table Op Msg_type Msg_text
test.t1 check note The storage engine for the table doesn't support check
ALTER TABLE t1 REPAIR PARTITION p0;
ERROR HY000: Table storage engine for 't1' doesn't have this option
Table Op Msg_type Msg_text
test.t1 repair note The storage engine for the table doesn't support repair
ALTER TABLE t1 ANALYZE PARTITION p0;
ERROR HY000: Table storage engine for 't1' doesn't have this option
Table Op Msg_type Msg_text
test.t1 analyze note The storage engine for the table doesn't support analyze
ALTER TABLE t1 REBUILD PARTITION p0;
ERROR HY000: Table storage engine for 't1' doesn't have this option
DROP TABLE t1;
......
......@@ -175,15 +175,15 @@ DROP TABLE t1;
CREATE TABLE t1 (a int primary key)
ENGINE=NDB
PARTITION BY KEY(a);
--error 1031
ANALYZE TABLE t1;
CHECK TABLE t1;
OPTIMIZE TABLE t1;
REPAIR TABLE t1;
ALTER TABLE t1 OPTIMIZE PARTITION p0;
--error 1031
ALTER TABLE t1 CHECK PARTITION p0;
--error 1031
ALTER TABLE t1 REPAIR PARTITION p0;
--error 1031
ALTER TABLE t1 ANALYZE PARTITION p0;
--error 1031
--error ER_ILLEGAL_HA
ALTER TABLE t1 REBUILD PARTITION p0;
DROP TABLE t1;
......
......@@ -31,6 +31,9 @@ let $alter= ALTER TABLE t1 ANALYZE PARTITION part_1,part_2,part_5,part_6,part_10
--echo # 1.4 ALTER ... ANALYZE PARTITION part_1,part_1,part_1;
let $alter= ALTER TABLE t1 ANALYZE PARTITION part_1,part_1,part_1;
--source suite/parts/inc/partition_alter_41.inc
--echo # 1.5 ALTER ... ANALYZE PARTITION ALL;
let $alter= ALTER TABLE t1 ANALYZE PARTITION ALL;
--source suite/parts/inc/partition_alter_41.inc
--echo #------------------------------------------------------------------------
--echo # 2 ALTER ... CHECK PARTITION
......@@ -47,6 +50,9 @@ let $alter= ALTER TABLE t1 CHECK PARTITION part_1,part_2,part_5,part_6,part_10;
--echo # 2.4 ALTER ... CHECK PARTITION part_1,part_1,part_1;
let $alter= ALTER TABLE t1 CHECK PARTITION part_1,part_1,part_1;
--source suite/parts/inc/partition_alter_41.inc
--echo # 2.5 ALTER ... CHECK PARTITION ALL;
let $alter= ALTER TABLE t1 CHECK PARTITION ALL;
--source suite/parts/inc/partition_alter_41.inc
--echo #------------------------------------------------------------------------
--echo # 3 ALTER ... OPTIMIZE PARTITION
......@@ -63,6 +69,9 @@ let $alter= ALTER TABLE t1 OPTIMIZE PARTITION part_1,part_2,part_5,part_6,part_1
--echo # 3.4 ALTER ... OPTIMIZE PARTITION part_1,part_1,part_1;
let $alter= ALTER TABLE t1 OPTIMIZE PARTITION part_1,part_1,part_1;
--source suite/parts/inc/partition_alter_41.inc
--echo # 3.5 ALTER ... OPTIMIZE PARTITION ALL;
let $alter= ALTER TABLE t1 OPTIMIZE PARTITION ALL;
--source suite/parts/inc/partition_alter_41.inc
--echo #------------------------------------------------------------------------
--echo # 4 ALTER ... REBUILD PARTITION
......@@ -79,6 +88,9 @@ let $alter= ALTER TABLE t1 REBUILD PARTITION part_1,part_2,part_5,part_6,part_10
--echo # 4.4 ALTER ... REBUILD PARTITION part_1,part_1,part_1;
let $alter= ALTER TABLE t1 REBUILD PARTITION part_1,part_1,part_1;
--source suite/parts/inc/partition_alter_41.inc
--echo # 4.5 ALTER ... REBUILD PARTITION ALL;
let $alter= ALTER TABLE t1 REBUILD PARTITION ALL;
--source suite/parts/inc/partition_alter_41.inc
--echo #------------------------------------------------------------------------
--echo # 5 ALTER ... REPAIR PARTITION
......@@ -95,6 +107,9 @@ let $alter= ALTER TABLE t1 REPAIR PARTITION part_1,part_2,part_5,part_6,part_10;
--echo # 5.4 ALTER ... REPAIR PARTITION part_1,part_1,part_1;
let $alter= ALTER TABLE t1 REPAIR PARTITION part_1,part_1,part_1;
--source suite/parts/inc/partition_alter_41.inc
--echo # 5.5 ALTER ... REPAIR PARTITION ALL;
let $alter= ALTER TABLE t1 REPAIR PARTITION ALL;
--source suite/parts/inc/partition_alter_41.inc
--echo #------------------------------------------------------------------------
--echo # 6 ALTER ... REMOVE PARTITIONING
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -9,6 +9,7 @@ BEGIN;
INSERT INTO t1 VALUES (1);
OPTIMIZE TABLE t1;
Table Op Msg_type Msg_text
test.t1 optimize note Table does not support optimize, doing recreate + analyze instead
test.t1 optimize error Lock wait timeout exceeded; try restarting transaction
test.t1 optimize status Operation failed
Warnings:
......
......@@ -570,6 +570,7 @@ test_rpl.t1 1837058639
******************** OPTIMIZE TABLE ********************
OPTIMIZE TABLE t1;
Table Op Msg_type Msg_text
test_rpl.t1 optimize note Table does not support optimize, doing recreate + analyze instead
test_rpl.t1 optimize status OK
******************** REPAIR TABLE ********************
......
......@@ -1333,11 +1333,9 @@ SHOW TABLE STATUS;
DELETE from t1 where a = 1;
--replace_column 9 0 12 NULL 13 NULL 14 NULL
SHOW TABLE STATUS;
# restore this after WL#4176 is completed
-- error ER_CHECK_NOT_IMPLEMENTED
ALTER TABLE t1 OPTIMIZE PARTITION p0;
#--replace_column 12 NULL 13 NULL 14 NULL
#SHOW TABLE STATUS;
--replace_column 12 NULL 13 NULL 14 NULL
SHOW TABLE STATUS;
DROP TABLE t1;
#
......@@ -1672,13 +1670,9 @@ PARTITION BY RANGE (a) (
ALTER TABLE t1 OPTIMIZE PARTITION p1 EXTENDED;
--error ER_PARSE_ERROR
ALTER TABLE t1 ANALYZE PARTITION p1 EXTENDED;
--error ER_CHECK_NOT_IMPLEMENTED
ALTER TABLE t1 ANALYZE PARTITION p1;
--error ER_CHECK_NOT_IMPLEMENTED
ALTER TABLE t1 CHECK PARTITION p1;
--error ER_CHECK_NOT_IMPLEMENTED
ALTER TABLE t1 REPAIR PARTITION p1;
--error ER_CHECK_NOT_IMPLEMENTED
ALTER TABLE t1 OPTIMIZE PARTITION p1;
DROP TABLE t1;
......
......@@ -841,6 +841,9 @@ int ha_partition::rename_partitions(const char *path)
#define CHECK_PARTS 3
#define REPAIR_PARTS 4
static const char *opt_op_name[]= {NULL,
"optimize", "analyze", "check", "repair" };
/*
Optimize table
......@@ -858,8 +861,10 @@ int ha_partition::optimize(THD *thd, HA_CHECK_OPT *check_opt)
{
DBUG_ENTER("ha_partition::optimize");
DBUG_RETURN(handle_opt_partitions(thd, &thd->lex->check_opt,
OPTIMIZE_PARTS, TRUE));
DBUG_RETURN(handle_opt_partitions(thd, check_opt,
OPTIMIZE_PARTS,
thd->lex->alter_info.flags &
ALTER_OPTIMIZE_PARTITION ? FALSE : TRUE));
}
......@@ -880,8 +885,10 @@ int ha_partition::analyze(THD *thd, HA_CHECK_OPT *check_opt)
{
DBUG_ENTER("ha_partition::analyze");
DBUG_RETURN(handle_opt_partitions(thd, &thd->lex->check_opt,
ANALYZE_PARTS, TRUE));
DBUG_RETURN(handle_opt_partitions(thd, check_opt,
ANALYZE_PARTS,
thd->lex->alter_info.flags &
ALTER_ANALYZE_PARTITION ? FALSE : TRUE));
}
......@@ -902,8 +909,10 @@ int ha_partition::check(THD *thd, HA_CHECK_OPT *check_opt)
{
DBUG_ENTER("ha_partition::check");
DBUG_RETURN(handle_opt_partitions(thd, &thd->lex->check_opt,
CHECK_PARTS, TRUE));
DBUG_RETURN(handle_opt_partitions(thd, check_opt,
CHECK_PARTS,
thd->lex->alter_info.flags &
ALTER_CHECK_PARTITION ? FALSE : TRUE));
}
......@@ -924,95 +933,12 @@ int ha_partition::repair(THD *thd, HA_CHECK_OPT *check_opt)
{
DBUG_ENTER("ha_partition::repair");
DBUG_RETURN(handle_opt_partitions(thd, &thd->lex->check_opt,
REPAIR_PARTS, TRUE));
}
/*
Optimize partitions
SYNOPSIS
optimize_partitions()
thd Thread object
RETURN VALUE
>0 Failure
0 Success
DESCRIPTION
Call optimize on each partition marked with partition state PART_CHANGED
*/
int ha_partition::optimize_partitions(THD *thd)
{
DBUG_ENTER("ha_partition::optimize_partitions");
DBUG_RETURN(handle_opt_partitions(thd, &thd->lex->check_opt,
OPTIMIZE_PARTS, FALSE));
}
/*
Analyze partitions
SYNOPSIS
analyze_partitions()
thd Thread object
RETURN VALUE
>0 Failure
0 Success
DESCRIPTION
Call analyze on each partition marked with partition state PART_CHANGED
*/
int ha_partition::analyze_partitions(THD *thd)
{
DBUG_ENTER("ha_partition::analyze_partitions");
DBUG_RETURN(handle_opt_partitions(thd, &thd->lex->check_opt,
ANALYZE_PARTS, FALSE));
}
/*
Check partitions
SYNOPSIS
check_partitions()
thd Thread object
RETURN VALUE
>0 Failure
0 Success
DESCRIPTION
Call check on each partition marked with partition state PART_CHANGED
*/
int ha_partition::check_partitions(THD *thd)
{
DBUG_ENTER("ha_partition::check_partitions");
DBUG_RETURN(handle_opt_partitions(thd, &thd->lex->check_opt,
CHECK_PARTS, FALSE));
DBUG_RETURN(handle_opt_partitions(thd, check_opt,
REPAIR_PARTS,
thd->lex->alter_info.flags &
ALTER_REPAIR_PARTITION ? FALSE : TRUE));
}
/*
Repair partitions
SYNOPSIS
repair_partitions()
thd Thread object
RETURN VALUE
>0 Failure
0 Success
DESCRIPTION
Call repair on each partition marked with partition state PART_CHANGED
*/
int ha_partition::repair_partitions(THD *thd)
{
DBUG_ENTER("ha_partition::repair_partitions");
DBUG_RETURN(handle_opt_partitions(thd, &thd->lex->check_opt,
REPAIR_PARTS, FALSE));
}
/*
Handle optimize/analyze/check/repair of one partition
......@@ -1028,7 +954,6 @@ int ha_partition::repair_partitions(THD *thd)
0 Success
*/
#ifdef WL4176_IS_DONE
static int handle_opt_part(THD *thd, HA_CHECK_OPT *check_opt,
handler *file, uint flag)
{
......@@ -1036,12 +961,6 @@ static int handle_opt_part(THD *thd, HA_CHECK_OPT *check_opt,
DBUG_ENTER("handle_opt_part");
DBUG_PRINT("enter", ("flag = %u", flag));
/*
TODO:
Rewrite the code for ANALYZE/CHECK/OPTIMIZE/REPAIR PARTITION WL4176
*/
DBUG_RETURN(HA_ADMIN_NOT_IMPLEMENTED);
if (flag == OPTIMIZE_PARTS)
error= file->ha_optimize(thd, check_opt);
else if (flag == ANALYZE_PARTS)
......@@ -1059,7 +978,59 @@ static int handle_opt_part(THD *thd, HA_CHECK_OPT *check_opt,
error= 0;
DBUG_RETURN(error);
}
#endif
/*
print a message row formatted for ANALYZE/CHECK/OPTIMIZE/REPAIR TABLE
(modelled after mi_check_print_msg)
TODO: move this into the handler, or rewrite mysql_admin_table.
*/
static bool print_admin_msg(THD* thd, const char* msg_type,
const char* db_name, const char* table_name,
const char* op_name, const char *fmt, ...)
{
va_list args;
Protocol *protocol= thd->protocol;
uint length, msg_length;
char msgbuf[MI_MAX_MSG_BUF];
char name[NAME_LEN*2+2];
va_start(args, fmt);
msg_length= my_vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
va_end(args);
msgbuf[sizeof(msgbuf) - 1] = 0; // healthy paranoia
if (!thd->vio_ok())
{
sql_print_error(msgbuf);
return TRUE;
}
length=(uint) (strxmov(name, db_name, ".", table_name,NullS) - name);
/*
TODO: switch from protocol to push_warning here. The main reason we didn't
it yet is parallel repair. Due to following trace:
mi_check_print_msg/push_warning/sql_alloc/my_pthread_getspecific_ptr.
Also we likely need to lock mutex here (in both cases with protocol and
push_warning).
*/
DBUG_PRINT("info",("print_admin_msg: %s, %s, %s, %s", name, op_name,
msg_type, msgbuf));
protocol->prepare_for_resend();
protocol->store(name, length, system_charset_info);
protocol->store(op_name, system_charset_info);
protocol->store(msg_type, system_charset_info);
protocol->store(msgbuf, msg_length, system_charset_info);
if (protocol->write())
{
sql_print_error("Failed on my_net_write, writing to stderr instead: %s\n",
msgbuf);
return TRUE;
}
return FALSE;
}
/*
......@@ -1080,55 +1051,89 @@ static int handle_opt_part(THD *thd, HA_CHECK_OPT *check_opt,
int ha_partition::handle_opt_partitions(THD *thd, HA_CHECK_OPT *check_opt,
uint flag, bool all_parts)
{
#ifdef WL4176_IS_DONE
List_iterator<partition_element> part_it(m_part_info->partitions);
uint no_parts= m_part_info->no_parts;
uint no_subparts= m_part_info->no_subparts;
uint i= 0;
int error;
#endif
DBUG_ENTER("ha_partition::handle_opt_partitions");
DBUG_PRINT("enter", ("all_parts %u, flag= %u", all_parts, flag));
/*
TODO:
Rewrite the code for ANALYZE/CHECK/OPTIMIZE/REPAIR PARTITION WL4176
*/
DBUG_RETURN(HA_ADMIN_NOT_IMPLEMENTED);
#ifdef WL4176_IS_DONE
do
{
partition_element *part_elem= part_it++;
if (all_parts || part_elem->part_state == PART_CHANGED)
/*
when ALTER TABLE <CMD> PARTITION ...
it should only do named partitions, otherwise all partitions
*/
if (all_parts ||
part_elem->part_state == PART_CHANGED)
{
if (m_is_sub_partitioned)
{
List_iterator<partition_element> subpart_it(part_elem->subpartitions);
partition_element *sub_elem;
uint j= 0, part;
do
{
sub_elem= subpart_it++;
part= i * no_subparts + j;
DBUG_PRINT("info", ("Optimize subpartition %u",
part));
DBUG_PRINT("info", ("Optimize subpartition %u (%s)",
part, sub_elem->partition_name));
#ifdef NOT_USED
if (print_admin_msg(thd, "note", table_share->db.str, table->alias,
opt_op_name[flag],
"Start to operate on subpartition %s",
sub_elem->partition_name))
DBUG_RETURN(HA_ADMIN_INTERNAL_ERROR);
#endif
if ((error= handle_opt_part(thd, check_opt, m_file[part], flag)))
{
/* print a line which partition the error belongs to */
if (error != HA_ADMIN_NOT_IMPLEMENTED &&
error != HA_ADMIN_ALREADY_DONE &&
error != HA_ADMIN_TRY_ALTER)
{
print_admin_msg(thd, "error", table_share->db.str, table->alias,
opt_op_name[flag],
"Subpartition %s returned error",
sub_elem->partition_name);
}
DBUG_RETURN(error);
}
} while (++j < no_subparts);
}
else
{
DBUG_PRINT("info", ("Optimize partition %u", i));
DBUG_PRINT("info", ("Optimize partition %u (%s)", i,
part_elem->partition_name));
#ifdef NOT_USED
if (print_admin_msg(thd, "note", table_share->db.str, table->alias,
opt_op_name[flag],
"Start to operate on partition %s",
part_elem->partition_name))
DBUG_RETURN(HA_ADMIN_INTERNAL_ERROR);
#endif
if ((error= handle_opt_part(thd, check_opt, m_file[i], flag)))
{
/* print a line which partition the error belongs to */
if (error != HA_ADMIN_NOT_IMPLEMENTED &&
error != HA_ADMIN_ALREADY_DONE &&
error != HA_ADMIN_TRY_ALTER)
{
print_admin_msg(thd, "error", table_share->db.str, table->alias,
opt_op_name[flag], "Partition %s returned error",
part_elem->partition_name);
}
DBUG_RETURN(error);
}
}
}
} while (++i < no_parts);
DBUG_RETURN(FALSE);
#endif
}
/*
Prepare by creating a new partition
......
......@@ -932,10 +932,6 @@ class ha_partition :public handler
virtual int analyze(THD* thd, HA_CHECK_OPT *check_opt);
virtual int check(THD* thd, HA_CHECK_OPT *check_opt);
virtual int repair(THD* thd, HA_CHECK_OPT *check_opt);
virtual int optimize_partitions(THD *thd);
virtual int analyze_partitions(THD *thd);
virtual int check_partitions(THD *thd);
virtual int repair_partitions(THD *thd);
private:
int handle_opt_partitions(THD *thd, HA_CHECK_OPT *check_opt,
......
......@@ -3284,66 +3284,6 @@ handler::ha_rename_partitions(const char *path)
}
/**
Optimize partitions: public interface.
@sa handler::optimize_partitions()
*/
int
handler::ha_optimize_partitions(THD *thd)
{
mark_trx_read_write();
return optimize_partitions(thd);
}
/**
Analyze partitions: public interface.
@sa handler::analyze_partitions()
*/
int
handler::ha_analyze_partitions(THD *thd)
{
mark_trx_read_write();
return analyze_partitions(thd);
}
/**
Check partitions: public interface.
@sa handler::check_partitions()
*/
int
handler::ha_check_partitions(THD *thd)
{
mark_trx_read_write();
return check_partitions(thd);
}
/**
Repair partitions: public interface.
@sa handler::repair_partitions()
*/
int
handler::ha_repair_partitions(THD *thd)
{
mark_trx_read_write();
return repair_partitions(thd);
}
/**
Tell the storage engine that it is allowed to "disable transaction" in the
handler. It is a hint that ACID is not required - it is used in NDB for
......
......@@ -1247,10 +1247,6 @@ class handler :public Sql_alloc
size_t pack_frm_len);
int ha_drop_partitions(const char *path);
int ha_rename_partitions(const char *path);
int ha_optimize_partitions(THD *thd);
int ha_analyze_partitions(THD *thd);
int ha_check_partitions(THD *thd);
int ha_repair_partitions(THD *thd);
void adjust_next_insert_id_after_explicit_value(ulonglong nr);
int update_auto_increment();
......@@ -1911,14 +1907,6 @@ class handler :public Sql_alloc
{ return HA_ERR_WRONG_COMMAND; }
virtual int rename_partitions(const char *path)
{ return HA_ERR_WRONG_COMMAND; }
virtual int optimize_partitions(THD *thd)
{ return HA_ERR_WRONG_COMMAND; }
virtual int analyze_partitions(THD *thd)
{ return HA_ERR_WRONG_COMMAND; }
virtual int check_partitions(THD *thd)
{ return HA_ERR_WRONG_COMMAND; }
virtual int repair_partitions(THD *thd)
{ return HA_ERR_WRONG_COMMAND; }
};
......
......@@ -1571,6 +1571,8 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
char *db,
const char *table_name,
uint fast_alter_partition);
uint set_part_state(Alter_info *alter_info, partition_info *tab_part_info,
enum partition_state part_state);
uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info,
HA_CREATE_INFO *create_info,
handlerton *old_db_type,
......
......@@ -788,6 +788,9 @@ bool Protocol_text::store(const char *from, size_t length,
{
CHARSET_INFO *tocs= this->thd->variables.character_set_results;
#ifndef DBUG_OFF
DBUG_PRINT("info", ("Protocol_text::store field %u (%u): %s", field_pos,
field_count, from));
DBUG_ASSERT(field_pos < field_count);
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_DECIMAL ||
field_types[field_pos] == MYSQL_TYPE_BIT ||
......
......@@ -4079,6 +4079,38 @@ static bool check_native_partitioned(HA_CREATE_INFO *create_info,bool *ret_val,
}
/*
Sets which partitions to be used in the command
*/
uint set_part_state(Alter_info *alter_info, partition_info *tab_part_info,
enum partition_state part_state)
{
uint part_count= 0;
uint no_parts_found= 0;
List_iterator<partition_element> part_it(tab_part_info->partitions);
do
{
partition_element *part_elem= part_it++;
if ((alter_info->flags & ALTER_ALL_PARTITION) ||
(is_name_in_list(part_elem->partition_name,
alter_info->partition_names)))
{
/*
Mark the partition.
I.e mark the partition as a partition to be "changed" by
analyzing/optimizing/rebuilding/checking/repairing
*/
no_parts_found++;
part_elem->part_state= part_state;
DBUG_PRINT("info", ("Setting part_state to %u for partition %s",
part_state, part_elem->partition_name));
}
} while (++part_count < tab_part_info->no_parts);
return no_parts_found;
}
/*
Prepare for ALTER TABLE of partition structure
......@@ -4534,26 +4566,9 @@ that are reorganised.
(alter_info->flags & ALTER_REPAIR_PARTITION) ||
(alter_info->flags & ALTER_REBUILD_PARTITION))
{
uint no_parts_found;
uint no_parts_opt= alter_info->partition_names.elements;
uint part_count= 0;
uint no_parts_found= 0;
List_iterator<partition_element> part_it(tab_part_info->partitions);
do
{
partition_element *part_elem= part_it++;
if ((alter_info->flags & ALTER_ALL_PARTITION) ||
(is_name_in_list(part_elem->partition_name,
alter_info->partition_names)))
{
/*
Mark the partition as a partition to be "changed" by
analyzing/optimizing/rebuilding/checking/repairing
*/
no_parts_found++;
part_elem->part_state= PART_CHANGED;
}
} while (++part_count < tab_part_info->no_parts);
no_parts_found= set_part_state(alter_info, tab_part_info, PART_CHANGED);
if (no_parts_found != no_parts_opt &&
(!(alter_info->flags & ALTER_ALL_PARTITION)))
{
......@@ -6026,48 +6041,7 @@ uint fast_alter_partition_table(THD *thd, TABLE *table,
lpt->pack_frm_len= 0;
thd->work_part_info= part_info;
if (alter_info->flags & ALTER_OPTIMIZE_PARTITION ||
alter_info->flags & ALTER_ANALYZE_PARTITION ||
alter_info->flags & ALTER_CHECK_PARTITION ||
alter_info->flags & ALTER_REPAIR_PARTITION)
{
/*
In this case the user has specified that he wants a set of partitions
to be optimised and the partition engine can handle optimising
partitions natively without requiring a full rebuild of the
partitions.
In this case it is enough to call optimise_partitions, there is no
need to change frm files or anything else.
*/
int error;
written_bin_log= FALSE;
if (((alter_info->flags & ALTER_OPTIMIZE_PARTITION) &&
(error= table->file->ha_optimize_partitions(thd))) ||
((alter_info->flags & ALTER_ANALYZE_PARTITION) &&
(error= table->file->ha_analyze_partitions(thd))) ||
((alter_info->flags & ALTER_CHECK_PARTITION) &&
(error= table->file->ha_check_partitions(thd))) ||
((alter_info->flags & ALTER_REPAIR_PARTITION) &&
(error= table->file->ha_repair_partitions(thd))))
{
if (error == HA_ADMIN_NOT_IMPLEMENTED) {
if (alter_info->flags & ALTER_OPTIMIZE_PARTITION)
my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "optimize partition");
else if (alter_info->flags & ALTER_ANALYZE_PARTITION)
my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "analyze partition");
else if (alter_info->flags & ALTER_CHECK_PARTITION)
my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "check partition");
else if (alter_info->flags & ALTER_REPAIR_PARTITION)
my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "repair partition");
else
table->file->print_error(error, MYF(0));
} else
table->file->print_error(error, MYF(0));
goto err;
}
}
else if (fast_alter_partition & HA_PARTITION_ONE_PHASE)
if (fast_alter_partition & HA_PARTITION_ONE_PHASE)
{
/*
In the case where the engine supports one phase online partition
......
......@@ -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 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
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 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
((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 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
/* 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);
......
......@@ -5543,6 +5543,7 @@ alter_commands:
all_or_alt_part_name_list
{
LEX *lex= Lex;
lex->sql_command = SQLCOM_OPTIMIZE;
lex->alter_info.flags|= ALTER_OPTIMIZE_PARTITION;
lex->no_write_to_binlog= $3;
lex->check_opt.init();
......@@ -5552,6 +5553,7 @@ alter_commands:
all_or_alt_part_name_list
{
LEX *lex= Lex;
lex->sql_command = SQLCOM_ANALYZE;
lex->alter_info.flags|= ALTER_ANALYZE_PARTITION;
lex->no_write_to_binlog= $3;
lex->check_opt.init();
......@@ -5559,6 +5561,7 @@ alter_commands:
| CHECK_SYM PARTITION_SYM all_or_alt_part_name_list
{
LEX *lex= Lex;
lex->sql_command = SQLCOM_CHECK;
lex->alter_info.flags|= ALTER_CHECK_PARTITION;
lex->check_opt.init();
}
......@@ -5567,6 +5570,7 @@ alter_commands:
all_or_alt_part_name_list
{
LEX *lex= Lex;
lex->sql_command = SQLCOM_REPAIR;
lex->alter_info.flags|= ALTER_REPAIR_PARTITION;
lex->no_write_to_binlog= $3;
lex->check_opt.init();
......@@ -6009,6 +6013,7 @@ repair:
lex->sql_command = SQLCOM_REPAIR;
lex->no_write_to_binlog= $2;
lex->check_opt.init();
lex->alter_info.reset();
}
table_list opt_mi_repair_type
{}
......@@ -6037,6 +6042,7 @@ analyze:
lex->sql_command = SQLCOM_ANALYZE;
lex->no_write_to_binlog= $2;
lex->check_opt.init();
lex->alter_info.reset();
}
table_list
{}
......@@ -6062,6 +6068,7 @@ check:
}
lex->sql_command = SQLCOM_CHECK;
lex->check_opt.init();
lex->alter_info.reset();
}
table_list opt_mi_check_type
{}
......@@ -6093,6 +6100,7 @@ optimize:
lex->sql_command = SQLCOM_OPTIMIZE;
lex->no_write_to_binlog= $2;
lex->check_opt.init();
lex->alter_info.reset();
}
table_list
{}
......
......@@ -1338,7 +1338,7 @@ int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend)
if (splits != info->s->state.split)
{
mi_check_print_warning(param,
"Found %10s parts Should be: %s parts",
"Found %10s key parts. Should be: %s",
llstr(splits,llbuff),
llstr(info->s->state.split,llbuff2));
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment