summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/partition_binlog.result56
-rw-r--r--mysql-test/t/partition_binlog.test42
-rw-r--r--sql/ha_partition.cc7
-rw-r--r--sql/ha_partition.h2
-rw-r--r--sql/sql_partition_admin.cc11
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());
/*