| Bug #14553 | NULL in WHERE resets LAST_INSERT_ID | ||
|---|---|---|---|
| Submitted: | 1 Nov 2005 22:37 | Modified: | 20 Jul 2006 17:43 |
| Reporter: | Scott Noyes (Basic Quality Contributor) | Email Updates: | |
| Status: | Closed | Impact on me: | |
| Category: | MySQL Server: Optimizer | Severity: | S2 (Serious) |
| Version: | 5.0.16-BK, 5.0.15 | OS: | Linux (Linux, Windows XP) |
| Assigned to: | Georgi Kodinov | CPU Architecture: | Any |
[1 Nov 2005 22:37]
Scott Noyes
[2 Nov 2005 8:01]
Valeriy Kravchuk
Thank you for a bug report. I was able to verify it just as you described, both with 5.0.15-nt and on Linux, with 5.0.16-BK (ChangeSet@1.1957, 2005-10-29 13:11:34+04:00, konstantin@mysql.com), with InnoDB and MyISAM tables.
But, I think, the main problem is the SELECT result itself:
mysql> CREATE TABLE test (id INT AUTO_INCREMENT PRIMARY KEY);
Query OK, 0 rows affected (0,01 sec)
mysql> INSERT INTO test VALUES (NULL);
Query OK, 1 row affected (0,00 sec)
mysql> SELECT LAST_INSERT_ID();
+------------------+
| LAST_INSERT_ID() |
+------------------+
| 1 |
+------------------+
1 row in set (0,03 sec)
That is OK, expected and described. But the following:
mysql> SELECT * FROM test WHERE id IS NULL;
+----+
| id |
+----+
| 1 |
+----+
1 row in set (0,00 sec)
is WEIRD, WRONG (from my point of view). You are asking for rows with NULL id, and got row with id=1? It is a BUG, even if it is a documented feature!!!
Then:
mysql> SELECT LAST_INSERT_ID();
+------------------+
| LAST_INSERT_ID() |
+------------------+
| 0 |
+------------------+
1 row in set (0,00 sec)
mysql> SELECT * FROM test WHERE id = 1;
+----+
| id |
+----+
| 1 |
+----+
1 row in set (0,01 sec)
mysql> SELECT * FROM test;
+----+
| id |
+----+
| 1 |
+----+
1 row in set (0,00 sec)
mysql> SELECT * FROM test WHERE id IS NULL;
Empty set (0,00 sec)
The results magically changed. After a couple of SELECTs... It is a BUG!
mysql> SELECT LAST_INSERT_ID();
+------------------+
| LAST_INSERT_ID() |
+------------------+
| 0 |
+------------------+
1 row in set (0,00 sec)
mysql> INSERT INTO test VALUES (NULL);
Query OK, 1 row affected (0,00 sec)
mysql> SELECT LAST_INSERT_ID();
+------------------+
| LAST_INSERT_ID() |
+------------------+
| 2 |
+------------------+
1 row in set (0,00 sec)
mysql> SELECT * FROM test;
+----+
| id |
+----+
| 1 |
| 2 |
+----+
2 rows in set (0,00 sec)
mysql> SELECT LAST_INSERT_ID();
+------------------+
| LAST_INSERT_ID() |
+------------------+
| 2 |
+------------------+
1 row in set (0,00 sec)
You are right, the other SELECTs do not influence the LAST_INSERT_ID() results...
mysql> SELECT * FROM test WHERE id IS NULL;
+----+
| id |
+----+
| 2 |
+----+
1 row in set (0,00 sec)
But, NULL is still = 2 here. It is a BUG!
mysql> select version();
+-----------+
| version() |
+-----------+
| 5.0.16 |
+-----------+
1 row in set (0,01 sec)
mysql> show create table test;
+-------+-----------------------------------------------------------------------
-----------------------------------------------------+
| Table | Create Table
|
+-------+-----------------------------------------------------------------------
-----------------------------------------------------+
| test | CREATE TABLE `test` (
`id` int(11) NOT NULL auto_increment,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 |
+-------+-----------------------------------------------------------------------
-----------------------------------------------------+
1 row in set (0,00 sec)
mysql> show variables like 'sql_mode%';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| sql_mode | |
+---------------+-------+
[2 Nov 2005 14:49]
Scott Noyes
It would seem that the extra SELECT queries are not even required to produce that WHERE id IS NULL bug. Two in a row produce different results. mysql> CREATE TABLE test (id INT AUTO_INCREMENT PRIMARY KEY); mysql> INSERT INTO test VALUES (NULL); mysql> SELECT * FROM test WHERE id IS NULL; +----+ | id | +----+ | 1 | +----+ 1 row in set (0.00 sec) mysql> SELECT * FROM test WHERE id IS NULL; Empty set (0.00 sec)
[15 May 2006 11:17]
Georgi Kodinov
Actually this is a documented feature. The Reference manual (chapther 13.1.5) says : "To make MySQL compatible with some ODBC applications, you can find the AUTO_INCREMENT value for the last inserted row with the following query: SELECT * FROM tbl_name WHERE auto_col IS NULL"
[15 May 2006 19:53]
Scott Noyes
Yes, that part is a documented feature. But running that query modifies the value returned by LAST_INSERT_ID(), which is the point of this bug.
[16 May 2006 7:13]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/6437
[10 Jul 2006 13:20]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/8996
[10 Jul 2006 14:45]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/9002
[10 Jul 2006 23:12]
Konstantin Osipov
Reviewed by email with a few minor notes.
[19 Jul 2006 0:07]
Evgeny Potemkin
To make MySQL compatible with some ODBC applications, you can find the AUTO_INCREMENT value for the last inserted row with the following query: SELECT * FROM tbl_name WHERE auto_col IS NULL. This is done with a special code that replaces 'auto_col IS NULL' with 'auto_col = LAST_INSERT_ID'. However this also resets the LAST_INSERT_ID to 0 as it uses it for a flag so as to ensure that only the first SELECT ... WHERE auto_col IS NULL after an INSERT has this special behaviour. Fixed in 4.1.22, 5.0.25
[20 Jul 2006 17:43]
Paul DuBois
Noted in 4.1.22, 5.0.25 changelogs. The use of WHERE col_name IS NULL in SELECT statements reset the value of LAST_INSERT_ID() to zero.
