Commit 3b6f9aac authored by Nisha Gopalakrishnan's avatar Nisha Gopalakrishnan

BUG#23135731: INSERT WITH DUPLICATE KEY UPDATE REPORTS

              INCORRECT ERROR.

Analysis
========
INSERT with DUPLICATE KEY UPDATE and REPLACE on a table
where foreign key constraint is defined fails with an
incorrect 'duplicate entry' error rather than foreign
key constraint violation error.

As part of the bug fix for BUG#22037930, a new flag
'HA_CHECK_FK_ERROR' was added while checking for non fatal
errors to manage FK errors based on the 'IGNORE' flag. For
INSERT with DUPLICATE KEY UPDATE and REPLACE queries, the
foreign key constraint violation error was marked as non-fatal,
even though IGNORE was not set. Hence it continued with the
duplicate key processing resulting in an incorrect error.

Fix:
===
Foreign key violation errors are treated as non fatal only when
the IGNORE is not set in the above mentioned queries. Hence reports
the appropriate foreign key violation error.
parent fbf44eed
...@@ -724,3 +724,18 @@ ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (` ...@@ -724,3 +724,18 @@ ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`
UPDATE t1, t2 SET t1.fld1= t1.fld1 + 3; UPDATE t1, t2 SET t1.fld1= t1.fld1 + 3;
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`)) ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`))
DROP TABLE t2, t1; DROP TABLE t2, t1;
#
# BUG#22037930: INSERT IGNORE FAILS TO IGNORE FOREIGN
# KEY CONSTRAINT
CREATE TABLE t1 (fld1 INT PRIMARY KEY) ENGINE= INNODB;
CREATE TABLE t2 (fld1 VARCHAR(10), fld2 INT NOT NULL,
CONSTRAINT fk FOREIGN KEY (fld2) REFERENCES t1(fld1)) ENGINE= INNODB;
# Without patch, reports incorrect error.
INSERT INTO t2 VALUES('abc', 2) ON DUPLICATE KEY UPDATE fld1= 'def';
ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`))
REPLACE INTO t2 VALUES('abc', 2);
ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `fk` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`))
INSERT IGNORE INTO t2 VALUES('abc', 2) ON DUPLICATE KEY UPDATE fld1= 'def';
Warnings:
Warning 1452 `test`.`t2`, CONSTRAINT `fk` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`)
DROP TABLE t2, t1;
...@@ -591,3 +591,25 @@ UPDATE t1, t2 SET t2.fld2= t2.fld2 + 3; ...@@ -591,3 +591,25 @@ UPDATE t1, t2 SET t2.fld2= t2.fld2 + 3;
UPDATE t1, t2 SET t1.fld1= t1.fld1 + 3; UPDATE t1, t2 SET t1.fld1= t1.fld1 + 3;
DROP TABLE t2, t1; DROP TABLE t2, t1;
--echo #
--echo # BUG#22037930: INSERT IGNORE FAILS TO IGNORE FOREIGN
--echo # KEY CONSTRAINT
CREATE TABLE t1 (fld1 INT PRIMARY KEY) ENGINE= INNODB;
CREATE TABLE t2 (fld1 VARCHAR(10), fld2 INT NOT NULL,
CONSTRAINT fk FOREIGN KEY (fld2) REFERENCES t1(fld1)) ENGINE= INNODB;
--echo # Without patch, reports incorrect error.
--error ER_NO_REFERENCED_ROW_2
INSERT INTO t2 VALUES('abc', 2) ON DUPLICATE KEY UPDATE fld1= 'def';
--error ER_NO_REFERENCED_ROW_2
REPLACE INTO t2 VALUES('abc', 2);
--enable_warnings
INSERT IGNORE INTO t2 VALUES('abc', 2) ON DUPLICATE KEY UPDATE fld1= 'def';
--disable_warnings
DROP TABLE t2, t1;
...@@ -1521,16 +1521,25 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info) ...@@ -1521,16 +1521,25 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
insert_id_for_cur_row= table->file->insert_id_for_cur_row; insert_id_for_cur_row= table->file->insert_id_for_cur_row;
else else
table->file->insert_id_for_cur_row= insert_id_for_cur_row; table->file->insert_id_for_cur_row= insert_id_for_cur_row;
bool is_duplicate_key_error;
if (table->file->is_fatal_error(error, HA_CHECK_DUP | HA_CHECK_FK_ERROR)) /*
If it is a FK constraint violation and 'ignore' flag is set,
report a warning instead of error.
*/
if (info->ignore && !table->file->is_fatal_error(error,
HA_CHECK_FK_ERROR))
goto ok_or_after_trg_err;
if (table->file->is_fatal_error(error, HA_CHECK_DUP))
goto err; goto err;
is_duplicate_key_error= table->file->is_fatal_error(error, 0);
if (!is_duplicate_key_error) if (!table->file->is_fatal_error(error, 0))
{ {
/* /*
We come here when we had an ignorable error which is not a duplicate We come here when we have an ignorable error which is not a duplicate
key error. In this we ignore error if ignore flag is set, otherwise key error or FK error(Ex: Partition related errors). In this case we
report error as usual. We will not do any duplicate key processing. ignore the error if ignore flag is set, otherwise report error as usual.
We will not do any duplicate key processing.
*/ */
if (info->ignore) if (info->ignore)
goto ok_or_after_trg_err; /* Ignoring a not fatal error, return 0 */ goto ok_or_after_trg_err; /* Ignoring a not fatal error, return 0 */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment