diff --git a/src/main/java/com/alibaba/druid/filter/stat/StatFilter.java b/src/main/java/com/alibaba/druid/filter/stat/StatFilter.java index 6b97631c77..957347ca9e 100644 --- a/src/main/java/com/alibaba/druid/filter/stat/StatFilter.java +++ b/src/main/java/com/alibaba/druid/filter/stat/StatFilter.java @@ -41,7 +41,6 @@ import com.alibaba.druid.proxy.jdbc.StatementProxy; import com.alibaba.druid.stat.JdbcConnectionStat; import com.alibaba.druid.stat.JdbcDataSourceStat; import com.alibaba.druid.stat.JdbcResultSetStat; -import com.alibaba.druid.stat.JdbcResultSetStat.Entry; import com.alibaba.druid.stat.JdbcSqlStat; import com.alibaba.druid.stat.JdbcStatContext; import com.alibaba.druid.stat.JdbcStatManager; @@ -162,16 +161,15 @@ public class StatFilter extends FilterEventAdapter implements StatFilterMBean { if (connection != null) { JdbcConnectionStat.Entry statEntry = getConnectionInfo(connection); - + dataSourceStat.getConnections().put(connection.getId(), statEntry); - + statEntry.setConnectTime(new Date(startTime)); statEntry.setConnectTimespanNano(nanoSpan); statEntry.setEstablishNano(System.nanoTime()); statEntry.setEstablishTime(nowTime); statEntry.setConnectStackTrace(new Exception()); - - + connectStat.setActiveCount(dataSourceStat.getConnections().size()); dataSourceStat.getConnectionStat().setActiveCount(dataSourceStat.getConnections().size()); } @@ -467,68 +465,32 @@ public class StatFilter extends FilterEventAdapter implements StatFilterMBean { resultSetStat.beforeOpen(); dataSourceStat.getResultSetStat().beforeOpen(); - JdbcResultSetStat.Entry rsStatEntry = new Entry(); - - resultSet.getAttributes().put(ATTR_NAME_RESULT_SET_STAT, rsStatEntry); + resultSet.setConstructNano(System.nanoTime()); // super.resultSetOpenAfter(resultSet); } - @Override - public boolean resultSet_previous(FilterChain chain, ResultSetProxy resultSet) throws SQLException { - boolean moreRows = super.resultSet_previous(chain, resultSet); - - if (moreRows) { - JdbcResultSetStat.Entry resultSetCounter = getResultSetInfo(resultSet); - if (resultSetCounter != null) { - resultSetCounter.decrementCusorIndex(); - } - } - - return moreRows; - } - - @Override - public boolean resultSet_next(FilterChain chain, ResultSetProxy resultSet) throws SQLException { - boolean moreRows = super.resultSet_next(chain, resultSet); - - if (moreRows) { - JdbcResultSetStat.Entry resultSetCounter = getResultSetInfo(resultSet); - if (resultSetCounter != null) { - resultSetCounter.setCusorIndex(resultSetCounter.getCusorIndex() + 1); - if (resultSetCounter.getCusorIndex() > resultSetCounter.getFetchRowCount()) { - resultSetCounter.setFetchRowCount(resultSetCounter.getCusorIndex()); - } - } - } - - return moreRows; - } - @Override public void resultSet_close(FilterChain chain, ResultSetProxy resultSet) throws SQLException { - JdbcResultSetStat.Entry rsStatEntry = getResultSetInfo(resultSet); - if (rsStatEntry != null) { - long nanoSpan = System.nanoTime() - rsStatEntry.getConstructNano(); + long nanoSpan = System.nanoTime() - resultSet.getConstructNano(); - int fetchCount = rsStatEntry.getFetchRowCount(); + int fetchCount = resultSet.getFetchRowCount(); - resultSetStat.afterClose(nanoSpan); - dataSourceStat.getResultSetStat().afterClose(nanoSpan); + resultSetStat.afterClose(nanoSpan); + dataSourceStat.getResultSetStat().afterClose(nanoSpan); - resultSetStat.addFetchRowCount(fetchCount); - dataSourceStat.getResultSetStat().addFetchRowCount(fetchCount); + resultSetStat.addFetchRowCount(fetchCount); + dataSourceStat.getResultSetStat().addFetchRowCount(fetchCount); - resultSetStat.incrementCloseCounter(); - dataSourceStat.getResultSetStat().incrementCloseCounter(); + resultSetStat.incrementCloseCounter(); + dataSourceStat.getResultSetStat().incrementCloseCounter(); - String sql = resultSet.getSql(); - if (sql != null) { - JdbcSqlStat sqlStat = dataSourceStat.getSqlStatMap().get(sql); - if (sqlStat != null) { - sqlStat.addFetchRowCount(fetchCount); - } + String sql = resultSet.getSql(); + if (sql != null) { + JdbcSqlStat sqlStat = dataSourceStat.getSqlStatMap().get(sql); + if (sqlStat != null) { + sqlStat.addFetchRowCount(fetchCount); } } @@ -537,7 +499,6 @@ public class StatFilter extends FilterEventAdapter implements StatFilterMBean { public final static String ATTR_NAME_CONNECTION_STAT = "stat.conn"; public final static String ATTR_NAME_STATEMENT_STAT = "stat.stmt"; - public final static String ATTR_NAME_RESULT_SET_STAT = "stat.rs"; public JdbcConnectionStat.Entry getConnectionInfo(ConnectionProxy connection) { JdbcConnectionStat.Entry counter = (JdbcConnectionStat.Entry) connection.getAttributes().get(ATTR_NAME_CONNECTION_STAT); @@ -562,16 +523,6 @@ public class StatFilter extends FilterEventAdapter implements StatFilterMBean { return counter; } - public static JdbcResultSetStat.Entry getResultSetInfo(ResultSetProxy resultSet) { - if (resultSet == null) { - return null; - } - - JdbcResultSetStat.Entry rsStatEntry = (JdbcResultSetStat.Entry) resultSet.getAttributes().get(ATTR_NAME_RESULT_SET_STAT); - - return rsStatEntry; - } - @Override public long getConnectionActiveCount() { return dataSourceStat.getConnections().size(); diff --git a/src/main/java/com/alibaba/druid/pool/PoolableConnection.java b/src/main/java/com/alibaba/druid/pool/PoolableConnection.java index 9e9fcecab0..f6f698bf83 100644 --- a/src/main/java/com/alibaba/druid/pool/PoolableConnection.java +++ b/src/main/java/com/alibaba/druid/pool/PoolableConnection.java @@ -121,6 +121,9 @@ public class PoolableConnection implements PooledConnection, Connection { if (holder.isPoolPreparedStatements()) { stmt.clearResultSet(); holder.removeTrace(stmt); + + stmt.getPreparedStatementHolder().setFetchRowPeak(stmt.getFetchRowPeak()); + stmt.setClosed(true); // soft set close if (stmt.getHitCount() == 0 && isOracle()) { diff --git a/src/main/java/com/alibaba/druid/pool/PoolableResultSet.java b/src/main/java/com/alibaba/druid/pool/PoolableResultSet.java index 5373b272c6..6d2bb35f88 100644 --- a/src/main/java/com/alibaba/druid/pool/PoolableResultSet.java +++ b/src/main/java/com/alibaba/druid/pool/PoolableResultSet.java @@ -40,7 +40,10 @@ public final class PoolableResultSet extends PoolableWrapper implements ResultSe private final ResultSet rs; private final PoolableStatement stmt; - private boolean closed = false; + private boolean closed = false; + + protected int cursorIndex = 0; + protected int fetchRowCount = 0; public PoolableResultSet(PoolableStatement stmt, ResultSet rs){ super(rs); @@ -63,7 +66,15 @@ public final class PoolableResultSet extends PoolableWrapper implements ResultSe @Override public boolean next() throws SQLException { try { - return rs.next(); + boolean moreRows = rs.next(); + + if (moreRows) { + cursorIndex++; + if (cursorIndex > fetchRowCount) { + fetchRowCount = cursorIndex; + } + } + return moreRows; } catch (Throwable t) { throw checkException(t); } @@ -74,6 +85,8 @@ public final class PoolableResultSet extends PoolableWrapper implements ResultSe try { this.closed = true; rs.close(); + + stmt.recordFetchRowCount(fetchRowCount); } catch (Throwable t) { throw checkException(t); } @@ -581,7 +594,13 @@ public final class PoolableResultSet extends PoolableWrapper implements ResultSe @Override public boolean previous() throws SQLException { try { - return rs.previous(); + boolean moreRows = rs.previous(); + + if (moreRows) { + cursorIndex--; + } + + return moreRows; } catch (Throwable t) { throw checkException(t); } diff --git a/src/main/java/com/alibaba/druid/pool/PoolableStatement.java b/src/main/java/com/alibaba/druid/pool/PoolableStatement.java index 2f657e1b1c..c3895f0c32 100644 --- a/src/main/java/com/alibaba/druid/pool/PoolableStatement.java +++ b/src/main/java/com/alibaba/druid/pool/PoolableStatement.java @@ -37,6 +37,7 @@ public class PoolableStatement extends PoolableWrapper implements Statement { protected PoolableConnection conn; protected final List resultSetTrace = new ArrayList(); protected boolean closed = false; + protected int fetchRowPeak = -1; public PoolableStatement(PoolableConnection conn, Statement stmt){ super(stmt); @@ -45,6 +46,16 @@ public class PoolableStatement extends PoolableWrapper implements Statement { this.stmt = stmt; } + protected void recordFetchRowCount(int fetchRowCount) { + if (fetchRowPeak < fetchRowCount) { + fetchRowPeak = fetchRowCount; + } + } + + public int getFetchRowPeak() { + return fetchRowPeak; + } + protected SQLException checkException(Throwable error) throws SQLException { return conn.handleException(error); } @@ -79,7 +90,7 @@ public class PoolableStatement extends PoolableWrapper implements Statement { } resultSetTrace.clear(); } - + public void incrementExecuteCount() { this.getPoolableConnection().getConnectionHolder().getDataSource().incrementExecuteCount(); } @@ -87,7 +98,7 @@ public class PoolableStatement extends PoolableWrapper implements Statement { @Override public final ResultSet executeQuery(String sql) throws SQLException { checkOpen(); - + incrementExecuteCount(); transactionRecord(sql); @@ -397,7 +408,7 @@ public class PoolableStatement extends PoolableWrapper implements Statement { @Override public int[] executeBatch() throws SQLException { checkOpen(); - + incrementExecuteCount(); try { diff --git a/src/main/java/com/alibaba/druid/pool/PreparedStatementHolder.java b/src/main/java/com/alibaba/druid/pool/PreparedStatementHolder.java index 0acc6b61dd..bf5bf53f9d 100644 --- a/src/main/java/com/alibaba/druid/pool/PreparedStatementHolder.java +++ b/src/main/java/com/alibaba/druid/pool/PreparedStatementHolder.java @@ -26,13 +26,25 @@ public final class PreparedStatementHolder { private final PreparedStatementKey key; private final PreparedStatement statement; - private int hitCount = 0; + private int hitCount = 0; + + private int fetchRowPeak = -1; public PreparedStatementHolder(PreparedStatementKey key, PreparedStatement stmt){ this.key = key; this.statement = stmt; } + public int getFetchRowPeak() { + return fetchRowPeak; + } + + public void setFetchRowPeak(int fetchRowPeak) { + if (fetchRowPeak > this.fetchRowPeak) { + this.fetchRowPeak = fetchRowPeak; + } + } + public PreparedStatement getStatement() { return statement; } diff --git a/src/main/java/com/alibaba/druid/proxy/jdbc/ResultSetProxy.java b/src/main/java/com/alibaba/druid/proxy/jdbc/ResultSetProxy.java index d3df258367..49d1d729f5 100644 --- a/src/main/java/com/alibaba/druid/proxy/jdbc/ResultSetProxy.java +++ b/src/main/java/com/alibaba/druid/proxy/jdbc/ResultSetProxy.java @@ -27,4 +27,12 @@ public interface ResultSetProxy extends ResultSet, WrapperProxy { StatementProxy getStatementProxy(); String getSql(); + + int getCursorIndex(); + + int getFetchRowCount(); + + long getConstructNano(); + + void setConstructNano(long constructNano); } diff --git a/src/main/java/com/alibaba/druid/proxy/jdbc/ResultSetProxyImpl.java b/src/main/java/com/alibaba/druid/proxy/jdbc/ResultSetProxyImpl.java index 520ec43e60..79bd97fd08 100644 --- a/src/main/java/com/alibaba/druid/proxy/jdbc/ResultSetProxyImpl.java +++ b/src/main/java/com/alibaba/druid/proxy/jdbc/ResultSetProxyImpl.java @@ -50,6 +50,10 @@ public class ResultSetProxyImpl extends WrapperProxyImpl implements ResultSetPro private final StatementProxy statement; private final String sql; + protected int cursorIndex = 0; + protected int fetchRowCount = 0; + protected long constructNano; + public ResultSetProxyImpl(StatementProxy statement, ResultSet resultSet, long id, String sql){ super(resultSet, id); this.statement = statement; @@ -57,6 +61,22 @@ public class ResultSetProxyImpl extends WrapperProxyImpl implements ResultSetPro this.sql = sql; } + public long getConstructNano() { + return constructNano; + } + + public void setConstructNano(long constructNano) { + this.constructNano = constructNano; + } + + public int getCursorIndex() { + return cursorIndex; + } + + public int getFetchRowCount() { + return fetchRowCount; + } + public String getSql() { return sql; } @@ -545,12 +565,26 @@ public class ResultSetProxyImpl extends WrapperProxyImpl implements ResultSetPro @Override public boolean next() throws SQLException { - return createChain().resultSet_next(this); + boolean moreRows = createChain().resultSet_next(this); + + if (moreRows) { + cursorIndex++; + if (cursorIndex > fetchRowCount) { + fetchRowCount = cursorIndex; + } + } + return moreRows; } @Override public boolean previous() throws SQLException { - return createChain().resultSet_previous(this); + boolean moreRows = createChain().resultSet_previous(this); + + if (moreRows) { + cursorIndex--; + } + + return moreRows; } @Override diff --git a/src/main/java/com/alibaba/druid/stat/JdbcResultSetStat.java b/src/main/java/com/alibaba/druid/stat/JdbcResultSetStat.java index 0e21648891..f893c418f3 100644 --- a/src/main/java/com/alibaba/druid/stat/JdbcResultSetStat.java +++ b/src/main/java/com/alibaba/druid/stat/JdbcResultSetStat.java @@ -185,38 +185,4 @@ public class JdbcResultSetStat implements JdbcResultSetStatMBean { closeCount.incrementAndGet(); } - public static class Entry { - - protected final long constructNano; - protected int cusorIndex = 0; - protected int fetchRowCount = 0; - - public Entry(){ - this.constructNano = System.nanoTime(); - } - - public void decrementCusorIndex() { - cusorIndex--; - } - - public long getConstructNano() { - return constructNano; - } - - public int getCusorIndex() { - return cusorIndex; - } - - public void setCusorIndex(int cusorIndex) { - this.cusorIndex = cusorIndex; - } - - public int getFetchRowCount() { - return fetchRowCount; - } - - public void setFetchRowCount(int fetchRowCount) { - this.fetchRowCount = fetchRowCount; - } - } } diff --git a/src/test/java/com/alibaba/druid/pool/TestOraclePreparedStatement.java b/src/test/java/com/alibaba/druid/pool/TestOraclePreparedStatement.java index f1087d6891..65f5b6d7a7 100644 --- a/src/test/java/com/alibaba/druid/pool/TestOraclePreparedStatement.java +++ b/src/test/java/com/alibaba/druid/pool/TestOraclePreparedStatement.java @@ -31,22 +31,28 @@ public class TestOraclePreparedStatement extends TestCase { // ResultSet metaRs = conn.getMetaData().getTables(null, "ALIBABA", null, new String[] {"TABLE"}); // JdbcUtils.printResultSet(metaRs); // metaRs.close(); + + String sql = "SELECT * FROM WS_OFFER WHERE ROWNUM <= ?"; OraclePreparedStatement oracleStmt = null; - PreparedStatement stmt = conn.prepareStatement("SELECT ? FROM DUAL"); + PreparedStatement stmt = conn.prepareStatement(sql); oracleStmt = (OraclePreparedStatement) stmt; + oracleStmt.setRowPrefetch(1); { - stmt.setString(1, "aaa"); + stmt.setInt(1, 1); ResultSet rs = stmt.executeQuery(); - rs.next(); + while (rs.next()) { + + } rs.close(); oracleStmt.clearDefines(); } + oracleStmt.setRowPrefetch(1000); { - stmt.setString(1, "bbb"); + stmt.setInt(1, 11); ResultSet rs = stmt.executeQuery(); rs.next();