blob: 145f7a60cdf69df592e0a1f5e6bc836633c9290e [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.dbcp;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import junit.framework.Test;
import junit.framework.TestSuite;
/**
* TestSuite for BasicDataSource with prepared statement pooling enabled
*
* @author Dirk Verbeeck
* @version $Revision$ $Date$
*/
public class TestPStmtPoolingBasicDataSource extends TestBasicDataSource {
public TestPStmtPoolingBasicDataSource(String testName) {
super(testName);
}
public static Test suite() {
return new TestSuite(TestPStmtPoolingBasicDataSource.class);
}
public void setUp() throws Exception {
super.setUp();
// PoolPreparedStatements enabled, should not affect the basic tests
ds.setPoolPreparedStatements(true);
ds.setMaxOpenPreparedStatements(2);
}
public void tearDown() throws Exception {
super.tearDown();
// nothing to do here
}
public void testPreparedStatementPooling() throws Exception {
Connection conn = getConnection();
assertNotNull(conn);
PreparedStatement stmt1 = conn.prepareStatement("select 'a' from dual");
assertNotNull(stmt1);
PreparedStatement stmt2 = conn.prepareStatement("select 'b' from dual");
assertNotNull(stmt2);
assertTrue(stmt1 != stmt2);
// go over the maxOpen limit
PreparedStatement stmt3 = null;
try {
conn.prepareStatement("select 'c' from dual");
fail("expected SQLException");
}
catch (SQLException e) {}
// make idle
stmt2.close();
// test cleanup the 'b' statement
stmt3 = conn.prepareStatement("select 'c' from dual");
assertNotNull(stmt3);
assertTrue(stmt3 != stmt1);
assertTrue(stmt3 != stmt2);
// normal reuse of statement
stmt1.close();
PreparedStatement stmt4 = conn.prepareStatement("select 'a' from dual");
assertNotNull(stmt4);
}
/**
* Verifies that the prepared statement pool behaves as an LRU cache,
* closing least-recently-used statements idle in the pool to make room
* for new ones if necessary.
*/
public void testLRUBehavior() throws Exception {
ds.setMaxOpenPreparedStatements(3);
Connection conn = getConnection();
assertNotNull(conn);
// Open 3 statements and then close them into the pool
PreparedStatement stmt1 = conn.prepareStatement("select 'a' from dual");
PreparedStatement inner1 = (PreparedStatement) ((DelegatingPreparedStatement) stmt1).getInnermostDelegate();
PreparedStatement stmt2 = conn.prepareStatement("select 'b' from dual");
PreparedStatement inner2 = (PreparedStatement) ((DelegatingPreparedStatement) stmt2).getInnermostDelegate();
PreparedStatement stmt3 = conn.prepareStatement("select 'c' from dual");
PreparedStatement inner3 = (PreparedStatement) ((DelegatingPreparedStatement) stmt3).getInnermostDelegate();
stmt1.close();
Thread.sleep(100); // Make sure return timestamps are different
stmt2.close();
Thread.sleep(100);
stmt3.close();
// Pool now has three idle statements, getting another one will force oldest (stmt1) out
PreparedStatement stmt4 = conn.prepareStatement("select 'd' from dual");
assertNotNull(stmt4);
// Verify that inner1 has been closed
try {
inner1.clearParameters();
fail("expecting SQLExcption - statement should be closed");
} catch (SQLException ex) {
//Expected
}
// But others are still open
inner2.clearParameters();
inner3.clearParameters();
// Now make sure stmt1 does not come back from the dead
PreparedStatement stmt5 = conn.prepareStatement("select 'a' from dual");
PreparedStatement inner5 = (PreparedStatement) ((DelegatingPreparedStatement) stmt5).getInnermostDelegate();
assertNotSame(inner5, inner1);
// inner2 should be closed now
try {
inner2.clearParameters();
fail("expecting SQLExcption - statement should be closed");
} catch (SQLException ex) {
//Expected
}
// But inner3 should still be open
inner3.clearParameters();
}
// Bugzilla Bug 27246
// PreparedStatement cache should be different depending on the Catalog
public void testPStmtCatalog() throws Exception {
Connection conn = getConnection();
conn.setCatalog("catalog1");
DelegatingPreparedStatement stmt1 = (DelegatingPreparedStatement) conn.prepareStatement("select 'a' from dual");
TesterPreparedStatement inner1 = (TesterPreparedStatement) stmt1.getInnermostDelegate();
assertEquals("catalog1", inner1.getCatalog());
stmt1.close();
conn.setCatalog("catalog2");
DelegatingPreparedStatement stmt2 = (DelegatingPreparedStatement) conn.prepareStatement("select 'a' from dual");
TesterPreparedStatement inner2 = (TesterPreparedStatement) stmt2.getInnermostDelegate();
assertEquals("catalog2", inner2.getCatalog());
stmt2.close();
conn.setCatalog("catalog1");
DelegatingPreparedStatement stmt3 = (DelegatingPreparedStatement) conn.prepareStatement("select 'a' from dual");
TesterPreparedStatement inner3 = (TesterPreparedStatement) stmt1.getInnermostDelegate();
assertEquals("catalog1", inner3.getCatalog());
stmt3.close();
assertNotSame(inner1, inner2);
assertSame(inner1, inner3);
}
public void testPStmtPoolingWithNoClose() throws Exception {
ds.setMaxActive(1); // only one connection in pool needed
ds.setMaxIdle(1);
ds.setAccessToUnderlyingConnectionAllowed(true);
Connection conn1 = getConnection();
assertNotNull(conn1);
assertEquals(1, ds.getNumActive());
assertEquals(0, ds.getNumIdle());
PreparedStatement stmt1 = conn1.prepareStatement("select 'a' from dual");
assertNotNull(stmt1);
Statement inner1 = ((DelegatingPreparedStatement) stmt1).getInnermostDelegate();
assertNotNull(inner1);
stmt1.close();
Connection conn2 = conn1;
assertNotNull(conn2);
assertEquals(1, ds.getNumActive());
assertEquals(0, ds.getNumIdle());
PreparedStatement stmt2 = conn2.prepareStatement("select 'a' from dual");
assertNotNull(stmt2);
Statement inner2 = ((DelegatingPreparedStatement) stmt2).getInnermostDelegate();
assertNotNull(inner2);
assertSame(inner1, inner2);
}
public void testPStmtPoolingAccrossClose() throws Exception {
ds.setMaxActive(1); // only one connection in pool needed
ds.setMaxIdle(1);
ds.setAccessToUnderlyingConnectionAllowed(true);
Connection conn1 = getConnection();
assertNotNull(conn1);
assertEquals(1, ds.getNumActive());
assertEquals(0, ds.getNumIdle());
PreparedStatement stmt1 = conn1.prepareStatement("select 'a' from dual");
assertNotNull(stmt1);
Statement inner1 = ((DelegatingPreparedStatement) stmt1).getInnermostDelegate();
assertNotNull(inner1);
stmt1.close();
conn1.close();
assertEquals(0, ds.getNumActive());
assertEquals(1, ds.getNumIdle());
Connection conn2 = getConnection();
assertNotNull(conn2);
assertEquals(1, ds.getNumActive());
assertEquals(0, ds.getNumIdle());
PreparedStatement stmt2 = conn2.prepareStatement("select 'a' from dual");
assertNotNull(stmt2);
Statement inner2 = ((DelegatingPreparedStatement) stmt2).getInnermostDelegate();
assertNotNull(inner2);
assertSame(inner1, inner2);
}
}