The storage engine that I am developing handles error reporting for
duplicate key values differently than MySQL expects. Specifically, when a
row causes duplicate value conflicts with multiple keys, only the last key
that caused the dup error is known. However, MySQL expects the keys to be
reported in ascending order.
For example, for the following sequence:
CREATE TABLE t1 (a INT, UNIQUE (a), b INT NOT NULL, UNIQUE (b), c INT NOT
NULL, INDEX(c));
REPLACE INTO t1 VALUES (1,1,1),(2,2,2),(2,1,3);
MySQL expects the conflict with 'a' to be reported before the conflict with
'b'. Our storage engine always reports 'b' before 'a'.
This causes a problem in sql_insert.cc::write_record() when a REPLACE
command is executed, because the loop that retries the replace after a
duplicate key error depends on the ascending key order. As a result, the
REPLACE command above will fail for our storage engine and return "ERROR
1062 (23000): Duplicate entry '1' for key 'b'".
I have a possible workaround, which is to always set handler::errkey to 0
when (thd_sql_command() == SQLCOM_REPLACE*). This seems to work for the
limited set of operations that I have tried and a quick inspection of
write_row leads me to believe that this should be OK. Can anyone convince
me that this is a bad idea?
Thank you,
Tim Clark