List:Commits« Previous MessageNext Message »
From:He Zhenxing Date:August 18 2008 12:27pm
Subject:Re: bzr commit into mysql-5.1 branch (mats:2658) Bug#34707
View as plain text  
Hi Mats

Nice work, approved

Mats Kindahl wrote:
> #At file:///home/bzr/bugs/b34707-5.1-rpl/
> 
>  2658 Mats Kindahl	2008-08-13
>       Bug #34707: Row based replication: slave creates table within wrong database
>       
>       The failure was caused by executing a CREATE-SELECT statement that creates a
>       table in another database than the current one. In row-based logging, the
>       CREATE statement was written to the binary log without the database, hence
>       creating the table in the wrong database, causing the following inserts to
>       fail since the table didn't exist in the given database.
>       
>       Fixed the bug by adding a parameter to store_create_info() that will make
>       the function print the database name before the table name and used that
>       in the calls that write the CREATE statement to the binary log. The database
>       name is only printed if it is different than the currently selected database.
>       
>       The output of SHOW CREATE TABLE has not changed and is still printed without
>       the database name.
> modified:
>   mysql-test/suite/rpl/r/rpl_row_create_table.result
>   mysql-test/suite/rpl/t/rpl_row_create_table.test
>   sql/sql_insert.cc
>   sql/sql_show.cc
>   sql/sql_show.h
>   sql/sql_table.cc
> 
> per-file messages:
>   mysql-test/suite/rpl/r/rpl_row_create_table.result
>     Result file change.
>   mysql-test/suite/rpl/t/rpl_row_create_table.test
>     Added test to check that CREATE-SELECT into another database than the
>     current one replicates.
>   sql/sql_insert.cc
>     Adding parameter to calls to store_create_info().
>   sql/sql_show.cc
>     Adding parameter to calls to store_create_info().
>     
>     Extending store_create_info() with parameter 'show_database' that will cause
>     the database to be written before the table name.
>   sql/sql_show.h
>     Adding parameter to call to store_create_info() to tell if the database should be
> shown or not.
>   sql/sql_table.cc
>     Adding parameter to calls to store_create_info().
> === modified file 'mysql-test/suite/rpl/r/rpl_row_create_table.result'
> --- a/mysql-test/suite/rpl/r/rpl_row_create_table.result	2008-04-08 07:43:00 +0000
> +++ b/mysql-test/suite/rpl/r/rpl_row_create_table.result	2008-08-13 13:06:25 +0000
> @@ -430,4 +430,25 @@ a
>  1
>  2
>  DROP TABLE t1;
> +stop slave;
> +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
> +reset master;
> +reset slave;
> +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
> +start slave;
> +CREATE DATABASE mysqltest1;
> +CREATE TABLE mysqltest1.without_select (f1 BIGINT);
> +CREATE TABLE mysqltest1.with_select AS SELECT 1 AS f1;
> +show binlog events from <binlog_start>;
> +Log_name	Pos	Event_type	Server_id	End_log_pos	Info
> +master-bin.000001	#	Query	#	#	CREATE DATABASE mysqltest1
> +master-bin.000001	#	Query	#	#	use `test`; CREATE TABLE mysqltest1.without_select (f1
> BIGINT)
> +master-bin.000001	#	Query	#	#	use `test`; BEGIN
> +master-bin.000001	#	Query	#	#	use `test`; CREATE TABLE `mysqltest1`.`with_select` (
> +  `f1` int(1) NOT NULL DEFAULT '0'
> +)
> +master-bin.000001	#	Table_map	#	#	table_id: # (mysqltest1.with_select)
> +master-bin.000001	#	Write_rows	#	#	table_id: # flags: STMT_END_F
> +master-bin.000001	#	Query	#	#	use `test`; COMMIT
> +DROP DATABASE mysqltest1;
>  end of the tests
> 
> === modified file 'mysql-test/suite/rpl/t/rpl_row_create_table.test'
> --- a/mysql-test/suite/rpl/t/rpl_row_create_table.test	2008-04-08 07:43:00 +0000
> +++ b/mysql-test/suite/rpl/t/rpl_row_create_table.test	2008-08-13 13:06:25 +0000
> @@ -259,5 +259,22 @@ connection master;
>  DROP TABLE t1;
>  sync_slave_with_master;
>  
> +#
> +# BUG#34707: Row based replication: slave creates table within wrong database
> +#
> +
> +source include/master-slave-reset.inc;
> +
> +connection master;
> +CREATE DATABASE mysqltest1;
> +
> +CREATE TABLE mysqltest1.without_select (f1 BIGINT);
> +CREATE TABLE mysqltest1.with_select AS SELECT 1 AS f1;
> +source include/show_binlog_events.inc;
> +sync_slave_with_master;
> +
> +connection master;
> +DROP DATABASE mysqltest1;
> +sync_slave_with_master;
>  
>  --echo end of the tests
> 
> === modified file 'sql/sql_insert.cc'
> --- a/sql/sql_insert.cc	2008-07-11 18:51:10 +0000
> +++ b/sql/sql_insert.cc	2008-08-13 13:06:25 +0000
> @@ -3616,7 +3616,8 @@ select_create::binlog_show_create_table(
>    tmp_table_list.table = *tables;
>    query.length(0);      // Have to zero it since constructor doesn't
>  
> -  result= store_create_info(thd, &tmp_table_list, &query, create_info);
> +  result= store_create_info(thd, &tmp_table_list, &query, create_info,
> +                            /* show_database */ TRUE);
>    DBUG_ASSERT(result == 0); /* store_create_info() always return 0 */
>  
>    thd->binlog_query(THD::STMT_QUERY_TYPE,
> 
> === modified file 'sql/sql_show.cc'
> --- a/sql/sql_show.cc	2008-05-12 10:09:10 +0000
> +++ b/sql/sql_show.cc	2008-08-13 13:06:25 +0000
> @@ -619,7 +619,8 @@ mysqld_show_create(THD *thd, TABLE_LIST 
>  
>    if ((table_list->view ?
>         view_store_create_info(thd, table_list, &buffer) :
> -       store_create_info(thd, table_list, &buffer, NULL)))
> +       store_create_info(thd, table_list, &buffer, NULL,
> +                         FALSE /* show_database */)))
>      DBUG_RETURN(TRUE);
>  
>    List<Item> field_list;
> @@ -810,7 +811,8 @@ mysqld_dump_create_info(THD *thd, TABLE_
>    DBUG_PRINT("enter",("table: %s",table_list->table->s->table_name.str));
>  
>    protocol->prepare_for_resend();
> -  if (store_create_info(thd, table_list, packet, NULL))
> +  if (store_create_info(thd, table_list, packet, NULL,
> +                        FALSE /* show_database */))
>      DBUG_RETURN(-1);
>  
>    if (fd < 0)
> @@ -1062,7 +1064,7 @@ static bool get_field_default_value(THD 
>   */
>  
>  int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
> -                      HA_CREATE_INFO *create_info_arg)
> +                      HA_CREATE_INFO *create_info_arg, bool show_database)
>  {
>    List<Item> field_list;
>    char tmp[MAX_FIELD_WIDTH], *for_str, buff[128], def_value_buf[MAX_FIELD_WIDTH];
> @@ -1110,6 +1112,25 @@ int store_create_info(THD *thd, TABLE_LI
>        alias= share->table_name.str;
>      }
>    }
> +
> +  /*
> +    Print the database before the table name if told to do that. The
> +    database name is only printed in the event that it is different
> +    from the current database.  The main reason for doing this is to
> +    avoid having to update gazillions of tests and result files, but
> +    it also saves a few bytes of the binary log.
> +   */
> +  if (show_database)
> +  {
> +    const LEX_STRING *const db=
> +      table_list->schema_table ? &INFORMATION_SCHEMA_NAME :
> &table->s->db;
> +    if (strcmp(db->str, thd->db) != 0)
> +    {
> +      append_identifier(thd, packet, db->str, db->length);
> +      packet->append(STRING_WITH_LEN("."));
> +    }
> +  }
> +
>    append_identifier(thd, packet, alias, strlen(alias));
>    packet->append(STRING_WITH_LEN(" (\n"));
>    /*
> 
> === modified file 'sql/sql_show.h'
> --- a/sql/sql_show.h	2007-08-02 22:14:05 +0000
> +++ b/sql/sql_show.h	2008-08-13 13:06:25 +0000
> @@ -33,7 +33,7 @@ find_files_result find_files(THD *thd, L
>                               const char *path, const char *wild, bool dir);
>  
>  int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
> -                      HA_CREATE_INFO  *create_info_arg);
> +                      HA_CREATE_INFO  *create_info_arg, bool show_database);
>  int view_store_create_info(THD *thd, TABLE_LIST *table, String *buff);
>  
>  int copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table);
> 
> === modified file 'sql/sql_table.cc'
> --- a/sql/sql_table.cc	2008-07-17 18:26:55 +0000
> +++ b/sql/sql_table.cc	2008-08-13 13:06:25 +0000
> @@ -4956,8 +4956,9 @@ bool mysql_create_like_table(THD* thd, T
>          }
>          VOID(pthread_mutex_unlock(&LOCK_open));
>  
> -        IF_DBUG(int result=) store_create_info(thd, table, &query,
> -                                               create_info);
> +        IF_DBUG(int result=)
> +          store_create_info(thd, table, &query,
> +                            create_info, TRUE /* show_database */);
>  
>          DBUG_ASSERT(result == 0); // store_create_info() always return 0
>          write_bin_log(thd, TRUE, query.ptr(), query.length());
> 
> 
-- 
Turbolinux China
A: A12 Jianguomenwai Avenue Chaoyang District Beijing PRC
Z: 100022
E: hezx@stripped
T: 86-010-65054020-318
F: 86-010-65054017

Thread
bzr commit into mysql-5.1 branch (mats:2658) Bug#34707Mats Kindahl13 Aug
  • Re: bzr commit into mysql-5.1 branch (mats:2658) Bug#34707He Zhenxing18 Aug