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]