Commit 8a1e18f4 authored by guilhem@mysql.com's avatar guilhem@mysql.com

Fix for bug #490 and #491 (see details below)

parent 6bbeecc6
...@@ -66,3 +66,17 @@ INSERT INTO crash1 (numeropost,icone,contenu,pseudo,date,signature,ip) ...@@ -66,3 +66,17 @@ INSERT INTO crash1 (numeropost,icone,contenu,pseudo,date,signature,ip)
SELECT 1718,icone,contenu,pseudo,date,signature,ip FROM crash2 SELECT 1718,icone,contenu,pseudo,date,signature,ip FROM crash2
WHERE numeropost=9 ORDER BY numreponse ASC; WHERE numeropost=9 ORDER BY numreponse ASC;
DROP TABLE IF EXISTS crash1,crash2; DROP TABLE IF EXISTS crash1,crash2;
drop table if exists t1;
drop table if exists t2;
create table t1(a int, unique(a));
insert into t1 values(2);
create table t2(a int);
insert into t2 values(1),(2);
reset master;
insert into t1 select * from t2;
Duplicate entry '2' for key 1
show binlog events;
Log_name Pos Event_type Server_id Orig_log_pos Info
master-bin.001 4 Start 1 4 Server ver: VERSION, Binlog ver: 3
master-bin.001 79 Query 1 79 use test; insert into t1 select * from t2
drop table t1, t2;
...@@ -39,3 +39,31 @@ b c ...@@ -39,3 +39,31 @@ b c
6 11 6 11
drop table t1; drop table t1;
drop table t2; drop table t2;
create table t1(a int auto_increment, key(a));
create table t2(b int auto_increment, c int, key(b));
insert into t1 values (10);
insert into t1 values (null),(null),(null);
insert into t2 values (5,0);
insert into t2 (c) select * from t1;
select * from t2;
b c
5 0
6 10
7 11
8 12
9 13
select * from t1;
a
10
11
12
13
select * from t2;
b c
5 0
6 10
7 11
8 12
9 13
drop table t1;
drop table t2;
...@@ -68,3 +68,22 @@ WHERE numeropost=9 ORDER BY numreponse ASC; ...@@ -68,3 +68,22 @@ WHERE numeropost=9 ORDER BY numreponse ASC;
DROP TABLE IF EXISTS crash1,crash2; DROP TABLE IF EXISTS crash1,crash2;
# Addendum by Guilhem:
# Check if a partly-completed INSERT SELECT in a MyISAM table goes
# into the binlog
drop table if exists t1;
drop table if exists t2;
create table t1(a int, unique(a));
insert into t1 values(2);
create table t2(a int);
insert into t2 values(1),(2);
reset master;
--error 1062
insert into t1 select * from t2;
# The above should produce an error, but still be in the binlog;
# verify the binlog :
let $VERSION=`select version()`;
--replace_result $VERSION VERSION
show binlog events;
drop table t1, t2;
#see if queries that use both # see if queries that use both
#auto_increment and LAST_INSERT_ID() # auto_increment and LAST_INSERT_ID()
#are replicated well # are replicated well
source include/master-slave.inc; source include/master-slave.inc;
connection master; connection master;
drop table if exists t1; drop table if exists t1;
...@@ -15,9 +16,11 @@ sync_with_master; ...@@ -15,9 +16,11 @@ sync_with_master;
select * from t1; select * from t1;
select * from t2; select * from t2;
connection master; connection master;
#check if multi-line inserts,
#which set last_insert_id to the first id inserted, # check if multi-line inserts,
#are replicated the same way # which set last_insert_id to the first id inserted,
# are replicated the same way
drop table t1; drop table t1;
drop table t2; drop table t2;
create table t1(a int auto_increment, key(a)); create table t1(a int auto_increment, key(a));
...@@ -32,6 +35,24 @@ sync_with_master; ...@@ -32,6 +35,24 @@ sync_with_master;
select * from t1; select * from t1;
select * from t2; select * from t2;
connection master; connection master;
# check if INSERT SELECT in auto_increment is well replicated (bug #490)
drop table t1;
drop table t2;
create table t1(a int auto_increment, key(a));
create table t2(b int auto_increment, c int, key(b));
insert into t1 values (10);
insert into t1 values (null),(null),(null);
insert into t2 values (5,0);
insert into t2 (c) select * from t1;
select * from t2;
save_master_pos;
connection slave;
sync_with_master;
select * from t1;
select * from t2;
connection master;
drop table t1; drop table t1;
drop table t2; drop table t2;
save_master_pos; save_master_pos;
......
...@@ -1350,6 +1350,24 @@ void select_insert::send_error(uint errcode,const char *err) ...@@ -1350,6 +1350,24 @@ void select_insert::send_error(uint errcode,const char *err)
::send_error(&thd->net,errcode,err); ::send_error(&thd->net,errcode,err);
table->file->extra(HA_EXTRA_NO_CACHE); table->file->extra(HA_EXTRA_NO_CACHE);
table->file->activate_all_index(thd); table->file->activate_all_index(thd);
/*
If at least one row has been inserted/modified and will stay in the table
(the table doesn't have transactions) (example: we got a duplicate key
error while inserting into a MyISAM table) we must write to the binlog (and
the error code will make the slave stop).
*/
if ((info.copied || info.deleted) && !table->file->has_transactions())
{
if (last_insert_id)
thd->insert_id(last_insert_id); // For binary log
mysql_update_log.write(thd,thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
Query_log_event qinfo(thd, thd->query, thd->query_length,
table->file->has_transactions());
mysql_bin_log.write(&qinfo);
}
}
ha_rollback_stmt(thd); ha_rollback_stmt(thd);
if (info.copied || info.deleted) if (info.copied || info.deleted)
{ {
...@@ -1365,7 +1383,10 @@ bool select_insert::send_eof() ...@@ -1365,7 +1383,10 @@ bool select_insert::send_eof()
error=table->file->activate_all_index(thd); error=table->file->activate_all_index(thd);
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
if (last_insert_id)
thd->insert_id(last_insert_id); // For binary log
/* Write to binlog before commiting transaction */ /* Write to binlog before commiting transaction */
mysql_update_log.write(thd,thd->query,thd->query_length);
if (mysql_bin_log.is_open()) if (mysql_bin_log.is_open())
{ {
Query_log_event qinfo(thd, thd->query, thd->query_length, Query_log_event qinfo(thd, thd->query, thd->query_length,
...@@ -1393,10 +1414,7 @@ bool select_insert::send_eof() ...@@ -1393,10 +1414,7 @@ bool select_insert::send_eof()
else else
sprintf(buff,ER(ER_INSERT_INFO),info.records,info.deleted, sprintf(buff,ER(ER_INSERT_INFO),info.records,info.deleted,
thd->cuted_fields); thd->cuted_fields);
if (last_insert_id)
thd->insert_id(last_insert_id); // For update log
::send_ok(&thd->net,info.copied+info.deleted,last_insert_id,buff); ::send_ok(&thd->net,info.copied+info.deleted,last_insert_id,buff);
mysql_update_log.write(thd,thd->query,thd->query_length);
return 0; return 0;
} }
} }
......
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