Commit 29cc2c28 authored by Venkatesh Duggirala's avatar Venkatesh Duggirala

BUG#20574550 MAIN.MERGE TEST CASE FAILS IF BINLOG_FORMAT=ROW

The main.merge test case was failing when tested using row based
binlog format.

While analyzing the issue it was found the following issues:

a) The server is calling binlog related code even when a statement will
   not be binlogged;
b) The child table list was not present into table structure by the time
   to generate the create table statement;
c) The tables in the child table list will not be opened yet when
   generating table create info using row based replication;
d) CREATE TABLE LIKE TEMP_TABLE does not preserve original table storage
   engine when using row based replication;

This patch addressed all above issues.

@ sql/sql_class.h

Added a function to determine if the binary log is disabled to
  the current session. This is related with issue (a) above.

@ sql/sql_table.cc

Added code to skip binary logging related code if the statement
  will not be binlogged. This is related with issue (a) above.

Added code to add the children to the query list of the table that
  will have its CREATE TABLE generated. This is related with issue (b)
  above.

Added code to force the storage engine to be generated into the
  CREATE TABLE. This is related with issue (d) above.

@ storage/myisammrg/ha_myisammrg.cc

Added a test to skip a table getting info about a child table if the
  child table is not opened. This is related to issue (c) above.
parent 4ed09d54
...@@ -1203,7 +1203,7 @@ master-bin.000001 # Query # # use `test`; CREATE TABLE IF NOT EXISTS `t2` ( ...@@ -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 # # COMMIT
master-bin.000001 # Query # # use `test`; CREATE TABLE IF NOT EXISTS `t3` ( master-bin.000001 # Query # # use `test`; CREATE TABLE IF NOT EXISTS `t3` (
`a` int(11) DEFAULT NULL `a` int(11) DEFAULT NULL
) ) ENGINE=MyISAM
master-bin.000001 # Query # # BEGIN master-bin.000001 # Query # # BEGIN
master-bin.000001 # Table_map # # table_id: # (mysql.user) master-bin.000001 # Table_map # # table_id: # (mysql.user)
master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F 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` ( ...@@ -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 # # COMMIT
master-bin.000001 # Query # # use `test`; CREATE TABLE IF NOT EXISTS `t3` ( master-bin.000001 # Query # # use `test`; CREATE TABLE IF NOT EXISTS `t3` (
`a` int(11) DEFAULT NULL `a` int(11) DEFAULT NULL
) ) ENGINE=MyISAM
master-bin.000001 # Query # # BEGIN master-bin.000001 # Query # # BEGIN
master-bin.000001 # Table_map # # table_id: # (mysql.user) master-bin.000001 # Table_map # # table_id: # (mysql.user)
master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F
......
...@@ -4,8 +4,9 @@ CREATE TABLE t1 (a int) ENGINE=MyISAM; ...@@ -4,8 +4,9 @@ CREATE TABLE t1 (a int) ENGINE=MyISAM;
CREATE TABLE t2 (a int) ENGINE=MyISAM; CREATE TABLE t2 (a int) ENGINE=MyISAM;
INSERT INTO t1 VALUES (1), (2), (3); INSERT INTO t1 VALUES (1), (2), (3);
INSERT INTO t2 VALUES (4), (5), (6); INSERT INTO t2 VALUES (4), (5), (6);
CREATE TABLE IF NOT EXISTS t1_merge LIKE t1; CREATE TEMPORARY TABLE IF NOT EXISTS tt1_merge LIKE t1;
ALTER TABLE t1_merge ENGINE=MERGE UNION (t2, 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.t1, slave:test.t1]
include/diff_tables.inc [master:test.t2, slave:test.t2] include/diff_tables.inc [master:test.t2, slave:test.t2]
UPDATE t1_merge SET a=10 WHERE a=1; UPDATE t1_merge SET a=10 WHERE a=1;
......
...@@ -192,4 +192,14 @@ DROP FUNCTION f2; ...@@ -192,4 +192,14 @@ DROP FUNCTION f2;
DROP PROCEDURE p2; DROP PROCEDURE p2;
DROP EVENT e2; DROP EVENT e2;
DROP TABLE t1, t2; 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 include/rpl_end.inc
...@@ -20,8 +20,10 @@ CREATE TABLE t1 (a int) ENGINE=MyISAM; ...@@ -20,8 +20,10 @@ CREATE TABLE t1 (a int) ENGINE=MyISAM;
CREATE TABLE t2 (a int) ENGINE=MyISAM; CREATE TABLE t2 (a int) ENGINE=MyISAM;
INSERT INTO t1 VALUES (1), (2), (3); INSERT INTO t1 VALUES (1), (2), (3);
INSERT INTO t2 VALUES (4), (5), (6); INSERT INTO t2 VALUES (4), (5), (6);
CREATE TABLE IF NOT EXISTS t1_merge LIKE t1; # Changed a little to check also an issue reported on BUG#20574550
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;
--sync_slave_with_master --sync_slave_with_master
......
...@@ -166,4 +166,55 @@ DROP PROCEDURE p2; ...@@ -166,4 +166,55 @@ DROP PROCEDURE p2;
DROP EVENT e2; DROP EVENT e2;
DROP TABLE t1, t2; DROP TABLE t1, t2;
--sync_slave_with_master
#
# BUG#20574550
# CREATE TABLE LIKE <TEMP_TABLE> 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 --source include/rpl_end.inc
/* 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 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 it under the terms of the GNU General Public License as published by
...@@ -1662,6 +1662,18 @@ class THD :public Statement, ...@@ -1662,6 +1662,18 @@ class THD :public Statement,
current_stmt_binlog_format == BINLOG_FORMAT_ROW); current_stmt_binlog_format == BINLOG_FORMAT_ROW);
return 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: private:
/** /**
......
/* /*
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 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 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, ...@@ -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. 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 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, ...@@ -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)) if (open_table(thd, table, thd->mem_root, &ot_ctx))
goto err; 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))= int result __attribute__((unused))=
store_create_info(thd, table, &query, store_create_info(thd, table, &query,
create_info, TRUE /* show_database */); create_info, TRUE /* show_database */);
......
/* 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 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 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) ...@@ -1481,6 +1481,8 @@ void ha_myisammrg::update_create_info(HA_CREATE_INFO *create_info)
open_table != file->end_table ; open_table != file->end_table ;
open_table++) open_table++)
{ {
if (!open_table->table)
continue;
TABLE_LIST *ptr; TABLE_LIST *ptr;
LEX_STRING db, name; LEX_STRING db, name;
LINT_INIT(db.str); LINT_INIT(db.str);
......
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