summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulien Danjou <julien@danjou.info>2016-06-22 10:22:38 +0200
committerJulien Danjou <julien@danjou.info>2016-06-27 17:36:54 +0200
commite59c2b5f9c52000c1418d57fd28329caa932c5f1 (patch)
treec82293c137648814e8c7d6c228f39ba24962103a
parentc4f025d2c3829a26dfa674823b1b06e99b9366d3 (diff)
downloadoslo-db-e59c2b5f9c52000c1418d57fd28329caa932c5f1.tar.gz
exc_filters: catch and translate non existent table on drop
This patches add a new exception type that is raised when an operation on a non existing table is executed. Change-Id: I931664987e359e7755b912ec25cb36f087ffcfa3
-rw-r--r--oslo_db/exception.py12
-rw-r--r--oslo_db/sqlalchemy/exc_filters.py12
-rw-r--r--oslo_db/tests/sqlalchemy/test_exc_filters.py67
3 files changed, 91 insertions, 0 deletions
diff --git a/oslo_db/exception.py b/oslo_db/exception.py
index e67ea01..9c0c6fb 100644
--- a/oslo_db/exception.py
+++ b/oslo_db/exception.py
@@ -142,6 +142,18 @@ class DBNonExistentConstraint(DBError):
super(DBNonExistentConstraint, self).__init__(inner_exception)
+class DBNonExistentTable(DBError):
+ """Table does not exist.
+
+ :param table: table name
+ :type table: str
+ """
+
+ def __init__(self, table, inner_exception=None):
+ self.table = table
+ super(DBNonExistentTable, self).__init__(inner_exception)
+
+
class DBDeadlock(DBError):
"""Database dead lock error.
diff --git a/oslo_db/sqlalchemy/exc_filters.py b/oslo_db/sqlalchemy/exc_filters.py
index 7b2d976..7170219 100644
--- a/oslo_db/sqlalchemy/exc_filters.py
+++ b/oslo_db/sqlalchemy/exc_filters.py
@@ -272,6 +272,18 @@ def _check_constraint_non_existing(
programming_error)
+@filters("sqlite", sqla_exc.OperationalError,
+ r".* no such table: (?P<table>.+)")
+@filters("mysql", sqla_exc.InternalError,
+ r".*1051,.*\"Unknown table '(.+\.)?(?P<table>.+)'\"")
+@filters("postgresql", sqla_exc.ProgrammingError,
+ r".* table \"(?P<table>.+)\" does not exist")
+def _check_table_non_existing(
+ programming_error, match, engine_name, is_disconnect):
+ """Filter for table non existing errors."""
+ raise exception.DBNonExistentTable(match.group("table"), programming_error)
+
+
@filters("ibm_db_sa", sqla_exc.IntegrityError, r"^.*SQL0803N.*$")
def _db2_dupe_key_error(integrity_error, match, engine_name, is_disconnect):
"""Filter for DB2 duplicate key errors.
diff --git a/oslo_db/tests/sqlalchemy/test_exc_filters.py b/oslo_db/tests/sqlalchemy/test_exc_filters.py
index 9dcf46b..6f65048 100644
--- a/oslo_db/tests/sqlalchemy/test_exc_filters.py
+++ b/oslo_db/tests/sqlalchemy/test_exc_filters.py
@@ -311,6 +311,73 @@ class TestNonExistentConstraintMySQL(
self.assertEqual("bar_fkey", matched.constraint)
+class TestNonExistentTable(
+ _SQLAExceptionMatcher,
+ test_base.DbTestCase):
+
+ def setUp(self):
+ super(TestNonExistentTable, self).setUp()
+
+ self.meta = sqla.MetaData(bind=self.engine)
+
+ self.table_1 = sqla.Table(
+ "foo", self.meta,
+ sqla.Column("id", sqla.Integer, primary_key=True),
+ mysql_engine='InnoDB',
+ mysql_charset='utf8',
+ )
+
+ def test_raise(self):
+ matched = self.assertRaises(
+ exception.DBNonExistentTable,
+ self.engine.execute,
+ sqla.schema.DropTable(self.table_1),
+ )
+ self.assertInnerException(
+ matched,
+ "OperationalError",
+ "no such table: foo",
+ "\nDROP TABLE foo",
+ )
+ self.assertEqual("foo", matched.table)
+
+
+class TestNonExistentTablePostgreSQL(
+ TestNonExistentTable,
+ test_base.PostgreSQLOpportunisticTestCase):
+
+ def test_raise(self):
+ matched = self.assertRaises(
+ exception.DBNonExistentTable,
+ self.engine.execute,
+ sqla.schema.DropTable(self.table_1),
+ )
+ self.assertInnerException(
+ matched,
+ "ProgrammingError",
+ "table \"foo\" does not exist\n",
+ "\nDROP TABLE foo",
+ )
+ self.assertEqual("foo", matched.table)
+
+
+class TestNonExistentTableMySQL(
+ TestNonExistentTable,
+ test_base.MySQLOpportunisticTestCase):
+
+ def test_raise(self):
+ matched = self.assertRaises(
+ exception.DBNonExistentTable,
+ self.engine.execute,
+ sqla.schema.DropTable(self.table_1),
+ )
+ # 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.InternalError)
+ self.assertEqual("foo", matched.table)
+
+
class TestReferenceErrorSQLite(_SQLAExceptionMatcher, test_base.DbTestCase):
def setUp(self):