diff --git a/src/main/java/org/apache/commons/dbcp2/DelegatingConnection.java b/src/main/java/org/apache/commons/dbcp2/DelegatingConnection.java index af1a6128c..b128957a3 100644 --- a/src/main/java/org/apache/commons/dbcp2/DelegatingConnection.java +++ b/src/main/java/org/apache/commons/dbcp2/DelegatingConnection.java @@ -839,6 +839,7 @@ public void rollback(final Savepoint savepoint) throws SQLException { @Override public void setAutoCommit(final boolean autoCommit) throws SQLException { checkOpen(); + cachedAutoCommit = null; try { connection.setAutoCommit(autoCommit); if (cacheState) { diff --git a/src/test/java/org/apache/commons/dbcp2/TestDelegatingConnection.java b/src/test/java/org/apache/commons/dbcp2/TestDelegatingConnection.java index f6e310819..25598a8e4 100644 --- a/src/test/java/org/apache/commons/dbcp2/TestDelegatingConnection.java +++ b/src/test/java/org/apache/commons/dbcp2/TestDelegatingConnection.java @@ -22,6 +22,7 @@ import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -343,6 +344,112 @@ void testRollbackSavepoint() throws Exception { } } + @Test + void testSetAutoCommitErrorAfterPhysicalChange() throws SQLException { + try (Connection physical = DriverManager.getConnection("jdbc:h2:mem:dcp522_autocommit_error")) { + physical.setAutoCommit(true); + final AssertionError failure = new AssertionError("setAutoCommit failed"); + final Connection faulty = new DelegatingConnection(physical) { + @Override + public void setAutoCommit(final boolean autoCommit) throws SQLException { + super.setAutoCommit(autoCommit); + throw failure; + } + }; + try (DelegatingConnection outer = new DelegatingConnection<>(faulty)) { + assertTrue(outer.getAutoCommit()); + final AssertionError thrown = assertThrows(AssertionError.class, () -> outer.setAutoCommit(false)); + assertSame(failure, thrown); + assertFalse(physical.getAutoCommit()); + assertFalse(outer.getAutoCommit()); + } + } + } + + @Test + void testSetAutoCommitErrorFromDelegateGetter() throws SQLException { + try (Connection physical = DriverManager.getConnection("jdbc:h2:mem:dcp522_autocommit_getter_error")) { + physical.setAutoCommit(true); + final AssertionError failure = new AssertionError("getAutoCommit failed"); + final Connection faulty = new DelegatingConnection(physical) { + private boolean failedOnce; + + @Override + public boolean getAutoCommit() throws SQLException { + if (!failedOnce && !physical.getAutoCommit()) { + failedOnce = true; + throw failure; + } + return physical.getAutoCommit(); + } + }; + try (DelegatingConnection outer = new DelegatingConnection<>(faulty)) { + assertTrue(outer.getAutoCommit()); + final AssertionError thrown = assertThrows(AssertionError.class, () -> outer.setAutoCommit(false)); + assertSame(failure, thrown); + assertFalse(physical.getAutoCommit()); + assertFalse(outer.getAutoCommit()); + } + } + } + + @Test + void testSetAutoCommitErrorWithCacheStateDisabled() throws SQLException { + try (Connection physical = DriverManager.getConnection("jdbc:h2:mem:dcp522_autocommit_no_cache")) { + physical.setAutoCommit(true); + final AssertionError failure = new AssertionError("setAutoCommit failed"); + final DelegatingConnection faulty = new DelegatingConnection(physical) { + @Override + public void setAutoCommit(final boolean autoCommit) throws SQLException { + super.setAutoCommit(autoCommit); + throw failure; + } + }; + faulty.setCacheState(false); + try (DelegatingConnection> outer = new DelegatingConnection<>(faulty)) { + outer.setCacheState(false); + assertTrue(outer.getAutoCommit()); + final AssertionError thrown = assertThrows(AssertionError.class, () -> outer.setAutoCommit(false)); + assertSame(failure, thrown); + assertFalse(physical.getAutoCommit()); + assertFalse(outer.getAutoCommit()); + } + } + } + + @Test + void testSetAutoCommitSqlExceptionAfterPhysicalChange() throws SQLException { + try (Connection physical = DriverManager.getConnection("jdbc:h2:mem:dcp522_autocommit_sql_exception")) { + physical.setAutoCommit(true); + final SQLException failure = new SQLException("setAutoCommit failed"); + final Connection faulty = new DelegatingConnection(physical) { + @Override + public void setAutoCommit(final boolean autoCommit) throws SQLException { + super.setAutoCommit(autoCommit); + throw failure; + } + }; + try (DelegatingConnection outer = new DelegatingConnection<>(faulty)) { + assertTrue(outer.getAutoCommit()); + final SQLException thrown = assertThrows(SQLException.class, () -> outer.setAutoCommit(false)); + assertSame(failure, thrown); + assertFalse(physical.getAutoCommit()); + assertFalse(outer.getAutoCommit()); + } + } + } + + @Test + void testSetAutoCommitSuccessUpdatesCache() throws SQLException { + try (Connection physical = DriverManager.getConnection("jdbc:h2:mem:dcp522_autocommit_success"); + DelegatingConnection outer = new DelegatingConnection<>(physical)) { + assertTrue(outer.getAutoCommit()); + outer.setAutoCommit(false); + assertFalse(physical.getAutoCommit()); + assertFalse(outer.getAutoCommit()); + } + } + @Test void testSetClientInfo() throws Exception { // TODO