diff --git a/mysql-test/suite/binlog/r/binlog_row_innodb_truncate.result b/mysql-test/suite/binlog/r/binlog_row_innodb_truncate.result new file mode 100644 index 00000000000..39f8b43f207 --- /dev/null +++ b/mysql-test/suite/binlog/r/binlog_row_innodb_truncate.result @@ -0,0 +1,28 @@ +CREATE TABLE t1 ( c1 int , primary key (c1)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1), (2), (3); +CREATE TEMPORARY TABLE IF NOT EXISTS t2 LIKE t1; +TRUNCATE TABLE t2; +DROP TABLE t1; +############################################### +### assertion: No event for 'TRUNCATE TABLE t2' +############################################### +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; CREATE TABLE t1 ( c1 int , primary key (c1)) ENGINE=InnoDB +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Table_map # # table_id: # (test.t1) +master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # use `test`; DROP TABLE t1 +############################################### +RESET MASTER; +CREATE TEMPORARY TABLE t1 (c1 int) Engine=InnoDB; +INSERT INTO t1 VALUES (1), (2), (3); +TRUNCATE t1; +DROP TEMPORARY TABLE t1; +############################################### +### assertion: No event for 'TRUNCATE TABLE t1' +############################################### +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +############################################### diff --git a/mysql-test/suite/binlog/r/binlog_row_mix_innodb_myisam.result b/mysql-test/suite/binlog/r/binlog_row_mix_innodb_myisam.result index 87e9b7f8685..a41961cd2ce 100644 --- a/mysql-test/suite/binlog/r/binlog_row_mix_innodb_myisam.result +++ b/mysql-test/suite/binlog/r/binlog_row_mix_innodb_myisam.result @@ -413,7 +413,6 @@ master-bin.000001 # Query # # BEGIN master-bin.000001 # Table_map # # table_id: # (test.t1) master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F master-bin.000001 # Query # # COMMIT -master-bin.000001 # Query # # use `test`; TRUNCATE table t2 master-bin.000001 # Query # # BEGIN master-bin.000001 # Table_map # # table_id: # (test.t1) master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F diff --git a/mysql-test/suite/binlog/t/binlog_row_innodb_truncate.test b/mysql-test/suite/binlog/t/binlog_row_innodb_truncate.test new file mode 100644 index 00000000000..d7c177d4632 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_row_innodb_truncate.test @@ -0,0 +1,37 @@ +-- source include/have_binlog_format_row.inc +-- source include/have_innodb.inc + +# +# BUG#51251 +# +# The test case checks if truncating a temporary table created with +# engine InnoDB will not cause the truncate statement to be binlogged. + +# Before patch for BUG#51251, the TRUNCATE statements below would be +# binlogged, which would cause the slave to fail with "table does not +# exist". + +CREATE TABLE t1 ( c1 int , primary key (c1)) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1), (2), (3); +CREATE TEMPORARY TABLE IF NOT EXISTS t2 LIKE t1; +TRUNCATE TABLE t2; +DROP TABLE t1; + +-- echo ############################################### +-- echo ### assertion: No event for 'TRUNCATE TABLE t2' +-- echo ############################################### +-- source include/show_binlog_events.inc +-- echo ############################################### + +RESET MASTER; + +CREATE TEMPORARY TABLE t1 (c1 int) Engine=InnoDB; +INSERT INTO t1 VALUES (1), (2), (3); +TRUNCATE t1; +DROP TEMPORARY TABLE t1; + +-- echo ############################################### +-- echo ### assertion: No event for 'TRUNCATE TABLE t1' +-- echo ############################################### +-- source include/show_binlog_events.inc +-- echo ############################################### diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index af3fdf11696..ef4b35486f6 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -50,6 +50,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, SELECT_LEX *select_lex= &thd->lex->select_lex; THD::killed_state killed_status= THD::NOT_KILLED; DBUG_ENTER("mysql_delete"); + bool save_binlog_row_based; THD::enum_binlog_query_type query_type= thd->lex->sql_command == SQLCOM_TRUNCATE ? @@ -293,6 +294,11 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, table->mark_columns_needed_for_delete(); + save_binlog_row_based= thd->current_stmt_binlog_row_based; + if (thd->lex->sql_command == SQLCOM_TRUNCATE && + thd->current_stmt_binlog_row_based) + thd->clear_current_stmt_binlog_row_based(); + while (!(error=info.read_record(&info)) && !thd->killed && ! thd->is_error()) { @@ -342,6 +348,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, else table->file->unlock_row(); // Row failed selection, release lock on it } + thd->current_stmt_binlog_row_based= save_binlog_row_based; killed_status= thd->killed; if (killed_status != THD::NOT_KILLED || thd->is_error()) error= 1; // Aborted @@ -390,7 +397,10 @@ cleanup: /* See similar binlogging code in sql_update.cc, for comments */ if ((error < 0) || thd->transaction.stmt.modified_non_trans_table) { - if (mysql_bin_log.is_open()) + if (mysql_bin_log.is_open() && + !(thd->lex->sql_command == SQLCOM_TRUNCATE && + thd->current_stmt_binlog_row_based && + find_temporary_table(thd, table_list))) { bool const is_trans= thd->lex->sql_command == SQLCOM_TRUNCATE ? @@ -1059,15 +1069,13 @@ bool multi_delete::send_eof() static bool mysql_truncate_by_delete(THD *thd, TABLE_LIST *table_list) { - bool error, save_binlog_row_based= thd->current_stmt_binlog_row_based; + bool error; DBUG_ENTER("mysql_truncate_by_delete"); table_list->lock_type= TL_WRITE; mysql_init_select(thd->lex); - thd->clear_current_stmt_binlog_row_based(); error= mysql_delete(thd, table_list, NULL, NULL, HA_POS_ERROR, LL(0), TRUE); ha_autocommit_or_rollback(thd, error); end_trans(thd, error ? ROLLBACK : COMMIT); - thd->current_stmt_binlog_row_based= save_binlog_row_based; DBUG_RETURN(error); }