Fix DBReferenceError and DBNonExistentTable with new PyMySQL version

PyMySQL 0.7.7 changed the string format of the error raised, making
oslo.db unable to catch the error:

(pymysql.err.IntegrityError) (1452, u'23000Cannot add or update a child row: a foreign key constraint fails (`vaceciqnzs`.`resource_entity`, CONSTRAINT `foo_fkey` FOREIGN KEY (`foo_id`) REFERENCES `resource_foo` (`id`))') [SQL: u'INSERT INTO resource_entity (id, foo_id) VALUES (%(id)s, %(foo_id)s)'] [parameters: {'foo_id': 2, 'id': 1}]

Change-Id: Ice7d7767842225951eaf48b71cedb2aabe5a84e4
(cherry picked from commit 1f3d509cab)
This commit is contained in:
Julien Danjou
2016-08-30 17:45:14 +02:00
committed by Ihar Hrachyshka
parent 87fb9cc841
commit 363e710295
2 changed files with 17 additions and 40 deletions

View File

@@ -197,7 +197,7 @@ def _sqlite_dupe_key_error(integrity_error, match, engine_name, is_disconnect):
"is (not present in|still referenced from) table "
"\"(?P<key_table>[^\"]+)\".")
@filters("mysql", sqla_exc.IntegrityError,
r".* u?'Cannot (add|delete) or update a (child|parent) row: "
r".*Cannot (add|delete) or update a (child|parent) row: "
'a foreign key constraint fails \([`"].+[`"]\.[`"](?P<table>.+)[`"], '
'CONSTRAINT [`"](?P<constraint>.+)[`"] FOREIGN KEY '
'\([`"](?P<key>.+)[`"]\) REFERENCES [`"](?P<key_table>.+)[`"] ')
@@ -276,7 +276,7 @@ def _check_constraint_non_existing(
@filters("sqlite", sqla_exc.OperationalError,
r".* no such table: (?P<table>.+)")
@filters("mysql", sqla_exc.InternalError,
r".*1051,.*\"Unknown table '(.+\.)?(?P<table>.+)'\"")
r".*1051,.*Unknown table '(.+\.)?(?P<table>.+)'\"")
@filters("postgresql", sqla_exc.ProgrammingError,
r".* table \"(?P<table>.+)\" does not exist")
def _check_table_non_existing(

View File

@@ -512,16 +512,11 @@ class TestReferenceErrorMySQL(TestReferenceErrorSQLite,
self.table_2.insert({'id': 1, 'foo_id': 2})
)
self.assertInnerException(
matched,
"IntegrityError",
(1452, "Cannot add or update a child row: a "
"foreign key constraint fails (`{0}`.`resource_entity`, "
"CONSTRAINT `foo_fkey` FOREIGN KEY (`foo_id`) REFERENCES "
"`resource_foo` (`id`))".format(self.engine.url.database)),
"INSERT INTO resource_entity (id, foo_id) VALUES (%s, %s)",
(1, 2)
)
# NOTE(jd) Cannot check precisely with assertInnerException since MySQL
# error are not the same depending on its version…
self.assertIsInstance(matched.inner_exception,
sqlalchemy.exc.IntegrityError)
self.assertEqual(matched.inner_exception.orig.args[0], 1452)
self.assertEqual("resource_entity", matched.table)
self.assertEqual("foo_fkey", matched.constraint)
self.assertEqual("foo_id", matched.key)
@@ -540,19 +535,11 @@ class TestReferenceErrorMySQL(TestReferenceErrorSQLite,
self.table_2.insert({'id': 1, 'foo_id': 2})
)
self.assertInnerException(
matched,
"IntegrityError",
(
1452,
'Cannot add or update a child row: a '
'foreign key constraint fails ("{0}"."resource_entity", '
'CONSTRAINT "foo_fkey" FOREIGN KEY ("foo_id") REFERENCES '
'"resource_foo" ("id"))'.format(self.engine.url.database)
),
"INSERT INTO resource_entity (id, foo_id) VALUES (%s, %s)",
(1, 2)
)
# NOTE(jd) Cannot check precisely with assertInnerException since MySQL
# error are not the same depending on its version…
self.assertIsInstance(matched.inner_exception,
sqlalchemy.exc.IntegrityError)
self.assertEqual(matched.inner_exception.orig.args[0], 1452)
self.assertEqual("resource_entity", matched.table)
self.assertEqual("foo_fkey", matched.constraint)
self.assertEqual("foo_id", matched.key)
@@ -567,21 +554,11 @@ class TestReferenceErrorMySQL(TestReferenceErrorSQLite,
self.engine.execute,
self.table_1.delete()
)
self.assertInnerException(
matched,
"IntegrityError",
(
1451,
"Cannot delete or update a parent row: a foreign key "
"constraint fails (`{0}`.`resource_entity`, "
"constraint `foo_fkey` "
"foreign key (`foo_id`) references "
"`resource_foo` (`id`))".format(self.engine.url.database)
),
"DELETE FROM resource_foo",
(),
)
# NOTE(jd) Cannot check precisely with assertInnerException since MySQL
# error are not the same depending on its version…
self.assertIsInstance(matched.inner_exception,
sqlalchemy.exc.IntegrityError)
self.assertEqual(1451, matched.inner_exception.orig.args[0])
self.assertEqual("resource_entity", matched.table)
self.assertEqual("foo_fkey", matched.constraint)
self.assertEqual("foo_id", matched.key)