diff options
-rw-r--r-- | mysql-test/r/insert_update.result | 22 | ||||
-rw-r--r-- | mysql-test/t/insert_update.test | 17 | ||||
-rw-r--r-- | sql/handler.cc | 7 | ||||
-rw-r--r-- | sql/sql_class.h | 4 |
4 files changed, 50 insertions, 0 deletions
diff --git a/mysql-test/r/insert_update.result b/mysql-test/r/insert_update.result index fd70fcb9084..4a3e87d9d48 100644 --- a/mysql-test/r/insert_update.result +++ b/mysql-test/r/insert_update.result @@ -336,3 +336,25 @@ id f1 0 test1 DROP TABLE t1; SET SQL_MODE=''; +CREATE TABLE t1 ( +id INT AUTO_INCREMENT PRIMARY KEY, +c1 CHAR(1) UNIQUE KEY, +cnt INT DEFAULT 1 +); +INSERT INTO t1 (c1) VALUES ('A'), ('B'), ('C'); +SELECT * FROM t1; +id c1 cnt +1 A 1 +2 B 1 +3 C 1 +INSERT INTO t1 (c1) VALUES ('A'), ('X'), ('Y'), ('Z') +ON DUPLICATE KEY UPDATE cnt=cnt+1; +SELECT * FROM t1; +id c1 cnt +1 A 2 +2 B 1 +3 C 1 +4 X 1 +5 Y 1 +6 Z 1 +DROP TABLE t1; diff --git a/mysql-test/t/insert_update.test b/mysql-test/t/insert_update.test index 76df4502769..0e199dab4bd 100644 --- a/mysql-test/t/insert_update.test +++ b/mysql-test/t/insert_update.test @@ -247,3 +247,20 @@ REPLACE INTO t1 VALUES (0,"test1",null); SELECT id, f1 FROM t1; DROP TABLE t1; SET SQL_MODE=''; + +# +# Bug#27954: multi-row INSERT ... ON DUPLICATE with duplicated +# row at the first place into table with AUTO_INCREMENT and +# additional UNIQUE key. +# +CREATE TABLE t1 ( + id INT AUTO_INCREMENT PRIMARY KEY, + c1 CHAR(1) UNIQUE KEY, + cnt INT DEFAULT 1 +); +INSERT INTO t1 (c1) VALUES ('A'), ('B'), ('C'); +SELECT * FROM t1; +INSERT INTO t1 (c1) VALUES ('A'), ('X'), ('Y'), ('Z') + ON DUPLICATE KEY UPDATE cnt=cnt+1; +SELECT * FROM t1; +DROP TABLE t1; diff --git a/sql/handler.cc b/sql/handler.cc index c6c31593a5f..867ac7ff778 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1685,7 +1685,14 @@ void handler::restore_auto_increment() { THD *thd= table->in_use; if (thd->next_insert_id) + { thd->next_insert_id= thd->prev_insert_id; + if (thd->next_insert_id == 0) + { + /* we didn't generate a value, engine will be called again */ + thd->clear_next_insert_id= 0; + } + } } diff --git a/sql/sql_class.h b/sql/sql_class.h index 12d7cb2368f..7dd46e2efe7 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1431,6 +1431,10 @@ public: */ bool insert_id_used; + /* + clear_next_insert_id is set if engine was called at least once + for this statement to generate auto_increment value. + */ bool clear_next_insert_id; /* for IS NULL => = last_insert_id() fix in remove_eq_conds() */ bool substitute_null_with_insert_id; |