summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoman Podoliaka <rpodolyaka@mirantis.com>2015-04-09 17:20:21 +0300
committerRoman Podoliaka <rpodolyaka@mirantis.com>2015-04-09 17:43:08 +0300
commitaf9a99b1b93fce7523be81860a6668cdbab03b49 (patch)
treef98143c77c219dad8180eb9d0750b665b3bbf535
parente95e8ef78297f0b9e4283278e4eed3fc9ef9a5fb (diff)
downloadoslo-db-af9a99b1b93fce7523be81860a6668cdbab03b49.tar.gz
Add filters for DBDataError exception
We currently don't distinguish DB errors, that are due to problems with the processed data (like division by zero, numeric value out of range, incorrect data type passed, etc) This actually led to a problem when MySQL threw two different errors depending on the randomly generated UUID value and we wrapped only one of those cases properly, which caused the test case to fail time to time in the gate. Closes-Bug: #1442178 Change-Id: I02891f3b1ede6f33834e5637be43496499cc88e7
-rw-r--r--oslo_db/exception.py8
-rw-r--r--oslo_db/sqlalchemy/exc_filters.py12
-rw-r--r--oslo_db/tests/old_import_api/sqlalchemy/test_exc_filters.py49
3 files changed, 69 insertions, 0 deletions
diff --git a/oslo_db/exception.py b/oslo_db/exception.py
index f950f6a..111c4b5 100644
--- a/oslo_db/exception.py
+++ b/oslo_db/exception.py
@@ -155,6 +155,14 @@ class DBConnectionError(DBError):
pass
+class DBDataError(DBError):
+ """Raised for errors that are due to problems with the processed data.
+
+ E.g. division by zero, numeric value out of range, incorrect data type, etc
+
+ """
+
+
class InvalidSortKey(Exception):
"""A sort key destined for database query usage is invalid."""
diff --git a/oslo_db/sqlalchemy/exc_filters.py b/oslo_db/sqlalchemy/exc_filters.py
index 777fda6..539041b 100644
--- a/oslo_db/sqlalchemy/exc_filters.py
+++ b/oslo_db/sqlalchemy/exc_filters.py
@@ -250,6 +250,18 @@ def _raise_mysql_table_doesnt_exist_asis(
raise error
+@filters("mysql", sqla_exc.OperationalError,
+ r".*(1292|1366).*Incorrect \w+ value.*")
+@filters("mysql", sqla_exc.DataError,
+ r".*1265.*Data truncated for column.*")
+@filters("mysql", sqla_exc.DataError,
+ r".*1264.*Out of range value for column.*")
+def _raise_data_error(error, match, engine_name, is_disconnect):
+ """Raise DBDataError exception for different data errors."""
+
+ raise exception.DBDataError(error)
+
+
@filters("*", sqla_exc.OperationalError, r".*")
def _raise_operational_errors_directly_filter(operational_error,
match, engine_name,
diff --git a/oslo_db/tests/old_import_api/sqlalchemy/test_exc_filters.py b/oslo_db/tests/old_import_api/sqlalchemy/test_exc_filters.py
index 4d4609a..77670be 100644
--- a/oslo_db/tests/old_import_api/sqlalchemy/test_exc_filters.py
+++ b/oslo_db/tests/old_import_api/sqlalchemy/test_exc_filters.py
@@ -78,6 +78,9 @@ class TestsExceptionFilter(_SQLAExceptionMatcher, oslo_test_base.BaseTestCase):
class ProgrammingError(Error):
pass
+ class DataError(Error):
+ pass
+
class TransactionRollbackError(OperationalError):
"""Special psycopg2-only error class.
@@ -223,6 +226,52 @@ class TestFallthroughsAndNonDBAPI(TestsExceptionFilter):
self.assertEqual("mysqldb has an attribute error", matched.args[0])
+class TestDataError(TestsExceptionFilter):
+
+ def test_mysql_incorrect_value(self):
+ matched = self._run_test(
+ "mysql", "insert into testtbl (id, b) values (4242, 4242)",
+ self.OperationalError(
+ "ERROR 1292 (22007): Incorrect datetime value: '4242' "
+ "for column 'b' at row 1"
+ ),
+ exception.DBDataError
+ )
+ self.assertInnerException(
+ matched,
+ "OperationalError",
+ ("ERROR 1292 (22007): Incorrect datetime value: '4242' for column "
+ "'b' at row 1"),
+ "insert into testtbl (id, b) values (4242, 4242)", ())
+
+ def test_mysql_data_truncated_for_column(self):
+ matched = self._run_test(
+ "mysql", "insert into testtbl (id, b) values (4242, '42aabbccdd')",
+ self.DataError(
+ "ERROR 1265 (01000): Data truncated for column 'b' at row 1"),
+ exception.DBDataError
+ )
+ self.assertInnerException(
+ matched,
+ "DataError",
+ "ERROR 1265 (01000): Data truncated for column 'b' at row 1",
+ "insert into testtbl (id, b) values (4242, '42aabbccdd')", ())
+
+ def test_mysql_out_of_range_value(self):
+ matched = self._run_test(
+ "mysql", "insert into testtbl (id, b) values (4242, 424242424242)",
+ self.DataError(
+ "ERROR 1264 (22003): Out of range value for column 'b' "
+ "at row 1"),
+ exception.DBDataError
+ )
+ self.assertInnerException(
+ matched,
+ "DataError",
+ "ERROR 1264 (22003): Out of range value for column 'b' at row 1",
+ "insert into testtbl (id, b) values (4242, 424242424242)", ())
+
+
class TestReferenceErrorSQLite(_SQLAExceptionMatcher, test_base.DbTestCase):
def setUp(self):