Loading include/my_base.h +4 −1 Original line number Diff line number Diff line Loading @@ -367,8 +367,11 @@ enum ha_base_keytype { given value */ #define HA_ERR_RBR_LOGGING_FAILED 161 /* Row-based binlogging of row failed */ #define HA_ERR_DROP_INDEX_FK 162 /* Index needed in foreign key constr. */ #define HA_ERR_FOREIGN_DUPLICATE_KEY 163 /* Upholding foreign key constraints would lead to a duplicate key error in some other table. */ #define HA_ERR_LAST 162 /* Copy last error no */ #define HA_ERR_LAST 163 /* Copy last error no */ /* Add error numbers before HA_ERR_LAST and change it accordingly. */ #define HA_ERR_ERRORS (HA_ERR_LAST - HA_ERR_FIRST + 1) Loading mysql-test/r/innodb.result +18 −0 Original line number Diff line number Diff line Loading @@ -2758,3 +2758,21 @@ e varchar(255) character set utf8, key (a,b,c,d,e)) engine=innodb; ERROR 42000: Specified key was too long; max key length is 3072 bytes End of 5.0 tests CREATE TABLE t1 ( field1 varchar(8) NOT NULL DEFAULT '', field2 varchar(8) NOT NULL DEFAULT '', PRIMARY KEY (field1, field2) ) ENGINE=InnoDB; CREATE TABLE t2 ( field1 varchar(8) NOT NULL DEFAULT '' PRIMARY KEY, FOREIGN KEY (field1) REFERENCES t1 (field1) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB; INSERT INTO t1 VALUES ('old', 'somevalu'); INSERT INTO t1 VALUES ('other', 'anyvalue'); INSERT INTO t2 VALUES ('old'); INSERT INTO t2 VALUES ('other'); UPDATE t1 SET field1 = 'other' WHERE field2 = 'somevalu'; ERROR 23000: Upholding foreign key constraints for table 't1', entry 'other-somevalu', key 1 would lead to a duplicate entry DROP TABLE t2; DROP TABLE t1; mysql-test/t/innodb.test +29 −0 Original line number Diff line number Diff line Loading @@ -1715,3 +1715,32 @@ create table t1 (a varchar(255) character set utf8, key (a,b,c,d,e)) engine=innodb; --echo End of 5.0 tests # # Test that cascading updates leading to duplicate keys give the correct # error message (bug #9680) # CREATE TABLE t1 ( field1 varchar(8) NOT NULL DEFAULT '', field2 varchar(8) NOT NULL DEFAULT '', PRIMARY KEY (field1, field2) ) ENGINE=InnoDB; CREATE TABLE t2 ( field1 varchar(8) NOT NULL DEFAULT '' PRIMARY KEY, FOREIGN KEY (field1) REFERENCES t1 (field1) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB; INSERT INTO t1 VALUES ('old', 'somevalu'); INSERT INTO t1 VALUES ('other', 'anyvalue'); INSERT INTO t2 VALUES ('old'); INSERT INTO t2 VALUES ('other'); --error ER_FOREIGN_DUPLICATE_KEY UPDATE t1 SET field1 = 'other' WHERE field2 = 'somevalu'; DROP TABLE t2; DROP TABLE t1; sql/ha_innodb.cc +4 −0 Original line number Diff line number Diff line Loading @@ -465,6 +465,10 @@ convert_error_code_to_mysql( return(HA_ERR_FOUND_DUPP_KEY); } else if (error == (int) DB_FOREIGN_DUPLICATE_KEY) { return(HA_ERR_FOREIGN_DUPLICATE_KEY); } else if (error == (int) DB_RECORD_NOT_FOUND) { return(HA_ERR_NO_ACTIVE_RECORD); Loading sql/handler.cc +27 −2 Original line number Diff line number Diff line Loading @@ -358,6 +358,7 @@ static int ha_init_errors(void) SETMSG(HA_ERR_TABLE_EXIST, ER(ER_TABLE_EXISTS_ERROR)); SETMSG(HA_ERR_NO_CONNECTION, "Could not connect to storage engine"); SETMSG(HA_ERR_TABLE_DEF_CHANGED, ER(ER_TABLE_DEF_CHANGED)); SETMSG(HA_ERR_FOREIGN_DUPLICATE_KEY, "FK constraint would lead to duplicate key"); /* Register the error messages for use with my_error(). */ return my_error_register(errmsgs, HA_ERR_FIRST, HA_ERR_LAST); Loading Loading @@ -1868,6 +1869,29 @@ void handler::print_error(int error, myf errflag) textno=ER_DUP_KEY; break; } case HA_ERR_FOREIGN_DUPLICATE_KEY: { uint key_nr= get_dup_key(error); if ((int) key_nr >= 0) { /* Write the key in the error message */ char key[MAX_KEY_LENGTH]; String str(key,sizeof(key),system_charset_info); /* Table is opened and defined at this point */ key_unpack(&str,table,(uint) key_nr); uint max_length= MYSQL_ERRMSG_SIZE-(uint) strlen(ER(ER_FOREIGN_DUPLICATE_KEY)); if (str.length() >= max_length) { str.length(max_length-4); str.append(STRING_WITH_LEN("...")); } my_error(ER_FOREIGN_DUPLICATE_KEY, MYF(0), table_share->table_name.str, str.c_ptr(), key_nr+1); DBUG_VOID_RETURN; } textno= ER_DUP_KEY; break; } case HA_ERR_NULL_IN_SPATIAL: textno= ER_UNKNOWN_ERROR; break; Loading Loading @@ -2003,8 +2027,9 @@ 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 || error == HA_ERR_NULL_IN_SPATIAL || error == HA_ERR_DROP_INDEX_FK) if (error == HA_ERR_FOUND_DUPP_KEY || error == HA_ERR_FOREIGN_DUPLICATE_KEY || error == HA_ERR_FOUND_DUPP_UNIQUE || error == HA_ERR_NULL_IN_SPATIAL || error == HA_ERR_DROP_INDEX_FK) info(HA_STATUS_ERRKEY | HA_STATUS_NO_LOCK); DBUG_RETURN(table->file->errkey); } Loading Loading
include/my_base.h +4 −1 Original line number Diff line number Diff line Loading @@ -367,8 +367,11 @@ enum ha_base_keytype { given value */ #define HA_ERR_RBR_LOGGING_FAILED 161 /* Row-based binlogging of row failed */ #define HA_ERR_DROP_INDEX_FK 162 /* Index needed in foreign key constr. */ #define HA_ERR_FOREIGN_DUPLICATE_KEY 163 /* Upholding foreign key constraints would lead to a duplicate key error in some other table. */ #define HA_ERR_LAST 162 /* Copy last error no */ #define HA_ERR_LAST 163 /* Copy last error no */ /* Add error numbers before HA_ERR_LAST and change it accordingly. */ #define HA_ERR_ERRORS (HA_ERR_LAST - HA_ERR_FIRST + 1) Loading
mysql-test/r/innodb.result +18 −0 Original line number Diff line number Diff line Loading @@ -2758,3 +2758,21 @@ e varchar(255) character set utf8, key (a,b,c,d,e)) engine=innodb; ERROR 42000: Specified key was too long; max key length is 3072 bytes End of 5.0 tests CREATE TABLE t1 ( field1 varchar(8) NOT NULL DEFAULT '', field2 varchar(8) NOT NULL DEFAULT '', PRIMARY KEY (field1, field2) ) ENGINE=InnoDB; CREATE TABLE t2 ( field1 varchar(8) NOT NULL DEFAULT '' PRIMARY KEY, FOREIGN KEY (field1) REFERENCES t1 (field1) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB; INSERT INTO t1 VALUES ('old', 'somevalu'); INSERT INTO t1 VALUES ('other', 'anyvalue'); INSERT INTO t2 VALUES ('old'); INSERT INTO t2 VALUES ('other'); UPDATE t1 SET field1 = 'other' WHERE field2 = 'somevalu'; ERROR 23000: Upholding foreign key constraints for table 't1', entry 'other-somevalu', key 1 would lead to a duplicate entry DROP TABLE t2; DROP TABLE t1;
mysql-test/t/innodb.test +29 −0 Original line number Diff line number Diff line Loading @@ -1715,3 +1715,32 @@ create table t1 (a varchar(255) character set utf8, key (a,b,c,d,e)) engine=innodb; --echo End of 5.0 tests # # Test that cascading updates leading to duplicate keys give the correct # error message (bug #9680) # CREATE TABLE t1 ( field1 varchar(8) NOT NULL DEFAULT '', field2 varchar(8) NOT NULL DEFAULT '', PRIMARY KEY (field1, field2) ) ENGINE=InnoDB; CREATE TABLE t2 ( field1 varchar(8) NOT NULL DEFAULT '' PRIMARY KEY, FOREIGN KEY (field1) REFERENCES t1 (field1) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB; INSERT INTO t1 VALUES ('old', 'somevalu'); INSERT INTO t1 VALUES ('other', 'anyvalue'); INSERT INTO t2 VALUES ('old'); INSERT INTO t2 VALUES ('other'); --error ER_FOREIGN_DUPLICATE_KEY UPDATE t1 SET field1 = 'other' WHERE field2 = 'somevalu'; DROP TABLE t2; DROP TABLE t1;
sql/ha_innodb.cc +4 −0 Original line number Diff line number Diff line Loading @@ -465,6 +465,10 @@ convert_error_code_to_mysql( return(HA_ERR_FOUND_DUPP_KEY); } else if (error == (int) DB_FOREIGN_DUPLICATE_KEY) { return(HA_ERR_FOREIGN_DUPLICATE_KEY); } else if (error == (int) DB_RECORD_NOT_FOUND) { return(HA_ERR_NO_ACTIVE_RECORD); Loading
sql/handler.cc +27 −2 Original line number Diff line number Diff line Loading @@ -358,6 +358,7 @@ static int ha_init_errors(void) SETMSG(HA_ERR_TABLE_EXIST, ER(ER_TABLE_EXISTS_ERROR)); SETMSG(HA_ERR_NO_CONNECTION, "Could not connect to storage engine"); SETMSG(HA_ERR_TABLE_DEF_CHANGED, ER(ER_TABLE_DEF_CHANGED)); SETMSG(HA_ERR_FOREIGN_DUPLICATE_KEY, "FK constraint would lead to duplicate key"); /* Register the error messages for use with my_error(). */ return my_error_register(errmsgs, HA_ERR_FIRST, HA_ERR_LAST); Loading Loading @@ -1868,6 +1869,29 @@ void handler::print_error(int error, myf errflag) textno=ER_DUP_KEY; break; } case HA_ERR_FOREIGN_DUPLICATE_KEY: { uint key_nr= get_dup_key(error); if ((int) key_nr >= 0) { /* Write the key in the error message */ char key[MAX_KEY_LENGTH]; String str(key,sizeof(key),system_charset_info); /* Table is opened and defined at this point */ key_unpack(&str,table,(uint) key_nr); uint max_length= MYSQL_ERRMSG_SIZE-(uint) strlen(ER(ER_FOREIGN_DUPLICATE_KEY)); if (str.length() >= max_length) { str.length(max_length-4); str.append(STRING_WITH_LEN("...")); } my_error(ER_FOREIGN_DUPLICATE_KEY, MYF(0), table_share->table_name.str, str.c_ptr(), key_nr+1); DBUG_VOID_RETURN; } textno= ER_DUP_KEY; break; } case HA_ERR_NULL_IN_SPATIAL: textno= ER_UNKNOWN_ERROR; break; Loading Loading @@ -2003,8 +2027,9 @@ 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 || error == HA_ERR_NULL_IN_SPATIAL || error == HA_ERR_DROP_INDEX_FK) if (error == HA_ERR_FOUND_DUPP_KEY || error == HA_ERR_FOREIGN_DUPLICATE_KEY || error == HA_ERR_FOUND_DUPP_UNIQUE || error == HA_ERR_NULL_IN_SPATIAL || error == HA_ERR_DROP_INDEX_FK) info(HA_STATUS_ERRKEY | HA_STATUS_NO_LOCK); DBUG_RETURN(table->file->errkey); } Loading