| 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.

