From 2c2e6d48ace2d91dce94d2e62fb0bdda904bc2bd Mon Sep 17 00:00:00 2001 From: Kamlesh Chauvhan Date: Wed, 19 May 2021 10:41:16 +0000 Subject: [PATCH] Added handler for mysql 8.0.19 duplicate key error update In mysql 8.0.19 , Duplicate key error information is extended to include the table name of the key.Previously, duplicate key error information included only the key value and key name. Unit tests are provided for updated changes. Change-Id: Ic78059b625e73cece355541cb4d89e641abc1103 Closes-Bug: #1896916 --- oslo_db/sqlalchemy/exc_filters.py | 9 +++++++ oslo_db/tests/sqlalchemy/test_exc_filters.py | 26 ++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/oslo_db/sqlalchemy/exc_filters.py b/oslo_db/sqlalchemy/exc_filters.py index 7f186a35..2b3ce2cb 100644 --- a/oslo_db/sqlalchemy/exc_filters.py +++ b/oslo_db/sqlalchemy/exc_filters.py @@ -120,6 +120,12 @@ def _default_dupe_key_error(integrity_error, match, engine_name, N columns - (IntegrityError) duplicate key value violates unique constraint "name_of_our_constraint" + mysql since 8.0.19: + 1 column - (IntegrityError) (1062, "Duplicate entry 'value_of_c1' for key + 'table_name.c1'") + N columns - (IntegrityError) (1062, "Duplicate entry 'values joined + with -' for key 'table_name.name_of_our_constraint'") + mysql+mysqldb: 1 column - (IntegrityError) (1062, "Duplicate entry 'value_of_c1' for key 'c1'") @@ -145,6 +151,9 @@ def _default_dupe_key_error(integrity_error, match, engine_name, if not columns.startswith(uniqbase): if engine_name == "postgresql": columns = [columns[columns.index("_") + 1:columns.rindex("_")]] + elif (engine_name == "mysql") and \ + (uniqbase in str(columns.split("0")[:1])): + columns = columns.split("0")[1:] else: columns = [columns] else: diff --git a/oslo_db/tests/sqlalchemy/test_exc_filters.py b/oslo_db/tests/sqlalchemy/test_exc_filters.py index 49826e0b..677516d1 100644 --- a/oslo_db/tests/sqlalchemy/test_exc_filters.py +++ b/oslo_db/tests/sqlalchemy/test_exc_filters.py @@ -821,6 +821,14 @@ class TestDuplicate(TestsExceptionFilter): expected_value='2' ) + def test_mysql_duplicate_entry_key_start_with_tablename(self): + self._run_dupe_constraint_test( + "mysql", + "1062 (23000): Duplicate entry '2' for key 'tbl.uniq_tbl0b'", + expected_columns=['b'], + expected_value='2' + ) + def test_mysql_binary(self): self._run_dupe_constraint_test( "mysql", @@ -839,6 +847,24 @@ class TestDuplicate(TestsExceptionFilter): expected_value="'\\\\x8A$\\\\x8D\\\\xA6\"s\\\\x8E!," ) + def test_mysql_duplicate_entry_key_start_with_tablename_binary(self): + self._run_dupe_constraint_test( + "mysql", + "(1062, \'Duplicate entry " + "\\\'\\\\x8A$\\\\x8D\\\\xA6\"s\\\\x8E\\\' " + "for key \\\'tbl.uniq_tbl0c1\\\'\')", + expected_columns=['c1'], + expected_value="\\\\x8A$\\\\x8D\\\\xA6\"s\\\\x8E" + ) + self._run_dupe_constraint_test( + "mysql", + "(1062, \'Duplicate entry " + "''\\\\x8A$\\\\x8D\\\\xA6\"s\\\\x8E!,' " + "for key 'tbl.uniq_tbl0c1'\')", + expected_columns=['c1'], + expected_value="'\\\\x8A$\\\\x8D\\\\xA6\"s\\\\x8E!," + ) + def test_postgresql_single(self): self._run_dupe_constraint_test( 'postgresql',