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;
}
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; }