diff --git a/mysql-test/suite/binlog/r/binlog_row_binlog.result b/mysql-test/suite/binlog/r/binlog_row_binlog.result index 75105689246..1fcc915fa1f 100644 --- a/mysql-test/suite/binlog/r/binlog_row_binlog.result +++ b/mysql-test/suite/binlog/r/binlog_row_binlog.result @@ -1203,7 +1203,7 @@ master-bin.000001 # Query # # use `test`; CREATE TABLE IF NOT EXISTS `t2` ( master-bin.000001 # Query # # COMMIT master-bin.000001 # Query # # use `test`; CREATE TABLE IF NOT EXISTS `t3` ( `a` int(11) DEFAULT NULL -) +) ENGINE=MyISAM master-bin.000001 # Query # # BEGIN master-bin.000001 # Table_map # # table_id: # (mysql.user) master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F @@ -1238,7 +1238,7 @@ master-bin.000001 # Query # # use `test`; CREATE TABLE IF NOT EXISTS `t2` ( master-bin.000001 # Query # # COMMIT master-bin.000001 # Query # # use `test`; CREATE TABLE IF NOT EXISTS `t3` ( `a` int(11) DEFAULT NULL -) +) ENGINE=MyISAM master-bin.000001 # Query # # BEGIN master-bin.000001 # Table_map # # table_id: # (mysql.user) master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F diff --git a/mysql-test/suite/rpl/r/rpl_row_merge_engine.result b/mysql-test/suite/rpl/r/rpl_row_merge_engine.result index c61167e84e0..3b2e02bf97c 100644 --- a/mysql-test/suite/rpl/r/rpl_row_merge_engine.result +++ b/mysql-test/suite/rpl/r/rpl_row_merge_engine.result @@ -4,8 +4,9 @@ CREATE TABLE t1 (a int) ENGINE=MyISAM; CREATE TABLE t2 (a int) ENGINE=MyISAM; INSERT INTO t1 VALUES (1), (2), (3); INSERT INTO t2 VALUES (4), (5), (6); -CREATE TABLE IF NOT EXISTS t1_merge LIKE t1; -ALTER TABLE t1_merge ENGINE=MERGE UNION (t2, t1); +CREATE TEMPORARY TABLE IF NOT EXISTS tt1_merge LIKE t1; +ALTER TABLE tt1_merge ENGINE=MERGE UNION (t2, t1); +CREATE TABLE t1_merge LIKE tt1_merge; include/diff_tables.inc [master:test.t1, slave:test.t1] include/diff_tables.inc [master:test.t2, slave:test.t2] UPDATE t1_merge SET a=10 WHERE a=1; diff --git a/mysql-test/suite/rpl/r/rpl_tmp_table_and_DDL.result b/mysql-test/suite/rpl/r/rpl_tmp_table_and_DDL.result index 0264c9421fc..fb4e8f8ab8a 100644 --- a/mysql-test/suite/rpl/r/rpl_tmp_table_and_DDL.result +++ b/mysql-test/suite/rpl/r/rpl_tmp_table_and_DDL.result @@ -192,4 +192,14 @@ DROP FUNCTION f2; DROP PROCEDURE p2; DROP EVENT e2; DROP TABLE t1, t2; +CREATE TEMPORARY TABLE temp_t1 (c1 INT) ENGINE=InnoDB; +CREATE TEMPORARY TABLE temp_t2 (c1 INT) ENGINE=MyISAM; +CREATE TABLE t1 LIKE temp_t1; +CREATE TABLE t2 LIKE temp_t2; +include/assert.inc ["t1 on master and temp_t1 have the same storage engine"] +include/assert.inc ["t2 on master and temp_t2 have the same storage engine"] +include/assert.inc ["t1 on slave and temp_t1 have the same storage engine"] +include/assert.inc ["t2 on slave and temp_t2 have the same storage engine"] +DROP TEMPORARY TABLE temp_t1, temp_t2; +DROP TABLE t1, t2; include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_merge_engine.test b/mysql-test/suite/rpl/t/rpl_row_merge_engine.test index 5add8dc1cda..dcbb8b891d8 100644 --- a/mysql-test/suite/rpl/t/rpl_row_merge_engine.test +++ b/mysql-test/suite/rpl/t/rpl_row_merge_engine.test @@ -20,8 +20,10 @@ CREATE TABLE t1 (a int) ENGINE=MyISAM; CREATE TABLE t2 (a int) ENGINE=MyISAM; INSERT INTO t1 VALUES (1), (2), (3); INSERT INTO t2 VALUES (4), (5), (6); -CREATE TABLE IF NOT EXISTS t1_merge LIKE t1; -ALTER TABLE t1_merge ENGINE=MERGE UNION (t2, t1); +# Changed a little to check also an issue reported on BUG#20574550 +CREATE TEMPORARY TABLE IF NOT EXISTS tt1_merge LIKE t1; +ALTER TABLE tt1_merge ENGINE=MERGE UNION (t2, t1); +CREATE TABLE t1_merge LIKE tt1_merge; --sync_slave_with_master diff --git a/mysql-test/suite/rpl/t/rpl_tmp_table_and_DDL.test b/mysql-test/suite/rpl/t/rpl_tmp_table_and_DDL.test index d722a15f255..decbdcc1f99 100644 --- a/mysql-test/suite/rpl/t/rpl_tmp_table_and_DDL.test +++ b/mysql-test/suite/rpl/t/rpl_tmp_table_and_DDL.test @@ -166,4 +166,55 @@ DROP PROCEDURE p2; DROP EVENT e2; DROP TABLE t1, t2; +--sync_slave_with_master +# +# BUG#20574550 +# CREATE TABLE LIKE does not preserve original table storage +# engine when using row based replication +# +--connection master + +# Define temp_t1 and temp_t2 storage engines +--let $engine_temp_t1= InnoDB +--let $engine_temp_t2= MyISAM + +# Create the two temporary tables +--eval CREATE TEMPORARY TABLE temp_t1 (c1 INT) ENGINE=$engine_temp_t1 +--eval CREATE TEMPORARY TABLE temp_t2 (c1 INT) ENGINE=$engine_temp_t2 + +# Create t1 and t2 based on temporary tables +CREATE TABLE t1 LIKE temp_t1; +CREATE TABLE t2 LIKE temp_t2; +--sync_slave_with_master + +# On master +--connection master +# Assert that t1 and t2 have the same storage engines as temp_t1 and temp_t2 +--let $engine_t1= query_get_value(SHOW TABLE STATUS WHERE Name='t1', Engine, 1) +--let $assert_cond= "$engine_t1" = "$engine_temp_t1" +--let $assert_text= "t1 on master and temp_t1 have the same storage engine" +--source include/assert.inc + +--let $engine_t2= query_get_value(SHOW TABLE STATUS WHERE Name='t2', Engine, 1) +--let $assert_cond= "$engine_t2" = "$engine_temp_t2" +--let $assert_text= "t2 on master and temp_t2 have the same storage engine" +--source include/assert.inc + +# On slave +--connection slave +# Assert that t1 and t2 have the same storage engines as temp_t1 and temp_t2 +--let $engine_t1= query_get_value(SHOW TABLE STATUS WHERE Name='t1', Engine, 1) +--let $assert_cond= "$engine_t1" = "$engine_temp_t1" +--let $assert_text= "t1 on slave and temp_t1 have the same storage engine" +--source include/assert.inc + +--let $engine_t2= query_get_value(SHOW TABLE STATUS WHERE Name='t2', Engine, 1) +--let $assert_cond= "$engine_t2" = "$engine_temp_t2" +--let $assert_text= "t2 on slave and temp_t2 have the same storage engine" +--source include/assert.inc + +# Cleanup +--connection master +DROP TEMPORARY TABLE temp_t1, temp_t2; +DROP TABLE t1, t2; --source include/rpl_end.inc diff --git a/sql/sql_class.h b/sql/sql_class.h index c9900231615..0df8c70e184 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1662,6 +1662,18 @@ public: current_stmt_binlog_format == BINLOG_FORMAT_ROW); return current_stmt_binlog_format == BINLOG_FORMAT_ROW; } + /** + Determine if binlogging is disabled for this session + @retval 0 if the current statement binlogging is disabled + (could be because of binlog closed/binlog option + is set to false). + @retval 1 if the current statement will be binlogged + */ + inline bool is_current_stmt_binlog_disabled() const + { + return (!(variables.option_bits & OPTION_BIN_LOG) || + !mysql_bin_log.is_open()); + } private: /** diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 7b4d08613cf..49f05c6116e 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -4709,7 +4709,8 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table, /* We have to write the query before we unlock the tables. */ - if (thd->is_current_stmt_binlog_format_row()) + if (!thd->is_current_stmt_binlog_disabled() && + thd->is_current_stmt_binlog_format_row()) { /* Since temporary tables are not replicated under row-based @@ -4751,6 +4752,21 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table, if (open_table(thd, table, thd->mem_root, &ot_ctx)) goto err; + /* + After opening a MERGE table add the children to the query list of + tables, so that children tables info can be used on "CREATE TABLE" + statement generation by the binary log. + Note that placeholders don't have the handler open. + */ + if (table->table->file->extra(HA_EXTRA_ADD_CHILDREN_LIST)) + goto err; + + /* + As the reference table is temporary and may not exist on slave, we must + force the ENGINE to be present into CREATE TABLE. + */ + create_info->used_fields|= HA_CREATE_USED_ENGINE; + int result __attribute__((unused))= store_create_info(thd, table, &query, create_info, TRUE /* show_database */); diff --git a/storage/myisammrg/ha_myisammrg.cc b/storage/myisammrg/ha_myisammrg.cc index b7e043c99f1..1ffdd83358d 100644 --- a/storage/myisammrg/ha_myisammrg.cc +++ b/storage/myisammrg/ha_myisammrg.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1481,6 +1481,8 @@ void ha_myisammrg::update_create_info(HA_CREATE_INFO *create_info) open_table != file->end_table ; open_table++) { + if (!open_table->table) + continue; TABLE_LIST *ptr; LEX_STRING db, name; LINT_INIT(db.str);