mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-02-23 19:39:53 +08:00
Closing a Connection or Statement object twice should be a no-op
instead of throwing an Exception. Per report from Victor Sergienko.
This commit is contained in:
parent
27ae96c2b6
commit
935e6e502d
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user