Commit 3b974039 authored by guilhem@mysql.com's avatar guilhem@mysql.com

-- Waiting for Monty's approval before push --

Bug 571: play LOAD DATA INFILE the same way on the slave as it was on the master: 
if it was with IGNORE, do it with IGNORE,
if it was with REPLACE, do it with REPLACE,
and (the change) if it was with nothing, do it with nothing (not with IGNORE !!).
Bug 573: print a proper error message in case of duplicate entry in LOAD DATA INFILE
on the slave, i.e. a message where the keyname and key value appear :
'Duplicate entry '1' for key 1' and not 'Duplicate entry '%-.64s' for key %d'
parent 41a5f79a
...@@ -22,3 +22,9 @@ day id category name ...@@ -22,3 +22,9 @@ day id category name
drop table t1; drop table t1;
drop table t2; drop table t2;
drop table t3; drop table t3;
create table t1(a int, b int, unique(b));
insert into t1 values(1,10);
load data infile '../../std_data/rpl_loaddata.dat' into table t1;
show status like 'slave_running';
Variable_name Value
Slave_running OFF
...@@ -4,6 +4,9 @@ ...@@ -4,6 +4,9 @@
# #
# check replication of load data for temporary tables with additional parameters # check replication of load data for temporary tables with additional parameters
# #
# check if duplicate entries trigger an error (they should unless IGNORE or
# REPLACE was used on the master) (bug 571).
source include/master-slave.inc; source include/master-slave.inc;
create table t1(a int not null auto_increment, b int, primary key(a) ); create table t1(a int not null auto_increment, b int, primary key(a) );
...@@ -27,7 +30,21 @@ connection master; ...@@ -27,7 +30,21 @@ connection master;
drop table t1; drop table t1;
drop table t2; drop table t2;
drop table t3; drop table t3;
create table t1(a int, b int, unique(b));
save_master_pos; save_master_pos;
connection slave; connection slave;
sync_with_master; sync_with_master;
insert into t1 values(1,10);
connection master;
load data infile '../../std_data/rpl_loaddata.dat' into table t1;
save_master_pos;
connection slave;
# don't sync_with_master because the slave SQL thread should be stopped because
# of the error so MASTER_POS_WAIT() will not return; just sleep and hope the
# slave SQL thread will have had time to stop.
sleep 1;
show status like 'slave_running';
...@@ -1886,9 +1886,27 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, ...@@ -1886,9 +1886,27 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
else else
{ {
char llbuff[22]; char llbuff[22];
enum enum_duplicates handle_dup = DUP_IGNORE; enum enum_duplicates handle_dup;
if (sql_ex.opt_flags & REPLACE_FLAG) if (sql_ex.opt_flags & REPLACE_FLAG)
handle_dup= DUP_REPLACE; handle_dup= DUP_REPLACE;
else if (sql_ex.opt_flags & IGNORE_FLAG)
handle_dup= DUP_IGNORE;
else
/*
Note that when replication is running fine, if it was DUP_ERROR on the
master then we could choose DUP_IGNORE here, because if DUP_ERROR
suceeded on master, and data is identical on the master and slave,
then there should be no uniqueness errors on slave, so DUP_IGNORE is
the same as DUP_ERROR. But in the unlikely case of uniqueness errors
(because the data on the master and slave happen to be different (user
error or bug), we want LOAD DATA to print an error message on the
slave to discover the problem.
If reading from net (a 3.23 master), mysql_load() will change this
to DUP_IGNORE.
*/
handle_dup= DUP_ERROR;
sql_exchange ex((char*)fname, sql_ex.opt_flags & DUMPFILE_FLAG); sql_exchange ex((char*)fname, sql_ex.opt_flags & DUMPFILE_FLAG);
String field_term(sql_ex.field_term,sql_ex.field_term_len); String field_term(sql_ex.field_term,sql_ex.field_term_len);
String enclosed(sql_ex.enclosed,sql_ex.enclosed_len); String enclosed(sql_ex.enclosed,sql_ex.enclosed_len);
...@@ -1949,12 +1967,19 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, ...@@ -1949,12 +1967,19 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
close_thread_tables(thd); close_thread_tables(thd);
if (thd->query_error) if (thd->query_error)
{ {
int sql_error= thd->net.last_errno; /* this err/sql_errno code is copy-paste from send_error() */
if (!sql_error) const char *err;
sql_error= ER_UNKNOWN_ERROR; int sql_errno;
slave_print_error(rli,sql_error, if ((err=thd->net.last_error)[0])
sql_errno=thd->net.last_errno;
else
{
sql_errno=ER_UNKNOWN_ERROR;
err=ER(sql_errno);
}
slave_print_error(rli,sql_errno,
"Error '%s' running load data infile", "Error '%s' running load data infile",
ER_SAFE(sql_error)); err);
free_root(&thd->mem_root,0); free_root(&thd->mem_root,0);
return 1; return 1;
} }
......
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