-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
Co-authored-by: Sebastian Bär <[email protected]>
- Loading branch information
1 parent
53de628
commit db6e18d
Showing
5 changed files
with
136 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,4 +2,4 @@ error-tags: | |
TDBJ: | ||
packages: | ||
- com.exasol.dbbuilder | ||
highest-index: 35 | ||
highest-index: 37 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
61 changes: 61 additions & 0 deletions
61
src/main/java/com/exasol/dbbuilder/dialects/AutoCommit.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
package com.exasol.dbbuilder.dialects; | ||
|
||
import java.sql.*; | ||
import java.util.logging.Logger; | ||
|
||
import com.exasol.errorreporting.ExaError; | ||
|
||
/** | ||
* This class allows temporarily deactivating AutoCommit for a given {@link Connection} and restores the original state | ||
* in {@link #close()}. If the database does not support deactivating AutoCommit (i.e. throws a | ||
* {@link SQLFeatureNotSupportedException}), this class will silently ignore it. | ||
*/ | ||
class AutoCommit implements AutoCloseable { | ||
private static final Logger LOG = Logger.getLogger(AutoCommit.class.getName()); | ||
private final Connection connection; | ||
|
||
private AutoCommit(final Connection connection) { | ||
this.connection = connection; | ||
} | ||
|
||
static AutoCommit tryDeactivate(final Connection connection) { | ||
try { | ||
final boolean originalState = connection.getAutoCommit(); | ||
if (!originalState) { | ||
return new AutoCommit(null); | ||
} | ||
if (deactivatingAutoCommitSuccessful(connection)) { | ||
return new AutoCommit(connection); | ||
} else { | ||
return new AutoCommit(null); | ||
} | ||
} catch (final SQLException exception) { | ||
throw new DatabaseObjectException( | ||
ExaError.messageBuilder("E-TDBJ-36").message("Failed to check AutoCommit state").toString(), | ||
exception); | ||
} | ||
} | ||
|
||
private static boolean deactivatingAutoCommitSuccessful(final Connection connection) throws SQLException { | ||
try { | ||
connection.setAutoCommit(false); | ||
return true; | ||
} catch (final SQLFeatureNotSupportedException exception) { | ||
LOG.fine("Database does not support deactivating AutoCommit: " + exception.getMessage()); | ||
return false; | ||
} | ||
} | ||
|
||
@Override | ||
public void close() { | ||
if (connection != null) { | ||
try { | ||
connection.setAutoCommit(true); | ||
} catch (final SQLException exception) { | ||
throw new DatabaseObjectException( | ||
ExaError.messageBuilder("E-TDBJ-37").message("Failed to re-enable AutoCommit").toString(), | ||
exception); | ||
} | ||
} | ||
} | ||
} |
68 changes: 68 additions & 0 deletions
68
src/test/java/com/exasol/dbbuilder/dialects/AutoCommitTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package com.exasol.dbbuilder.dialects; | ||
|
||
import static org.hamcrest.MatcherAssert.assertThat; | ||
import static org.hamcrest.Matchers.equalTo; | ||
import static org.junit.jupiter.api.Assertions.assertThrows; | ||
import static org.mockito.ArgumentMatchers.anyBoolean; | ||
import static org.mockito.Mockito.*; | ||
|
||
import java.sql.*; | ||
|
||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.api.extension.ExtendWith; | ||
import org.mockito.InOrder; | ||
import org.mockito.Mock; | ||
import org.mockito.junit.jupiter.MockitoExtension; | ||
|
||
@ExtendWith(MockitoExtension.class) | ||
class AutoCommitTest { | ||
@Mock | ||
Connection connectionMock; | ||
|
||
@Test | ||
void autoCommitAlreadyDeactivated() throws SQLException { | ||
when(connectionMock.getAutoCommit()).thenReturn(false); | ||
AutoCommit.tryDeactivate(connectionMock).close(); | ||
verify(connectionMock, never()).setAutoCommit(anyBoolean()); | ||
verifyNoMoreInteractions(connectionMock); | ||
} | ||
|
||
@Test | ||
void autoCommitEnabledAndSupported() throws SQLException { | ||
when(connectionMock.getAutoCommit()).thenReturn(true); | ||
AutoCommit.tryDeactivate(connectionMock).close(); | ||
final InOrder inOrder = inOrder(connectionMock); | ||
inOrder.verify(connectionMock).setAutoCommit(false); | ||
inOrder.verify(connectionMock).setAutoCommit(true); | ||
inOrder.verifyNoMoreInteractions(); | ||
} | ||
|
||
@Test | ||
void autoCommitEnabledAndNotSupported() throws SQLException { | ||
when(connectionMock.getAutoCommit()).thenReturn(true); | ||
doThrow(new SQLFeatureNotSupportedException("unsupported")).when(connectionMock).setAutoCommit(false); | ||
AutoCommit.tryDeactivate(connectionMock).close(); | ||
verify(connectionMock).setAutoCommit(false); | ||
verifyNoMoreInteractions(connectionMock); | ||
} | ||
|
||
@Test | ||
void settingAutoCommitFailsWithOtherException() throws SQLException { | ||
when(connectionMock.getAutoCommit()).thenReturn(true); | ||
doThrow(new SQLException("mock")).when(connectionMock).setAutoCommit(false); | ||
final DatabaseObjectException exception = assertThrows(DatabaseObjectException.class, | ||
() -> AutoCommit.tryDeactivate(connectionMock)); | ||
assertThat(exception.getMessage(), equalTo("E-TDBJ-36: Failed to check AutoCommit state")); | ||
assertThat(exception.getCause().getMessage(), equalTo("mock")); | ||
} | ||
|
||
@Test | ||
void reactivatingAutoCommitFails() throws SQLException { | ||
when(connectionMock.getAutoCommit()).thenReturn(true); | ||
final AutoCommit autoCommit = AutoCommit.tryDeactivate(connectionMock); | ||
doThrow(new SQLException("mock")).when(connectionMock).setAutoCommit(true); | ||
final DatabaseObjectException exception = assertThrows(DatabaseObjectException.class, autoCommit::close); | ||
assertThat(exception.getMessage(), equalTo("E-TDBJ-37: Failed to re-enable AutoCommit")); | ||
assertThat(exception.getCause().getMessage(), equalTo("mock")); | ||
} | ||
} |