Implement further exception handling improvements.
parent
a2ba0fb2b1
commit
4ededf479d
|
|
@ -173,6 +173,9 @@ Changelog
|
||||||
|
|
||||||
- Enrich exceptions with message from java SQLExceptions
|
- Enrich exceptions with message from java SQLExceptions
|
||||||
|
|
||||||
|
- Be more specific about DB API exceptions: Distinguish DatabaseError and
|
||||||
|
InterfaceError.
|
||||||
|
|
||||||
- Fix typo LONGNARCHAR vs LONGVARCHAR (thanks @datdo for reporting #4)
|
- Fix typo LONGNARCHAR vs LONGVARCHAR (thanks @datdo for reporting #4)
|
||||||
|
|
||||||
- 0.1.5 - 2015-03-02
|
- 0.1.5 - 2015-03-02
|
||||||
|
|
|
||||||
|
|
@ -13,9 +13,20 @@ public abstract class MockConnection implements Connection {
|
||||||
|
|
||||||
ResultSet mockResultSet;
|
ResultSet mockResultSet;
|
||||||
|
|
||||||
public final void mockExceptionOnExecute(String exceptionMessage) throws SQLException {
|
public final void mockExceptionOnCommit(String className, String exceptionMessage) throws SQLException {
|
||||||
|
Throwable exception = createException(className, exceptionMessage);
|
||||||
|
Mockito.doThrow(exception).when(this).commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void mockExceptionOnRollback(String className, String exceptionMessage) throws SQLException {
|
||||||
|
Throwable exception = createException(className, exceptionMessage);
|
||||||
|
Mockito.doThrow(exception).when(this).rollback();
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void mockExceptionOnExecute(String className, String exceptionMessage) throws SQLException {
|
||||||
PreparedStatement mockPreparedStatement = Mockito.mock(PreparedStatement.class);
|
PreparedStatement mockPreparedStatement = Mockito.mock(PreparedStatement.class);
|
||||||
Mockito.when(mockPreparedStatement.execute()).thenThrow(new SQLException(exceptionMessage));
|
Throwable exception = createException(className, exceptionMessage);
|
||||||
|
Mockito.when(mockPreparedStatement.execute()).thenThrow(exception);
|
||||||
Mockito.when(this.prepareStatement(Mockito.anyString())).thenReturn(mockPreparedStatement);
|
Mockito.when(this.prepareStatement(Mockito.anyString())).thenReturn(mockPreparedStatement);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -33,7 +44,19 @@ public abstract class MockConnection implements Connection {
|
||||||
Mockito.when(this.prepareStatement(Mockito.anyString())).thenReturn(mockPreparedStatement);
|
Mockito.when(this.prepareStatement(Mockito.anyString())).thenReturn(mockPreparedStatement);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int extractTypeCodeForName(String sqlTypesName) {
|
public final ResultSet verifyResultSet() {
|
||||||
|
return Mockito.verify(mockResultSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Throwable createException(String className, String exceptionMessage) {
|
||||||
|
try {
|
||||||
|
return (Throwable) Class.forName(className).getConstructor(String.class).newInstance(exceptionMessage);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("Couldn't initialize class " + className + ".", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int extractTypeCodeForName(String sqlTypesName) {
|
||||||
try {
|
try {
|
||||||
Field field = Types.class.getField(sqlTypesName);
|
Field field = Types.class.getField(sqlTypesName);
|
||||||
return field.getInt(null);
|
return field.getInt(null);
|
||||||
|
|
@ -48,8 +71,4 @@ public abstract class MockConnection implements Connection {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public final ResultSet verifyResultSet() {
|
|
||||||
return Mockito.verify(mockResultSet);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,13 +41,14 @@ _java_array_byte = None
|
||||||
|
|
||||||
_handle_sql_exception = None
|
_handle_sql_exception = None
|
||||||
|
|
||||||
def _handle_sql_exception_jython(ex):
|
def _handle_sql_exception_jython():
|
||||||
from java.sql import SQLException
|
from java.sql import SQLException
|
||||||
if isinstance(ex, SQLException):
|
exc_info = sys.exc_info()
|
||||||
# TODO get stacktrace
|
if isinstance(exc_info[1], SQLException):
|
||||||
raise Error, ex.getMessage()
|
exc_type = DatabaseError
|
||||||
else:
|
else:
|
||||||
raise ex
|
exc_type = InterfaceError
|
||||||
|
raise exc_type, exc_info[1], exc_info[2]
|
||||||
|
|
||||||
def _jdbc_connect_jython(jclassname, jars, libs, *args):
|
def _jdbc_connect_jython(jclassname, jars, libs, *args):
|
||||||
if _jdbc_name_to_const is None:
|
if _jdbc_name_to_const is None:
|
||||||
|
|
@ -103,14 +104,15 @@ def _prepare_jython():
|
||||||
global _handle_sql_exception
|
global _handle_sql_exception
|
||||||
_handle_sql_exception = _handle_sql_exception_jython
|
_handle_sql_exception = _handle_sql_exception_jython
|
||||||
|
|
||||||
def _handle_sql_exception_jpype(ex):
|
def _handle_sql_exception_jpype():
|
||||||
import jpype
|
import jpype
|
||||||
SQLException = jpype.java.sql.SQLException
|
SQLException = jpype.java.sql.SQLException
|
||||||
if issubclass(ex.__javaclass__, SQLException):
|
exc_info = sys.exc_info()
|
||||||
# TODO get stacktrace
|
if issubclass(exc_info[1].__javaclass__, SQLException):
|
||||||
raise Error, ex.message()
|
exc_type = DatabaseError
|
||||||
else:
|
else:
|
||||||
raise ex
|
exc_type = InterfaceError
|
||||||
|
raise exc_type, exc_info[1], exc_info[2]
|
||||||
|
|
||||||
def _jdbc_connect_jpype(jclassname, jars, libs, *driver_args):
|
def _jdbc_connect_jpype(jclassname, jars, libs, *driver_args):
|
||||||
import jpype
|
import jpype
|
||||||
|
|
@ -353,15 +355,13 @@ class Connection(object):
|
||||||
try:
|
try:
|
||||||
self.jconn.commit()
|
self.jconn.commit()
|
||||||
except:
|
except:
|
||||||
ex = sys.exc_info()[1]
|
_handle_sql_exception()
|
||||||
_handle_sql_exception(ex)
|
|
||||||
|
|
||||||
def rollback(self):
|
def rollback(self):
|
||||||
try:
|
try:
|
||||||
self.jconn.rollback()
|
self.jconn.rollback()
|
||||||
except:
|
except:
|
||||||
ex = sys.exc_info()[1]
|
_handle_sql_exception()
|
||||||
_handle_sql_exception(ex)
|
|
||||||
|
|
||||||
def cursor(self):
|
def cursor(self):
|
||||||
return Cursor(self, self._converters)
|
return Cursor(self, self._converters)
|
||||||
|
|
@ -445,8 +445,7 @@ class Cursor(object):
|
||||||
try:
|
try:
|
||||||
is_rs = self._prep.execute()
|
is_rs = self._prep.execute()
|
||||||
except:
|
except:
|
||||||
ex = sys.exc_info()[1]
|
_handle_sql_exception()
|
||||||
_handle_sql_exception(ex)
|
|
||||||
if is_rs:
|
if is_rs:
|
||||||
self._rs = self._prep.getResultSet()
|
self._rs = self._prep.getResultSet()
|
||||||
self._meta = self._rs.getMetaData()
|
self._meta = self._rs.getMetaData()
|
||||||
|
|
@ -454,7 +453,7 @@ class Cursor(object):
|
||||||
else:
|
else:
|
||||||
self.rowcount = self._prep.getUpdateCount()
|
self.rowcount = self._prep.getUpdateCount()
|
||||||
# self._prep.getWarnings() ???
|
# self._prep.getWarnings() ???
|
||||||
|
|
||||||
def executemany(self, operation, seq_of_parameters):
|
def executemany(self, operation, seq_of_parameters):
|
||||||
self._close_last()
|
self._close_last()
|
||||||
self._prep = self._connection.jconn.prepareStatement(operation)
|
self._prep = self._connection.jconn.prepareStatement(operation)
|
||||||
|
|
|
||||||
|
|
@ -47,12 +47,52 @@ class MockTest(unittest.TestCase):
|
||||||
'getObject'))
|
'getObject'))
|
||||||
verify_get(1)
|
verify_get(1)
|
||||||
|
|
||||||
def test_exception_on_execute(self):
|
def test_sql_exception_on_execute(self):
|
||||||
dummy_msg = "expected"
|
self.conn.jconn.mockExceptionOnExecute("java.sql.SQLException", "expected")
|
||||||
self.conn.jconn.mockExceptionOnExecute(dummy_msg)
|
|
||||||
cursor = self.conn.cursor()
|
cursor = self.conn.cursor()
|
||||||
try:
|
try:
|
||||||
cursor.execute("dummy stmt")
|
cursor.execute("dummy stmt")
|
||||||
fail("expected exception")
|
fail("expected exception")
|
||||||
except jaydebeapi.Error, e:
|
except jaydebeapi.DatabaseError, e:
|
||||||
self.assertEquals(str(e), 'expected')
|
self.assertEquals(str(e), "java.sql.SQLException: expected")
|
||||||
|
|
||||||
|
def test_runtime_exception_on_execute(self):
|
||||||
|
self.conn.jconn.mockExceptionOnExecute("java.lang.RuntimeException", "expected")
|
||||||
|
cursor = self.conn.cursor()
|
||||||
|
try:
|
||||||
|
cursor.execute("dummy stmt")
|
||||||
|
fail("expected exception")
|
||||||
|
except jaydebeapi.InterfaceError, e:
|
||||||
|
self.assertEquals(str(e), "java.lang.RuntimeException: expected")
|
||||||
|
|
||||||
|
def test_sql_exception_on_commit(self):
|
||||||
|
self.conn.jconn.mockExceptionOnCommit("java.sql.SQLException", "expected")
|
||||||
|
try:
|
||||||
|
self.conn.commit()
|
||||||
|
fail("expected exception")
|
||||||
|
except jaydebeapi.DatabaseError, e:
|
||||||
|
self.assertEquals(str(e), "java.sql.SQLException: expected")
|
||||||
|
|
||||||
|
def test_runtime_exception_on_commit(self):
|
||||||
|
self.conn.jconn.mockExceptionOnCommit("java.lang.RuntimeException", "expected")
|
||||||
|
try:
|
||||||
|
self.conn.commit()
|
||||||
|
fail("expected exception")
|
||||||
|
except jaydebeapi.InterfaceError, e:
|
||||||
|
self.assertEquals(str(e), "java.lang.RuntimeException: expected")
|
||||||
|
|
||||||
|
def test_sql_exception_on_rollback(self):
|
||||||
|
self.conn.jconn.mockExceptionOnRollback("java.sql.SQLException", "expected")
|
||||||
|
try:
|
||||||
|
self.conn.rollback()
|
||||||
|
fail("expected exception")
|
||||||
|
except jaydebeapi.DatabaseError, e:
|
||||||
|
self.assertEquals(str(e), "java.sql.SQLException: expected")
|
||||||
|
|
||||||
|
def test_runtime_exception_on_rollback(self):
|
||||||
|
self.conn.jconn.mockExceptionOnRollback("java.lang.RuntimeException", "expected")
|
||||||
|
try:
|
||||||
|
self.conn.rollback()
|
||||||
|
fail("expected exception")
|
||||||
|
except jaydebeapi.InterfaceError, e:
|
||||||
|
self.assertEquals(str(e), "java.lang.RuntimeException: expected")
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue