diff --git a/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java index a16c23f5e8..e01ccb7b86 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java @@ -1515,6 +1515,8 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements return; } closedPreparedStatementCount.incrementAndGet(); + decrementCachedPreparedStatementCount(); + incrementCachedPreparedStatementDeleteCount(); JdbcUtils.close(stmtHolder.getStatement()); } diff --git a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java index 452313f6bd..01ae419fa9 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java @@ -218,8 +218,9 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat return; } + this.poolPreparedStatements = value; + if (!inited) { - this.poolPreparedStatements = value; return; } @@ -227,22 +228,22 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat LOG.info("set poolPreparedStatements " + this.poolPreparedStatements + " -> " + value); } - lock.lock(); - try { - if (this.poolPreparedStatements && (!value)) { + if (!value) { + lock.lock(); + try { + for (int i = 0; i < poolingCount; ++i) { DruidConnectionHolder connection = connections[i]; for (PreparedStatementHolder holder : connection.getStatementPool().getMap().values()) { closePreapredStatement(holder); - decrementCachedPreparedStatementCount(); } connection.getStatementPool().getMap().clear(); } + } finally { + lock.unlock(); } - } finally { - lock.unlock(); } } @@ -1804,6 +1805,10 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat return this.getDataSourceStat().getSqlStat(sqlId); } + public JdbcSqlStat getSqlStat(long sqlId) { + return this.getDataSourceStat().getSqlStat(sqlId); + } + public Map getSqlStatMap() { return this.getDataSourceStat().getSqlStatMap(); } diff --git a/src/main/java/com/alibaba/druid/pool/PreparedStatementPool.java b/src/main/java/com/alibaba/druid/pool/PreparedStatementPool.java index 8dc90d55c8..f397de07b5 100644 --- a/src/main/java/com/alibaba/druid/pool/PreparedStatementPool.java +++ b/src/main/java/com/alibaba/druid/pool/PreparedStatementPool.java @@ -159,8 +159,6 @@ public class PreparedStatementPool { OracleUtils.exitImplicitCacheToClose(holder.getStatement()); } dataSource.closePreapredStatement(holder); - dataSource.decrementCachedPreparedStatementCount(); - dataSource.incrementCachedPreparedStatementDeleteCount(); } public Map getMap() { diff --git a/src/test/java/com/alibaba/druid/bvt/pool/DruidPooledResultSetTest.java b/src/test/java/com/alibaba/druid/bvt/pool/DruidPooledResultSetTest.java new file mode 100644 index 0000000000..eaf935090b --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/pool/DruidPooledResultSetTest.java @@ -0,0 +1,88 @@ +package com.alibaba.druid.bvt.pool; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLFeatureNotSupportedException; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import com.alibaba.druid.mock.MockResultSet; +import com.alibaba.druid.pool.DruidDataSource; +import com.alibaba.druid.pool.DruidPooledResultSet; + +public class DruidPooledResultSetTest extends TestCase { + + private DruidDataSource dataSource; + + protected void setUp() throws Exception { + dataSource = new DruidDataSource(); + dataSource.setUrl("jdbc:mock:xxx"); + dataSource.setTestOnBorrow(false); + dataSource.setFilters("stat"); + } + + protected void tearDown() throws Exception { + dataSource.close(); + } + + public void testWrap() throws Exception { + String sql = "select ?"; + Connection conn = dataSource.getConnection(); + + PreparedStatement stmt = conn.prepareStatement(sql); + stmt.setString(1, "xxx"); + ResultSet rs = stmt.executeQuery(); + + ResultSet raw = rs.unwrap(ResultSet.class); + + Assert.assertTrue(raw instanceof MockResultSet); + + rs.close(); + + conn.close(); + } + + public void test_notSupport() throws Exception { + String sql = "select ?"; + Connection conn = dataSource.getConnection(); + + PreparedStatement stmt = conn.prepareStatement(sql); + stmt.setString(1, "xxx"); + DruidPooledResultSet rs = (DruidPooledResultSet) stmt.executeQuery(); + + Exception error = null; + try { + rs.getObject(1, String.class); + } catch (SQLFeatureNotSupportedException e) { + error = e; + } + Assert.assertNotNull(error); + + rs.close(); + + conn.close(); + } + + public void test_notSupport_1() throws Exception { + String sql = "select ?"; + Connection conn = dataSource.getConnection(); + + PreparedStatement stmt = conn.prepareStatement(sql); + stmt.setString(1, "xxx"); + DruidPooledResultSet rs = (DruidPooledResultSet) stmt.executeQuery(); + + Exception error = null; + try { + rs.getObject("1", String.class); + } catch (SQLFeatureNotSupportedException e) { + error = e; + } + Assert.assertNotNull(error); + + rs.close(); + + conn.close(); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/pool/DumpTest.java b/src/test/java/com/alibaba/druid/bvt/pool/DumpTest.java new file mode 100644 index 0000000000..e0e1a60dad --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/pool/DumpTest.java @@ -0,0 +1,111 @@ +package com.alibaba.druid.bvt.pool; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.util.List; +import java.util.Map; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import com.alibaba.druid.pool.DruidDataSource; +import com.alibaba.druid.stat.JdbcSqlStat; + +public class DumpTest extends TestCase { + + private DruidDataSource dataSource; + + protected void setUp() throws Exception { + dataSource = new DruidDataSource(); + dataSource.setUrl("jdbc:mock:xxx"); + dataSource.setTestOnBorrow(false); + dataSource.setFilters("stat"); + + dataSource.setPoolPreparedStatements(true); + } + + protected void tearDown() throws Exception { + dataSource.close(); + } + + public void testWrap() throws Exception { + String sql = "select ?"; + Connection conn = dataSource.getConnection(); + + PreparedStatement stmt = conn.prepareStatement(sql); + stmt.setString(1, "xxx"); + ResultSet rs = stmt.executeQuery(); + rs.next(); + rs.close(); + + conn.close(); + + dataSource.dump(); + } + + public void testToString() throws Exception { + String sql = "select ?, ?"; + Connection conn = dataSource.getConnection(); + + PreparedStatement stmt = conn.prepareStatement(sql); + stmt.setString(1, "xxx"); + stmt.setInt(2, 33); + ResultSet rs = stmt.executeQuery(); + rs.next(); + rs.close(); + + conn.close(); + + dataSource.toString(); + } + + public void test_getPoolingConnectionInfo() throws Exception { + String sql = "select ?, ?"; + Connection conn = dataSource.getConnection(); + Connection conn1 = dataSource.getConnection(); + + PreparedStatement stmt = conn.prepareStatement(sql); + stmt.setString(1, "xxx"); + stmt.setInt(2, 33); + ResultSet rs = stmt.executeQuery(); + rs.next(); + rs.close(); + + conn.close(); + conn1.close(); + + List> poolingList = dataSource.getPoolingConnectionInfo(); + Assert.assertEquals(2, poolingList.size()); + } + + public void test_getStatData() throws Exception { + String sql = "select ?, ?"; + Connection conn = dataSource.getConnection(); + Connection conn1 = dataSource.getConnection(); + + PreparedStatement stmt = conn.prepareStatement(sql); + stmt.setString(1, "xxx"); + stmt.setInt(2, 33); + ResultSet rs = stmt.executeQuery(); + rs.next(); + rs.close(); + + conn.close(); + conn1.close(); + + Map statData = dataSource.getStatData(); + Assert.assertEquals(2, statData.get("PoolingCount")); + Assert.assertEquals(2, statData.get("PoolingPeak")); + Assert.assertEquals(2L, statData.get("LogicConnectCount")); + Assert.assertEquals(2L, statData.get("LogicCloseCount")); + Assert.assertEquals(0L, statData.get("LogicConnectErrorCount")); + + Assert.assertEquals(1, dataSource.getSqlStatMap().size()); + JdbcSqlStat sqlStat = dataSource.getSqlStatMap().get(sql); + Assert.assertNotNull(sqlStat); + Assert.assertNotNull(dataSource.getSqlStat(sqlStat.getId())); + Assert.assertNotNull(dataSource.getSqlStat((int) sqlStat.getId())); + } + +} diff --git a/src/test/java/com/alibaba/druid/bvt/pool/dynamic/PoolPreparedStatementsChangeTest.java b/src/test/java/com/alibaba/druid/bvt/pool/dynamic/PoolPreparedStatementsChangeTest.java new file mode 100644 index 0000000000..3e859d5cca --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/pool/dynamic/PoolPreparedStatementsChangeTest.java @@ -0,0 +1,116 @@ +/* + * Copyright 1999-2011 Alibaba Group Holding Ltd. + * + * Licensed 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 com.alibaba.druid.bvt.pool.dynamic; + +import java.lang.reflect.Field; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import com.alibaba.druid.mock.MockResultSet; +import com.alibaba.druid.pool.DruidDataSource; +import com.alibaba.druid.support.logging.Log; + +public class PoolPreparedStatementsChangeTest extends TestCase { + + private DruidDataSource dataSource; + + private Log dataSourceLog; + + protected void setUp() throws Exception { + Field logField = DruidDataSource.class.getDeclaredField("LOG"); + logField.setAccessible(true); + dataSourceLog = (Log) logField.get(null); + + dataSourceLog.resetStat(); + + dataSource = new DruidDataSource(); + dataSource.setUrl("jdbc:mock:xxx"); + dataSource.setTestOnBorrow(false); + dataSource.init(); + + Assert.assertEquals(1, dataSourceLog.getInfoCount()); + } + + protected void tearDown() throws Exception { + dataSource.close(); + } + + public void test_connectPropertiesChange() throws Exception { + { + Connection conn = dataSource.getConnection(); + conn.close(); + } + + Assert.assertEquals(false, dataSource.isPoolPreparedStatements()); + + dataSource.setPoolPreparedStatements(true); + + Assert.assertEquals(true, dataSource.isPoolPreparedStatements()); + + String sql = "select ?"; + + Assert.assertEquals(0, dataSource.getCachedPreparedStatementCount()); + { + Connection conn = dataSource.getConnection(); + + PreparedStatement stmt = conn.prepareStatement(sql); + stmt.setString(1, "xxx"); + ResultSet rs = stmt.executeQuery(); + + rs.close(); + + conn.close(); + } + Assert.assertEquals(1, dataSource.getCachedPreparedStatementCount()); + Assert.assertEquals(1, dataSource.getCachedPreparedStatementAccessCount()); + + { + Connection conn = dataSource.getConnection(); + + PreparedStatement stmt = conn.prepareStatement(sql); + stmt.setString(1, "xxx"); + ResultSet rs = stmt.executeQuery(); + + rs.close(); + + conn.close(); + } + Assert.assertEquals(1, dataSource.getCachedPreparedStatementCount()); + Assert.assertEquals(2, dataSource.getCachedPreparedStatementAccessCount()); + + dataSource.setPoolPreparedStatements(false); + Assert.assertEquals(0, dataSource.getCachedPreparedStatementCount()); + Assert.assertEquals(2, dataSource.getCachedPreparedStatementAccessCount()); + + { + Connection conn = dataSource.getConnection(); + + PreparedStatement stmt = conn.prepareStatement(sql); + stmt.setString(1, "xxx"); + ResultSet rs = stmt.executeQuery(); + + rs.close(); + + conn.close(); + } + Assert.assertEquals(0, dataSource.getCachedPreparedStatementCount()); + Assert.assertEquals(2, dataSource.getCachedPreparedStatementAccessCount()); + } +}