diff options
-rw-r--r-- | mysql-test/r/insert_select.result | 14 | ||||
-rw-r--r-- | mysql-test/r/rpl_insert_id.result | 28 | ||||
-rw-r--r-- | mysql-test/t/insert_select.test | 19 | ||||
-rw-r--r-- | mysql-test/t/rpl_insert_id.test | 33 | ||||
-rw-r--r-- | sql/sql_insert.cc | 24 |
5 files changed, 109 insertions, 9 deletions
diff --git a/mysql-test/r/insert_select.result b/mysql-test/r/insert_select.result index e24c3179a0c..b49ca3a6c2f 100644 --- a/mysql-test/r/insert_select.result +++ b/mysql-test/r/insert_select.result @@ -66,3 +66,17 @@ INSERT INTO crash1 (numeropost,icone,contenu,pseudo,date,signature,ip) SELECT 1718,icone,contenu,pseudo,date,signature,ip FROM crash2 WHERE numeropost=9 ORDER BY numreponse ASC; 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; diff --git a/mysql-test/r/rpl_insert_id.result b/mysql-test/r/rpl_insert_id.result index d524818985e..6d996481a5c 100644 --- a/mysql-test/r/rpl_insert_id.result +++ b/mysql-test/r/rpl_insert_id.result @@ -39,3 +39,31 @@ b c 6 11 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; +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; diff --git a/mysql-test/t/insert_select.test b/mysql-test/t/insert_select.test index 42f65858d77..695f891f678 100644 --- a/mysql-test/t/insert_select.test +++ b/mysql-test/t/insert_select.test @@ -68,3 +68,22 @@ WHERE numeropost=9 ORDER BY numreponse ASC; 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; diff --git a/mysql-test/t/rpl_insert_id.test b/mysql-test/t/rpl_insert_id.test index 3f3636d3082..3478aedf3eb 100644 --- a/mysql-test/t/rpl_insert_id.test +++ b/mysql-test/t/rpl_insert_id.test @@ -1,6 +1,7 @@ -#see if queries that use both -#auto_increment and LAST_INSERT_ID() -#are replicated well +# see if queries that use both +# auto_increment and LAST_INSERT_ID() +# are replicated well + source include/master-slave.inc; connection master; drop table if exists t1; @@ -15,9 +16,11 @@ sync_with_master; select * from t1; select * from t2; connection master; -#check if multi-line inserts, -#which set last_insert_id to the first id inserted, -#are replicated the same way + +# check if multi-line inserts, +# which set last_insert_id to the first id inserted, +# are replicated the same way + drop table t1; drop table t2; create table t1(a int auto_increment, key(a)); @@ -32,6 +35,24 @@ sync_with_master; select * from t1; select * from t2; 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 t2; save_master_pos; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 33a13fabdc6..167ccf974c7 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1350,6 +1350,24 @@ void select_insert::send_error(uint errcode,const char *err) ::send_error(&thd->net,errcode,err); table->file->extra(HA_EXTRA_NO_CACHE); 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); if (info.copied || info.deleted) { @@ -1365,7 +1383,10 @@ bool select_insert::send_eof() error=table->file->activate_all_index(thd); 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 */ + 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, @@ -1393,10 +1414,7 @@ bool select_insert::send_eof() else sprintf(buff,ER(ER_INSERT_INFO),info.records,info.deleted, 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); - mysql_update_log.write(thd,thd->query,thd->query_length); return 0; } } |