postgresql-jdbc.git / summary / log / commit / refs

commit    bb09f10c01d3f8fdbbcca1183f2cdaf4ae701650
Author:   Alexis Meneses <alexismeneses@users.noreply.github.com>
Date:     Mon May 05 16:36:14 2014 +0000

    Added JDBC4 support for CloseOnCompletion on Statement


org/postgresql/jdbc2/AbstractJdbc2Statement.java | 10 ++- org/postgresql/jdbc4/AbstractJdbc4ResultSet.java | 12 +++ org/postgresql/jdbc4/AbstractJdbc4Statement.java | 34 +++++++- .../test/jdbc4/CloseOnCompletionTest.java | 90 ++++++++++++++++++++++ org/postgresql/test/jdbc4/Jdbc4TestSuite.java | 1 + 5 files changed, 142 insertions(+), 5 deletions(-) diff --git a/org/postgresql/jdbc2/AbstractJdbc2Statement.java b/org/postgresql/jdbc2/AbstractJdbc2Statement.java index c8a6f6f5..ccb107f4 100644 --- a/org/postgresql/jdbc2/AbstractJdbc2Statement.java +++ b/org/postgresql/jdbc2/AbstractJdbc2Statement.java @@ -491,8 +491,14 @@ public abstract class AbstractJdbc2Statement implements BaseStatement // Close any existing resultsets associated with this statement. while (firstUnclosedResult != null) { - if (firstUnclosedResult.getResultSet() != null) - firstUnclosedResult.getResultSet().close(); + ResultSet rs = firstUnclosedResult.getResultSet(); + if (rs != null) + { + if (!rs.isClosed()) + { + rs.close(); + } + } firstUnclosedResult = firstUnclosedResult.getNext(); } result = null; diff --git a/org/postgresql/jdbc4/AbstractJdbc4ResultSet.java b/org/postgresql/jdbc4/AbstractJdbc4ResultSet.java index dabe640e..4c9cbfc8 100644 --- a/org/postgresql/jdbc4/AbstractJdbc4ResultSet.java +++ b/org/postgresql/jdbc4/AbstractJdbc4ResultSet.java @@ -52,6 +52,18 @@ abstract class AbstractJdbc4ResultSet extends org.postgresql.jdbc3g.AbstractJdbc return (rows == null); } + public void close() throws SQLException + { + try + { + super.close(); + } + finally + { + ((AbstractJdbc4Statement) statement).checkCompletion(); + } + } + public void updateNString(int columnIndex, String nString) throws SQLException { throw org.postgresql.Driver.notImplemented(this.getClass(), "updateNString(int, String)"); diff --git a/org/postgresql/jdbc4/AbstractJdbc4Statement.java b/org/postgresql/jdbc4/AbstractJdbc4Statement.java index 3f5ad522..5282dc43 100644 --- a/org/postgresql/jdbc4/AbstractJdbc4Statement.java +++ b/org/postgresql/jdbc4/AbstractJdbc4Statement.java @@ -8,11 +8,11 @@ package org.postgresql.jdbc4; import java.sql.*; - import java.io.Reader; import java.io.InputStream; import org.postgresql.core.Oid; +import org.postgresql.jdbc2.ResultWrapper; import org.postgresql.util.GT; import org.postgresql.util.PSQLState; import org.postgresql.util.PSQLException; @@ -21,6 +21,7 @@ abstract class AbstractJdbc4Statement extends org.postgresql.jdbc3g.AbstractJdbc { private boolean poolable; + private boolean closeOnCompletion = false; AbstractJdbc4Statement (Jdbc4Connection c, int rsType, int rsConcurrency, int rsHoldability) throws SQLException { @@ -383,12 +384,12 @@ abstract class AbstractJdbc4Statement extends org.postgresql.jdbc3g.AbstractJdbc public void closeOnCompletion() throws SQLException { - throw org.postgresql.Driver.notImplemented(this.getClass(), "closeOnCompletion()"); + closeOnCompletion = true; } public boolean isCloseOnCompletion() throws SQLException { - throw org.postgresql.Driver.notImplemented(this.getClass(), "isCloseOnCompletion()"); + return closeOnCompletion; } public <T> T getObject(int parameterIndex, Class<T> type) throws SQLException @@ -401,4 +402,31 @@ abstract class AbstractJdbc4Statement extends org.postgresql.jdbc3g.AbstractJdbc throw org.postgresql.Driver.notImplemented(this.getClass(), "getObject(String, Class<T>)"); } + protected void checkCompletion() throws SQLException + { + if (!closeOnCompletion) + return; + + ResultWrapper result = firstUnclosedResult; + while (result != null) + { + if (result.getResultSet() != null && !result.getResultSet().isClosed()) + { + return; + } + result = result.getNext(); + } + + // prevent all ResultSet.close arising from Statement.close to loop here + closeOnCompletion = false; + try + { + close(); + } + finally + { + // restore the status if one rely on isCloseOnCompletion + closeOnCompletion = true; + } + } } diff --git a/org/postgresql/test/jdbc4/CloseOnCompletionTest.java b/org/postgresql/test/jdbc4/CloseOnCompletionTest.java new file mode 100644 index 00000000..1cf774c6 --- /dev/null +++ b/org/postgresql/test/jdbc4/CloseOnCompletionTest.java @@ -0,0 +1,90 @@ +package org.postgresql.test.jdbc4; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +import junit.framework.TestCase; + +import org.postgresql.test.TestUtil; + +public class CloseOnCompletionTest extends TestCase +{ + + private Connection _conn; + + public CloseOnCompletionTest(String name) + { + super(name); + } + + protected void setUp() throws Exception + { + _conn = TestUtil.openDB(); + TestUtil.createTable(_conn, "table1", "id integer"); + } + + protected void tearDown() throws SQLException + { + TestUtil.dropTable(_conn, "table1"); + TestUtil.closeDB( _conn ); + } + + /** + * Test that the statement is not automatically closed if we do not ask for it + */ + public void testWithoutCloseOnCompletion() throws SQLException + { + Statement stmt = _conn.createStatement(); + + ResultSet rs = stmt.executeQuery(TestUtil.selectSQL("table1", "*")); + rs.close(); + assertFalse(stmt.isClosed()); + } + + /** + * Test the behavior of closeOnCompletion with a single result set + */ + public void testSingleResultSet() throws SQLException + { + Statement stmt = _conn.createStatement(); + stmt.closeOnCompletion(); + + ResultSet rs = stmt.executeQuery(TestUtil.selectSQL("table1", "*")); + rs.close(); + assertTrue(stmt.isClosed()); + } + + /** + * Test the behavior of closeOnCompletion with a multiple result sets + */ + public void testMultipleResultSet() throws SQLException + { + Statement stmt = _conn.createStatement(); + stmt.closeOnCompletion(); + + stmt.execute(TestUtil.selectSQL("table1", "*") + ";" + + TestUtil.selectSQL("table1", "*") + ";"); + ResultSet rs = stmt.getResultSet(); + rs.close(); + assertFalse(stmt.isClosed()); + stmt.getMoreResults(); + rs = stmt.getResultSet(); + rs.close(); + assertTrue(stmt.isClosed()); + } + + /** + * Test that when execution does not produce any result sets, + * closeOnCompletion has no effect (spec) + */ + public void testNoResultSet() throws SQLException + { + Statement stmt = _conn.createStatement(); + stmt.closeOnCompletion(); + + stmt.executeUpdate(TestUtil.insertSQL("table1", "1")); + assertFalse(stmt.isClosed()); + } +} diff --git a/org/postgresql/test/jdbc4/Jdbc4TestSuite.java b/org/postgresql/test/jdbc4/Jdbc4TestSuite.java index 51b0a676..1d97cf44 100644 --- a/org/postgresql/test/jdbc4/Jdbc4TestSuite.java +++ b/org/postgresql/test/jdbc4/Jdbc4TestSuite.java @@ -35,6 +35,7 @@ public class Jdbc4TestSuite extends TestSuite suite.addTestSuite(SchemaTest.class); suite.addTestSuite(AbortTest.class); suite.addTestSuite(ClientInfoTest.class); + suite.addTestSuite(CloseOnCompletionTest.class); Connection connection = TestUtil.openDB(); try [parent: 9992e8a53b1f]