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.sql.Types;
|
||||||
import java.util.Vector;
|
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
|
* This class defines methods of the jdbc1 specification. This class is
|
||||||
* extended by org.postgresql.jdbc2.AbstractJdbc2Statement which adds the jdbc2
|
* extended by org.postgresql.jdbc2.AbstractJdbc2Statement which adds the jdbc2
|
||||||
* methods. The real Statement class (for jdbc1) is org.postgresql.jdbc1.Jdbc1Statement
|
* 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 m_useServerPrepare = false;
|
||||||
|
|
||||||
|
private boolean isClosed = false;
|
||||||
|
|
||||||
// m_preparedCount is used for naming of auto-cursors and must
|
// m_preparedCount is used for naming of auto-cursors and must
|
||||||
// be synchronized so that multiple threads using the same
|
// be synchronized so that multiple threads using the same
|
||||||
// connection don't stomp over each others cursors.
|
// connection don't stomp over each others cursors.
|
||||||
@ -785,6 +787,10 @@ public abstract class AbstractJdbc1Statement implements BaseStatement
|
|||||||
*/
|
*/
|
||||||
public void close() throws SQLException
|
public void close() throws SQLException
|
||||||
{
|
{
|
||||||
|
// closing an already closed Statement is a no-op.
|
||||||
|
if (isClosed)
|
||||||
|
return;
|
||||||
|
|
||||||
// Force the ResultSet to close
|
// Force the ResultSet to close
|
||||||
java.sql.ResultSet rs = getResultSet();
|
java.sql.ResultSet rs = getResultSet();
|
||||||
if (rs != null)
|
if (rs != null)
|
||||||
@ -794,6 +800,7 @@ public abstract class AbstractJdbc1Statement implements BaseStatement
|
|||||||
|
|
||||||
// Disasociate it from us (For Garbage Collection)
|
// Disasociate it from us (For Garbage Collection)
|
||||||
result = null;
|
result = null;
|
||||||
|
isClosed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -14,7 +14,7 @@ import org.postgresql.PGConnection;
|
|||||||
*
|
*
|
||||||
* @author Aaron Mulder (ammulder@chariotsolutions.com)
|
* @author Aaron Mulder (ammulder@chariotsolutions.com)
|
||||||
* @author Csaba Nagy (ncsaba@yahoo.com)
|
* @author Csaba Nagy (ncsaba@yahoo.com)
|
||||||
* @version $Revision: 1.7.4.2 $
|
* @version $Revision: 1.7.4.3 $
|
||||||
*/
|
*/
|
||||||
public class PooledConnectionImpl implements PooledConnection
|
public class PooledConnectionImpl implements PooledConnection
|
||||||
{
|
{
|
||||||
@ -234,12 +234,17 @@ public class PooledConnectionImpl implements PooledConnection
|
|||||||
{
|
{
|
||||||
return con == null ? Boolean.TRUE : Boolean.FALSE;
|
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");
|
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"))
|
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;
|
SQLException ex = null;
|
||||||
if (!con.getAutoCommit())
|
if (!con.getAutoCommit())
|
||||||
{
|
{
|
||||||
@ -358,12 +363,12 @@ public class PooledConnectionImpl implements PooledConnection
|
|||||||
return method.invoke(st, args);
|
return method.invoke(st, args);
|
||||||
}
|
}
|
||||||
// All the rest is from the Statement interface
|
// 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"))
|
if (method.getName().equals("close"))
|
||||||
{
|
{
|
||||||
|
// closing an already closed object is a no-op
|
||||||
|
if (st == null || con.isClosed())
|
||||||
|
return null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
st.close();
|
st.close();
|
||||||
} finally {
|
} finally {
|
||||||
@ -372,6 +377,10 @@ public class PooledConnectionImpl implements PooledConnection
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
if (st == null || con.isClosed())
|
||||||
|
{
|
||||||
|
throw new SQLException("Statement has been closed");
|
||||||
|
}
|
||||||
else if (method.getName().equals("getConnection"))
|
else if (method.getName().equals("getConnection"))
|
||||||
{
|
{
|
||||||
return con.getProxy(); // the proxied connection, not a physical connection
|
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? ;-)
|
* 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
|
public class ConnectionTest extends TestCase
|
||||||
@ -347,4 +347,14 @@ public class ConnectionTest extends TestCase
|
|||||||
assertTrue(ex.getMessage(), false);
|
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.
|
* interface to the PooledConnection is through the CPDS.
|
||||||
*
|
*
|
||||||
* @author Aaron Mulder (ammulder@chariotsolutions.com)
|
* @author Aaron Mulder (ammulder@chariotsolutions.com)
|
||||||
* @version $Revision: 1.6.4.3 $
|
* @version $Revision: 1.6.4.4 $
|
||||||
*/
|
*/
|
||||||
public class ConnectionPoolTest extends BaseDataSourceTest
|
public class ConnectionPoolTest extends BaseDataSourceTest
|
||||||
{
|
{
|
||||||
@ -131,13 +131,6 @@ public class ConnectionPoolTest extends BaseDataSourceTest
|
|||||||
}
|
}
|
||||||
catch (SQLException e)
|
catch (SQLException e)
|
||||||
{}
|
{}
|
||||||
try
|
|
||||||
{
|
|
||||||
con.close();
|
|
||||||
fail("Original connection wrapper should be closed when new connection wrapper is generated");
|
|
||||||
}
|
|
||||||
catch (SQLException e)
|
|
||||||
{}
|
|
||||||
con2.close();
|
con2.close();
|
||||||
pc.close();
|
pc.close();
|
||||||
}
|
}
|
||||||
@ -194,13 +187,8 @@ public class ConnectionPoolTest extends BaseDataSourceTest
|
|||||||
con.close();
|
con.close();
|
||||||
assertTrue(cc.getCount() == 2);
|
assertTrue(cc.getCount() == 2);
|
||||||
assertTrue(cc.getErrorCount() == 0);
|
assertTrue(cc.getErrorCount() == 0);
|
||||||
try
|
// a double close shouldn't fire additional events
|
||||||
{
|
|
||||||
con.close();
|
con.close();
|
||||||
fail("Should not be able to close a connection wrapper twice");
|
|
||||||
}
|
|
||||||
catch (SQLException e)
|
|
||||||
{}
|
|
||||||
assertTrue(cc.getCount() == 2);
|
assertTrue(cc.getCount() == 2);
|
||||||
assertTrue(cc.getErrorCount() == 0);
|
assertTrue(cc.getErrorCount() == 0);
|
||||||
pc.close();
|
pc.close();
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package org.postgresql.test.jdbc2.optional;
|
package org.postgresql.test.jdbc2.optional;
|
||||||
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Statement;
|
||||||
import org.postgresql.test.TestUtil;
|
import org.postgresql.test.TestUtil;
|
||||||
import org.postgresql.jdbc2.optional.PoolingDataSource;
|
import org.postgresql.jdbc2.optional.PoolingDataSource;
|
||||||
import org.postgresql.jdbc2.optional.BaseDataSource;
|
import org.postgresql.jdbc2.optional.BaseDataSource;
|
||||||
@ -9,7 +10,7 @@ import org.postgresql.jdbc2.optional.BaseDataSource;
|
|||||||
* Minimal tests for pooling DataSource. Needs many more.
|
* Minimal tests for pooling DataSource. Needs many more.
|
||||||
*
|
*
|
||||||
* @author Aaron Mulder (ammulder@chariotsolutions.com)
|
* @author Aaron Mulder (ammulder@chariotsolutions.com)
|
||||||
* @version $Revision: 1.1.6.1 $
|
* @version $Revision: 1.1.6.2 $
|
||||||
*/
|
*/
|
||||||
public class PoolingDataSourceTest extends BaseDataSourceTest
|
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…
x
Reference in New Issue
Block a user