diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index a5b263b759d..98e03239567 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -432,22 +432,44 @@ ifnull( c, 0 ) + 1; select last_insert_id(); last_insert_id() -1 +2 +select last_insert_id(0); +last_insert_id(0) +0 +insert into t2 ( a ) values ( 6 ) on duplicate key update c = +ifnull( c, +0 ) + 1; +select last_insert_id(); +last_insert_id() +0 select * from t2; k a c -1 6 1 +1 6 2 2 7 NULL insert ignore into t2 values (null,6,1),(10,8,1); select last_insert_id(); last_insert_id() -1 +0 insert ignore into t2 values (null,6,1),(null,8,1),(null,15,1),(null,20,1); select last_insert_id(); last_insert_id() 11 select * from t2; k a c -1 6 1 +1 6 2 +2 7 NULL +10 8 1 +11 15 1 +12 20 1 +insert into t2 ( a ) values ( 6 ) on duplicate key update c = +ifnull( c, +0 ) + 1, k=last_insert_id(k); +select last_insert_id(); +last_insert_id() +1 +select * from t2; +k a c +1 6 3 2 7 NULL 10 8 1 11 15 1 diff --git a/mysql-test/t/innodb_mysql.test b/mysql-test/t/innodb_mysql.test index d61509317ca..73c642cd334 100644 --- a/mysql-test/t/innodb_mysql.test +++ b/mysql-test/t/innodb_mysql.test @@ -369,8 +369,8 @@ insert into t1 values('aaa'); drop table t1; # Fix for BUG#19243 "wrong LAST_INSERT_ID() after ON DUPLICATE KEY -# UPDATE": now LAST_INSERT_ID() will return the id of the updated -# row. +# UPDATE": if the row is updated, it's like a regular UPDATE: +# LAST_INSERT_ID() is not affected. CREATE TABLE `t2` ( `k` int(11) NOT NULL auto_increment, `a` int(11) default NULL, @@ -390,6 +390,12 @@ insert into t2 ( a ) values ( 6 ) on duplicate key update c = ifnull( c, 0 ) + 1; select last_insert_id(); +# test again when last_insert_id() is 0 initially +select last_insert_id(0); +insert into t2 ( a ) values ( 6 ) on duplicate key update c = +ifnull( c, +0 ) + 1; +select last_insert_id(); select * from t2; # Test of LAST_INSERT_ID() when autogenerated will fail: @@ -402,5 +408,14 @@ insert ignore into t2 values (null,6,1),(null,8,1),(null,15,1),(null,20,1); select last_insert_id(); select * from t2; -drop table t2; +# Test of the workaround which enables people to know the id of the +# updated row in INSERT ON DUPLICATE KEY UPDATE, by using +# LAST_INSERT_ID(autoinc_col) in the UPDATE clause. +insert into t2 ( a ) values ( 6 ) on duplicate key update c = +ifnull( c, +0 ) + 1, k=last_insert_id(k); +select last_insert_id(); +select * from t2; + +drop table t2; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 4ae368cc0e4..623dbe802e7 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1145,16 +1145,15 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) } info->updated++; /* - If ON DUP KEY UPDATE updates a row instead of inserting one, and - there is an auto_increment column, then SELECT LAST_INSERT_ID() - returns the id of the updated row: + If ON DUP KEY UPDATE updates a row instead of inserting one, it's + like a regular UPDATE statement: it should not affect the value of a + next SELECT LAST_INSERT_ID() or mysql_insert_id(). + Except if LAST_INSERT_ID(#) was in the INSERT query, which is + handled separately by THD::arg_of_last_insert_id_function. */ + insert_id_for_cur_row= table->file->insert_id_for_cur_row= 0; if (table->next_number_field) - { - longlong field_val= table->next_number_field->val_int(); - thd->record_first_successful_insert_id_in_cur_stmt(field_val); - table->file->adjust_next_insert_id_after_explicit_value(field_val); - } + table->file->adjust_next_insert_id_after_explicit_value(table->next_number_field->val_int()); trg_error= (table->triggers && table->triggers->process_triggers(thd, TRG_EVENT_UPDATE, TRG_ACTION_AFTER, TRUE));