mirror of
https://github.com/MariaDB/server.git
synced 2025-07-27 18:02:13 +03:00
5.0 version of the fix for bug #9481: mysql_insert_id() returns 0 after
insert ... select. The 5.0 manual page for mysql_insert_id() does not mention anything about INSERT ... SELECT, though its current behavior is incosistent with what the manual says about the plain INSERT. Fixed by changing the AUTO_INCREMENT and mysql_insert_id() handling logic in INSERT ... SELECT to be consistent with the INSERT behavior, the manual, and the changes in 5.1 introduced by WL3146: - mysql_insert_id() now returns the first automatically generated AUTO_INCREMENT value that was successfully inserted by INSERT ... SELECT - if an INSERT ... SELECT statement is executed, and no automatically generated value is successfully inserted, mysql_insert_id() now returns the ID of the last inserted row.
This commit is contained in:
@ -15199,6 +15199,187 @@ static void test_bug14169()
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Test that mysql_insert_id() behaves as documented in our manual
|
||||
*/
|
||||
|
||||
static void test_mysql_insert_id()
|
||||
{
|
||||
my_ulonglong res;
|
||||
int rc;
|
||||
|
||||
myheader("test_mysql_insert_id");
|
||||
|
||||
rc= mysql_query(mysql, "drop table if exists t1");
|
||||
myquery(rc);
|
||||
/* table without auto_increment column */
|
||||
rc= mysql_query(mysql, "create table t1 (f1 int, f2 varchar(255), key(f1))");
|
||||
myquery(rc);
|
||||
rc= mysql_query(mysql, "insert into t1 values (1,'a')");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(res == 0);
|
||||
rc= mysql_query(mysql, "insert into t1 values (null,'b')");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(res == 0);
|
||||
rc= mysql_query(mysql, "insert into t1 select 5,'c'");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(res == 0);
|
||||
rc= mysql_query(mysql, "insert into t1 select null,'d'");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(res == 0);
|
||||
rc= mysql_query(mysql, "insert into t1 values (null,last_insert_id(300))");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(res == 300);
|
||||
rc= mysql_query(mysql, "insert into t1 select null,last_insert_id(400)");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
/*
|
||||
Behaviour change: old code used to return 0; but 400 is consistent
|
||||
with INSERT VALUES, and the manual's section of mysql_insert_id() does not
|
||||
say INSERT SELECT should be different.
|
||||
*/
|
||||
DIE_UNLESS(res == 400);
|
||||
|
||||
/* table with auto_increment column */
|
||||
rc= mysql_query(mysql, "create table t2 (f1 int not null primary key auto_increment, f2 varchar(255))");
|
||||
myquery(rc);
|
||||
rc= mysql_query(mysql, "insert into t2 values (1,'a')");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(res == 1);
|
||||
/* this should not influence next INSERT if it doesn't have auto_inc */
|
||||
rc= mysql_query(mysql, "insert into t1 values (10,'e')");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(res == 0);
|
||||
|
||||
rc= mysql_query(mysql, "insert into t2 values (null,'b')");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(res == 2);
|
||||
rc= mysql_query(mysql, "insert into t2 select 5,'c'");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
/*
|
||||
Manual says that for multirow insert this should have been 5, but does not
|
||||
say for INSERT SELECT. This is a behaviour change: old code used to return
|
||||
0. We try to be consistent with INSERT VALUES.
|
||||
*/
|
||||
DIE_UNLESS(res == 5);
|
||||
rc= mysql_query(mysql, "insert into t2 select null,'d'");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(res == 6);
|
||||
/* with more than one row */
|
||||
rc= mysql_query(mysql, "insert into t2 values (10,'a'),(11,'b')");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(res == 11);
|
||||
rc= mysql_query(mysql, "insert into t2 select 12,'a' union select 13,'b'");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
/*
|
||||
Manual says that for multirow insert this should have been 13, but does
|
||||
not say for INSERT SELECT. This is a behaviour change: old code used to
|
||||
return 0. We try to be consistent with INSERT VALUES.
|
||||
*/
|
||||
DIE_UNLESS(res == 13);
|
||||
rc= mysql_query(mysql, "insert into t2 values (null,'a'),(null,'b')");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(res == 14);
|
||||
rc= mysql_query(mysql, "insert into t2 select null,'a' union select null,'b'");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(res == 16);
|
||||
rc= mysql_query(mysql, "insert into t2 select 12,'a' union select 13,'b'");
|
||||
myquery_r(rc);
|
||||
rc= mysql_query(mysql, "insert ignore into t2 select 12,'a' union select 13,'b'");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(res == 0);
|
||||
rc= mysql_query(mysql, "insert into t2 values (12,'a'),(13,'b')");
|
||||
myquery_r(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(res == 0);
|
||||
rc= mysql_query(mysql, "insert ignore into t2 values (12,'a'),(13,'b')");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(res == 0);
|
||||
/* mixing autogenerated and explicit values */
|
||||
rc= mysql_query(mysql, "insert into t2 values (null,'e'),(12,'a'),(13,'b')");
|
||||
myquery_r(rc);
|
||||
rc= mysql_query(mysql, "insert into t2 values (null,'e'),(12,'a'),(13,'b'),(25,'g')");
|
||||
myquery_r(rc);
|
||||
rc= mysql_query(mysql, "insert into t2 values (null,last_insert_id(300))");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
/*
|
||||
according to the manual, this might be 20 or 300, but it looks like
|
||||
auto_increment column takes priority over last_insert_id().
|
||||
*/
|
||||
DIE_UNLESS(res == 20);
|
||||
/* If first autogenerated number fails and 2nd works: */
|
||||
rc= mysql_query(mysql, "drop table t2");
|
||||
myquery(rc);
|
||||
rc= mysql_query(mysql, "create table t2 (f1 int not null primary key "
|
||||
"auto_increment, f2 varchar(255), unique (f2))");
|
||||
myquery(rc);
|
||||
rc= mysql_query(mysql, "insert into t2 values (null,'e')");
|
||||
res= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(res == 1);
|
||||
rc= mysql_query(mysql, "insert ignore into t2 values (null,'e'),(null,'a'),(null,'e')");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(res == 2);
|
||||
/* If autogenerated fails and explicit works: */
|
||||
rc= mysql_query(mysql, "insert ignore into t2 values (null,'e'),(12,'c'),(null,'d')");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(res == 3);
|
||||
/* UPDATE may update mysql_insert_id() if it uses LAST_INSERT_ID(#) */
|
||||
rc= mysql_query(mysql, "update t2 set f1=14 where f1=12");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(res == 0);
|
||||
rc= mysql_query(mysql, "update t2 set f1=NULL where f1=14");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(res == 0);
|
||||
rc= mysql_query(mysql, "update t2 set f2=last_insert_id(372) where f1=0");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(res == 372);
|
||||
/* check that LAST_INSERT_ID() does not update mysql_insert_id(): */
|
||||
rc= mysql_query(mysql, "insert into t2 values (null,'g')");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(res == 15);
|
||||
rc= mysql_query(mysql, "update t2 set f2=(@li:=last_insert_id()) where f1=15");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(res == 0);
|
||||
/*
|
||||
Behaviour change: now if ON DUPLICATE KEY UPDATE updates a row,
|
||||
mysql_insert_id() returns the id of the row, instead of not being
|
||||
affected.
|
||||
*/
|
||||
rc= mysql_query(mysql, "insert into t2 values (null,@li) on duplicate key "
|
||||
"update f2=concat('we updated ',f2)");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(res == 15);
|
||||
|
||||
rc= mysql_query(mysql, "drop table t1,t2");
|
||||
myquery(rc);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Bug#20152: mysql_stmt_execute() writes to MYSQL_TYPE_DATE buffer
|
||||
*/
|
||||
@ -16237,6 +16418,7 @@ static struct my_tests_st my_tests[]= {
|
||||
{ "test_bug17667", test_bug17667 },
|
||||
{ "test_bug19671", test_bug19671 },
|
||||
{ "test_bug15752", test_bug15752 },
|
||||
{ "test_mysql_insert_id", test_mysql_insert_id },
|
||||
{ "test_bug21206", test_bug21206 },
|
||||
{ "test_bug21726", test_bug21726 },
|
||||
{ "test_bug15518", test_bug15518 },
|
||||
|
Reference in New Issue
Block a user