diff options
-rw-r--r-- | mysql-test/r/partition_binlog.result | 56 | ||||
-rw-r--r-- | mysql-test/t/partition_binlog.test | 42 | ||||
-rw-r--r-- | sql/ha_partition.cc | 7 | ||||
-rw-r--r-- | sql/ha_partition.h | 2 | ||||
-rw-r--r-- | sql/sql_partition_admin.cc | 11 |
5 files changed, 112 insertions, 6 deletions
diff --git a/mysql-test/r/partition_binlog.result b/mysql-test/r/partition_binlog.result new file mode 100644 index 00000000000..8b449371d0e --- /dev/null +++ b/mysql-test/r/partition_binlog.result @@ -0,0 +1,56 @@ +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; diff --git a/mysql-test/t/partition_binlog.test b/mysql-test/t/partition_binlog.test new file mode 100644 index 00000000000..432cdc922d6 --- /dev/null +++ b/mysql-test/t/partition_binlog.test @@ -0,0 +1,42 @@ +--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; diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index f4e240e5cc1..4e0fb7c804a 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -3428,7 +3428,7 @@ int ha_partition::truncate() ALTER TABLE t TRUNCATE PARTITION ... */ -int ha_partition::truncate_partition(Alter_info *alter_info) +int ha_partition::truncate_partition(Alter_info *alter_info, bool *binlog_stmt) { int error= 0; List_iterator<partition_element> part_it(m_part_info->partitions); @@ -3440,6 +3440,9 @@ int ha_partition::truncate_partition(Alter_info *alter_info) PART_ADMIN); DBUG_ENTER("ha_partition::truncate_partition"); + /* Only binlog when it starts any call to the partitions handlers */ + *binlog_stmt= false; + /* TRUNCATE also means resetting auto_increment. Hence, reset 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) (!(alter_info->flags & ALTER_ALL_PARTITION))) DBUG_RETURN(HA_ERR_NO_PARTITION_FOUND); + *binlog_stmt= true; + do { partition_element *part_elem= part_it++; diff --git a/sql/ha_partition.h b/sql/ha_partition.h index f1abc0cefe2..57456ddf8ae 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -362,7 +362,7 @@ public: @remark This method is a partitioning-specific hook and thus not a member of the general SE API. */ - int truncate_partition(Alter_info *); + int truncate_partition(Alter_info *, bool *binlog_stmt); virtual bool is_fatal_error(int error, uint flags) { diff --git a/sql/sql_partition_admin.cc b/sql/sql_partition_admin.cc index 8f6ab5803d7..cadfc587c1c 100644 --- a/sql/sql_partition_admin.cc +++ b/sql/sql_partition_admin.cc @@ -110,6 +110,7 @@ bool Alter_table_truncate_partition_statement::execute(THD *thd) ha_partition *partition; ulong timeout= thd->variables.lock_wait_timeout; TABLE_LIST *first_table= thd->lex->select_lex.table_list.first; + bool binlog_stmt; DBUG_ENTER("Alter_table_truncate_partition_statement::execute"); /* @@ -161,16 +162,18 @@ bool Alter_table_truncate_partition_statement::execute(THD *thd) partition= (ha_partition *) first_table->table->file; /* 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, + &binlog_stmt))) first_table->table->file->print_error(error, MYF(0)); /* All effects of a truncate operation are committed even if the operation fails. Thus, the query must be written to the binary - log. The only exception is a unimplemented truncate method. Also, - it is logged in statement format, regardless of the binlog format. + log. The exception is a unimplemented truncate method or failure + 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 && binlog_stmt) error|= write_bin_log(thd, !error, thd->query(), thd->query_length()); /* |