]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Closing a Connection or Statement object twice should be a no-op
authorKris Jurka <books@ejurka.com>
Tue, 24 Feb 2004 13:11:45 +0000 (13:11 +0000)
committerKris Jurka <books@ejurka.com>
Tue, 24 Feb 2004 13:11:45 +0000 (13:11 +0000)
instead of throwing an Exception.

Per report from Victor Sergienko.

src/interfaces/jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java
src/interfaces/jdbc/org/postgresql/jdbc2/optional/PooledConnectionImpl.java
src/interfaces/jdbc/org/postgresql/test/jdbc2/ConnectionTest.java
src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/ConnectionPoolTest.java
src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/PoolingDataSourceTest.java

index 50c214a30d9d8c13bc72332939b05ef440bd63f0..0addc9e47f9bf05a85eabe284ff317d53be1e0b3 100644 (file)
@@ -26,7 +26,7 @@ import java.sql.Timestamp;
 import java.sql.Types;
 import java.util.Vector;
 
-/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Statement.java,v 1.41.2.3 2004/02/03 05:13:55 jurka Exp $
+/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Statement.java,v 1.41.2.4 2004/02/24 13:11:44 jurka Exp $
  * This class defines methods of the jdbc1 specification.  This class is
  * extended by org.postgresql.jdbc2.AbstractJdbc2Statement which adds the jdbc2
  * methods.  The real Statement class (for jdbc1) is org.postgresql.jdbc1.Jdbc1Statement
@@ -84,6 +84,8 @@ public abstract class AbstractJdbc1Statement implements BaseStatement
 
        private boolean m_useServerPrepare = false;
 
+       private boolean isClosed = false;
+
     // m_preparedCount is used for naming of auto-cursors and must
     // be synchronized so that multiple threads using the same
     // connection don't stomp over each others cursors.
@@ -785,6 +787,10 @@ public abstract class AbstractJdbc1Statement implements BaseStatement
         */
        public void close() throws SQLException
        {
+               // closing an already closed Statement is a no-op.
+               if (isClosed)
+                       return;
+
                // Force the ResultSet to close
                java.sql.ResultSet rs = getResultSet();
                if (rs != null)
@@ -794,6 +800,7 @@ public abstract class AbstractJdbc1Statement implements BaseStatement
 
                // Disasociate it from us (For Garbage Collection)
                result = null;
+               isClosed = true;
        }
 
        /**
index a8be118d083eda9cdf9ea042f853650eacf3592a..5047a956f2adf253858aa54be517ab7fd4f05aba 100644 (file)
@@ -14,7 +14,7 @@ import org.postgresql.PGConnection;
  *
  * @author Aaron Mulder (ammulder@chariotsolutions.com)
  * @author Csaba Nagy (ncsaba@yahoo.com)
- * @version $Revision: 1.7.4.2 $
+ * @version $Revision: 1.7.4.3 $
  */
 public class PooledConnectionImpl implements PooledConnection
 {
@@ -234,12 +234,17 @@ public class PooledConnectionImpl implements PooledConnection
                        {
                                return con == null ? Boolean.TRUE : Boolean.FALSE;
                        }
-                       if (con == null)
+                       if (con == null && !method.getName().equals("close"))
                        {
                                throw new SQLException(automatic ? "Connection has been closed automatically because a new connection was opened for the same PooledConnection or the PooledConnection has been closed" : "Connection has been closed");
                        }
                        if (method.getName().equals("close"))
                        {
+                               // we are already closed and a double close
+                               // is not an error.
+                               if (con == null)
+                                       return null;
+
                                SQLException ex = null;
                                if (!con.getAutoCommit())
                                {
@@ -358,12 +363,12 @@ public class PooledConnectionImpl implements PooledConnection
                 return method.invoke(st, args);
             }
             // All the rest is from the Statement interface
-            if (st == null || con.isClosed())
-            {
-                throw new SQLException("Statement has been closed");
-            }
             if (method.getName().equals("close"))
             {
+                // closing an already closed object is a no-op
+                if (st == null || con.isClosed())
+                    return null;
+
                 try {
                     st.close();
                 } finally {
@@ -372,6 +377,10 @@ public class PooledConnectionImpl implements PooledConnection
                 }
                 return null;
             }
+            if (st == null || con.isClosed())
+            {
+                throw new SQLException("Statement has been closed");
+            }
             else if (method.getName().equals("getConnection"))
             {
                 return con.getProxy(); // the proxied connection, not a physical connection
index 1d79463eb1693d8e0c310a39662a2459ccaf74d7..2a28124f168b41364e738c0961a161ebc00c4958 100644 (file)
@@ -10,7 +10,7 @@ import java.sql.*;
  *
  * PS: Do you know how difficult it is to type on a train? ;-)
  *
- * $Id: ConnectionTest.java,v 1.10 2002/10/17 05:33:52 barry Exp $
+ * $Id: ConnectionTest.java,v 1.10.6.1 2004/02/24 13:11:44 jurka Exp $
  */
 
 public class ConnectionTest extends TestCase
@@ -347,4 +347,14 @@ public class ConnectionTest extends TestCase
                        assertTrue(ex.getMessage(), false);
                }
        }
+
+       /**
+        * Closing a Connection more than once is not an error.
+        */
+       public void testDoubleClose() throws SQLException
+       {
+               Connection con = TestUtil.openDB();
+               con.close();
+               con.close();
+       }
 }
index 6c226d0219aa200b9d73bde0c195f7499578072e..662f7b6264dfe0bc1b517eaa6c26cf1ccc7918b6 100644 (file)
@@ -12,7 +12,7 @@ import java.io.*;
  * interface to the PooledConnection is through the CPDS.
  *
  * @author Aaron Mulder (ammulder@chariotsolutions.com)
- * @version $Revision: 1.6.4.3 $
+ * @version $Revision: 1.6.4.4 $
  */
 public class ConnectionPoolTest extends BaseDataSourceTest
 {
@@ -131,13 +131,6 @@ public class ConnectionPoolTest extends BaseDataSourceTest
                        }
                        catch (SQLException e)
                        {}
-                       try
-                       {
-                               con.close();
-                               fail("Original connection wrapper should be closed when new connection wrapper is generated");
-                       }
-                       catch (SQLException e)
-                       {}
                        con2.close();
                        pc.close();
                }
@@ -194,13 +187,8 @@ public class ConnectionPoolTest extends BaseDataSourceTest
                        con.close();
                        assertTrue(cc.getCount() == 2);
                        assertTrue(cc.getErrorCount() == 0);
-                       try
-                       {
+                       // a double close shouldn't fire additional events
                                con.close();
-                               fail("Should not be able to close a connection wrapper twice");
-                       }
-                       catch (SQLException e)
-                       {}
                        assertTrue(cc.getCount() == 2);
                        assertTrue(cc.getErrorCount() == 0);
                        pc.close();
index 701f835332e2f9472113158ffca2ea3949cf64d2..75bb4ac2e7bc1ab667e6f87efcdaf8954d3af9cb 100644 (file)
@@ -1,6 +1,7 @@
 package org.postgresql.test.jdbc2.optional;
 
 import java.sql.SQLException;
+import java.sql.Statement;
 import org.postgresql.test.TestUtil;
 import org.postgresql.jdbc2.optional.PoolingDataSource;
 import org.postgresql.jdbc2.optional.BaseDataSource;
@@ -9,7 +10,7 @@ import org.postgresql.jdbc2.optional.BaseDataSource;
  * Minimal tests for pooling DataSource.  Needs many more.
  *
  * @author Aaron Mulder (ammulder@chariotsolutions.com)
- * @version $Revision: 1.1.6.1 $
+ * @version $Revision: 1.1.6.2 $
  */
 public class PoolingDataSourceTest extends BaseDataSourceTest
 {
@@ -96,4 +97,26 @@ public class PoolingDataSourceTest extends BaseDataSourceTest
         {
         }
     }
+
+    /**
+     * Closing a Connection twice is not an error.
+     */
+    public void testDoubleConnectionClose() throws SQLException
+    {
+        con = getDataSourceConnection();
+        con.close();
+        con.close();
+    }
+
+    /**
+     * Closing a Statement twice is not an error.
+     */
+    public void testDoubleStatementClose() throws SQLException
+    {
+        con = getDataSourceConnection();
+        Statement stmt = con.createStatement();
+        stmt.close();
+        stmt.close();
+        con.close();
+    }
 }