List:Commits« Previous MessageNext Message »
From:Mats Kindahl Date:October 27 2009 2:05pm
Subject:Re: bzr commit into mysql-5.1-bugteam branch (luis.soares:3199)
Bug#48297
View as plain text  
Hi Luis,

Just one comment: see below.

/Matz

Luis Soares wrote:
> #At file:///home/lsoares/Workspace/bzr/work/bugfixing/48297/mysql-5.1-bugteam/ based
> on revid:joro@stripped
> 
>  3199 Luis Soares	2009-10-27
>       BUG#48297: Schema name is ignored when LOAD DATA is written into 
>       binlog, replication aborts
>       
>       In SBR or MBR, the schema name is not being written to the binlog
>       when executing a LOAD DATA statement. This becomes a problem when
>       the current database (lets call it db1) is different from the
>       table's schema (lets call it db2). For instance, take the
>       following statements:
>         
>         use db1;
>         load data local infile 'infile.txt' into table db2.t
>       
>       Should this statement be logged without t's schema (db2), when
>       replaying it, one can get db1.t populated instead of db2.t (if
>       db1.t exists). On the other hand, if there is no db1.t at all,
>       replication will stop.
>       
>       We fix this by always logging the table (in load file) with fully
>       qualified name when its schema is different from the current
>       database or when no default database was selected.
> 
>     modified:
>       mysql-test/extra/rpl_tests/rpl_loaddata.test
>       mysql-test/suite/rpl/r/rpl_loaddata.result
>       sql/sql_load.cc
> === modified file 'mysql-test/extra/rpl_tests/rpl_loaddata.test'
> --- a/mysql-test/extra/rpl_tests/rpl_loaddata.test	2008-11-13 19:19:00 +0000
> +++ b/mysql-test/extra/rpl_tests/rpl_loaddata.test	2009-10-27 10:52:21 +0000
> @@ -158,4 +158,65 @@ LOAD DATA INFILE "../../std_data/words.d
>  
>  DROP TABLE IF EXISTS t1;
>  
> +# BUG#48297: Schema name is ignored when LOAD DATA is written into binlog,
> +# replication aborts
> +-- source include/master-slave-reset.inc
> +
> +-- let $db1= b48297_db1
> +-- let $db2= b42897_db2
> +
> +-- connection master
> +
> +-- disable_warnings
> +-- eval drop database if exists $db1
> +-- eval drop database if exists $db2
> +-- enable_warnings
> +
> +-- eval create database $db1
> +-- eval create database $db2
> +
> +-- eval use $db1
> +-- eval CREATE TABLE t1 (c1 VARCHAR(256)) engine=$engine_type;
> +
> +-- eval use $db2
> +
> +-- echo ### assertion: works with cross-referenced database
> +-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
> +-- eval LOAD DATA LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE
> $db1.t1
> +
> +-- eval use $db1
> +-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
> +-- echo ### assertion: works with fully qualified name on current database
> +-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
> +-- eval LOAD DATA LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE
> $db1.t1
> +
> +-- echo ### assertion: works without fully qualified name on current database
> +-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
> +-- eval LOAD DATA LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE
> t1
> +
> +-- echo ### create connection without default database
> +-- echo ### connect (conn2,localhost,root,,*NO-ONE*);
> +connect (conn2,localhost,root,,*NO-ONE*);
> +-- connection conn2
> +-- echo ### assertion: works without stating the default database
> +-- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
> +-- eval LOAD DATA LOCAL INFILE '$MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE
> $db1.t1
> +-- echo ### disconnect and switch back to master connection
> +-- disconnect conn2
> +-- connection master
> +
> +-- sync_slave_with_master
> +-- eval use $db1
> +
> +let $diff_table_1=master:$db1.t1;
> +let $diff_table_2=slave:$db1.t1;
> +source include/diff_tables.inc;
> +
> +-- connection master
> +
> +-- eval DROP DATABASE $db1
> +-- eval DROP DATABASE $db2
> +
> +-- sync_slave_with_master
> +
>  # End of 4.1 tests
> 
> === modified file 'mysql-test/suite/rpl/r/rpl_loaddata.result'
> --- a/mysql-test/suite/rpl/r/rpl_loaddata.result	2009-09-28 12:41:10 +0000
> +++ b/mysql-test/suite/rpl/r/rpl_loaddata.result	2009-10-27 10:52:21 +0000
> @@ -86,3 +86,32 @@ CREATE TABLE t1 (word CHAR(20) NOT NULL 
>  LOAD DATA INFILE "../../std_data/words.dat" INTO TABLE t1;
>  ERROR 23000: Duplicate entry 'Aarhus' for key 'PRIMARY'
>  DROP TABLE IF EXISTS 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;
> +drop database if exists b48297_db1;
> +drop database if exists b42897_db2;
> +create database b48297_db1;
> +create database b42897_db2;
> +use b48297_db1;
> +CREATE TABLE t1 (c1 VARCHAR(256)) engine=MyISAM;;
> +use b42897_db2;
> +### assertion: works with cross-referenced database
> +LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE
> b48297_db1.t1;
> +use b48297_db1;
> +### assertion: works with fully qualified name on current database
> +LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE
> b48297_db1.t1;
> +### assertion: works without fully qualified name on current database
> +LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE t1;
> +### create connection without default database
> +### connect (conn2,localhost,root,,*NO-ONE*);
> +### assertion: works without stating the default database
> +LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/std_data/loaddata5.dat' INTO TABLE
> b48297_db1.t1;
> +### disconnect and switch back to master connection
> +use b48297_db1;
> +Comparing tables master:b48297_db1.t1 and slave:b48297_db1.t1
> +DROP DATABASE b48297_db1;
> +DROP DATABASE b42897_db2;
> 
> === modified file 'sql/sql_load.cc'
> --- a/sql/sql_load.cc	2009-10-16 10:29:42 +0000
> +++ b/sql/sql_load.cc	2009-10-27 10:52:21 +0000
> @@ -84,7 +84,7 @@ static int read_sep_field(THD *thd, COPY
>  			  bool ignore_check_option_errors);
>  #ifndef EMBEDDED_LIBRARY
>  static bool write_execute_load_query_log_event(THD *thd, sql_exchange* ex,
> -                                               const char* db_arg,
> +                                               const char* db_arg, /* table's
> database */
>                                                 const char* table_name_arg,
>                                                 enum enum_duplicates duplicates,
>                                                 bool ignore,
> @@ -501,7 +501,8 @@ int mysql_load(THD *thd,sql_exchange *ex
>            
>  	  if (thd->transaction.stmt.modified_non_trans_table)
>              write_execute_load_query_log_event(thd, ex,
> -                                               tdb, table_list->table_name,
> +                                               table_list->db, 
> +                                               table_list->table_name,
>                                                 handle_duplicates, ignore,
>                                                 transactional_table,
>                                                 errcode);
> @@ -548,7 +549,7 @@ int mysql_load(THD *thd,sql_exchange *ex
>        {
>          int errcode= query_error_code(thd, killed_status == THD::NOT_KILLED);
>          write_execute_load_query_log_event(thd, ex,
> -                                           tdb, table_list->table_name,
> +                                           table_list->db,
> table_list->table_name,
>                                             handle_duplicates, ignore,
>                                             transactional_table,
>                                             errcode);
> @@ -573,7 +574,7 @@ err:
>  
>  /* Not a very useful function; just to avoid duplication of code */
>  static bool write_execute_load_query_log_event(THD *thd, sql_exchange* ex,
> -                                               const char* db_arg,
> +                                               const char* db_arg,  /* table's
> database */
>                                                 const char* table_name_arg,
>                                                 enum enum_duplicates duplicates,
>                                                 bool ignore,
> @@ -590,8 +591,26 @@ static bool write_execute_load_query_log
>    Item                *item, *val;
>    String               pfield, pfields;
>    int                  n;
> +  const char          *tbl= table_name_arg;
> +  String              string_buf;
>  
> -  Load_log_event       lle(thd, ex, db_arg, table_name_arg, fv, duplicates,
> +  if (!thd->db || strcmp(db_arg, thd->db)) 
> +  {
> +    /*
> +      If used database differs from table's database, 
> +      prefix table name with database name so that it 
> +      becomes a FQ name.
> +     */
> +    string_buf.set_charset(system_charset_info);
> +    string_buf.append(db_arg);
> +    string_buf.append("`");
> +    string_buf.append(".");
> +    string_buf.append("`");
> +    string_buf.append(table_name_arg);
> +    tbl= string_buf.ptr();

Use c_ptr_safe(). Otherwise, the string will not be NUL-terminated properly.

> +  }
> +
> +  Load_log_event       lle(thd, ex, db_arg, tbl, fv, duplicates,
>                             ignore, transactional_table);
>  
>    /*
> 
> 
> 
> ------------------------------------------------------------------------
> 
> 

-- 
Mats Kindahl
Senior Software Engineer
Database Technology Group
Sun Microsystems
Thread
bzr commit into mysql-5.1-bugteam branch (luis.soares:3199) Bug#48297Luis Soares27 Oct
  • Re: bzr commit into mysql-5.1-bugteam branch (luis.soares:3199)Bug#48297Mats Kindahl27 Oct