diff options
author | Roman Podoliaka <rpodolyaka@mirantis.com> | 2015-04-09 17:20:21 +0300 |
---|---|---|
committer | Roman Podoliaka <rpodolyaka@mirantis.com> | 2015-04-09 17:43:08 +0300 |
commit | af9a99b1b93fce7523be81860a6668cdbab03b49 (patch) | |
tree | f98143c77c219dad8180eb9d0750b665b3bbf535 | |
parent | e95e8ef78297f0b9e4283278e4eed3fc9ef9a5fb (diff) | |
download | oslo-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.py | 8 | ||||
-rw-r--r-- | oslo_db/sqlalchemy/exc_filters.py | 12 | ||||
-rw-r--r-- | oslo_db/tests/old_import_api/sqlalchemy/test_exc_filters.py | 49 |
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): |