Commit f3c6e6ff authored by Mattias Jonsson's avatar Mattias Jonsson

Bug#58147: ALTER TABLE w/ TRUNCATE PARTITION fails

           but the statement is written to binlog

TRUNCATE PARTITION was written to the binlog
even if it failed before calling any partition's
truncate function.

Solved by adding an argument to truncate_partition,
to flag if it should be written to the binlog or not.

It should be written to the binlog when a call to any
partitions truncate function is done.
parent 938c61dc
DROP TABLE IF EXISTS t1;
#
# Bug#58147: ALTER TABLE w/ TRUNCATE PARTITION fails
# but the statement is written to binlog
#
CREATE TABLE t1(id INT)
PARTITION BY RANGE (id)
(PARTITION p0 VALUES LESS THAN (100),
PARTITION pmax VALUES LESS THAN (MAXVALUE));
INSERT INTO t1 VALUES (1), (10), (100), (1000);
ALTER TABLE t1 TRUNCATE PARTITION p1;
ERROR HY000: Incorrect partition name
ALTER TABLE t1 DROP PARTITION p1;
ERROR HY000: Error in list of partitions to DROP
# No error returned, output in table format instead:
ALTER TABLE t1 ANALYZE PARTITION p1;
Table Op Msg_type Msg_text
test.t1 analyze error Error in list of partitions to test.t1
ALTER TABLE t1 CHECK PARTITION p1;
Table Op Msg_type Msg_text
test.t1 check error Error in list of partitions to test.t1
ALTER TABLE t1 OPTIMIZE PARTITION p1;
Table Op Msg_type Msg_text
test.t1 optimize error Error in list of partitions to test.t1
ALTER TABLE t1 REPAIR PARTITION p1;
Table Op Msg_type Msg_text
test.t1 repair error Error in list of partitions to test.t1
ALTER TABLE t1 ANALYZE PARTITION p0;
Table Op Msg_type Msg_text
test.t1 analyze status OK
ALTER TABLE t1 CHECK PARTITION p0;
Table Op Msg_type Msg_text
test.t1 check status OK
ALTER TABLE t1 OPTIMIZE PARTITION p0;
Table Op Msg_type Msg_text
test.t1 optimize status OK
ALTER TABLE t1 REPAIR PARTITION p0;
Table Op Msg_type Msg_text
test.t1 repair status OK
ALTER TABLE t1 TRUNCATE PARTITION p0;
ALTER TABLE t1 DROP PARTITION p0;
show binlog events in 'master-bin.000001' from <binlog_start>;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Query # # use `test`; CREATE TABLE t1(id INT)
PARTITION BY RANGE (id)
(PARTITION p0 VALUES LESS THAN (100),
PARTITION pmax VALUES LESS THAN (MAXVALUE))
master-bin.000001 # Query # # BEGIN
master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (1), (10), (100), (1000)
master-bin.000001 # Query # # COMMIT
master-bin.000001 # Query # # use `test`; ALTER TABLE t1 ANALYZE PARTITION p0
master-bin.000001 # Query # # use `test`; ALTER TABLE t1 OPTIMIZE PARTITION p0
master-bin.000001 # Query # # use `test`; ALTER TABLE t1 REPAIR PARTITION p0
master-bin.000001 # Query # # use `test`; ALTER TABLE t1 TRUNCATE PARTITION p0
master-bin.000001 # Query # # use `test`; ALTER TABLE t1 DROP PARTITION p0
DROP TABLE t1;
--source include/have_log_bin.inc
--disable_warnings
DROP TABLE IF EXISTS t1;
--enable_warnings
--echo #
--echo # Bug#58147: ALTER TABLE w/ TRUNCATE PARTITION fails
--echo # but the statement is written to binlog
--echo #
--let $binlog_file=query_get_value(SHOW MASTER STATUS, File, 1)
--let $binlog_start=query_get_value(SHOW MASTER STATUS, Position, 1)
CREATE TABLE t1(id INT)
PARTITION BY RANGE (id)
(PARTITION p0 VALUES LESS THAN (100),
PARTITION pmax VALUES LESS THAN (MAXVALUE));
INSERT INTO t1 VALUES (1), (10), (100), (1000);
--error ER_WRONG_PARTITION_NAME
ALTER TABLE t1 TRUNCATE PARTITION p1;
--error ER_DROP_PARTITION_NON_EXISTENT
ALTER TABLE t1 DROP PARTITION p1;
--echo # No error returned, output in table format instead:
ALTER TABLE t1 ANALYZE PARTITION p1;
ALTER TABLE t1 CHECK PARTITION p1;
ALTER TABLE t1 OPTIMIZE PARTITION p1;
ALTER TABLE t1 REPAIR PARTITION p1;
ALTER TABLE t1 ANALYZE PARTITION p0;
ALTER TABLE t1 CHECK PARTITION p0;
ALTER TABLE t1 OPTIMIZE PARTITION p0;
ALTER TABLE t1 REPAIR PARTITION p0;
ALTER TABLE t1 TRUNCATE PARTITION p0;
ALTER TABLE t1 DROP PARTITION p0;
--source include/show_binlog_events.inc
DROP TABLE t1;
...@@ -3428,7 +3428,7 @@ int ha_partition::truncate() ...@@ -3428,7 +3428,7 @@ int ha_partition::truncate()
ALTER TABLE t TRUNCATE PARTITION ... ALTER TABLE t TRUNCATE PARTITION ...
*/ */
int ha_partition::truncate_partition(Alter_info *alter_info) int ha_partition::truncate_partition(Alter_info *alter_info, bool *to_binlog)
{ {
int error= 0; int error= 0;
List_iterator<partition_element> part_it(m_part_info->partitions); List_iterator<partition_element> part_it(m_part_info->partitions);
...@@ -3440,6 +3440,9 @@ int ha_partition::truncate_partition(Alter_info *alter_info) ...@@ -3440,6 +3440,9 @@ int ha_partition::truncate_partition(Alter_info *alter_info)
PART_ADMIN); PART_ADMIN);
DBUG_ENTER("ha_partition::truncate_partition"); DBUG_ENTER("ha_partition::truncate_partition");
/* Only binlog when it starts any call to the partitions handlers */
*to_binlog= false;
/* /*
TRUNCATE also means resetting auto_increment. Hence, reset TRUNCATE also means resetting auto_increment. Hence, reset
it so that it will be initialized again at the next use. it so that it will be initialized again at the next use.
...@@ -3453,6 +3456,8 @@ int ha_partition::truncate_partition(Alter_info *alter_info) ...@@ -3453,6 +3456,8 @@ int ha_partition::truncate_partition(Alter_info *alter_info)
(!(alter_info->flags & ALTER_ALL_PARTITION))) (!(alter_info->flags & ALTER_ALL_PARTITION)))
DBUG_RETURN(HA_ERR_NO_PARTITION_FOUND); DBUG_RETURN(HA_ERR_NO_PARTITION_FOUND);
*to_binlog= true;
do do
{ {
partition_element *part_elem= part_it++; partition_element *part_elem= part_it++;
......
...@@ -362,7 +362,7 @@ public: ...@@ -362,7 +362,7 @@ public:
@remark This method is a partitioning-specific hook @remark This method is a partitioning-specific hook
and thus not a member of the general SE API. and thus not a member of the general SE API.
*/ */
int truncate_partition(Alter_info *); int truncate_partition(Alter_info *, bool *to_binlog);
virtual bool is_fatal_error(int error, uint flags) virtual bool is_fatal_error(int error, uint flags)
{ {
......
...@@ -110,6 +110,7 @@ bool Alter_table_truncate_partition_statement::execute(THD *thd) ...@@ -110,6 +110,7 @@ bool Alter_table_truncate_partition_statement::execute(THD *thd)
ha_partition *partition; ha_partition *partition;
ulong timeout= thd->variables.lock_wait_timeout; ulong timeout= thd->variables.lock_wait_timeout;
TABLE_LIST *first_table= thd->lex->select_lex.table_list.first; TABLE_LIST *first_table= thd->lex->select_lex.table_list.first;
bool to_binlog;
DBUG_ENTER("Alter_table_truncate_partition_statement::execute"); DBUG_ENTER("Alter_table_truncate_partition_statement::execute");
/* /*
...@@ -161,16 +162,18 @@ bool Alter_table_truncate_partition_statement::execute(THD *thd) ...@@ -161,16 +162,18 @@ bool Alter_table_truncate_partition_statement::execute(THD *thd)
partition= (ha_partition *) first_table->table->file; partition= (ha_partition *) first_table->table->file;
/* Invoke the handler method responsible for truncating the partition. */ /* Invoke the handler method responsible for truncating the partition. */
if ((error= partition->truncate_partition(&thd->lex->alter_info))) if ((error= partition->truncate_partition(&thd->lex->alter_info,
&to_binlog)))
first_table->table->file->print_error(error, MYF(0)); first_table->table->file->print_error(error, MYF(0));
/* /*
All effects of a truncate operation are committed even if the All effects of a truncate operation are committed even if the
operation fails. Thus, the query must be written to the binary operation fails. Thus, the query must be written to the binary
log. The only exception is a unimplemented truncate method. Also, log. The exception is a unimplemented truncate method or failure
it is logged in statement format, regardless of the binlog format. before any call to handler::truncate() is done.
Also, it is logged in statement format, regardless of the binlog format.
*/ */
if (error != HA_ERR_WRONG_COMMAND) if (error != HA_ERR_WRONG_COMMAND && to_binlog)
error|= write_bin_log(thd, !error, thd->query(), thd->query_length()); error|= write_bin_log(thd, !error, thd->query(), thd->query_length());
/* /*
......
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