Bug #5312 Ndb Cluster returns wrong error code for duplicate key at insert
Submitted: 31 Aug 2004 9:08 Modified: 17 Nov 2004 14:04
Reporter: Martin Skold Email Updates:
Status: Won't fix Impact on me:
None 
Category:MySQL Cluster: Cluster (NDB) storage engine Severity:S3 (Non-critical)
Version: OS:Any
Assigned to: Assigned Account CPU Architecture:Any

[31 Aug 2004 9:08] Martin Skold
Description:
Ndb Cluster returns wrong error code for duplicate key at insert

How to repeat:
Trudy Pelzer wrote: 
I have three tables, called s (Type=MyISAM), s_i (Type=InnoDB),
and s_n (Type=NDBCluster). The tables all look like this (note
the primary key on column sno):

mysql> show columns from s_n;
+--------+--------------+------+-----+---------+-------+
| Field  | Type         | Null | Key | Default | Extra |
+--------+--------------+------+-----+---------+-------+
| sno    | char(3)      |      | PRI |         |       |
| sname  | varchar(8)   | YES  |     | NULL    |       |
| status | decimal(3,0) | YES  |     | NULL    |       |
| city   | varchar(10)  | YES  |     | NULL    |       |
+--------+--------------+------+-----+---------+-------+
4 rows in set (0.01 sec)

I attempt to add duplicate key values to each table:

mysql> insert into s (sno) values('s6');
Query OK, 1 row affected (0.00 sec)
mysql> insert into s (sno) values('s6');
ERROR 1062 (23000): Duplicate entry 's6' for key 1

mysql> insert into s_i (sno) values('s6');
Query OK, 1 row affected (0.00 sec)
mysql> insert into s_i (sno) values('s6');
ERROR 1062 (23000): Duplicate entry 's6' for key 1

mysql> insert into s_n (sno) values('s6');
Query OK, 1 row affected (0.00 sec)
mysql> insert into s_n (sno) values('s6');
ERROR 1022 (23000): Can't write; duplicate key in table 's_n'

Note that the MyISAM and InnoDB table attempts return
ERROR 1062 (23000): Duplicate entry 's6' for key 1.
But the Cluster table attempt returns
ERROR 1022 (23000): Can't write; duplicate key in table 's_n'

I consider this a bug. If a programmer, writing an error handling
routine, is depending on a specific error being returned by MySQL,
it should be the same error regardless of which engine is in use. 

Suggested fix:
Handler must set errkey before returning error at write_row:
In handler.cc
/* Return key if error because of duplicated keys */

uint handler::get_dup_key(int error)
{
  DBUG_ENTER("handler::get_dup_key");
  table->file->errkey  = (uint) -1;
  if (error == HA_ERR_FOUND_DUPP_KEY || error == HA_ERR_FOUND_DUPP_UNIQUE)
    info(HA_STATUS_ERRKEY | HA_STATUS_NO_LOCK);
  DBUG_RETURN(table->file->errkey);
}

  case HA_ERR_FOUND_DUPP_KEY:
  {
    uint key_nr=get_dup_key(error);
    if ((int) key_nr >= 0)
    {
      /* Write the dupplicated key in the error message */
      char key[MAX_KEY_LENGTH];
      String str(key,sizeof(key),system_charset_info);
      key_unpack(&str,table,(uint) key_nr);
      uint max_length=MYSQL_ERRMSG_SIZE-(uint) strlen(ER(ER_DUP_ENTRY)); // 1062
      if (str.length() >= max_length)
      {
        str.length(max_length-4);
        str.append("...");
      }
      my_error(ER_DUP_ENTRY,MYF(0),str.c_ptr(),key_nr+1);
      DBUG_VOID_RETURN;
    }
    textno=ER_DUP_KEY; // 1022
    break;
  }
[31 Aug 2004 15:01] Martin Skold
Pushed to mysql-4.1
[17 Nov 2004 14:04] Martin Skold
We are backing out of this fix since this error code requires that the
handler returns the key value that caused the error. This would be
very expensive to do in a handler that can batch many inserts at once,
all primary keys would then have to be saved for each batch wasting
a lot of space. Error code 1022 is also a valid MySQL code and users
should be prepared to get that one as well. An alternative would be to
have some way of disable the key value part of error 1062 output (but
then 1062 and 1022 would be identical).
[17 Nov 2004 15:52] Martin Skold
Does not seem to be possible to use error code 1022 since
then INSERT ... ON DUPLICATE KEY ... will not work!
Oh well, innodb has the same bug, see we use 1062 anyhow then.
[14 May 2006 21:32] Hartmut Holzgraefe
This seems to work as expected now in latest 4.1 and 5.0 now so that we can close this bug?
[13 Mar 2014 13:33] Omer Barnir
This bug is not scheduled to be fixed at this time.