Fixed bug #27650:

INSERT into InnoDB table may cause "ERROR 1062 (23000): Duplicate entry..."
errors or lost records after multi-row INSERT of the form:
"INSERT INTO t (id...) VALUES (NULL...) ON DUPLICATE KEY UPDATE id=VALUES(id)",
where "id" is an AUTO_INCREMENT column.

It happens because InnoDB handler forgets to save next insert id after
updating of auto_increment column with new values. As result of that
last insert id stored inside InnoDB dictionary tables differs from it's
cached thd->next_insert_id value.
parent b77a85ef
...@@ -446,4 +446,43 @@ a ...@@ -446,4 +446,43 @@ a
2 2
5 5
drop table t1; drop table t1;
create table t1(
id int auto_increment,
c char(1) not null,
counter int not null default 1,
primary key (id),
unique key (c)
) engine=innodb;
insert into t1 (id, c) values
(NULL, 'a'),
(NULL, 'a')
on duplicate key update id = values(id), counter = counter + 1;
select * from t1;
id c counter
2 a 2
insert into t1 (id, c) values
(NULL, 'b')
on duplicate key update id = values(id), counter = counter + 1;
select * from t1;
id c counter
2 a 2
3 b 1
truncate table t1;
insert into t1 (id, c) values (NULL, 'a');
select * from t1;
id c counter
1 a 1
insert into t1 (id, c) values (NULL, 'b'), (NULL, 'b')
on duplicate key update id = values(id), c = values(c), counter = counter + 1;
select * from t1;
id c counter
1 a 1
3 b 2
insert into t1 (id, c) values (NULL, 'a')
on duplicate key update id = values(id), c = values(c), counter = counter + 1;
select * from t1;
id c counter
3 b 2
4 a 2
drop table t1;
End of 5.0 tests End of 5.0 tests
...@@ -412,4 +412,51 @@ DROP TABLE t1; ...@@ -412,4 +412,51 @@ DROP TABLE t1;
--source include/innodb_rollback_on_timeout.inc --source include/innodb_rollback_on_timeout.inc
-- source include/have_innodb.inc
#
# Bug #27650: INSERT fails after multi-row INSERT of the form:
# INSERT INTO t (id...) VALUES (NULL...) ON DUPLICATE KEY UPDATE id=VALUES(id)
#
create table t1(
id int auto_increment,
c char(1) not null,
counter int not null default 1,
primary key (id),
unique key (c)
) engine=innodb;
insert into t1 (id, c) values
(NULL, 'a'),
(NULL, 'a')
on duplicate key update id = values(id), counter = counter + 1;
select * from t1;
insert into t1 (id, c) values
(NULL, 'b')
on duplicate key update id = values(id), counter = counter + 1;
select * from t1;
truncate table t1;
insert into t1 (id, c) values (NULL, 'a');
select * from t1;
insert into t1 (id, c) values (NULL, 'b'), (NULL, 'b')
on duplicate key update id = values(id), c = values(c), counter = counter + 1;
select * from t1;
insert into t1 (id, c) values (NULL, 'a')
on duplicate key update id = values(id), c = values(c), counter = counter + 1;
select * from t1;
drop table t1;
--echo End of 5.0 tests --echo End of 5.0 tests
...@@ -3299,6 +3299,8 @@ no_commit: ...@@ -3299,6 +3299,8 @@ no_commit:
if (error == DB_DUPLICATE_KEY && auto_inc_used if (error == DB_DUPLICATE_KEY && auto_inc_used
&& (user_thd->lex->sql_command == SQLCOM_REPLACE && (user_thd->lex->sql_command == SQLCOM_REPLACE
|| user_thd->lex->sql_command == SQLCOM_REPLACE_SELECT || user_thd->lex->sql_command == SQLCOM_REPLACE_SELECT
|| (user_thd->lex->sql_command == SQLCOM_INSERT
&& user_thd->lex->duplicates == DUP_UPDATE)
|| (user_thd->lex->sql_command == SQLCOM_LOAD || (user_thd->lex->sql_command == SQLCOM_LOAD
&& user_thd->lex->duplicates == DUP_REPLACE))) { && user_thd->lex->duplicates == DUP_REPLACE))) {
......
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